diff --git a/app/Services/HR/AttendanceService.php b/app/Services/HR/AttendanceService.php index 1aace6bf..e548a9b3 100644 --- a/app/Services/HR/AttendanceService.php +++ b/app/Services/HR/AttendanceService.php @@ -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") diff --git a/app/Services/HR/LeaveService.php b/app/Services/HR/LeaveService.php index c7dbaaef..f20e0563 100644 --- a/app/Services/HR/LeaveService.php +++ b/app/Services/HR/LeaveService.php @@ -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']); }