calculateScreenMotor($weight, $inch); } return $this->calculateSteelMotor($weight, $inch); } /** * 스크린 모터 용량 계산 */ private function calculateScreenMotor(float $weight, int $inch): string { if ($inch === 4) { if ($weight <= 150) { return '150K'; } if ($weight <= 300) { return '300K'; } return '400K'; } if ($inch === 5) { if ($weight <= 123) { return '150K'; } if ($weight <= 246) { return '300K'; } if ($weight <= 327) { return '400K'; } if ($weight <= 500) { return '500K'; } return '600K'; } if ($inch === 6) { if ($weight <= 104) { return '150K'; } if ($weight <= 208) { return '300K'; } if ($weight <= 300) { return '400K'; } if ($weight <= 424) { return '500K'; } return '600K'; } // 기본값 return '300K'; } /** * 철재 모터 용량 계산 */ private function calculateSteelMotor(float $weight, int $inch): string { if ($inch === 4) { if ($weight <= 300) { return '300K'; } return '400K'; } if ($inch === 5) { if ($weight <= 246) { return '300K'; } if ($weight <= 327) { return '400K'; } if ($weight <= 500) { return '500K'; } return '600K'; } if ($inch === 6) { if ($weight <= 208) { return '300K'; } if ($weight <= 277) { return '400K'; } if ($weight <= 424) { return '500K'; } if ($weight <= 508) { return '600K'; } if ($weight <= 800) { return '800K'; } return '1000K'; } if ($inch === 8) { if ($weight <= 324) { return '500K'; } if ($weight <= 388) { return '600K'; } if ($weight <= 611) { return '800K'; } return '1000K'; } // 기본값 return '300K'; } // ========================================================================= // 브라켓 크기 계산 // ========================================================================= /** * 브라켓 크기 결정 * * @param float $weight 중량 (kg) * @param string|null $bracketInch 브라켓 인치 (선택) * @return string 브라켓 크기 (530*320, 600*350, 690*390) */ public function calculateBracketSize(float $weight, ?string $bracketInch = null): string { $motorCapacity = $this->getMotorCapacityByWeight($weight, $bracketInch); return match ($motorCapacity) { '300K', '400K' => '530*320', '500K', '600K' => '600*350', '800K', '1000K' => '690*390', default => '530*320', }; } /** * 중량으로 모터 용량 판단 (인치 없을 때) */ private function getMotorCapacityByWeight(float $weight, ?string $bracketInch = null): string { if ($bracketInch) { // 인치가 있으면 철재 기준으로 계산 return $this->calculateSteelMotor($weight, (int) $bracketInch); } // 인치 없으면 중량만으로 판단 if ($weight <= 300) { return '300K'; } if ($weight <= 400) { return '400K'; } if ($weight <= 500) { return '500K'; } if ($weight <= 600) { return '600K'; } if ($weight <= 800) { return '800K'; } return '1000K'; } // ========================================================================= // 주자재(스크린) 계산 // ========================================================================= /** * 스크린 주자재 가격 계산 * * @param float $width 폭 (mm) * @param float $height 높이 (mm) * @return array [unit_price, area, total_price] */ public function calculateScreenPrice(float $width, float $height): array { // 면적 계산: W × (H + 550) / 1,000,000 $calculateHeight = $height + 550; $area = ($width * $calculateHeight) / 1000000; // 원자재 단가 조회 (실리카/스크린) $unitPrice = $this->getRawMaterialPrice('실리카'); return [ 'unit_price' => $unitPrice, 'area' => round($area, 2), 'total_price' => round($unitPrice * $area), ]; } // ========================================================================= // 단가 조회 메서드 (KdPriceTable 사용) // ========================================================================= /** * BDmodels 테이블에서 단가 조회 * * @param string $modelName 모델코드 (KSS01, KWS01 등) * @param string $secondItem 부품분류 (케이스, 가이드레일, 하단마감재, L-BAR 등) * @param string|null $finishingType 마감재질 (SUS, EGI) * @param string|null $spec 규격 (120*70, 650*550 등) * @return float 단가 */ public function getBDModelPrice( string $modelName, string $secondItem, ?string $finishingType = null, ?string $spec = null ): float { // BDmodels는 복잡한 구조이므로 items 테이블의 기존 데이터 활용 // TODO: 필요시 kd_price_tables TYPE_BDMODELS 추가 return 0.0; } /** * price_* 테이블에서 단가 조회 (모터, 샤프트, 파이프, 앵글) * * @param string $tableName 테이블명 (motor, shaft, pipe, angle) * @param array $conditions 조회 조건 * @return float 단가 */ public function getPriceFromTable(string $tableName, array $conditions): float { $query = KdPriceTable::where('table_type', $tableName)->active(); foreach ($conditions as $field => $value) { $query->where($field, $value); } $record = $query->first(); return (float) ($record?->unit_price ?? 0); } /** * 원자재 단가 조회 * * @param string $materialName 원자재명 (실리카, 스크린 등) * @return float 단가 */ public function getRawMaterialPrice(string $materialName): float { return KdPriceTable::getRawMaterialPrice($materialName); } /** * 모터 단가 조회 * * @param string $motorCapacity 모터 용량 (150K, 300K 등) * @return float 단가 */ public function getMotorPrice(string $motorCapacity): float { return KdPriceTable::getMotorPrice($motorCapacity); } /** * 제어기 단가 조회 * * @param string $controllerType 제어기 타입 (매립형, 노출형, 뒷박스) * @return float 단가 */ public function getControllerPrice(string $controllerType): float { return KdPriceTable::getControllerPrice($controllerType); } /** * 샤프트 단가 조회 * * @param string $size 사이즈 (3, 4, 5인치) * @param float $length 길이 (m 단위) * @return float 단가 */ public function getShaftPrice(string $size, float $length): float { return KdPriceTable::getShaftPrice($size, $length); } /** * 파이프 단가 조회 * * @param string $thickness 두께 (1.4 등) * @param int $length 길이 (3000, 6000) * @return float 단가 */ public function getPipePrice(string $thickness, int $length): float { return KdPriceTable::getPipePrice($thickness, $length); } /** * 앵글 단가 조회 * * @param string $type 타입 (스크린용, 철재용) * @param string $bracketSize 브라켓크기 (530*320, 600*350, 690*390) * @param string $angleType 앵글타입 (앵글3T, 앵글4T) * @return float 단가 */ public function getAnglePrice(string $type, string $bracketSize, string $angleType): float { return KdPriceTable::getAnglePrice($type, $bracketSize, $angleType); } // ========================================================================= // 절곡품 계산 (10종) // ========================================================================= /** * 절곡품 항목 계산 (10종) * * 케이스, 케이스용 연기차단재, 케이스 마구리, 가이드레일, * 레일용 연기차단재, 하장바, L바, 보강평철, 무게평철12T, 환봉 * * @param array $params 입력 파라미터 * @return array 절곡품 항목 배열 */ public function calculateSteelItems(array $params): array { $items = []; // 기본 파라미터 $width = (float) ($params['W0'] ?? 0); $height = (float) ($params['H0'] ?? 0); $quantity = (int) ($params['QTY'] ?? 1); $modelName = $params['model_name'] ?? 'KSS01'; $finishingType = $params['finishing_type'] ?? 'SUS'; // 절곡품 관련 파라미터 $caseSpec = $params['case_spec'] ?? '500*380'; $caseLength = (float) ($params['case_length'] ?? $width); // mm 단위 $guideType = $params['guide_type'] ?? '벽면형'; // 벽면형, 측면형, 혼합형 $guideSpec = $params['guide_spec'] ?? '120*70'; // 120*70, 120*100 $guideLength = (float) ($params['guide_length'] ?? ($height + 550)) / 1000; // m 단위 $bottomBarLength = (float) ($params['bottombar_length'] ?? $width) / 1000; // m 단위 $lbarLength = (float) ($params['lbar_length'] ?? $width) / 1000; // m 단위 $flatBarLength = (float) ($params['flatbar_length'] ?? $width) / 1000; // m 단위 $weightPlateQty = (int) ($params['weight_plate_qty'] ?? 0); // 무게평철 수량 $roundBarQty = (int) ($params['round_bar_qty'] ?? 0); // 환봉 수량 // 1. 케이스 (단가/1000 × 길이mm × 수량) $casePrice = KdPriceTable::getCasePrice($caseSpec); if ($casePrice > 0 && $caseLength > 0) { $totalPrice = ($casePrice / 1000) * $caseLength * $quantity; $items[] = [ 'category' => 'steel', 'item_name' => '케이스', 'specification' => "{$caseSpec} {$caseLength}mm", 'unit' => 'm', 'quantity' => $caseLength / 1000 * $quantity, 'unit_price' => $casePrice, 'total_price' => round($totalPrice), ]; } // 2. 케이스용 연기차단재 (단가 × 길이m × 수량) $caseSmokePrice = KdPriceTable::getCaseSmokeBlockPrice(); if ($caseSmokePrice > 0 && $caseLength > 0) { $lengthM = $caseLength / 1000; $items[] = [ 'category' => 'steel', 'item_name' => '케이스용 연기차단재', 'specification' => "{$lengthM}m", 'unit' => 'm', 'quantity' => $lengthM * $quantity, 'unit_price' => $caseSmokePrice, 'total_price' => round($caseSmokePrice * $lengthM * $quantity), ]; } // 3. 케이스 마구리 (단가 × 수량) $caseCapPrice = KdPriceTable::getCaseCapPrice($caseSpec); if ($caseCapPrice > 0) { $capQty = 2 * $quantity; // 좌우 2개 $items[] = [ 'category' => 'steel', 'item_name' => '케이스 마구리', 'specification' => $caseSpec, 'unit' => 'EA', 'quantity' => $capQty, 'unit_price' => $caseCapPrice, 'total_price' => round($caseCapPrice * $capQty), ]; } // 4. 가이드레일 (단가 × 길이m × 수량) - 타입별 처리 $guideItems = $this->calculateGuideRails($modelName, $finishingType, $guideType, $guideSpec, $guideLength, $quantity); $items = array_merge($items, $guideItems); // 5. 레일용 연기차단재 (단가 × 길이m × 2 × 수량) $railSmokePrice = KdPriceTable::getRailSmokeBlockPrice(); if ($railSmokePrice > 0 && $guideLength > 0) { $railSmokeQty = 2 * $quantity; // 좌우 2개 $items[] = [ 'category' => 'steel', 'item_name' => '레일용 연기차단재', 'specification' => "{$guideLength}m × 2", 'unit' => 'm', 'quantity' => $guideLength * $railSmokeQty, 'unit_price' => $railSmokePrice, 'total_price' => round($railSmokePrice * $guideLength * $railSmokeQty), ]; } // 6. 하장바 (단가 × 길이m × 수량) $bottomBarPrice = KdPriceTable::getBottomBarPrice($modelName, $finishingType); if ($bottomBarPrice > 0 && $bottomBarLength > 0) { $items[] = [ 'category' => 'steel', 'item_name' => '하장바', 'specification' => "{$modelName} {$finishingType} {$bottomBarLength}m", 'unit' => 'm', 'quantity' => $bottomBarLength * $quantity, 'unit_price' => $bottomBarPrice, 'total_price' => round($bottomBarPrice * $bottomBarLength * $quantity), ]; } // 7. L바 (단가 × 길이m × 수량) $lbarPrice = KdPriceTable::getLBarPrice($modelName); if ($lbarPrice > 0 && $lbarLength > 0) { $items[] = [ 'category' => 'steel', 'item_name' => 'L바', 'specification' => "{$modelName} {$lbarLength}m", 'unit' => 'm', 'quantity' => $lbarLength * $quantity, 'unit_price' => $lbarPrice, 'total_price' => round($lbarPrice * $lbarLength * $quantity), ]; } // 8. 보강평철 (단가 × 길이m × 수량) $flatBarPrice = KdPriceTable::getFlatBarPrice(); if ($flatBarPrice > 0 && $flatBarLength > 0) { $items[] = [ 'category' => 'steel', 'item_name' => '보강평철', 'specification' => "{$flatBarLength}m", 'unit' => 'm', 'quantity' => $flatBarLength * $quantity, 'unit_price' => $flatBarPrice, 'total_price' => round($flatBarPrice * $flatBarLength * $quantity), ]; } // 9. 무게평철12T (고정 12,000원 × 수량) if ($weightPlateQty > 0) { $weightPlatePrice = 12000; $items[] = [ 'category' => 'steel', 'item_name' => '무게평철12T', 'specification' => '12T', 'unit' => 'EA', 'quantity' => $weightPlateQty * $quantity, 'unit_price' => $weightPlatePrice, 'total_price' => $weightPlatePrice * $weightPlateQty * $quantity, ]; } // 10. 환봉 (고정 2,000원 × 수량) if ($roundBarQty > 0) { $roundBarPrice = 2000; $items[] = [ 'category' => 'steel', 'item_name' => '환봉', 'specification' => '', 'unit' => 'EA', 'quantity' => $roundBarQty * $quantity, 'unit_price' => $roundBarPrice, 'total_price' => $roundBarPrice * $roundBarQty * $quantity, ]; } return $items; } /** * 가이드레일 계산 (타입별 처리) * * @param string $modelName 모델코드 * @param string $finishingType 마감재질 * @param string $guideType 가이드레일 타입 (벽면형, 측면형, 혼합형) * @param string $guideSpec 가이드레일 규격 (120*70, 120*100) * @param float $guideLength 가이드레일 길이 (m) * @param int $quantity 수량 * @return array 가이드레일 항목 배열 */ private function calculateGuideRails( string $modelName, string $finishingType, string $guideType, string $guideSpec, float $guideLength, int $quantity ): array { $items = []; if ($guideLength <= 0) { return $items; } switch ($guideType) { case '벽면형': // 120*70 × 2개 $price = KdPriceTable::getGuideRailPrice($modelName, $finishingType, '120*70'); if ($price > 0) { $guideQty = 2 * $quantity; $items[] = [ 'category' => 'steel', 'item_name' => '가이드레일', 'specification' => "{$modelName} {$finishingType} 120*70 {$guideLength}m × 2", 'unit' => 'm', 'quantity' => $guideLength * $guideQty, 'unit_price' => $price, 'total_price' => round($price * $guideLength * $guideQty), ]; } break; case '측면형': // 120*100 × 2개 $price = KdPriceTable::getGuideRailPrice($modelName, $finishingType, '120*100'); if ($price > 0) { $guideQty = 2 * $quantity; $items[] = [ 'category' => 'steel', 'item_name' => '가이드레일', 'specification' => "{$modelName} {$finishingType} 120*100 {$guideLength}m × 2", 'unit' => 'm', 'quantity' => $guideLength * $guideQty, 'unit_price' => $price, 'total_price' => round($price * $guideLength * $guideQty), ]; } break; case '혼합형': // 120*70 × 1개 + 120*100 × 1개 $price70 = KdPriceTable::getGuideRailPrice($modelName, $finishingType, '120*70'); $price100 = KdPriceTable::getGuideRailPrice($modelName, $finishingType, '120*100'); if ($price70 > 0) { $items[] = [ 'category' => 'steel', 'item_name' => '가이드레일', 'specification' => "{$modelName} {$finishingType} 120*70 {$guideLength}m", 'unit' => 'm', 'quantity' => $guideLength * $quantity, 'unit_price' => $price70, 'total_price' => round($price70 * $guideLength * $quantity), ]; } if ($price100 > 0) { $items[] = [ 'category' => 'steel', 'item_name' => '가이드레일', 'specification' => "{$modelName} {$finishingType} 120*100 {$guideLength}m", 'unit' => 'm', 'quantity' => $guideLength * $quantity, 'unit_price' => $price100, 'total_price' => round($price100 * $guideLength * $quantity), ]; } break; } return $items; } // ========================================================================= // 부자재 계산 (3종) // ========================================================================= /** * 부자재 항목 계산 * * @param array $params 입력 파라미터 * @return array 부자재 항목 배열 */ public function calculatePartItems(array $params): array { $items = []; $width = (float) ($params['W0'] ?? 0); $bracketInch = $params['bracket_inch'] ?? '5'; $bracketSize = $params['BRACKET_SIZE'] ?? $this->calculateBracketSize(100, $bracketInch); $productType = $params['product_type'] ?? 'screen'; $quantity = (int) ($params['QTY'] ?? 1); // 1. 감기샤프트 $shaftSize = $bracketInch; $shaftLength = ceil($width / 1000); // mm → m 변환 후 올림 $shaftPrice = $this->getShaftPrice($shaftSize, $shaftLength); if ($shaftPrice > 0) { $items[] = [ 'category' => 'parts', 'item_name' => "감기샤프트 {$shaftSize}인치", 'specification' => "{$shaftLength}m", 'unit' => 'EA', 'quantity' => $quantity, 'unit_price' => $shaftPrice, 'total_price' => $shaftPrice * $quantity, ]; } // 2. 각파이프 $pipeThickness = '1.4'; $pipeLength = $width > 3000 ? 6000 : 3000; $pipePrice = $this->getPipePrice($pipeThickness, $pipeLength); if ($pipePrice > 0) { $items[] = [ 'category' => 'parts', 'item_name' => '각파이프', 'specification' => "{$pipeThickness}T {$pipeLength}mm", 'unit' => 'EA', 'quantity' => $quantity, 'unit_price' => $pipePrice, 'total_price' => $pipePrice * $quantity, ]; } // 3. 앵글 $angleType = $productType === 'steel' ? '철재용' : '스크린용'; $angleSpec = $bracketSize === '690*390' ? '앵글4T' : '앵글3T'; $anglePrice = $this->getAnglePrice($angleType, $bracketSize, $angleSpec); if ($anglePrice > 0) { $items[] = [ 'category' => 'parts', 'item_name' => "앵글 {$angleSpec}", 'specification' => "{$angleType} {$bracketSize}", 'unit' => 'EA', 'quantity' => 2 * $quantity, // 좌우 2개 'unit_price' => $anglePrice, 'total_price' => $anglePrice * 2 * $quantity, ]; } return $items; } // ========================================================================= // 전체 동적 항목 계산 // ========================================================================= /** * 동적 항목 전체 계산 * * @param array $inputs 입력 파라미터 * @return array 계산된 항목 배열 */ public function calculateDynamicItems(array $inputs): array { $items = []; $width = (float) ($inputs['W0'] ?? 0); $height = (float) ($inputs['H0'] ?? 0); $quantity = (int) ($inputs['QTY'] ?? 1); $bracketInch = $inputs['bracket_inch'] ?? '5'; $productType = $inputs['product_type'] ?? 'screen'; // 중량 계산 (5130 로직) $area = ($width * ($height + 550)) / 1000000; $weight = $area * ($productType === 'steel' ? 25 : 2) + ($width / 1000) * 14.17; // 모터 용량/브라켓 크기 계산 $motorCapacity = $this->calculateMotorCapacity($productType, $weight, $bracketInch); $bracketSize = $this->calculateBracketSize($weight, $bracketInch); // 입력값에 계산된 값 추가 (부자재 계산용) $inputs['WEIGHT'] = $weight; $inputs['MOTOR_CAPACITY'] = $motorCapacity; $inputs['BRACKET_SIZE'] = $bracketSize; // 1. 주자재 (스크린) $screenResult = $this->calculateScreenPrice($width, $height); $items[] = [ 'category' => 'material', 'item_code' => 'KD-SCREEN', 'item_name' => '주자재(스크린)', 'specification' => "면적 {$screenResult['area']}㎡", 'unit' => '㎡', 'quantity' => $screenResult['area'] * $quantity, 'unit_price' => $screenResult['unit_price'], 'total_price' => $screenResult['total_price'] * $quantity, ]; // 2. 모터 $motorPrice = $this->getMotorPrice($motorCapacity); $items[] = [ 'category' => 'motor', 'item_code' => "KD-MOTOR-{$motorCapacity}", 'item_name' => "모터 {$motorCapacity}", 'specification' => $motorCapacity, 'unit' => 'EA', 'quantity' => $quantity, 'unit_price' => $motorPrice, 'total_price' => $motorPrice * $quantity, ]; // 3. 제어기 $controllerType = $inputs['controller_type'] ?? '매립형'; $controllerPrice = $this->getControllerPrice($controllerType); $items[] = [ 'category' => 'controller', 'item_code' => 'KD-CTRL-'.strtoupper($controllerType), 'item_name' => "제어기 {$controllerType}", 'specification' => $controllerType, 'unit' => 'EA', 'quantity' => $quantity, 'unit_price' => $controllerPrice, 'total_price' => $controllerPrice * $quantity, ]; // 4. 절곡품 $steelItems = $this->calculateSteelItems($inputs); $items = array_merge($items, $steelItems); // 5. 부자재 $partItems = $this->calculatePartItems($inputs); $items = array_merge($items, $partItems); return $items; } }