diff --git a/app/Models/Qualitys/QualityDocumentLocation.php b/app/Models/Qualitys/QualityDocumentLocation.php index 311ed9d..fd362bc 100644 --- a/app/Models/Qualitys/QualityDocumentLocation.php +++ b/app/Models/Qualitys/QualityDocumentLocation.php @@ -12,6 +12,8 @@ class QualityDocumentLocation extends Model const STATUS_PENDING = 'pending'; + const STATUS_IN_PROGRESS = 'in_progress'; + const STATUS_COMPLETED = 'completed'; protected $fillable = [ diff --git a/app/Services/QualityDocumentService.php b/app/Services/QualityDocumentService.php index e3142cd..2391b2f 100644 --- a/app/Services/QualityDocumentService.php +++ b/app/Services/QualityDocumentService.php @@ -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(); }); }