# 5130 견적 수식 분석

> **핵심 문서** - 모든 견적 계산 수식 상세 분석
> **분석 일자:** 2025-12-19

---

## 📋 수식 개요

### 수식 파일 위치
| 파일 | 용도 | 핵심 함수 |
|------|------|----------|
| `common/calculation.js` | 프론트엔드 행 계산 | `calculateRowTotal()` |
| `fetch_unitprice.php` | 단가 조회/계산 헬퍼 | 30+ 함수 |
| `get_screen_amount.php` | 스크린 견적 계산 | `calculateScreenAmount()` |
| `get_slat_amount.php` | 슬랫 견적 계산 | `calculateSlatAmount()` |

---

## 🔢 기본 계산 수식

### 1. 행별 합계 계산 (calculation.js)
```javascript
// 기본 수식
totalPrice = 수량(su) × 단가(unitPrice)

// 면적 기반 수식
if (면적단가 > 0) {
    단가 = 면적(areaLength) × 면적단가(areaPrice)
    totalPrice = 수량 × 단가
}
```

### 2. 면적 계산
```php
// 스크린 면적 (m²)
// 기본 높이 350에 +550 추가 = 900 기준
$calculateHeight = $height + 550;
$area = $width * $calculateHeight / 1000000;

// 슬랫 면적 (m²)
// 기본 높이 350에 +50 추가 = 400 기준
$calculateHeight = $height + 50;
$area = $width * $calculateHeight / 1000000;
```

---

## 💰 항목별 수식 상세

### 1. 검사비 (인정검사비)
```php
$inspectionFee = 기본값(50000);
$검사비 = $inspectionFee × $수량;
```
| 입력 | 출력 | 단위 |
|------|------|------|
| 검사비 단가 | 검사비 총액 | 원 |

---

### 2. 주자재 (스크린/슬랫)
```php
// 스크린 (실리카/와이어)
$screen_price = $price_raw_materials × round($area, 2);
$주자재_스크린 = $screen_price × $수량;

// 슬랫 (방화)
$slat_price = $price_raw_materials × round($area, 2);
$주자재_슬랫 = $slat_price × $수량;
```
| 입력 | 계산 | 출력 |
|------|------|------|
| 폭(W), 높이(H), 단가 | 면적 × 단가 × 수량 | 주자재 금액 |

**조건:** `slatcheck == '1'` 일 때만 슬랫 주자재 계산

---

### 3. 조인트바 (슬랫 전용)
```php
$jointbar_price = $price_jointbar × $item['col76'];
```
| 입력 | 출력 |
|------|------|
| 조인트바 개수(col76) × 단가 | 조인트바 금액 |

**조건:** `slatcheck == '1'` 일 때만 계산

---

### 4. 모터
```php
// 모터 용량 추출 (숫자만)
$motorSpec = preg_replace('/[a-zA-Z]/', '', $item['col19']);
$motorUnit_price = getPriceForMotor($motorSpec, $itemList);
$모터 = $motorUnit_price × $수량;
```
| 입력 | 조건 | 출력 |
|------|------|------|
| 모터 용량, 수량 | 모터공급처='경동(견적가포함)' AND motor='1' | 모터 금액 |

**모터 용량 판별 로직:**
```php
function calculateMotorSpec($item, $weight, $BracketInch) {
    // 스크린/철재 구분
    $ItemSel = (substr($item['col4'], 0, 2) === 'KS') ? '스크린' : '철재';

    // 중량 + 인치 조합으로 용량 결정
    // 스크린: 150K, 300K, 400K, 500K, 600K
    // 철재: 300K, 400K, 500K, 600K, 800K, 1000K

    // 예시 조건 (스크린 150K)
    if ($ItemSel === '스크린' && $BracketInch == 4 && $weight <= 150) {
        return 150;
    }
    // ... 기타 조건들
}
```

