feat: 휴가 사용현황 전체 직원 목록 API 추가

- GET /api/v1/leaves/balances 엔드포인트 추가
- LeaveService.getAllBalances() 메서드 구현
- TenantUserProfile 기준 전체 활성 직원 조회
- LeaveBalance 서브쿼리로 연차 정보 LEFT JOIN
- 부서/검색/정렬 필터링 및 페이지네이션 지원
- User 모델에 tenantProfiles/tenantProfile 관계 추가
This commit is contained in:
2025-12-24 19:29:15 +09:00
parent 6ee3378377
commit 3988372ca4
4 changed files with 91 additions and 0 deletions

View File

@@ -4,6 +4,7 @@
use App\Models\Tenants\Leave;
use App\Models\Tenants\LeaveBalance;
use App\Models\Tenants\TenantUserProfile;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
@@ -307,6 +308,66 @@ public function cancel(int $id, ?string $reason = null): Leave
});
}
/**
* 전체 직원 휴가 사용현황 목록 조회
* TenantUserProfile 기준으로 전체 직원 조회 후 LeaveBalance LEFT JOIN
*/
public function getAllBalances(array $params): LengthAwarePaginator
{
$tenantId = $this->tenantId();
$year = $params['year'] ?? now()->year;
$query = TenantUserProfile::query()
->where('tenant_id', $tenantId)
->where('employee_status', 'active')
->with([
'user:id,name,email',
'department:id,name',
])
->addSelect([
'tenant_user_profiles.*',
'leave_balance_total' => LeaveBalance::selectRaw('total_days')
->whereColumn('leave_balances.user_id', 'tenant_user_profiles.user_id')
->where('leave_balances.tenant_id', $tenantId)
->where('leave_balances.year', $year)
->limit(1),
'leave_balance_used' => LeaveBalance::selectRaw('used_days')
->whereColumn('leave_balances.user_id', 'tenant_user_profiles.user_id')
->where('leave_balances.tenant_id', $tenantId)
->where('leave_balances.year', $year)
->limit(1),
]);
// 부서 필터
if (! empty($params['department_id'])) {
$query->where('department_id', $params['department_id']);
}
// 검색 (사용자명)
if (! empty($params['search'])) {
$query->whereHas('user', function ($q) use ($params) {
$q->where('name', 'like', '%'.$params['search'].'%');
});
}
// 정렬
$sortBy = $params['sort_by'] ?? 'user_id';
$sortDir = $params['sort_dir'] ?? 'asc';
if ($sortBy === 'user_id') {
$query->orderBy('user_id', $sortDir);
} elseif ($sortBy === 'department') {
$query->orderBy('department_id', $sortDir);
} else {
$query->orderBy($sortBy, $sortDir);
}
// 페이지네이션
$perPage = $params['per_page'] ?? 20;
return $query->paginate($perPage);
}
/**
* 내 잔여 휴가 조회
*/