fix: 5130 견적 금액 정합성 수정 (5항목)

- guide_type 매핑: installation_type → guide_type 파라미터 전달 추가 (측면형/혼합형 가이드레일 가격 반영)
- 제어기/뒷박스 수량: QTY 곱셈 제거 (5130 동일: col15/col16/col17은 고정 수량)
- 샤프트 규격 매핑: W0 기반 임의 길이 → 5130 고정 제품(5인치: 6/7/8.2m)으로 매핑
- 환봉/앵글 이중 곱셈 수정: 자동계산에 이미 QTY 포함, 추가 곱셈 제거
- 모터/브라켓 입력값 우선: MOTOR_CAPACITY/BRACKET_SIZE 입력 시 자동계산 대신 사용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 21:31:22 +09:00
parent 06552ad64e
commit 86ec5c4185

View File

@@ -283,6 +283,33 @@ public function getShaftPrice(string $size, float $length): float
return $this->priceService->getShaftPrice($size, $length);
}
/**
* 5130 고정 샤프트 제품 규격 매핑
* col59~65: 3인치 300, 4인치 3000/4500/6000, 5인치 6000/7000/8200
*
* @param string $size 인치 (3, 4, 5)
* @param float $lengthMm W0 올림값 (mm)
* @return float 매핑된 길이 (m 단위), 0이면 매핑 불가
*/
private function mapShaftToFixedProduct(string $size, float $lengthMm): float
{
$products = match ($size) {
'3' => [300],
'4' => [3000, 4500, 6000],
'5' => [6000, 7000, 8200],
default => [6000, 7000, 8200], // 기본 5인치
};
// 올림값 이상인 제품 중 가장 작은 것 선택
foreach ($products as $productMm) {
if ($lengthMm <= $productMm) {
return $productMm / 1000; // mm → m
}
}
return 0; // 매핑 불가 (초과)
}
/**
* 파이프 단가 조회
*/
@@ -495,9 +522,9 @@ public function calculateSteelItems(array $params): array
'item_name' => '환봉',
'specification' => '',
'unit' => 'EA',
'quantity' => $roundBarQty * $quantity,
'quantity' => $roundBarQty,
'unit_price' => $roundBarPrice,
'total_price' => $roundBarPrice * $roundBarQty * $quantity,
'total_price' => $roundBarPrice * $roundBarQty,
];
}
@@ -635,10 +662,12 @@ public function calculatePartItems(array $params): array
$productType = $params['product_type'] ?? 'screen';
$quantity = (int) ($params['QTY'] ?? 1);
// 1. 감기샤프트
// 1. 감기샤프트 (5130: col59~65 고정 제품)
// 5130 고정 규격: 3인치→0.3m, 4인치→3/4.5/6m, 5인치→6/7/8.2m
$shaftSize = $bracketInch;
$shaftLength = ceil($width / 1000); // mmm 변환 후 올림
$shaftPrice = $this->getShaftPrice($shaftSize, $shaftLength);
$shaftLengthMm = ceil($width / 1000) * 1000; // W0 → 올림 (mm)
$shaftLength = $this->mapShaftToFixedProduct($shaftSize, $shaftLengthMm);
$shaftPrice = $shaftLength > 0 ? $this->getShaftPrice($shaftSize, $shaftLength) : 0;
if ($shaftPrice > 0) {
$items[] = [
'category' => 'parts',
@@ -756,9 +785,9 @@ public function calculatePartItems(array $params): array
'item_name' => "앵글 {$mainAngleType}",
'specification' => "{$mainAngleSize}m",
'unit' => 'EA',
'quantity' => $mainAngleQty * $quantity,
'quantity' => $mainAngleQty,
'unit_price' => $mainAnglePrice,
'total_price' => $mainAnglePrice * $mainAngleQty * $quantity,
'total_price' => $mainAnglePrice * $mainAngleQty,
];
}
@@ -791,9 +820,9 @@ public function calculateDynamicItems(array $inputs): array
$area = ($W1 * ($H1 + 550)) / 1000000;
$weight = $area * ($productType === 'steel' ? 25 : 2) + ($width / 1000) * 14.17;
// 모터 용량/브라켓 크기 계산
$motorCapacity = $this->calculateMotorCapacity($productType, $weight, $bracketInch);
$bracketSize = $this->calculateBracketSize($weight, $bracketInch);
// 모터 용량/브라켓 크기 계산 (입력값 우선, 없으면 자동계산)
$motorCapacity = $inputs['MOTOR_CAPACITY'] ?? $this->calculateMotorCapacity($productType, $weight, $bracketInch);
$bracketSize = $inputs['BRACKET_SIZE'] ?? $this->calculateBracketSize($weight, $bracketInch);
// 입력값에 계산된 값 추가 (부자재 계산용)
$inputs['WEIGHT'] = $weight;
@@ -842,6 +871,8 @@ public function calculateDynamicItems(array $inputs): array
];
// 3. 제어기 (5130: 매립형×col15 + 노출형×col16 + 뒷박스×col17)
// 5130: 제어기 = price_매립 × col15 + price_노출 × col16 + price_뒷박스 × col17
// col15/col16/col17은 고정 수량 (QTY와 무관, $su를 곱하지 않음)
$controllerType = $inputs['controller_type'] ?? '매립형';
$controllerQty = (int) ($inputs['controller_qty'] ?? 1);
$controllerPrice = $this->getControllerPrice($controllerType);
@@ -852,13 +883,13 @@ public function calculateDynamicItems(array $inputs): array
'item_name' => "제어기 {$controllerType}",
'specification' => $controllerType,
'unit' => 'EA',
'quantity' => $controllerQty * $quantity,
'quantity' => $controllerQty,
'unit_price' => $controllerPrice,
'total_price' => $controllerPrice * $controllerQty * $quantity,
'total_price' => $controllerPrice * $controllerQty,
];
}
// 뒷박스 (5130: col17 수량)
// 뒷박스 (5130: col17 수량, QTY와 무관)
$backboxQty = (int) ($inputs['backbox_qty'] ?? 1);
if ($backboxQty > 0) {
$backboxPrice = $this->getControllerPrice('뒷박스');
@@ -869,14 +900,18 @@ public function calculateDynamicItems(array $inputs): array
'item_name' => '뒷박스',
'specification' => '',
'unit' => 'EA',
'quantity' => $backboxQty * $quantity,
'quantity' => $backboxQty,
'unit_price' => $backboxPrice,
'total_price' => $backboxPrice * $backboxQty * $quantity,
'total_price' => $backboxPrice * $backboxQty,
];
}
}
// 4. 절곡품
// installation_type → guide_type 매핑 (calculateSteelItems는 guide_type 사용)
if (isset($inputs['installation_type']) && ! isset($inputs['guide_type'])) {
$inputs['guide_type'] = $inputs['installation_type'];
}
$steelItems = $this->calculateSteelItems($inputs);
$items = array_merge($items, $steelItems);