**모터 용량 매핑표:**
| 인치 | 중량 범위 | 스크린 용량 | 철재 용량 |
|------|----------|------------|----------|
| 4" | ≤150kg | 150K | - |
| 4" | ≤300kg | 300K | 300K |
| 4" | ≤400kg | 400K | 400K |
| 5" | ≤500kg | 500K | 500K |
| 5" | ≤600kg | 600K | 600K |
| 6" | ≤800kg | - | 800K |
| 8" | ≤1000kg | - | 1000K |

---

### 5. 연동제어기
```php
$price1 = calculateControllerSpec($item['col15'], $itemList, '매립형');
$price2 = calculateControllerSpec($item['col16'], $itemList, '노출형');
$price3 = calculateControllerSpec($item['col17'], $itemList, '뒷박스');

$controller_price =
    $price1 × $매립형_수량 +
    $price2 × $노출형_수량 +
    $price3 × $뒷박스_수량;
```
| 유형 | 입력 컬럼 | 설명 |
|------|----------|------|
| 매립형 | col15 (스크린) / col16 (슬랫) | 벽 매립 타입 |
| 노출형 | col16 (스크린) / col17 (슬랫) | 외부 노출 타입 |
| 뒷박스 | col17 (스크린) / col18 (슬랫) | 뒷면 박스 타입 |

---

### 6. 케이스
```php
// 규격별 단가 조회 (BDmodels 테이블)
if ($item['col36'] === 'custom') {
    $dimension = $item['col36_custom'];  // 커스텀 규격
} else {
    $dimension = $item['col36'];          // 표준 규격
}

// 표준 규격이면 단가표에서 조회
if (array_key_exists($dimension, $shutterBoxprices)) {
    $shutter_price = $shutterBoxprices[$dimension] / 1000;
} else {
    // 비표준 규격은 기본 단가 기준 면적비로 계산
    $basicbox_price = $shutterBoxprices['500*380'];  // 스크린 기본
    // 또는 '650*550' (슬랫 기본)
    $basicbox_pricePermeter = $basicbox_price / (500 * 380 / 1000);
    $shutter_price = $basicbox_pricePermeter × $boxwidth × $boxheight / 1000;
}

$케이스 = round($shutter_price × $total_length × 1000) × $수량;
```
| 조건 | 계산 |
|------|------|
| steel='1' (절곡 체크) | 단가 × 길이(m) × 수량 |

---

### 7. 케이스용 연기차단재
```php
$boxSmokeBanPrices = BDmodels에서 '케이스용 연기차단재' 단가 조회;
$total_length = $item['col37'] / 1000;  // mm → m 변환
$케이스용_연기차단재 = round($boxSmokeBanPrices × $total_length) × $수량;
```
| 조건 | 계산 |
|------|------|
| steel='1' AND 케이스규격 있음 | 단가 × 길이(m) × 수량 |

---

### 8. 케이스 마구리
```php
$maguriCol = $item['col45'];  // 마구리 규격
$maguriPrices = BDmodels에서 seconditem='마구리' AND spec=$maguriCol 조회;
$케이스_마구리 = round($maguriPrices × $수량);
```
| 조건 | 계산 |
|------|------|
| steel='1' | 단가 × 수량 |

---

### 9. 모터 받침용 앵글
```php
// 스크린
$price_angle = calculateAngle($item['col14'], $itemList, '스크린용');

// 슬랫 (브라켓 크기 기반)
if (empty($item['col21'])) {
    $bracket_size = searchBracketSize($item['col13'], $item['col22']);
} else {
    $bracket_size = $item['col21'];
}
$price_angle = calculateAngleBracket_slat($item['col15'], $itemList, $bracket_size);

$모터받침용_앵글 = round($price_angle × $수량 × 4);  // 4개 세트
```

**브라켓 사이즈 결정 로직:**
```php
function searchBracketSize($motorWeight, $bracketInch) {
    // 모터 용량 판별
    $motorCapacity = calculateMotorKG($weight, $inch);

    // 용량별 브라켓 사이즈 매핑
    if (in_array($motorCapacity, [300, 400])) return '530*320';
    if (in_array($motorCapacity, [500, 600])) return '600*350';
    if (in_array($motorCapacity, [800, 1000])) return '690*390';
    return '530*320';  // 기본값
}
```

---

