feat: [품질관리] 품질관리서/실적신고/검사 API

- QualityDocument CRUD + 수주 연결 + 개소별 데이터 저장
- PerformanceReport 실적신고 확인/메모 API
- Inspection 검사 설정 + product_code 전파 수정
- 수주선택 API에 client_name 필드 추가
- 절곡 검사 프로파일 분리 (S1/S2/S3)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 02:57:48 +09:00
parent 091719e81b
commit f9cd219f67
29 changed files with 2495 additions and 10 deletions

View File

@@ -33,7 +33,7 @@ public function index(array $params)
$query = Inspection::query()
->where('tenant_id', $tenantId)
->with(['inspector:id,name', 'item:id,item_name']);
->with(['inspector:id,name', 'item:id,item_name', 'workOrder:id,work_order_no']);
// 검색어 (검사번호, LOT번호)
if ($q !== '') {
@@ -126,7 +126,7 @@ public function show(int $id)
$tenantId = $this->tenantId();
$inspection = Inspection::where('tenant_id', $tenantId)
->with(['inspector:id,name', 'item:id,item_name'])
->with(['inspector:id,name', 'item:id,item_name', 'workOrder:id,work_order_no'])
->find($id);
if (! $inspection) {
@@ -183,6 +183,7 @@ public function store(array $data)
'inspection_type' => $data['inspection_type'],
'request_date' => $data['request_date'] ?? now()->toDateString(),
'lot_no' => $data['lot_no'],
'work_order_id' => $data['work_order_id'] ?? null,
'inspector_id' => $data['inspector_id'] ?? null,
'meta' => $meta,
'items' => $items,
@@ -200,7 +201,7 @@ public function store(array $data)
$inspection->toArray()
);
return $this->transformToFrontend($inspection->load(['inspector:id,name']));
return $this->transformToFrontend($inspection->load(['inspector:id,name', 'workOrder:id,work_order_no']));
});
}
@@ -277,7 +278,7 @@ public function update(int $id, array $data)
$inspection->fresh()->toArray()
);
return $this->transformToFrontend($inspection->load(['inspector:id,name']));
return $this->transformToFrontend($inspection->load(['inspector:id,name', 'workOrder:id,work_order_no']));
});
}
@@ -360,10 +361,83 @@ public function complete(int $id, array $data)
$inspection->fresh()->toArray()
);
return $this->transformToFrontend($inspection->load(['inspector:id,name']));
return $this->transformToFrontend($inspection->load(['inspector:id,name', 'workOrder:id,work_order_no']));
});
}
/**
* 캘린더 스케줄 조회
*/
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 데이터를 프론트엔드 형식으로 변환
*/
@@ -380,6 +454,8 @@ private function transformToFrontend(Inspection $inspection): array
'inspection_date' => $inspection->inspection_date?->format('Y-m-d'),
'item_name' => $inspection->item?->item_name ?? ($meta['item_name'] ?? null),
'lot_no' => $inspection->lot_no,
'work_order_id' => $inspection->work_order_id,
'work_order_no' => $inspection->workOrder?->work_order_no,
'process_name' => $meta['process_name'] ?? null,
'quantity' => $meta['quantity'] ?? null,
'unit' => $meta['unit'] ?? null,