fix(WEB): 철재 모터용량/셔터박스 계산 레거시 일치 수정
- FormulaHandler: 철재 면적 공식 W1×(H1+550) → W1×H1 (레거시 Slat_updateCol12and13 동일) - FormulaHandler: 샤프트 인치 자동계산 추가 (레거시 Slat_updateCol22 동일) - BendingInfoBuilder: 셔터박스 크기를 모터용량→브라켓→박스 매핑으로 결정 (BOM 원자재 코드 BD-케이스-500*380 대신 조립 크기 650*550 등 사용) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -122,6 +122,9 @@ private function categorizeBomItem(array $bomItem): ?string
|
||||
if (str_starts_with($code, 'BD-보강평철')) {
|
||||
return 'detail_reinforce';
|
||||
}
|
||||
if (str_starts_with($code, 'EST-MOTOR-')) {
|
||||
return 'motor';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -180,6 +183,7 @@ private function assembleBendingInfo(array $productInfo, array $materials, array
|
||||
$caseBom = $agg['bomCategories']['shutterBox_case'] ?? null;
|
||||
$finCoverBom = $agg['bomCategories']['shutterBox_finCover'] ?? null;
|
||||
$lbarBom = $agg['bomCategories']['detail_lbar'] ?? null;
|
||||
$motorBom = $agg['bomCategories']['motor'] ?? null;
|
||||
$dimGroups = $agg['dimensionGroups'];
|
||||
|
||||
// 가이드레일 baseSize 추출: BD-가이드레일-KSS01-SUS-120*70 → "120*70"
|
||||
@@ -192,7 +196,7 @@ private function assembleBendingInfo(array $productInfo, array $materials, array
|
||||
'detailParts' => $this->buildDetailParts($guideRailBom, $lbarBom, $materials),
|
||||
'guideRail' => $this->buildGuideRail($productInfo['guideType'], $baseSize, $materials, $dimGroups, $productInfo['productCode']),
|
||||
'bottomBar' => $this->buildBottomBar($materials, $dimGroups),
|
||||
'shutterBox' => $this->buildShutterBox($caseBom, $finCoverBom, $baseSize, $dimGroups),
|
||||
'shutterBox' => $this->buildShutterBox($caseBom, $finCoverBom, $motorBom, $baseSize, $dimGroups),
|
||||
'smokeBarrier' => $this->buildSmokeBarrier($dimGroups),
|
||||
];
|
||||
}
|
||||
@@ -325,17 +329,24 @@ private function buildBottomBar(array $materials, array $dimGroups): array
|
||||
// shutterBox 섹션
|
||||
// ─────────────────────────────────────────────────
|
||||
|
||||
private function buildShutterBox(?array $caseBom, ?array $finCoverBom, string $guideBaseSize, array $dimGroups): array
|
||||
private function buildShutterBox(?array $caseBom, ?array $finCoverBom, ?array $motorBom, string $guideBaseSize, array $dimGroups): array
|
||||
{
|
||||
if (! $caseBom) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// BD-케이스-500*380 → "500*380"
|
||||
$caseSize = str_replace('BD-케이스-', '', $caseBom['item_code'] ?? '');
|
||||
$caseParts = explode('*', $caseSize);
|
||||
$caseWidth = (int) ($caseParts[0] ?? 0);
|
||||
$caseHeight = (int) ($caseParts[1] ?? 0);
|
||||
// 셔터박스 크기: 모터용량 → 브라켓 → 박스 매핑 (레거시 Slat_updateCol37)
|
||||
$motorCapacity = $this->extractMotorCapacity($motorBom);
|
||||
$boxSize = $motorCapacity ? $this->getShutterBoxSize($motorCapacity) : null;
|
||||
|
||||
if (! $boxSize) {
|
||||
// fallback: BOM 케이스 item_code에서 추출 (BD-케이스-500*380 → "500*380")
|
||||
$boxSize = str_replace('BD-케이스-', '', $caseBom['item_code'] ?? '');
|
||||
}
|
||||
|
||||
$boxParts = explode('*', $boxSize);
|
||||
$boxWidth = (int) ($boxParts[0] ?? 0);
|
||||
$boxHeight = (int) ($boxParts[1] ?? 0);
|
||||
|
||||
// railWidth: 가이드레일 baseSize에서 첫 번째 숫자 (120*70 → 120)
|
||||
$guideParts = explode('*', $guideBaseSize);
|
||||
@@ -355,10 +366,10 @@ private function buildShutterBox(?array $caseBom, ?array $finCoverBom, string $g
|
||||
|
||||
return [
|
||||
[
|
||||
'size' => $caseSize,
|
||||
'size' => $boxSize,
|
||||
'direction' => '양면',
|
||||
'railWidth' => $railWidth,
|
||||
'frontBottom' => $caseHeight,
|
||||
'frontBottom' => $boxHeight,
|
||||
'coverQty' => $coverQty,
|
||||
'finCoverQty' => $finCoverQty,
|
||||
'lengthData' => $widthData,
|
||||
@@ -647,6 +658,39 @@ private function getMaterialMapping(string $productCode, string $finishMaterial)
|
||||
// 유틸리티 메서드
|
||||
// ─────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 모터 BOM item_code에서 용량 추출
|
||||
* EST-MOTOR-220V-500K → "500K"
|
||||
*/
|
||||
private function extractMotorCapacity(?array $motorBom): ?string
|
||||
{
|
||||
if (! $motorBom) {
|
||||
return null;
|
||||
}
|
||||
$code = $motorBom['item_code'] ?? '';
|
||||
if (preg_match('/(\d+K)$/', $code, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 모터용량 → 셔터박스 조립 크기 매핑
|
||||
* 레거시 체인: 모터용량(col20) → 브라켓(col21) → 박스크기(col37)
|
||||
*
|
||||
* @see 5130/estimate/common/common_addrowJS.php Slat_updateCol21(), Slat_updateCol37()
|
||||
*/
|
||||
private function getShutterBoxSize(string $motorCapacity): string
|
||||
{
|
||||
return match ($motorCapacity) {
|
||||
'300K', '400K' => '650*550',
|
||||
'500K', '600K' => '700*600',
|
||||
'800K', '1000K' => '780*650',
|
||||
default => '650*550',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 가이드레일 item_code에서 baseSize 추출
|
||||
* BD-가이드레일-KSS01-SUS-120*70 → "120*70"
|
||||
|
||||
@@ -303,6 +303,29 @@ private function getMotorCapacityByWeight(float $weight, ?string $bracketInch =
|
||||
return '1000K';
|
||||
}
|
||||
|
||||
/**
|
||||
* 샤프트(브라켓) 인치 자동 계산
|
||||
* 레거시 5130 Slat_updateCol22() 동일: W1(셔터기장)과 중량으로 결정
|
||||
*
|
||||
* @param float $W1 제조폭 (mm)
|
||||
* @param float $weight 중량 (kg)
|
||||
* @return int 샤프트 인치 (4, 5, 6, 8)
|
||||
*/
|
||||
private function calculateShaftInch(float $W1, float $weight): int
|
||||
{
|
||||
if ($W1 <= 4500) {
|
||||
return $weight <= 400 ? 4 : 5;
|
||||
}
|
||||
if ($W1 <= 5600) {
|
||||
return $weight <= 600 ? 5 : 6;
|
||||
}
|
||||
if ($W1 <= 7800) {
|
||||
return $weight <= 800 ? 6 : 8;
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 주자재(스크린) 계산
|
||||
// =========================================================================
|
||||
@@ -983,16 +1006,23 @@ public function calculateDynamicItems(array $inputs): array
|
||||
// 슬랫: W0 × (H0 + 50) / 1M, 중량 = 면적 × 25
|
||||
$area = ($width * ($height + 50)) / 1000000;
|
||||
$weight = $area * 25;
|
||||
} elseif ($productType === 'steel') {
|
||||
// 철재: W1 × H1 / 1M (레거시 Slat_updateCol12and13 동일)
|
||||
$W1 = $width + 110;
|
||||
$H1 = $height + 350;
|
||||
$area = ($W1 * $H1) / 1000000;
|
||||
$weight = $area * 25;
|
||||
} else {
|
||||
// 스크린/철재: W1 × (H1 + 550) / 1M
|
||||
// 스크린: W1 × (H1 + 550) / 1M
|
||||
$W1 = $width + 160;
|
||||
$H1 = $height + 350;
|
||||
$area = ($W1 * ($H1 + 550)) / 1000000;
|
||||
if ($productType === 'steel') {
|
||||
$weight = $area * 25;
|
||||
} else {
|
||||
$weight = $area * 2 + ($width / 1000) * 14.17;
|
||||
}
|
||||
$weight = $area * 2 + ($width / 1000) * 14.17;
|
||||
}
|
||||
|
||||
// 샤프트 인치: 철재는 W1/중량 기반 자동계산 (레거시 Slat_updateCol22 동일)
|
||||
if ($productType === 'steel' && ! isset($inputs['bracket_inch'])) {
|
||||
$bracketInch = (string) $this->calculateShaftInch($W1 ?? ($width + 110), $weight);
|
||||
}
|
||||
|
||||
// 모터 용량/브라켓 크기 계산 (입력값 우선, 없으면 자동계산)
|
||||
|
||||
Reference in New Issue
Block a user