Files
sam-docs/plans/simulator-calculation-logic-mapping.md
hskwon 5e1e5b4fcf docs: 견적 시뮬레이터 계산 로직 분석 및 동기화 계획 문서 추가
- simulator-calculation-logic-mapping.md: design.sam.kr 계산 로직 상세 분석
  - 변수 계산 규칙 (W0,H0 → W1,H1,M)
  - 수식 평가 함수 및 지원 함수 목록
  - BOM 10단계 계산 과정
  - 단가 계산 방식 (pricing → itemMaster → 면적단가)
- simulator-planning-page-sync-plan.md: mng 시뮬레이터 동기화 계획
- index_plans.md: 새 문서 인덱스 추가
2025-12-23 23:41:47 +09:00

293 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 견적 시뮬레이터 계산 로직 매핑
> **작성일**: 2025-12-23
> **목표**: design.sam.kr 계산 로직 → mng 시뮬레이터 동기화
---
## 1. Design 계산 로직 분석
### 1.1 핵심 계산 변수 (AutoCalculationSimulator.tsx:429-444)
```typescript
const calculationVariables = {
W0: quote.w0, // 오픈사이즈 폭 (입력)
H0: quote.h0, // 오픈사이즈 높이 (입력)
W1: quote.category === '스크린' ? W0 + 140 : W0 + 110, // 제작폭
H1: H0 + 350, // 제작높이
W: W1, // W = W1 (매핑)
H: H1, // H = H1 (매핑)
M: (W1 * H1) / 1000000, // 면적 (㎡)
K: 0 // 중량 (미구현)
};
```
### 1.2 수식 평가 함수 (formulaEvaluator.ts)
**지원 함수:**
| 함수 | 설명 | 예시 |
|------|------|------|
| `SUM(a, b, ...)` | 합계 | `SUM(W0, H0, 100)` |
| `AVERAGE(a, b, ...)` | 평균 | `AVERAGE(W0, H0)` |
| `MAX(a, b, ...)` | 최대값 | `MAX(W0, 1000)` |
| `MIN(a, b, ...)` | 최소값 | `MIN(H0, 3000)` |
| `ROUND(value, decimals)` | 반올림 | `ROUND(M, 2)` |
| `CEIL(value)` | 올림 | `CEIL(H1 / 1000)` |
| `FLOOR(value)` | 내림 | `FLOOR(W1 / 500)` |
| `ABS(value)` | 절대값 | `ABS(W0 - 2000)` |
| `IF(cond, true, false)` | 조건문 | `IF(W0 > 3000, 2, 1)` |
| `SQRT(value)` | 제곱근 | `SQRT(M)` |
| `POWER(base, exp)` | 거듭제곱 | `POWER(W1, 2)` |
**평가 과정:**
```typescript
// 1. 변수 치환
let expr = formula;
Object.keys(vars).forEach(key => {
const regex = new RegExp(`\\b${key}\\b`, 'g');
expr = expr.replace(regex, vars[key].toString());
});
// 2. 함수 처리 (CEIL, FLOOR, ROUND 등)
expr = processFunctions(expr);
// 3. 최종 계산
return new Function(`return (${expr})`)();
```
### 1.3 BOM 계산 과정 (bomCalculatorWithDebug.ts)
**10단계 계산 과정:**
| 단계 | 설명 | 예시 |
|------|------|------|
| Step 1 | 수량 공식 확인 | `H/1000` |
| Step 2 | 변수 값 확인 | `{W0:2000, H0:2500, W1:2140, H1:2850, M:6.099}` |
| Step 3 | 수량 계산 과정 | `H/1000 = 2850/1000 = 2.85` |
| Step 4 | 계산된 수량 | `2.85` |
| Step 5 | 단가 소스 | `단가관리 (15,000원)` |
| Step 6 | 기본 단가 | `15,000` |
| Step 7 | 카테고리 승수 | `면적단가 (15,000원/㎡ × 6.099㎡)` |
| Step 8 | 최종 단가 | `91,485` |
| Step 9 | 금액 계산 | `2.85 × 91,485 = 260,732` |
| Step 10 | 최종 금액 | `260,732` |
### 1.4 단가 계산 방식
```typescript
// 1순위: pricing 테이블에서 조회
const itemPricing = pricings.find(p => p.itemCode === bomEntry.childItemCode);
if (itemPricing && itemPricing.salesPrice) {
unitPrice = itemPricing.salesPrice;
}
// 2순위: 품목마스터에서 조회
else if (childItem.salesPrice) {
unitPrice = childItem.salesPrice;
}
// 면적 기반 품목 판단 (원단, 패널, 도장, 표면처리)
const areaBasedCategories = ['원단', '패널', '도장', '표면처리'];
if (isAreaBased && M > 0) {
finalUnitPrice = unitPrice * M; // 면적 단가
}
```
---
## 2. MNG 현재 구현 상태
### 2.1 FormulaEvaluatorService.php
**✅ 구현됨:**
- `evaluate()` - 수식 평가
- `validateFormula()` - 수식 검증
- `executeAll()` - 전체 수식 실행
- `getItemPrice()` - 단가 조회 (Price 모델 연동)
- `getBomTree()` - BOM 트리 조회
- `enrichItemsWithDetails()` - 품목 상세 정보 추가
**지원 함수:**
- SUM, ROUND, CEIL, FLOOR, ABS, MIN, MAX, IF, AND, OR, NOT
**❌ 미구현:**
- 제품 카테고리별 변수 계산 규칙 (W1, H1, M)
- 면적/중량 기반 단가 계산
- 공정별 분류
### 2.2 simulator.blade.php
**✅ 구현됨:**
- 입력 변수 폼 (W0, H0, PC, GT, MP, CT 등)
- API 호출 (`/api/admin/quote-formulas/formulas/simulate`)
- 계산된 변수 표시
- 품목 목록 표시 (BOM 트리 포함)
**❌ 미구현:**
- 공정별 그룹화 표시
- 단가/금액 계산 결과 표시
- 총합계 표시
---
## 3. 매핑 계획
### 3.1 변수 계산 규칙 추가
**quote_formulas 테이블에 추가할 수식:**
```sql
-- 제작폭 (W1) - 스크린
INSERT INTO quote_formulas (category_id, variable, name, type, formula, output_type, sort_order)
VALUES (1, 'W1', '제작폭', 'calculation', 'IF(PC == "screen", W0 + 140, W0 + 110)', 'variable', 10);
-- 제작높이 (H1)
INSERT INTO quote_formulas (category_id, variable, name, type, formula, output_type, sort_order)
VALUES (1, 'H1', '제작높이', 'calculation', 'H0 + 350', 'variable', 20);
-- 면적 (M)
INSERT INTO quote_formulas (category_id, variable, name, type, formula, output_type, sort_order)
VALUES (1, 'M', '면적', 'calculation', '(W1 * H1) / 1000000', 'variable', 30);
-- W, H 매핑
INSERT INTO quote_formulas (category_id, variable, name, type, formula, output_type, sort_order)
VALUES (1, 'W', '제작폭', 'calculation', 'W1', 'variable', 40);
INSERT INTO quote_formulas (category_id, variable, name, type, formula, output_type, sort_order)
VALUES (1, 'H', '제작높이', 'calculation', 'H1', 'variable', 50);
```
### 3.2 FormulaEvaluatorService 확장
```php
// 추가할 메서드
/**
* 카테고리별 단가 계산
*/
private function calculateCategoryPrice(
array $item,
float $basePrice,
array $variables
): array {
$areaBasedCategories = ['원단', '패널', '도장', '표면처리'];
$itemCategory = $item['item_category'] ?? '';
if (in_array($itemCategory, $areaBasedCategories) && isset($variables['M'])) {
return [
'final_price' => $basePrice * $variables['M'],
'calculation_note' => "면적단가 ({$basePrice}원/㎡ × {$variables['M']}㎡)"
];
}
return [
'final_price' => $basePrice,
'calculation_note' => '수량단가'
];
}
/**
* 공정별 품목 그룹화
*/
private function groupItemsByProcess(array $items): array
{
$processOrder = ['screen' => '스크린 공정', 'bending' => '절곡 공정', 'electric' => '전기 공정'];
$grouped = [];
foreach ($processOrder as $code => $label) {
$grouped[$code] = [
'label' => $label,
'items' => [],
'subtotal' => 0
];
}
foreach ($items as $item) {
$process = $item['process_type'] ?? 'etc';
if (isset($grouped[$process])) {
$grouped[$process]['items'][] = $item;
$grouped[$process]['subtotal'] += $item['total_price'] ?? 0;
}
}
return $grouped;
}
```
### 3.3 items 테이블 확장
```sql
-- 공정 유형 필드 추가
ALTER TABLE items ADD COLUMN process_type VARCHAR(20) DEFAULT NULL
COMMENT '공정유형: screen(스크린), bending(절곡), electric(전기)';
-- 인덱스 추가
CREATE INDEX idx_items_process_type ON items(process_type);
```
---
## 4. 구현 순서
### Phase 1: DB 스키마 및 데이터 (1일)
1. ✅ items 테이블에 `process_type` 필드 추가
2. ✅ 기존 품목에 공정 유형 매핑
3. ✅ quote_formulas에 기본 변수 계산 수식 추가
### Phase 2: 백엔드 로직 (2일)
1. ✅ FormulaEvaluatorService에 카테고리별 단가 계산 추가
2. ✅ 공정별 그룹화 메서드 추가
3. ✅ executeAll() 반환 구조 확장
### Phase 3: 프론트엔드 (1일)
1. ✅ simulator.blade.php에 공정별 결과 표시
2. ✅ 단가/금액 표시 추가
3. ✅ 총합계 표시
### Phase 4: 검증 (1일)
1. ✅ design.sam.kr과 결과 비교
2. ✅ 금액 차이 분석 및 조정
---
## 5. 핵심 파일 참조
### Design (참조용)
```
/SAM/design/src/components/
├── AutoCalculationSimulator.tsx # 메인 시뮬레이터 (1068줄)
├── utils/
│ ├── formulaEvaluator.ts # 수식 평가 (312줄)
│ └── bomCalculatorWithDebug.ts # BOM 계산 (232줄)
└── contexts/
└── DataContext.tsx # 마스터 데이터 (9859줄)
```
### MNG (수정 대상)
```
/SAM/mng/
├── app/Services/Quote/
│ └── FormulaEvaluatorService.php # 핵심 서비스 (575줄)
├── resources/views/quote-formulas/
│ └── simulator.blade.php # 시뮬레이터 UI (867줄)
└── app/Models/
├── Price.php # 단가 모델 (135줄)
└── Item.php # 품목 모델
```
---
## 6. 테스트 케이스
| 입력 | Design 결과 | MNG 목표 |
|------|------------|----------|
| W0=2000, H0=2500, PC=스크린 | W1=2140, H1=2850, M=6.099 | 동일 |
| 스크린 원단 | 수량공식: W*H/1000000 = 6.099㎡ | 동일 |
| 가이드레일 | 수량공식: H/1000 = 2.85m | 동일 |
---
*이 문서는 design.sam.kr 분석 결과를 바탕으로 mng 시뮬레이터 구현 계획을 정리합니다.*