feat: [quality] 검사 상태 자동 재계산 + 수주처 선택 연동

- 개소별 inspection_status를 검사 데이터 내용 기반으로 자동 판정
  (15개 판정필드 + 사진 유무 → pending/in_progress/completed)
- 문서 status를 개소 상태 집계로 자동 재계산
- inspectLocation, updateLocations 모두 적용
- QualityDocumentLocation에 STATUS_IN_PROGRESS 상수 추가
- transformToFrontend에 client_id 매핑 추가
This commit is contained in:
2026-03-09 17:43:15 +09:00
parent ee9f4d0b8f
commit 3fc5f511bc
2 changed files with 92 additions and 6 deletions

View File

@@ -12,6 +12,8 @@ class QualityDocumentLocation extends Model
const STATUS_PENDING = 'pending';
const STATUS_IN_PROGRESS = 'in_progress';
const STATUS_COMPLETED = 'completed';
protected $fillable = [

View File

@@ -257,6 +257,9 @@ public function update(int $id, array $data)
$this->updateLocations($doc->id, $locations);
}
// 개소 상태 기반 문서 상태 재계산
$this->recalculateDocumentStatus($doc);
$this->auditLogger->log(
$doc->tenant_id,
self::AUDIT_TARGET,
@@ -476,9 +479,87 @@ private function updateLocations(int $docId, array $locations): void
if (! empty($updateData)) {
$location->update($updateData);
}
// 검사 데이터 내용 기반 inspection_status 재계산
$location->refresh();
$newStatus = $this->determineLocationStatus($location->inspection_data);
if ($location->inspection_status !== $newStatus) {
$location->update(['inspection_status' => $newStatus]);
}
}
}
/**
* 개소 상태 기반 문서 상태 재계산
*/
private function recalculateDocumentStatus(QualityDocument $doc): void
{
$doc->load('locations');
$total = $doc->locations->count();
if ($total === 0) {
$doc->update(['status' => QualityDocument::STATUS_RECEIVED]);
return;
}
$completedCount = $doc->locations
->where('inspection_status', QualityDocumentLocation::STATUS_COMPLETED)
->count();
$inProgressCount = $doc->locations
->where('inspection_status', QualityDocumentLocation::STATUS_IN_PROGRESS)
->count();
if ($completedCount === $total) {
$doc->update(['status' => QualityDocument::STATUS_COMPLETED]);
} elseif ($completedCount > 0 || $inProgressCount > 0) {
$doc->update(['status' => QualityDocument::STATUS_IN_PROGRESS]);
} else {
$doc->update(['status' => QualityDocument::STATUS_RECEIVED]);
}
}
/**
* 검사 데이터 내용 기반 개소 상태 판정
*
* - 데이터 없음 or 검사항목 0개+사진 없음 → pending
* - 검사항목 일부 or 사진 없음 → in_progress
* - 15개 검사항목 전부 + 사진 있음 → completed
*/
private function determineLocationStatus(?array $inspectionData): string
{
if (empty($inspectionData)) {
return QualityDocumentLocation::STATUS_PENDING;
}
$judgmentFields = [
'appearanceProcessing', 'appearanceSewing', 'appearanceAssembly',
'appearanceSmokeBarrier', 'appearanceBottomFinish', 'motor', 'material',
'lengthJudgment', 'heightJudgment', 'guideRailGap', 'bottomFinishGap',
'fireResistanceTest', 'smokeLeakageTest', 'openCloseTest', 'impactTest',
];
$inspected = 0;
foreach ($judgmentFields as $field) {
if (isset($inspectionData[$field]) && $inspectionData[$field] !== null && $inspectionData[$field] !== '') {
$inspected++;
}
}
$hasPhotos = ! empty($inspectionData['productImages']) && is_array($inspectionData['productImages']) && count($inspectionData['productImages']) > 0;
if ($inspected === 0 && ! $hasPhotos) {
return QualityDocumentLocation::STATUS_PENDING;
}
if ($inspected < count($judgmentFields) || ! $hasPhotos) {
return QualityDocumentLocation::STATUS_IN_PROGRESS;
}
return QualityDocumentLocation::STATUS_COMPLETED;
}
/**
* 수주 동기화 (update 시 사용)
*/
@@ -668,6 +749,7 @@ private function transformToFrontend(QualityDocument $doc, bool $detail = false)
'id' => $doc->id,
'quality_doc_number' => $doc->quality_doc_number,
'site_name' => $doc->site_name,
'client_id' => $doc->client_id,
'client' => $doc->client?->name ?? '',
'location_count' => $doc->locations?->count() ?? 0,
'required_info' => $this->calculateRequiredInfo($doc),
@@ -784,9 +866,6 @@ public function inspectLocation(int $docId, int $locId, array $data)
if (isset($data['change_reason'])) {
$updateData['change_reason'] = $data['change_reason'];
}
if (isset($data['inspection_status'])) {
$updateData['inspection_status'] = $data['inspection_status'];
}
if (array_key_exists('inspection_data', $data)) {
$updateData['inspection_data'] = $data['inspection_data'];
}
@@ -795,11 +874,16 @@ public function inspectLocation(int $docId, int $locId, array $data)
$location->update($updateData);
}
// 상태를 진행중으로 변경 (접수 상태일 때)
if ($doc->isReceived()) {
$doc->update(['status' => QualityDocument::STATUS_IN_PROGRESS]);
// 검사 데이터 기반 개소 상태 자동 판정
$location->refresh();
$newLocStatus = $this->determineLocationStatus($location->inspection_data);
if ($location->inspection_status !== $newLocStatus) {
$location->update(['inspection_status' => $newLocStatus]);
}
// 문서 상태 재계산
$this->recalculateDocumentStatus($doc);
return $location->fresh()->toArray();
});
}