- 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: 새 문서 인덱스 추가
14 KiB
14 KiB
견적 시뮬레이터 - 기획 페이지 동기화 작업 계획
작성일: 2025-12-23 수정일: 2025-12-23 (계산 로직 분석 완료) 목표: mng 시뮬레이터를 기획 페이지(design.sam.kr)와 동일한 결과 출력하도록 구현 참조 문서: 계산 로직 매핑
1. 현황 분석
1.1 기획 페이지 (localhost:3002) 분석
입력 항목:
| 변수 | 라벨 | 샘플값 | 설명 |
|---|---|---|---|
| 층수 | 층수 | 1층 | 건물 층수 |
| 부호 | 부호 | A | 식별 코드 |
| PC | 제품카테고리 | 스크린 | product_category |
| PRODUCT_ID | 제품명 | 스크린 셔터 (표준형) | 제품 선택 |
| W0 | 가로 | 2000 | 오픈사이즈 가로 (mm) |
| H0 | 세로 | 2500 | 오픈사이즈 세로 (mm) |
| GT | 설치유형 | 벽면 | guide_type (벽면/천장/바닥) |
| MP | 모터전원 | 220V | motor_power |
| CT | 제어기 | 단독제어 | controller_type |
| QTY | 수량 | 1 | 수량 |
산출 결과 (총 12개 품목, 1,393,683원):
| 공정 | 품목수 | 소계 | 품목 상세 |
|---|---|---|---|
| 스크린 공정 | 2 | 558,441원 | 스크린 원단(518,415), 연기차단재(40,026) |
| 절곡 공정 | 8 | 385,242원 | 가이드레일, 하부베이스, 케이스, 측면덮개, 상부덮개, 하단마감재, 하단보강빔바, 샤프트 |
| 전기 공정 | 2 | 400,000원 | 모터(250,000), 제어기(150,000) |
1.2 현재 mng 시뮬레이터 분석
현재 구현된 기능:
- ✅ 변수 입력 (W0, H0 등)
- ✅ 수식 계산 (FormulaEvaluatorService)
- ✅ BOM 트리 구조 표시
- ✅ 품목 목록 표시
미구현 기능:
- ❌ 공정별 분류 (스크린/절곡/전기)
- ❌ 단가 연동 (Price 모델)
- ❌ 금액 계산 (수량 × 단가)
- ❌ 공정별 소계
- ❌ 총합계 금액
1.3 데이터 구조 차이점
| 구분 | 기획 페이지 | mng 시뮬레이터 |
|---|---|---|
| 데이터 소스 | DataContext.tsx (하드코딩) | DB (quote_formulas, items) |
| 공정 분류 | process 필드로 그룹화 | 미구현 |
| 단가 | 하드코딩된 가격 | prices 테이블 |
| BOM | JSON 내 quantityFormula | bom JSON 필드 |
2. 작업 계획
Phase 1: 데이터 구조 정비 (1-2일)
1.1 items 테이블 공정 필드 추가
ALTER TABLE items ADD COLUMN process_type VARCHAR(20) DEFAULT NULL
COMMENT '공정유형: screen(스크린), bending(절곡), electric(전기)';
1.2 기존 품목에 공정 타입 매핑
| 품목명 | process_type |
|---|---|
| 스크린 원단 | screen |
| 연기차단재 | screen |
| 가이드레일, 하부베이스, 케이스, 측면덮개, 상부덮개, 하단마감재, 하단보강빔바, 샤프트 | bending |
| 모터, 제어기 | electric |
1.3 prices 테이블 더미 데이터 추가
- 기획 페이지의 가격 데이터를 prices 테이블에 시딩
- item_code와 연동 확인
파일 변경:
mng/database/migrations/xxxx_add_process_type_to_items.phpmng/database/seeders/ItemProcessTypeSeeder.phpmng/database/seeders/PriceSeeder.php
Phase 2: 백엔드 수정 (2-3일)
2.1 FormulaEvaluatorService 확장
현재 반환 구조:
[
'variables' => [...],
'items' => [
['item_code' => 'SCREEN-001', 'quantity' => 5.18, ...]
],
'bom_tree' => [...]
]
목표 반환 구조:
[
'variables' => [...],
'items' => [
[
'item_code' => 'SCREEN-001',
'item_name' => '스크린 원단',
'specification' => '...',
'unit' => 'm²',
'quantity' => 5.18,
'unit_price' => 100000, // 신규
'total_price' => 518000, // 신규
'process_type' => 'screen', // 신규
]
],
'items_by_process' => [ // 신규
'screen' => ['items' => [...], 'subtotal' => 558441],
'bending' => ['items' => [...], 'subtotal' => 385242],
'electric' => ['items' => [...], 'subtotal' => 400000],
],
'total_amount' => 1393683, // 신규
'bom_tree' => [...]
]
2.2 Price 연동 로직 추가
// FormulaEvaluatorService.php
private function enrichItemWithPrice(array $item, int $tenantId): array
{
$price = Price::getSalesPriceByItemCode($tenantId, $item['item_code']);
$item['unit_price'] = $price;
$item['total_price'] = $item['quantity'] * $price;
return $item;
}
private function groupItemsByProcess(array $items): array
{
$grouped = [
'screen' => ['items' => [], 'subtotal' => 0, 'label' => '스크린 공정'],
'bending' => ['items' => [], 'subtotal' => 0, 'label' => '절곡 공정'],
'electric' => ['items' => [], 'subtotal' => 0, 'label' => '전기 공정'],
];
foreach ($items as $item) {
$process = $item['process_type'] ?? 'etc';
if (isset($grouped[$process])) {
$grouped[$process]['items'][] = $item;
$grouped[$process]['subtotal'] += $item['total_price'];
}
}
return $grouped;
}
파일 변경:
mng/app/Services/FormulaEvaluatorService.phpmng/app/Models/Item.php(process_type 필드 추가)
Phase 3: 프론트엔드 수정 (2-3일)
3.1 simulator.blade.php UI 개선
현재 UI:
[변수 입력] → [계산] → [변수 결과] [품목 목록] [BOM 트리]
목표 UI:
[입력 섹션]
┌─────────────────────────────────────────────────────────┐
│ 층수 | 부호 | 제품카테고리 | 제품명 | 가로 | 세로 | ... │
│ 1층 | A | 스크린 | 표준형 | 2000 | 2500 | ... │
└─────────────────────────────────────────────────────────┘
[산출 결과]
┌─────────────────────────────────────────────────────────┐
│ 📦 스크린 공정 (2개 품목) 558,441원 │
│ ├─ 스크린 원단 5.18m² @100,000 = 518,415원 │
│ └─ 연기차단재 2.00m @20,013 = 40,026원 │
├─────────────────────────────────────────────────────────┤
│ 🔧 절곡 공정 (8개 품목) 385,242원 │
│ ├─ 가이드레일 2750mm @15,000 = 30,000원 │
│ ... │
├─────────────────────────────────────────────────────────┤
│ ⚡ 전기 공정 (2개 품목) 400,000원 │
│ ├─ 모터 1EA @250,000 = 250,000원 │
│ └─ 제어기 1EA @150,000 = 150,000원 │
├─────────────────────────────────────────────────────────┤
│ 📊 총합계: 12개 품목 1,393,683원 │
└─────────────────────────────────────────────────────────┘
3.2 JavaScript 수정
// 공정별 결과 렌더링
function renderProcessResults(data) {
const processOrder = ['screen', 'bending', 'electric'];
const processIcons = {
screen: '📦', bending: '🔧', electric: '⚡'
};
let html = '';
processOrder.forEach(process => {
const group = data.items_by_process[process];
if (group.items.length > 0) {
html += `
<div class="process-group">
<div class="process-header">
${processIcons[process]} ${group.label}
(${group.items.length}개 품목)
<span class="subtotal">${formatNumber(group.subtotal)}원</span>
</div>
<div class="process-items">
${renderItems(group.items)}
</div>
</div>
`;
}
});
html += `
<div class="total-section">
📊 총합계: ${data.items.length}개 품목
<span class="total">${formatNumber(data.total_amount)}원</span>
</div>
`;
return html;
}
파일 변경:
mng/resources/views/quote-formulas/simulator.blade.phpmng/public/css/simulator.css(스타일 추가)
Phase 4: 테스트 및 검증 (1일)
4.1 테스트 케이스
| 테스트 | 입력 | 예상 결과 |
|---|---|---|
| 기본 테스트 | W0=2000, H0=2500 | 12개 품목, 1,393,683원 |
| 크기 변경 | W0=3000, H0=3000 | 금액 증가 확인 |
| 수량 변경 | QTY=2 | 총액 2배 확인 |
4.2 검증 항목
- 기획 페이지와 동일한 품목 수
- 기획 페이지와 동일한 공정별 분류
- 기획 페이지와 동일한 금액 (±1원 오차 허용)
- 반올림 규칙 일치 확인
3. 파일 변경 목록
백엔드 (mng/)
| 파일 | 작업 | 우선순위 |
|---|---|---|
database/migrations/xxxx_add_process_type_to_items.php |
신규 | P1 |
database/seeders/ItemProcessTypeSeeder.php |
신규 | P1 |
database/seeders/PriceSeeder.php |
수정 | P1 |
app/Models/Item.php |
수정 (fillable 추가) | P1 |
app/Services/FormulaEvaluatorService.php |
수정 (핵심) | P1 |
프론트엔드 (mng/)
| 파일 | 작업 | 우선순위 |
|---|---|---|
resources/views/quote-formulas/simulator.blade.php |
수정 | P2 |
public/css/simulator.css |
신규/수정 | P2 |
4. 일정 (예상 5-7일)
| 단계 | 작업 | 예상 소요 |
|---|---|---|
| Phase 1 | 데이터 구조 정비 | 1-2일 |
| Phase 2 | 백엔드 수정 | 2-3일 |
| Phase 3 | 프론트엔드 수정 | 2-3일 |
| Phase 4 | 테스트 및 검증 | 1일 |
5. 기술적 고려사항
5.1 가격 계산 정확도
- 소수점 처리: 4자리까지 계산 후 최종 반올림
- 반올림 규칙: Price 모델의
rounding_rule필드 활용 - 단위: 원 단위로 표시
5.2 공정 분류 확장성
- process_type enum: 향후 공정 추가 가능하도록 설계
- 공정 순서: config/constants.php에서 관리
5.3 성능 고려
- 가격 조회: 배치 조회로 N+1 문제 방지
- 캐싱: 자주 사용되는 가격 데이터 캐싱 고려
6. 핵심 계산 로직 (2025-12-23 분석 완료)
6.1 변수 계산 규칙 (design.sam.kr 기준)
// AutoCalculationSimulator.tsx:429-444
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 // 미구현: 중량
};
6.2 수식 평가 (formulaEvaluator.ts)
지원 함수: SUM, AVERAGE, MAX, MIN, ROUND, CEIL, FLOOR, ABS, IF, SQRT, POWER
평가 과정:
- 변수를 실제 값으로 치환 (W0 → 2000)
- 함수를 JavaScript 코드로 변환 (CEIL → Math.ceil)
new Function()으로 최종 계산
6.3 단가 계산 방식
// 1순위: pricing 테이블
// 2순위: 품목마스터 salesPrice
// 면적 기반 품목 (원단, 패널, 도장, 표면처리)
if (isAreaBased && M > 0) {
finalUnitPrice = unitPrice * M; // 면적 × 기본단가
}
6.4 BOM 수량 공식 예시
| 품목 | 수량공식 | W0=2000, H0=2500 결과 |
|---|---|---|
| 스크린 원단 | W*H/1000000 |
2140×2850/1000000 = 6.099㎡ |
| 가이드레일 | H/1000 |
2850/1000 = 2.85m |
| 케이스 | (W1+100)/1000 |
(2140+100)/1000 = 2.24m |
7. 참고 자료
7.1 관련 파일
Design (분석 완료):
design/src/components/AutoCalculationSimulator.tsx- 메인 시뮬레이터design/src/components/utils/formulaEvaluator.ts- 수식 평가design/src/components/utils/bomCalculatorWithDebug.ts- BOM 계산
MNG (수정 대상):
mng/app/Services/Quote/FormulaEvaluatorService.php- 핵심 서비스mng/resources/views/quote-formulas/simulator.blade.php- UI
7.2 기획 데이터
- 기획 데이터:
react/src/contexts/DataContext.tsx.backup - 현재 시뮬레이터:
mng/resources/views/quote-formulas/simulator.blade.php - 수식 평가:
mng/app/Services/FormulaEvaluatorService.php - 가격 모델:
mng/app/Models/Price.php
6.2 DataContext.tsx.backup 핵심 로직
가이드레일 자재 선택 규칙:
// RULE-006: 가이드레일 제작길이 (G) = H0 + 250
// 자재 선택 기준:
// - G <= 3000: SM-GL-3000
// - 3000 < G <= 4000: SM-GL-4000
// - 4000 < G <= 5000: SM-GL-5000
// - G > 5000: SM-GL-6000
수량 공식 예시:
items: [
{ code: 'SCREEN-001', quantityFormula: '(W1 * H1) / 1000000' }, // m²
{ code: 'RAIL-001', quantityFormula: '2' }, // 2개 (좌/우)
{ code: 'MOTOR-001', quantityFormula: '1' }, // 1개
]
7. 체크리스트
시작 전
- 기획팀과 가격 데이터 확인
- 공정 분류 기준 확정
- 반올림 규칙 확정
개발 중
- Phase 1: 마이그레이션 및 시더 작성
- Phase 2: FormulaEvaluatorService 수정
- Phase 3: simulator.blade.php UI 개선
- Phase 4: 기획 페이지와 결과 비교 검증
완료 후
- 기획팀 확인
- CURRENT_WORKS.md 업데이트
- 문서 업데이트
이 문서는 견적 시뮬레이터와 기획 페이지 동기화 작업의 전체 계획을 담고 있습니다.