feat: [inspection] 캘린더 스케줄 조회 API 추가

- GET /api/v1/inspections/calendar 엔드포인트 추가
- year, month, inspector, status 파라미터 지원
- React 프론트엔드 CalendarItemApi 형식에 맞춰 응답
This commit is contained in:
김보곤
2026-03-04 08:33:32 +09:00
parent 23c6cf6919
commit e9fd75fa74
3 changed files with 84 additions and 0 deletions

View File

@@ -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'));
}
/**
* 단건 조회
*/

View File

@@ -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 데이터를 프론트엔드 형식으로 변환
*/

View File

@@ -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'); // 수정