From e9fd75fa741414acd8c6359be1a7d617aed11413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Wed, 4 Mar 2026 08:33:32 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[inspection]=20=EC=BA=98=EB=A6=B0?= =?UTF-8?q?=EB=8D=94=20=EC=8A=A4=EC=BC=80=EC=A4=84=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /api/v1/inspections/calendar 엔드포인트 추가 - year, month, inspector, status 파라미터 지원 - React 프론트엔드 CalendarItemApi 형식에 맞춰 응답 --- .../Api/V1/InspectionController.php | 10 +++ app/Services/InspectionService.php | 73 +++++++++++++++++++ routes/api/v1/production.php | 1 + 3 files changed, 84 insertions(+) diff --git a/app/Http/Controllers/Api/V1/InspectionController.php b/app/Http/Controllers/Api/V1/InspectionController.php index 2edc728..d543d12 100644 --- a/app/Http/Controllers/Api/V1/InspectionController.php +++ b/app/Http/Controllers/Api/V1/InspectionController.php @@ -34,6 +34,16 @@ public function stats(Request $request) }, __('message.inspection.fetched')); } + /** + * 캘린더 스케줄 조회 + */ + public function calendar(Request $request) + { + return ApiResponse::handle(function () use ($request) { + return $this->service->calendar($request->all()); + }, __('message.inspection.fetched')); + } + /** * 단건 조회 */ diff --git a/app/Services/InspectionService.php b/app/Services/InspectionService.php index 2964758..3f142c7 100644 --- a/app/Services/InspectionService.php +++ b/app/Services/InspectionService.php @@ -365,6 +365,79 @@ public function complete(int $id, array $data) }); } + /** + * 캘린더 스케줄 조회 + */ + public function calendar(array $params): array + { + $tenantId = $this->tenantId(); + + $year = (int) ($params['year'] ?? now()->year); + $month = (int) ($params['month'] ?? now()->month); + + // 해당 월의 시작일/종료일 + $startDate = sprintf('%04d-%02d-01', $year, $month); + $endDate = date('Y-m-t', strtotime($startDate)); + + $query = Inspection::query() + ->where('tenant_id', $tenantId) + ->where(function ($q) use ($startDate, $endDate) { + $q->whereBetween('request_date', [$startDate, $endDate]) + ->orWhereBetween('inspection_date', [$startDate, $endDate]); + }) + ->with(['inspector:id,name', 'item:id,item_name']); + + // 검사자 필터 + if (! empty($params['inspector'])) { + $query->whereHas('inspector', function ($q) use ($params) { + $q->where('name', $params['inspector']); + }); + } + + // 상태 필터 + if (! empty($params['status'])) { + $status = $params['status'] === 'reception' ? self::mapStatusFromFrontend('reception') : $params['status']; + $query->where('status', $status); + } + + return $query->orderBy('request_date') + ->get() + ->map(fn (Inspection $item) => [ + 'id' => $item->id, + 'start_date' => $item->request_date?->format('Y-m-d'), + 'end_date' => $item->inspection_date?->format('Y-m-d') ?? $item->request_date?->format('Y-m-d'), + 'inspector' => $item->inspector?->name ?? '', + 'site_name' => $item->item?->item_name ?? ($item->meta['process_name'] ?? $item->inspection_no), + 'status' => self::mapStatusToFrontend($item->status), + ]) + ->values() + ->toArray(); + } + + /** + * 상태를 프론트엔드 형식으로 매핑 + */ + private static function mapStatusToFrontend(string $status): string + { + return match ($status) { + Inspection::STATUS_WAITING => 'reception', + Inspection::STATUS_IN_PROGRESS => 'in_progress', + Inspection::STATUS_COMPLETED => 'completed', + default => $status, + }; + } + + /** + * 프론트엔드 상태를 DB 상태로 매핑 + */ + private static function mapStatusFromFrontend(string $status): string + { + return match ($status) { + 'reception' => Inspection::STATUS_WAITING, + default => $status, + }; + } + /** * DB 데이터를 프론트엔드 형식으로 변환 */ diff --git a/routes/api/v1/production.php b/routes/api/v1/production.php index 5fac326..d7600d9 100644 --- a/routes/api/v1/production.php +++ b/routes/api/v1/production.php @@ -114,6 +114,7 @@ Route::prefix('inspections')->group(function () { Route::get('', [InspectionController::class, 'index'])->name('v1.inspections.index'); // 목록 Route::get('/stats', [InspectionController::class, 'stats'])->name('v1.inspections.stats'); // 통계 + Route::get('/calendar', [InspectionController::class, 'calendar'])->name('v1.inspections.calendar'); // 캘린더 Route::post('', [InspectionController::class, 'store'])->name('v1.inspections.store'); // 생성 Route::get('/{id}', [InspectionController::class, 'show'])->whereNumber('id')->name('v1.inspections.show'); // 상세 Route::put('/{id}', [InspectionController::class, 'update'])->whereNumber('id')->name('v1.inspections.update'); // 수정