diff --git a/app/Services/Quote/FormulaEvaluatorService.php b/app/Services/Quote/FormulaEvaluatorService.php index 03eca59..7217ba0 100644 --- a/app/Services/Quote/FormulaEvaluatorService.php +++ b/app/Services/Quote/FormulaEvaluatorService.php @@ -1059,10 +1059,13 @@ private function addProcessGroupToItems(array $items, array $groupedItems): arra /** * 품목 단가 조회 + * + * @param string $itemCode 품목 코드 + * @param int|null $tenantIdOverride 테넌트 ID (외부 호출 시 사용) */ - private function getItemPrice(string $itemCode): float + public function getItemPrice(string $itemCode, ?int $tenantIdOverride = null): float { - $tenantId = $this->tenantId(); + $tenantId = $tenantIdOverride ?? $this->tenantId(); if (! $tenantId) { $this->errors[] = __('error.tenant_id_required'); @@ -1580,14 +1583,20 @@ private function calculateKyungdongBom( ]); // Step 1: 입력값 수집 + $W0 = (float) ($inputVariables['W0'] ?? 0); + $H0 = (float) ($inputVariables['H0'] ?? 0); + $QTY = (int) ($inputVariables['QTY'] ?? 1); + $bracketInch = $inputVariables['bracket_inch'] ?? '5'; + $productType = $inputVariables['product_type'] ?? 'screen'; + $this->addDebugStep(1, '입력값수집', [ - 'W0' => $inputVariables['W0'] ?? null, - 'H0' => $inputVariables['H0'] ?? null, - 'QTY' => $inputVariables['QTY'] ?? 1, - 'bracket_inch' => $inputVariables['bracket_inch'] ?? '5', - 'product_type' => $inputVariables['product_type'] ?? 'screen', - 'finishing_type' => $inputVariables['finishing_type'] ?? 'SUS', - 'finished_goods' => $finishedGoodsCode, + 'formulas' => [ + ['var' => 'W0', 'desc' => '개구부 폭', 'value' => $W0, 'unit' => 'mm'], + ['var' => 'H0', 'desc' => '개구부 높이', 'value' => $H0, 'unit' => 'mm'], + ['var' => 'QTY', 'desc' => '수량', 'value' => $QTY, 'unit' => 'EA'], + ['var' => 'bracket_inch', 'desc' => '브라켓 인치', 'value' => $bracketInch, 'unit' => '인치'], + ['var' => 'product_type', 'desc' => '제품 타입', 'value' => $productType, 'unit' => ''], + ], ]); // Step 2: 완제품 조회 @@ -1616,15 +1625,20 @@ private function calculateKyungdongBom( $handler = new KyungdongFormulaHandler; // Step 3: 경동 전용 변수 계산 - $W0 = (float) ($inputVariables['W0'] ?? 0); - $H0 = (float) ($inputVariables['H0'] ?? 0); - $QTY = (int) ($inputVariables['QTY'] ?? 1); - $bracketInch = $inputVariables['bracket_inch'] ?? '5'; - $productType = $inputVariables['product_type'] ?? 'screen'; - - // 중량 계산 (5130 로직) + $W1 = $W0 + 140; + $H1 = $H0 + 350; $area = ($W0 * ($H0 + 550)) / 1000000; - $weight = $area * ($productType === 'steel' ? 25 : 2) + ($W0 / 1000) * 14.17; + + // 중량 계산 (제품타입별) + if ($productType === 'steel') { + $weight = $area * 25; + $weightFormula = "AREA × 25"; + $weightCalc = "{$area} × 25"; + } else { + $weight = $area * 2 + ($W0 / 1000) * 14.17; + $weightFormula = "AREA × 2 + (W0 / 1000) × 14.17"; + $weightCalc = "{$area} × 2 + ({$W0} / 1000) × 14.17"; + } // 모터 용량 결정 $motorCapacity = $handler->calculateMotorCapacity($productType, $weight, $bracketInch); @@ -1636,8 +1650,8 @@ private function calculateKyungdongBom( 'W0' => $W0, 'H0' => $H0, 'QTY' => $QTY, - 'W1' => $W0 + 140, - 'H1' => $H0 + 350, + 'W1' => $W1, + 'H1' => $H1, 'AREA' => round($area, 4), 'WEIGHT' => round($weight, 2), 'MOTOR_CAPACITY' => $motorCapacity, @@ -1647,13 +1661,56 @@ private function calculateKyungdongBom( ]); $this->addDebugStep(3, '변수계산', [ - 'W0' => $W0, - 'H0' => $H0, - 'area' => round($area, 4), - 'weight' => round($weight, 2), - 'motor_capacity' => $motorCapacity, - 'bracket_size' => $bracketSize, - 'calculation_type' => '경동기업 전용 공식', + 'formulas' => [ + [ + 'var' => 'W1', + 'desc' => '제작 폭', + 'formula' => 'W0 + 140', + 'calculation' => "{$W0} + 140", + 'result' => $W1, + 'unit' => 'mm', + ], + [ + 'var' => 'H1', + 'desc' => '제작 높이', + 'formula' => 'H0 + 350', + 'calculation' => "{$H0} + 350", + 'result' => $H1, + 'unit' => 'mm', + ], + [ + 'var' => 'AREA', + 'desc' => '면적', + 'formula' => '(W0 × (H0 + 550)) / 1,000,000', + 'calculation' => "({$W0} × ({$H0} + 550)) / 1,000,000", + 'result' => round($area, 4), + 'unit' => '㎡', + ], + [ + 'var' => 'WEIGHT', + 'desc' => '중량', + 'formula' => $weightFormula, + 'calculation' => $weightCalc, + 'result' => round($weight, 2), + 'unit' => 'kg', + ], + [ + 'var' => 'MOTOR_CAPACITY', + 'desc' => '모터 용량', + 'formula' => '중량/브라켓 기준표 조회', + 'calculation' => "WEIGHT({$weight}) + INCH({$bracketInch}) → 조회", + 'result' => $motorCapacity, + 'unit' => '', + ], + [ + 'var' => 'BRACKET_SIZE', + 'desc' => '브라켓 크기', + 'formula' => '중량 기준표 조회', + 'calculation' => "WEIGHT({$weight}) → 조회", + 'result' => $bracketSize, + 'unit' => '인치', + ], + ], ]); // Step 4-7: 동적 항목 계산 (KyungdongFormulaHandler 사용) @@ -1662,22 +1719,26 @@ private function calculateKyungdongBom( $this->addDebugStep(4, 'BOM전개', [ 'total_items' => count($dynamicItems), 'item_categories' => array_unique(array_column($dynamicItems, 'category')), + 'items' => array_map(fn ($item) => [ + 'name' => $item['item_name'], + 'category' => $item['category'], + ], $dynamicItems), ]); // Step 5-7: 단가 계산 (각 항목별) $calculatedItems = []; - foreach ($dynamicItems as $item) { - $this->addDebugStep(6, '수량계산', [ - 'item_name' => $item['item_name'], - 'quantity' => $item['quantity'], - ]); + $itemFormulas = []; - $this->addDebugStep(7, '금액계산', [ - 'item_name' => $item['item_name'], - 'quantity' => $item['quantity'], + foreach ($dynamicItems as $item) { + $itemFormulas[] = [ + 'item' => $item['item_name'], + 'qty_formula' => $item['quantity_formula'] ?? '고정값', + 'qty_result' => $item['quantity'], 'unit_price' => $item['unit_price'], - 'total_price' => $item['total_price'], - ]); + 'price_formula' => '수량 × 단가', + 'price_calc' => "{$item['quantity']} × {$item['unit_price']}", + 'total' => $item['total_price'], + ]; $calculatedItems[] = [ 'item_code' => $item['item_code'] ?? '', @@ -1686,13 +1747,23 @@ private function calculateKyungdongBom( 'specification' => $item['specification'] ?? '', 'unit' => $item['unit'], 'quantity' => $item['quantity'], + 'quantity_formula' => $item['quantity_formula'] ?? '', 'unit_price' => $item['unit_price'], 'total_price' => $item['total_price'], 'category_group' => $item['category'], + 'process_group' => $item['category'], 'calculation_note' => '경동기업 전용 계산', ]; } + $this->addDebugStep(6, '수량계산', [ + 'formulas' => $itemFormulas, + ]); + + $this->addDebugStep(7, '금액계산', [ + 'formulas' => $itemFormulas, + ]); + // Step 8: 카테고리별 그룹화 $groupedItems = []; foreach ($calculatedItems as $item) { @@ -1718,22 +1789,33 @@ private function calculateKyungdongBom( // Step 9: 소계 계산 $subtotals = []; + $subtotalFormulas = []; foreach ($groupedItems as $category => $group) { $subtotals[$category] = [ 'name' => $group['name'], 'count' => count($group['items']), 'subtotal' => $group['subtotal'], ]; + $subtotalFormulas[] = [ + 'category' => $group['name'], + 'formula' => implode(' + ', array_map(fn ($i) => $i['item_name'], $group['items'])), + 'result' => $group['subtotal'], + ]; } - $this->addDebugStep(9, '소계계산', $subtotals); + $this->addDebugStep(9, '소계계산', [ + 'formulas' => $subtotalFormulas, + 'subtotals' => $subtotals, + ]); // Step 10: 최종 합계 $grandTotal = array_sum(array_column($calculatedItems, 'total_price')); + $subtotalValues = array_column($subtotals, 'subtotal'); $this->addDebugStep(10, '최종합계', [ - 'item_count' => count($calculatedItems), - 'grand_total' => $grandTotal, + 'formula' => implode(' + ', array_column($subtotals, 'name')), + 'calculation' => implode(' + ', array_map(fn ($v) => number_format($v), $subtotalValues)), + 'result' => $grandTotal, 'formatted' => number_format($grandTotal).'원', ]);