feat: [hr] 근태관리 영업팀 및 제외 사원 필터링 적용

- 근태 목록/통계/요약/초과근무에서 영업팀+제외 사원 제외
- 근태관리 부서 드롭다운에서 영업팀 제외
- 활성 사원 목록(드롭다운)에서 영업팀+제외 사원 제외
This commit is contained in:
김보곤
2026-03-05 16:54:21 +09:00
parent b0f821423d
commit d0d5a7acd9
2 changed files with 66 additions and 7 deletions

View File

@@ -12,6 +12,24 @@
class AttendanceService
{
/**
* 제외 대상 사원의 user_id 목록 (영업팀 + 강제 제외)
*/
private function getExcludedUserIds(?int $tenantId = null): array
{
$tenantId = $tenantId ?? session('selected_tenant_id');
return Employee::query()
->forTenant($tenantId)
->where(function ($q) {
$q->whereHas('department', function ($dq) {
$dq->where('name', 'like', '%영업팀%');
})->orWhere('json_extra->is_excluded', true);
})
->pluck('user_id')
->toArray();
}
/**
* 필터 적용 쿼리 생성 (목록/엑셀 공통)
*/
@@ -23,6 +41,12 @@ private function buildFilteredQuery(array $filters = [])
->with(['user', 'user.tenantProfiles' => fn ($q) => $q->where('tenant_id', $tenantId), 'user.tenantProfiles.department'])
->forTenant($tenantId);
// 제외 사원 필터링 (영업팀 부서 + 강제 제외)
$excludedUserIds = $this->getExcludedUserIds($tenantId);
if (! empty($excludedUserIds)) {
$query->whereNotIn('user_id', $excludedUserIds);
}
if (! empty($filters['q'])) {
$search = $filters['q'];
$query->whereHas('user', function ($q) use ($search) {
@@ -82,9 +106,18 @@ public function getMonthlyStats(?int $year = null, ?int $month = null): array
? now()->toDateString()
: Carbon::create($year, $month, 1)->endOfMonth()->toDateString();
$counts = Attendance::query()
// 제외 사원 필터링
$excludedUserIds = $this->getExcludedUserIds($tenantId);
$statsQuery = Attendance::query()
->forTenant($tenantId)
->betweenDates($startDate, $endDate)
->betweenDates($startDate, $endDate);
if (! empty($excludedUserIds)) {
$statsQuery->whereNotIn('user_id', $excludedUserIds);
}
$counts = $statsQuery
->select('status', DB::raw('COUNT(*) as cnt'))
->groupBy('status')
->pluck('cnt', 'status')
@@ -364,9 +397,17 @@ public function getEmployeeMonthlySummary(int $year, int $month): array
$startDate = sprintf('%04d-%02d-01', $year, $month);
$endDate = Carbon::create($year, $month, 1)->endOfMonth()->toDateString();
$raw = Attendance::query()
$excludedUserIds = $this->getExcludedUserIds($tenantId);
$summaryQuery = Attendance::query()
->forTenant($tenantId)
->betweenDates($startDate, $endDate)
->betweenDates($startDate, $endDate);
if (! empty($excludedUserIds)) {
$summaryQuery->whereNotIn('user_id', $excludedUserIds);
}
$raw = $summaryQuery
->select(
'user_id',
'status',
@@ -418,9 +459,17 @@ public function getOvertimeAlerts(): array
$weekStart = now()->startOfWeek(Carbon::MONDAY)->toDateString();
$weekEnd = now()->endOfWeek(Carbon::SUNDAY)->toDateString();
$results = Attendance::query()
$excludedUserIds = $this->getExcludedUserIds($tenantId);
$overtimeQuery = Attendance::query()
->forTenant($tenantId)
->betweenDates($weekStart, $weekEnd)
->betweenDates($weekStart, $weekEnd);
if (! empty($excludedUserIds)) {
$overtimeQuery->whereNotIn('user_id', $excludedUserIds);
}
$results = $overtimeQuery
->select(
'user_id',
DB::raw("SUM(GREATEST(0, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(json_details, '$.work_minutes')) AS SIGNED), 0))) as week_minutes")

View File

@@ -764,13 +764,14 @@ public function getDepartments(): \Illuminate\Database\Eloquent\Collection
return Department::query()
->where('is_active', true)
->when($tenantId, fn ($q) => $q->where('tenant_id', $tenantId))
->where('name', 'not like', '%영업팀%')
->orderBy('sort_order')
->orderBy('name')
->get(['id', 'name', 'code']);
}
/**
* 활성 사원 목록 (드롭다운용)
* 활성 사원 목록 (드롭다운용) — 영업팀 + 강제 제외 사원 제외
*/
public function getActiveEmployees(): \Illuminate\Database\Eloquent\Collection
{
@@ -780,6 +781,15 @@ public function getActiveEmployees(): \Illuminate\Database\Eloquent\Collection
->with('user:id,name')
->forTenant($tenantId)
->activeEmployees()
->where(function ($q) {
$q->whereDoesntHave('department', function ($dq) {
$dq->where('name', 'like', '%영업팀%');
})->orWhereNull('department_id');
})
->where(function ($q) {
$q->whereNull('json_extra->is_excluded')
->orWhere('json_extra->is_excluded', false);
})
->orderBy('display_name')
->get(['id', 'user_id', 'display_name', 'department_id']);
}