### 10. 가이드레일
```php
// 레일 유형에 따른 가격 계산
if (strpos($guideType, '혼합') !== false) {
    // 혼합형: 벽면 + 측면 각각 다른 규격
    $wallPrice = $guidrailPrices[$wallKey];
    $sidePrice = $guidrailPrices[$sideKey];
    $guidrail_price = $wallPrice + $sidePrice;  // 1개 세트
} else {
    // 단일형: 벽면 또는 측면
    $guidrail_price = $guidrailPrices[$guideKey] × 2;  // 2개 세트
}

$total_length = $item['col23'] / 1000;  // mm → m
$가이드레일 = round($guidrail_price × $total_length) × $수량;
```

**가이드레일 키 구성:**
```
$key = $modelCode|$finishingType|$spec
예: KS-100|도장|65*80
```

---

### 11. 레일용 연기차단재
```php
$guiderailSmokeBanPrices = BDmodels에서 '가이드레일용 연기차단재' 조회;
$total_length = $item['col23'] / 1000;
$레일용_연기차단재 = round($guiderailSmokeBanPrices × $total_length) × 2 × $수량;
```
| 조건 | 계산 |
|------|------|
| steel='1' AND 연기차단재 옵션 있음 | 단가 × 길이 × 2(양쪽) × 수량 |

---

### 12. 하장바
```php
$bottomBarPrices = BDmodels에서
    model_name=$modelCode AND
    seconditem='하단마감재' AND
    finishing_type=$finishingType 조회;

$total_length = $item['col48'] / 1000 × $수량;  // 스크린
// 또는 $item['col49'] (슬랫)
$하장바 = round($bottomBarPrices × $total_length);
```
| 조건 | 계산 |
|------|------|
| steel='1' AND 하장바 옵션 있음 | 단가 × 길이 × 수량 |

---

### 13. L바 (스크린 전용)
```php
$LBarPrices = BDmodels에서 seconditem='L-BAR' 조회;
$total_length = $item['col51'] / 1000 × $수량;
$L바 = round($LBarPrices × $total_length);
```
| 조건 | 계산 |
|------|------|
| steel='1' AND L바 옵션 있음 | 단가 × 길이 × 수량 |

---

### 14. 보강평철 (스크린 전용)
```php
$bottomPlatePrices = BDmodels에서 seconditem='보강평철' 조회;
$total_length = $item['col54'] / 1000 × $수량;
$보강평철 = round($bottomPlatePrices × $total_length);
```
| 조건 | 계산 |
|------|------|
| steel='1' AND 보강평철 옵션 있음 | 단가 × 길이 × 수량 |

---

### 15. 감기샤프트
```php
function calculateShaftPrice($item, $pdo) {
    // 샤프트 규격별 가격 합산
    // 컬럼: col59~col65 (스크린), col61~col71 (슬랫)

    addShaftPrice($item['col59'], $itemList, '3', '300', $sum);   // 3인치 300mm
    addShaftPrice($item['col60'], $itemList, '4', '3000', $sum);  // 4인치 3000mm
    addShaftPrice($item['col61'], $itemList, '4', '4500', $sum);  // 4인치 4500mm
    // ... 기타 규격

    return $sum_shaft_price;
}

function addShaftPrice($column, $itemList, $size, $length, &$sum) {
    $shaft_price = calculateShaft($column, $itemList, $size, $length);
    if ($shaft_price > 0) {
        $sum += $shaft_price;
    }
}
```

**샤프트 규격표:**
| 인치 | 길이 | 스크린 컬럼 | 슬랫 컬럼 |
|------|------|------------|----------|
| 3" | 300mm | col59 | - |
| 4" | 3000mm | col60 | col61 |
| 4" | 4500mm | col61 | col62 |
| 4" | 6000mm | col62 | col63 |
| 5" | 6000mm | col63 | col64 |
| 5" | 7000mm | col64 | col65 |
| 5" | 8200mm | col65 | col66 |
| 6" | 3000mm | - | col67 |
| 6" | 6000mm | - | col68 |
| 6" | 7000mm | - | col69 |
| 6" | 8000mm | - | col70 |
| 8" | 8200mm | - | col71 |

