From afc1aa72a83208088229bac7986a001ba91826f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Fri, 27 Feb 2026 17:36:28 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[inspection]=20=EC=A0=88=EA=B3=A1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EB=A7=88=EA=B0=90=EC=9C=A0=ED=98=95(S1/S2?= =?UTF-8?q?/S3)=20=ED=94=84=EB=A1=9C=ED=8C=8C=EC=9D=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=E2=80=94=205130=20=EB=A0=88=EA=B1=B0=EC=8B=9C=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BENDING_GAP_PROFILES를 S1/S2/S3 + common 계층 구조로 재구성 - S1(KSS01): 벽면 4pt, 측면 6pt, 하단 1pt - S2(KSS02): 벽면 3pt, 측면 5pt, 하단 1pt - S3(KWE01/KSE01+SUS): 벽면 5pt, 측면 7pt, 하단 2pt - resolveFinishingType() 신규: product_code → 마감유형 자동 판별 - buildBendingInspectionItems()에 마감유형별 프로파일 적용 - getInspectionConfig() 응답에 finishing_type 필드 추가 Co-Authored-By: Claude Opus 4.6 --- app/Services/WorkOrderService.php | 207 ++++++++++++++++++++++-------- 1 file changed, 157 insertions(+), 50 deletions(-) diff --git a/app/Services/WorkOrderService.php b/app/Services/WorkOrderService.php index d727b5cc..77d6a73e 100644 --- a/app/Services/WorkOrderService.php +++ b/app/Services/WorkOrderService.php @@ -1955,57 +1955,124 @@ public function getInspectionData(int $workOrderId, array $params = []): array // ────────────────────────────────────────────────────────────── /** - * 절곡 검사 기준 간격 프로파일 (단면 치수 공학 사양) + * 절곡 검사 기준 간격 프로파일 (5130 레거시 기준 S1/S2/S3 마감유형별) + * + * S1: KSS01 계열 (KQTS01 포함) + * S2: KSS02 계열 (EGI 마감 포함) + * S3: KWE01/KSE01 + SUS 별도마감 + * * 향후 DB 테이블 또는 테넌트 설정으로 이관 가능 */ private const BENDING_GAP_PROFILES = [ - 'guide_rail_wall' => [ - 'name' => '가이드레일 벽면', - 'gap_points' => [ - ['point' => '(1)', 'design_value' => '30'], - ['point' => '(2)', 'design_value' => '78'], - ['point' => '(3)', 'design_value' => '25'], - ['point' => '(4)', 'design_value' => '45'], + 'S1' => [ + 'guide_rail_wall' => [ + 'name' => '가이드레일(벽면형)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '30'], + ['point' => '(2)', 'design_value' => '80'], + ['point' => '(3)', 'design_value' => '45'], + ['point' => '(4)', 'design_value' => '40'], + ], + ], + 'guide_rail_side' => [ + 'name' => '가이드레일(측면형)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '30'], + ['point' => '(2)', 'design_value' => '70'], + ['point' => '(3)', 'design_value' => '45'], + ['point' => '(4)', 'design_value' => '35'], + ['point' => '(5)', 'design_value' => '95'], + ['point' => '(6)', 'design_value' => '90'], + ], + ], + 'bottom_bar' => [ + 'name' => '하단마감재', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '60'], + ], ], ], - 'guide_rail_side' => [ - 'name' => '가이드레일 측면', - 'gap_points' => [ - ['point' => '(1)', 'design_value' => '28'], - ['point' => '(2)', 'design_value' => '75'], - ['point' => '(3)', 'design_value' => '42'], - ['point' => '(4)', 'design_value' => '38'], - ['point' => '(5)', 'design_value' => '32'], + 'S2' => [ + 'guide_rail_wall' => [ + 'name' => '가이드레일(벽면형)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '30'], + ['point' => '(2)', 'design_value' => '80'], + ['point' => '(3)', 'design_value' => '45'], + ], + ], + 'guide_rail_side' => [ + 'name' => '가이드레일(측면형)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '30'], + ['point' => '(2)', 'design_value' => '70'], + ['point' => '(3)', 'design_value' => '45'], + ['point' => '(4)', 'design_value' => '35'], + ['point' => '(5)', 'design_value' => '95'], + ], + ], + 'bottom_bar' => [ + 'name' => '하단마감재', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '60'], + ], ], ], - 'bottom_bar' => [ - 'name' => '하단마감재', - 'gap_points' => [ - ['point' => '(1)', 'design_value' => '60'], + 'S3' => [ + 'guide_rail_wall' => [ + 'name' => '가이드레일(벽면형·별도마감)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '30'], + ['point' => '(2)', 'design_value' => '80'], + ['point' => '(3)', 'design_value' => '45'], + ['point' => '(4)', 'design_value' => '40'], + ['point' => '(5)', 'design_value' => '34'], + ], + ], + 'guide_rail_side' => [ + 'name' => '가이드레일(측면형·별도마감)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '30'], + ['point' => '(2)', 'design_value' => '70'], + ['point' => '(3)', 'design_value' => '80'], + ['point' => '(4)', 'design_value' => '45'], + ['point' => '(5)', 'design_value' => '40'], + ['point' => '(6)', 'design_value' => '34'], + ['point' => '(7)', 'design_value' => '74'], + ], + ], + 'bottom_bar' => [ + 'name' => '하단마감재(별도마감)', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '60'], + ['point' => '(2)', 'design_value' => '64'], + ], ], ], - 'case_box' => [ - 'name' => '케이스', - 'gap_points' => [ - ['point' => '(1)', 'design_value' => '550'], - ['point' => '(2)', 'design_value' => '50'], - ['point' => '(3)', 'design_value' => '385'], - ['point' => '(4)', 'design_value' => '50'], - ['point' => '(5)', 'design_value' => '410'], + 'common' => [ + 'case_box' => [ + 'name' => '케이스', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '550'], + ['point' => '(2)', 'design_value' => '50'], + ['point' => '(3)', 'design_value' => '385'], + ['point' => '(4)', 'design_value' => '50'], + ['point' => '(5)', 'design_value' => '410'], + ], ], - ], - 'smoke_w50' => [ - 'name' => '연기차단재 W50', - 'gap_points' => [ - ['point' => '(1)', 'design_value' => '50'], - ['point' => '(2)', 'design_value' => '12'], + 'smoke_w50' => [ + 'name' => '연기차단재 W50', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '50'], + ['point' => '(2)', 'design_value' => '12'], + ], ], - ], - 'smoke_w80' => [ - 'name' => '연기차단재 W80', - 'gap_points' => [ - ['point' => '(1)', 'design_value' => '80'], - ['point' => '(2)', 'design_value' => '12'], + 'smoke_w80' => [ + 'name' => '연기차단재 W80', + 'gap_points' => [ + ['point' => '(1)', 'design_value' => '80'], + ['point' => '(2)', 'design_value' => '12'], + ], ], ], ]; @@ -2030,7 +2097,9 @@ public function getInspectionConfig(int $workOrderId): array $templateId = $process?->document_template_id; $items = []; + $finishingType = null; if ($processType === 'bending') { + $finishingType = $this->resolveFinishingType($productCode); $items = $this->buildBendingInspectionItems($firstItem); } @@ -2038,6 +2107,7 @@ public function getInspectionConfig(int $workOrderId): array 'work_order_id' => $workOrder->id, 'process_type' => $processType, 'product_code' => $productCode, + 'finishing_type' => $finishingType, 'template_id' => $templateId, 'items' => $items, ]; @@ -2060,8 +2130,40 @@ private function resolveInspectionProcessType(?Process $process): string }; } + /** + * 제품코드에서 마감유형(S1/S2/S3) 결정 (5130 레거시 기준) + * + * KSS01, KQTS01 → S1 + * KSS02 (및 EGI 마감) → S2 + * KWE01/KSE01 + SUS → S3 + */ + private function resolveFinishingType(?string $productCode): string + { + if (! $productCode) { + return 'S1'; + } + + // FG-{model}-{type}-{material} 형식에서 모델코드와 재질 추출 + $parts = explode('-', $productCode); + $modelCode = $parts[1] ?? ''; + $material = $parts[3] ?? ''; + + // SUS 재질 + KWE/KSE 모델 → S3 (별도마감) + if (stripos($material, 'SUS') !== false && (str_starts_with($modelCode, 'KWE') || str_starts_with($modelCode, 'KSE'))) { + return 'S3'; + } + + return match (true) { + str_starts_with($modelCode, 'KSS01'), str_starts_with($modelCode, 'KQTS') => 'S1', + str_starts_with($modelCode, 'KSS02') => 'S2', + str_starts_with($modelCode, 'KWE'), str_starts_with($modelCode, 'KSE') => 'S2', // EGI마감 = S2 + default => 'S2', // 기본값: S2 (5130 기준 EGI와 동일) + }; + } + /** * 절곡 bending_info에서 검사 대상 구성품 + 간격 기준치 빌드 + * 마감유형(S1/S2/S3)에 따라 gap_points가 달라짐 */ private function buildBendingInspectionItems(?WorkOrderItem $firstItem): array { @@ -2069,6 +2171,11 @@ private function buildBendingInspectionItems(?WorkOrderItem $firstItem): array return []; } + $productCode = $firstItem->options['product_code'] ?? null; + $finishingType = $this->resolveFinishingType($productCode); + $typeProfiles = self::BENDING_GAP_PROFILES[$finishingType] ?? self::BENDING_GAP_PROFILES['S1']; + $commonProfiles = self::BENDING_GAP_PROFILES['common']; + $bendingInfo = $firstItem->options['bending_info'] ?? null; $items = []; @@ -2078,7 +2185,7 @@ private function buildBendingInspectionItems(?WorkOrderItem $firstItem): array $hasSide = $guideRail && ($guideRail['side'] ?? false); if ($hasWall) { - $profile = self::BENDING_GAP_PROFILES['guide_rail_wall']; + $profile = $typeProfiles['guide_rail_wall']; $items[] = [ 'id' => 'guide_rail_wall', 'name' => $profile['name'], @@ -2087,7 +2194,7 @@ private function buildBendingInspectionItems(?WorkOrderItem $firstItem): array } if ($hasSide) { - $profile = self::BENDING_GAP_PROFILES['guide_rail_side']; + $profile = $typeProfiles['guide_rail_side']; $items[] = [ 'id' => 'guide_rail_side', 'name' => $profile['name'], @@ -2095,32 +2202,32 @@ private function buildBendingInspectionItems(?WorkOrderItem $firstItem): array ]; } - // 하단마감재 (항상 포함) - $profile = self::BENDING_GAP_PROFILES['bottom_bar']; + // 하단마감재 (항상 포함, 마감유형별 gap_points 다름) + $profile = $typeProfiles['bottom_bar']; $items[] = [ 'id' => 'bottom_bar', 'name' => $profile['name'], 'gap_points' => $profile['gap_points'], ]; - // 케이스 (항상 포함) - $profile = self::BENDING_GAP_PROFILES['case_box']; + // 케이스 (항상 포함, 공통) + $profile = $commonProfiles['case_box']; $items[] = [ 'id' => 'case_box', 'name' => $profile['name'], 'gap_points' => $profile['gap_points'], ]; - // 연기차단재 W50 (항상 포함) - $profile = self::BENDING_GAP_PROFILES['smoke_w50']; + // 연기차단재 W50 (항상 포함, 공통) + $profile = $commonProfiles['smoke_w50']; $items[] = [ 'id' => 'smoke_w50', 'name' => $profile['name'], 'gap_points' => $profile['gap_points'], ]; - // 연기차단재 W80 (항상 포함) - $profile = self::BENDING_GAP_PROFILES['smoke_w80']; + // 연기차단재 W80 (항상 포함, 공통) + $profile = $commonProfiles['smoke_w80']; $items[] = [ 'id' => 'smoke_w80', 'name' => $profile['name'],