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

8.7 KiB
Raw Blame History

견적 시뮬레이터 계산 로직 매핑

작성일: 2025-12-23 목표: design.sam.kr 계산 로직 → mng 시뮬레이터 동기화


1. Design 계산 로직 분석

1.1 핵심 계산 변수 (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                                                    // 중량 (미구현)
};

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)

평가 과정:

// 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 단가 계산 방식

// 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 테이블에 추가할 수식:

-- 제작폭 (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 확장

// 추가할 메서드

/**
 * 카테고리별 단가 계산
 */
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 테이블 확장

-- 공정 유형 필드 추가
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 시뮬레이터 구현 계획을 정리합니다.