---

### 16. 무게평철 12T (스크린 전용)
```php
$baseWeightPlatePrice = 12000;  // 고정 단가
$무게평철 = $baseWeightPlatePrice × $item['col57'];
```
| 조건 | 계산 |
|------|------|
| steel='1' | 12,000원 × 개수 |

---

### 17. 환봉 (스크린 전용)
```php
$round_bar_price = 2000;  // 고정 단가
$round_bar_surang = $item['col70'];
$환봉 = round($round_bar_price × $round_bar_surang);
```
| 조건 | 계산 |
|------|------|
| steel='1' | 2,000원 × 개수 |

---

### 18. 각파이프
```php
$pipe_price_3000 = calculatePipe($itemList, '1.4', '3000');  // 1.4T 3000mm
$pipe_price_6000 = calculatePipe($itemList, '1.4', '6000');  // 1.4T 6000mm

$pipe_surang_3000 = $item['col68'];  // 스크린
$pipe_surang_6000 = $item['col69'];
// 또는 col74, col75 (슬랫)

$각파이프_총액 =
    ($pipe_price_3000 × $pipe_surang_3000) +
    ($pipe_price_6000 × $pipe_surang_6000);
```
| 조건 | 계산 |
|------|------|
| partscheck='1' | (3000mm 단가 × 수량) + (6000mm 단가 × 수량) |

---

### 19. 앵글
```php
$mainangle_price = calculateMainAngle(1, $itemList, '앵글3T', '2.5');  // 스크린
// 또는 '앵글4T' (슬랫)
$mainangle_surang = $item['col71'];  // 스크린
// 또는 col77 (슬랫)
$앵글 = round($mainangle_price × $mainangle_surang);
```
| 조건 | 계산 |
|------|------|
| partscheck='1' | 단가 × 수량 |

---

## 📊 전체 금액 계산

```php
$totalRowAmount = 0;
foreach ($rowItemDetails as $key => $value) {
    if (!in_array($key, ['TotalAmount', 'slatcheck', 'partscheck', 'steel', 'motor', 'warranty'])) {
        $totalRowAmount += $value;
    }
}
$rowItemDetails['TotalAmount'] = round($totalRowAmount);
```

**반환 데이터 구조:**
```php
return [
    'total_amount' => $total_amount,     // 전체 합계
    'details' => $sums,                  // 행별 소계 배열
    'itemDetails' => $itemDetails,       // 항목별 상세 금액
    'surangSum' => $surangSum            // 총 수량
];
```

---

## 🏷️ 테스트 케이스

### 스크린 견적 예시
| 입력 | 값 |
|------|-----|
| 폭(W) | 3,000mm |
| 높이(H) | 2,500mm |
| 수량 | 2 |
| 모터공급 | 경동(견적가포함) |
| 모터용량 | 300K |
| 케이스 | 500*380 |
| 검사비 | 50,000원 |

| 항목 | 계산식 | 금액 |
|------|--------|------|
| 검사비 | 50,000 × 2 | 100,000 |
| 주자재 | 면적 × 단가 × 2 | (계산 필요) |
| 모터 | 300K 단가 × 2 | (단가표 참조) |
| ... | ... | ... |

---

## ⚠️ 주의사항

1. **컬럼 번호 차이**: 스크린과 슬랫에서 같은 항목이 다른 컬럼 사용
2. **단위 변환**: mm → m 변환 필수 (/ 1000)
3. **반올림 처리**: 대부분 `round()` 사용
4. **조건부 계산**: 체크박스 옵션에 따라 계산 여부 결정
5. **JSON 데이터**: 단가 테이블의 `itemList` 컬럼은 JSON 형식

---

## 📚 참조

- [fetch_unitprice.php](../../../../5130/estimate/fetch_unitprice.php) - 헬퍼 함수
- [get_screen_amount.php](../../../../5130/estimate/get_screen_amount.php) - 스크린 계산
- [get_slat_amount.php](../../../../5130/estimate/get_slat_amount.php) - 슬랫 계산