feat: 슬랫(철재) 견적 계산 지원 추가 및 5130 정합성 검증
- calculateSlatPrice() 메서드 추가 (면적 = W0×(H0+50), 원자재 단가 '방화') - calculateDynamicItems() 주자재 분기 (screen→실리카, slat→방화) - 레일용 연기차단재: 슬랫 ×1 / 스크린 ×2 분기 처리 - 절곡품: 슬랫일 때 L바/보강평철/환봉 제외 (5130 동일) - 부자재 앵글: 슬랫은 앵글4T, 스크린은 앵글3T - 모터 받침용 앵글: 슬랫 기본 비활성 (bracket_angle_enabled 파라미터) - 조인트바: 슬랫 전용 항목 추가 (joint_bar_qty 파라미터) 검증: 치수 5종 × 수량 3종 모두 5130과 완벽 일치 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -247,6 +247,29 @@ public function calculateScreenPrice(float $width, float $height): array
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 슬랫(철재) 주자재 가격 계산
|
||||
* 5130 공식: W0 × (H0 + 50) / 1,000,000 × 단가
|
||||
*
|
||||
* @return array [unit_price, area, total_price]
|
||||
*/
|
||||
public function calculateSlatPrice(float $width, float $height): array
|
||||
{
|
||||
$calculateHeight = $height + 50;
|
||||
$area = ($width * $calculateHeight) / 1000000;
|
||||
|
||||
// 원자재 단가 조회 (방화/슬랫)
|
||||
$unitPrice = $this->getRawMaterialPrice('방화');
|
||||
|
||||
$roundedArea = round($area, 2);
|
||||
|
||||
return [
|
||||
'unit_price' => $unitPrice,
|
||||
'area' => $roundedArea,
|
||||
'total_price' => round($unitPrice * $roundedArea),
|
||||
];
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 단가 조회 메서드 (EstimatePriceService 사용)
|
||||
// =========================================================================
|
||||
@@ -360,6 +383,7 @@ public function calculateSteelItems(array $params): array
|
||||
$width = (float) ($params['W0'] ?? 0);
|
||||
$height = (float) ($params['H0'] ?? 0);
|
||||
$quantity = (int) ($params['QTY'] ?? 1);
|
||||
$productType = $params['product_type'] ?? 'screen';
|
||||
$modelName = $params['model_name'] ?? $params['product_model'] ?? 'KSS01';
|
||||
$rawFinish = $params['finishing_type'] ?? 'SUS';
|
||||
// DB에는 'SUS', 'EGI'로 저장 → 'SUS마감' → 'SUS' 변환
|
||||
@@ -443,14 +467,17 @@ public function calculateSteelItems(array $params): array
|
||||
$guideItems = $this->calculateGuideRails($modelName, $finishingType, $guideType, $guideSpec, $guideLength, $quantity);
|
||||
$items = array_merge($items, $guideItems);
|
||||
|
||||
// 5. 레일용 연기차단재 (단가 × 길이m × 2 × 수량)
|
||||
// 5. 레일용 연기차단재
|
||||
// 스크린: 단가 × 길이m × 2 × 수량 (좌우)
|
||||
// 슬랫: 단가 × 길이m × 수량 (×2 없음)
|
||||
$railSmokePrice = $this->priceService->getRailSmokeBlockPrice();
|
||||
if ($railSmokePrice > 0 && $guideLength > 0) {
|
||||
$railSmokeQty = 2 * $quantity; // 좌우 2개
|
||||
$railSmokeMultiplier = ($productType === 'slat') ? 1 : 2;
|
||||
$railSmokeQty = $railSmokeMultiplier * $quantity;
|
||||
$items[] = [
|
||||
'category' => 'steel',
|
||||
'item_name' => '레일용 연기차단재',
|
||||
'specification' => "{$guideLength}m × 2",
|
||||
'specification' => ($railSmokeMultiplier > 1) ? "{$guideLength}m × 2" : "{$guideLength}m",
|
||||
'unit' => 'm',
|
||||
'quantity' => $guideLength * $railSmokeQty,
|
||||
'unit_price' => $railSmokePrice,
|
||||
@@ -472,8 +499,8 @@ public function calculateSteelItems(array $params): array
|
||||
];
|
||||
}
|
||||
|
||||
// 7. L바 (단가 × 길이m × 수량)
|
||||
$lbarPrice = $this->priceService->getLBarPrice($modelName);
|
||||
// 7. L바 (단가 × 길이m × 수량) - 스크린 전용, 슬랫 미사용
|
||||
$lbarPrice = ($productType !== 'slat') ? $this->priceService->getLBarPrice($modelName) : 0;
|
||||
if ($lbarPrice > 0 && $lbarLength > 0) {
|
||||
$items[] = [
|
||||
'category' => 'steel',
|
||||
@@ -486,8 +513,8 @@ public function calculateSteelItems(array $params): array
|
||||
];
|
||||
}
|
||||
|
||||
// 8. 보강평철 (단가 × 길이m × 수량)
|
||||
$flatBarPrice = $this->priceService->getFlatBarPrice();
|
||||
// 8. 보강평철 (단가 × 길이m × 수량) - 스크린 전용, 슬랫 미사용
|
||||
$flatBarPrice = ($productType !== 'slat') ? $this->priceService->getFlatBarPrice() : 0;
|
||||
if ($flatBarPrice > 0 && $flatBarLength > 0) {
|
||||
$items[] = [
|
||||
'category' => 'steel',
|
||||
@@ -514,8 +541,8 @@ public function calculateSteelItems(array $params): array
|
||||
];
|
||||
}
|
||||
|
||||
// 10. 환봉 (고정 2,000원 × 수량)
|
||||
if ($roundBarQty > 0) {
|
||||
// 10. 환봉 (고정 2,000원 × 수량) - 스크린 전용, 슬랫 미사용
|
||||
if ($roundBarQty > 0 && $productType !== 'slat') {
|
||||
$roundBarPrice = 2000;
|
||||
$items[] = [
|
||||
'category' => 'steel',
|
||||
@@ -747,11 +774,13 @@ public function calculatePartItems(array $params): array
|
||||
|
||||
// 3. 모터 받침용 앵글 (bracket angle)
|
||||
// 5130: calculateAngle(qty, itemList, '스크린용') → col2 검색, qty × $su × 4
|
||||
// 5130 슬랫: col23(앵글사이즈) 비어있으면 생략
|
||||
$motorCapacity = $params['MOTOR_CAPACITY'] ?? '300K';
|
||||
$bracketAngleEnabled = (bool) ($params['bracket_angle_enabled'] ?? ($productType !== 'slat'));
|
||||
if ($productType === 'screen') {
|
||||
$angleSearchOption = '스크린용';
|
||||
} else {
|
||||
// 철재: bracketSize로 매핑 (530*320→철제300K, 600*350→철제400K, 690*390→철제800K)
|
||||
// 철재/슬랫: bracketSize로 매핑
|
||||
$angleSearchOption = match ($bracketSize) {
|
||||
'530*320' => '철제300K',
|
||||
'600*350' => '철제400K',
|
||||
@@ -759,7 +788,7 @@ public function calculatePartItems(array $params): array
|
||||
default => '철제300K',
|
||||
};
|
||||
}
|
||||
$anglePrice = $this->getAnglePrice($angleSearchOption);
|
||||
$anglePrice = $bracketAngleEnabled ? $this->getAnglePrice($angleSearchOption) : 0;
|
||||
if ($anglePrice > 0) {
|
||||
$angleQty = 4 * $quantity; // 5130: $su * 4
|
||||
$items[] = [
|
||||
@@ -774,10 +803,11 @@ public function calculatePartItems(array $params): array
|
||||
}
|
||||
|
||||
// 4. 부자재 앵글 (main angle)
|
||||
// 5130: calculateMainAngle(1, $itemList, '앵글3T', '2.5') × col71
|
||||
$mainAngleType = $bracketSize === '690*390' ? '앵글4T' : '앵글3T';
|
||||
// 스크린 5130: calculateMainAngle(1, $itemList, '앵글3T', '2.5') × col71
|
||||
// 슬랫 5130: calculateMainAngle(1, $itemList, '앵글4T', '2.5') × col77
|
||||
$mainAngleType = ($productType === 'slat') ? '앵글4T' : ($bracketSize === '690*390' ? '앵글4T' : '앵글3T');
|
||||
$mainAngleSize = '2.5';
|
||||
$mainAngleQty = (int) ($params['main_angle_qty'] ?? 2); // col71, default 2 (좌우)
|
||||
$mainAngleQty = (int) ($params['main_angle_qty'] ?? 2); // col71/col77, default 2 (좌우)
|
||||
$mainAnglePrice = $this->getMainAnglePrice($mainAngleType, $mainAngleSize);
|
||||
if ($mainAnglePrice > 0 && $mainAngleQty > 0) {
|
||||
$items[] = [
|
||||
@@ -791,6 +821,25 @@ public function calculatePartItems(array $params): array
|
||||
];
|
||||
}
|
||||
|
||||
// 5. 조인트바 (슬랫 전용, 5130: price × col76, QTY 미적용)
|
||||
if ($productType === 'slat') {
|
||||
$jointBarQty = (int) ($params['joint_bar_qty'] ?? 0);
|
||||
if ($jointBarQty > 0) {
|
||||
$jointBarPrice = $this->getRawMaterialPrice('조인트바');
|
||||
if ($jointBarPrice > 0) {
|
||||
$items[] = [
|
||||
'category' => 'parts',
|
||||
'item_name' => '조인트바',
|
||||
'specification' => '',
|
||||
'unit' => 'EA',
|
||||
'quantity' => $jointBarQty,
|
||||
'unit_price' => $jointBarPrice,
|
||||
'total_price' => round($jointBarPrice * $jointBarQty),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
@@ -844,17 +893,25 @@ public function calculateDynamicItems(array $inputs): array
|
||||
];
|
||||
}
|
||||
|
||||
// 1. 주자재 (스크린)
|
||||
$screenResult = $this->calculateScreenPrice($width, $height);
|
||||
// 1. 주자재 (스크린 또는 슬랫)
|
||||
if ($productType === 'slat') {
|
||||
$materialResult = $this->calculateSlatPrice($width, $height);
|
||||
$materialName = '주자재(슬랫)';
|
||||
$materialCode = 'KD-SLAT';
|
||||
} else {
|
||||
$materialResult = $this->calculateScreenPrice($width, $height);
|
||||
$materialName = '주자재(스크린)';
|
||||
$materialCode = 'KD-SCREEN';
|
||||
}
|
||||
$items[] = [
|
||||
'category' => 'material',
|
||||
'item_code' => 'KD-SCREEN',
|
||||
'item_name' => '주자재(스크린)',
|
||||
'specification' => "면적 {$screenResult['area']}㎡",
|
||||
'item_code' => $materialCode,
|
||||
'item_name' => $materialName,
|
||||
'specification' => "면적 {$materialResult['area']}㎡",
|
||||
'unit' => '㎡',
|
||||
'quantity' => $screenResult['area'] * $quantity,
|
||||
'unit_price' => $screenResult['unit_price'],
|
||||
'total_price' => $screenResult['total_price'] * $quantity,
|
||||
'quantity' => $materialResult['area'] * $quantity,
|
||||
'unit_price' => $materialResult['unit_price'],
|
||||
'total_price' => $materialResult['total_price'] * $quantity,
|
||||
];
|
||||
|
||||
// 2. 모터
|
||||
|
||||
Reference in New Issue
Block a user