tenantId()) ->forYear($year) ->orderBy('start_date'); if ($type) { $query->where('type', $type); } return $query->get()->map(function ($h) { return [ 'id' => $h->id, 'name' => $h->name, 'type' => $h->type, 'start_date' => $h->start_date->format('Y-m-d'), 'end_date' => $h->end_date->format('Y-m-d'), 'days' => $h->start_date->diffInDays($h->end_date) + 1, 'is_recurring' => $h->is_recurring, 'memo' => $h->memo, 'created_at' => $h->created_at?->toIso8601String(), 'updated_at' => $h->updated_at?->toIso8601String(), ]; })->all(); } /** * 통계 조회 */ public function stats(int $year): array { $tenantId = $this->tenantId(); $holidays = Holiday::forTenant($tenantId)->forYear($year)->get(); $totalDays = $holidays->sum(function ($h) { return $h->start_date->diffInDays($h->end_date) + 1; }); return [ 'total_count' => $holidays->count(), 'total_holiday_days' => $totalDays, 'public_holiday_count' => $holidays->where('type', 'public_holiday')->count(), ]; } /** * 단건 조회 */ public function show(int $id): array { $h = Holiday::forTenant($this->tenantId())->findOrFail($id); return [ 'id' => $h->id, 'name' => $h->name, 'type' => $h->type, 'start_date' => $h->start_date->format('Y-m-d'), 'end_date' => $h->end_date->format('Y-m-d'), 'days' => $h->start_date->diffInDays($h->end_date) + 1, 'is_recurring' => $h->is_recurring, 'memo' => $h->memo, 'created_at' => $h->created_at?->toIso8601String(), 'updated_at' => $h->updated_at?->toIso8601String(), ]; } /** * 등록 */ public function store(array $data): array { $tenantId = $this->tenantId(); $exists = Holiday::forTenant($tenantId) ->where('start_date', $data['start_date']) ->where('end_date', $data['end_date']) ->where('name', $data['name']) ->exists(); if ($exists) { throw new HttpException(422, __('error.duplicate')); } $holiday = Holiday::create([ 'tenant_id' => $tenantId, 'start_date' => $data['start_date'], 'end_date' => $data['end_date'], 'name' => $data['name'], 'type' => $data['type'] ?? 'public_holiday', 'is_recurring' => $data['is_recurring'] ?? false, 'memo' => $data['memo'] ?? null, 'created_by' => $this->apiUserId(), ]); return $this->show($holiday->id); } /** * 수정 */ public function update(int $id, array $data): array { $holiday = Holiday::forTenant($this->tenantId())->findOrFail($id); $holiday->update([ 'start_date' => $data['start_date'], 'end_date' => $data['end_date'], 'name' => $data['name'], 'type' => $data['type'], 'is_recurring' => $data['is_recurring'] ?? false, 'memo' => $data['memo'] ?? null, 'updated_by' => $this->apiUserId(), ]); return $this->show($id); } /** * 삭제 */ public function delete(int $id): void { $holiday = Holiday::forTenant($this->tenantId())->findOrFail($id); $holiday->delete(); } /** * 대량 등록 */ public function bulkStore(array $schedules): array { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $count = 0; $skipped = 0; foreach ($schedules as $item) { $exists = Holiday::forTenant($tenantId) ->where('start_date', $item['start_date']) ->where('end_date', $item['end_date']) ->where('name', $item['name']) ->exists(); if ($exists) { $skipped++; continue; } Holiday::create([ 'tenant_id' => $tenantId, 'start_date' => $item['start_date'], 'end_date' => $item['end_date'], 'name' => $item['name'], 'type' => $item['type'] ?? 'public_holiday', 'is_recurring' => $item['is_recurring'] ?? false, 'memo' => $item['memo'] ?? null, 'created_by' => $userId, ]); $count++; } return [ 'created' => $count, 'skipped' => $skipped, ]; } }