Files
sam-docs/plans/archive/quote-v2-auto-calculation-fix-plan.md
권혁성 28b69e5449 docs: archive 37개 + COMPLETED 3개 복원 - 향후 docs/ 정식 문서화 시 참조용
- 완료 문서의 상세 내용은 추후 docs/ 구조화 시 정식 문서에 반영 예정
- HISTORY.md는 요약 인덱스로 유지, 개별 파일은 상세 참조용 보관

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 22:32:20 +09:00

9.5 KiB
Raw Blame History

견적 V2 자동 견적 산출 오류 수정 계획

작성일: 2026-01-26 목적: 자동 견적 산출 기능의 4가지 오류 분석 및 수정 기준 문서: QuoteRegistrationV2.tsx, LocationDetailPanel.tsx, QuoteSummaryPanel.tsx, actions.ts 상태: 완료


📍 현재 진행 상태

항목 내용
마지막 완료 작업 테스트 및 검증 완료
다음 작업 -
진행률 4/4 (100%)
마지막 업데이트 2026-01-26

1. 개요

1.1 배경

견적 V2 페이지(/sales/quote-management/test-new)에서 자동 견적 산출 버튼 클릭 후 다음 4가지 문제 발생:

  1. 오른쪽 패널에 제품 리스트가 표시되지 않음
  2. 개소별 합계(상세소계)가 표시되지 않음
  3. 상세별 합계(그룹)가 표시되지 않음
  4. 예상 견적금액이 0원으로 표시됨

1.2 기준 원칙

┌─────────────────────────────────────────────────────────────────┐
│  🎯 핵심 원칙                                                   │
├─────────────────────────────────────────────────────────────────┤
│  - API 응답 구조와 프론트엔드 기대 구조의 일치 확보             │
│  - Mock 데이터 fallback 로직은 디버깅/테스트용으로만 유지       │
│  - 실제 BOM 계산 결과가 UI에 정확히 반영되도록 수정             │
└─────────────────────────────────────────────────────────────────┘

1.3 변경 승인 정책

분류 예시 승인
즉시 가능 타입 캐스팅 수정, 데이터 매핑 로직 수정 불필요
⚠️ 컨펌 필요 API 응답 구조 변경, 새 인터페이스 정의 필수
🔴 금지 API 엔드포인트 변경, DB 스키마 변경 별도 협의

2. 근본 원인 분석

2.1 API 응답 구조 불일치 (핵심 원인)

API 실제 응답 (actions.ts:962-965):

return {
  success: true,
  data: result.data || [],  // 배열을 직접 반환
};

API 서버 응답 (QuoteCalculationService.php:168-178):

return [
    'success' => $failCount === 0,
    'summary' => [
        'total_count' => count($inputItems),
        'success_count' => $successCount,
        'fail_count' => $failCount,
        'grand_total' => round($grandTotal, 2),
    ],
    'items' => $results,  // items 배열 안에 결과가 있음
];

컴포넌트 기대 구조 (QuoteRegistrationV2.tsx:459-462):

const apiData = result.data as {
  summary?: { grand_total: number };
  items?: Array<{ index: number; result: BomCalculationResult }>;
};
const bomItems = apiData.items || [];  // ❌ result.data가 배열이면 items가 없음!

2.2 문제 발생 흐름

사용자 → "자동 견적 산출" 클릭
    ↓
calculateBomBulk(bomItems) 호출
    ↓
API 서버: { success, summary, items: [...] } 반환
    ↓
actions.ts: result.data = 전체 응답 객체 (또는 배열로 잘못 파싱)
    ↓
QuoteRegistrationV2.tsx: result.data.items 접근 시도
    ↓
❌ items가 undefined → bomItems = []
    ↓
locations에 bomResult 저장 안됨
    ↓
LocationDetailPanel: bomResult?.items 없음 → Mock 데이터 표시
QuoteSummaryPanel: bomResult?.subtotals 없음 → Mock 데이터 표시
    ↓
💥 모든 UI 영역에 데이터 없음

2.3 영향 받는 컴포넌트

컴포넌트 파일 영향
QuoteRegistrationV2 QuoteRegistrationV2.tsx:457-481 bomResult 저장 안됨
LocationDetailPanel LocationDetailPanel.tsx:152-184 Mock 데이터로 fallback
QuoteSummaryPanel QuoteSummaryPanel.tsx:136-164 Mock 데이터로 fallback

3. 대상 범위

3.1 Phase 1: API 응답 처리 수정

# 작업 항목 상태 비고
1.1 actions.ts 응답 구조 확인 API 서버 응답과 비교
1.2 actions.ts BomBulkResponse 타입 추가 정확한 API 응답 구조 정의
1.3 QuoteRegistrationV2.tsx handleCalculate 수정 응답 매핑 로직 및 디버그 로그 추가

3.2 Phase 2: 데이터 바인딩 수정

# 작업 항목 상태 비고
2.1 FormulaEvaluatorService.php items에 process_group 추가 addProcessGroupToItems 메서드 추가
2.2 LocationDetailPanel.tsx bomItemsByTab 수정 process_group_key 기반 매핑
2.3 QuoteSummaryPanel.tsx detailTotals 수정 grouped_items에서 items 가져오기
2.4 actions.ts BomCalculationResult 타입 확장 process_group, grouped_items 필드 추가

4. 상세 작업 내용

4.1 Phase 1.2: handleCalculate 함수 수정

현재 코드 (QuoteRegistrationV2.tsx:457-479):

if (result.success && result.data) {
  // ❌ 잘못된 타입 캐스팅 - result.data 자체가 API 응답 객체임
  const apiData = result.data as {
    summary?: { grand_total: number };
    items?: Array<{ index: number; result: BomCalculationResult }>;
  };
  const bomItems = apiData.items || [];  // ❌ undefined
  // ...
}

수정 방안: actions.ts의 응답 처리를 확인하여 두 가지 접근법 중 선택:

방안 A: actions.ts 수정 (권장)

// actions.ts에서 API 응답 구조 유지
return {
  success: true,
  data: {
    summary: result.data.summary,
    items: result.data.items,
  },
};

방안 B: QuoteRegistrationV2.tsx 수정

if (result.success && result.data) {
  // result.data가 { summary, items } 구조인지 확인
  const apiData = result.data as unknown as {
    summary?: { grand_total: number };
    items?: Array<{ index: number; result: BomCalculationResult }>;
  };
  // ...
}

5. 컨펌 대기 목록

# 항목 변경 내용 영향 범위 상태
1 API 응답 구조 actions.ts의 result.data 반환 방식 검토 react/actions.ts 대기

6. 변경 이력

날짜 항목 변경 내용 파일 승인
2026-01-26 분석 문서 초안 작성 및 근본 원인 분석 완료 - -
2026-01-26 수정 actions.ts BomBulkResponse 타입 추가 react/src/components/quotes/actions.ts
2026-01-26 수정 QuoteRegistrationV2.tsx handleCalculate 수정 react/src/components/quotes/QuoteRegistrationV2.tsx
2026-01-26 수정 FormulaEvaluatorService.php process_group 추가 api/app/Services/Quote/FormulaEvaluatorService.php
2026-01-26 수정 LocationDetailPanel.tsx bomItemsByTab 수정 react/src/components/quotes/LocationDetailPanel.tsx
2026-01-26 수정 QuoteSummaryPanel.tsx detailTotals 수정 react/src/components/quotes/QuoteSummaryPanel.tsx
2026-01-26 수정 ItemService.php has_bom 필드 추가 api/app/Services/ItemService.php
2026-01-26 수정 actions.ts FinishedGoods에 has_bom, bom 필드 추가 react/src/components/quotes/actions.ts
2026-01-26 수정 QuoteRegistrationV2.tsx DevFill BOM 필터링 react/src/components/quotes/QuoteRegistrationV2.tsx
2026-01-26 검증 브라우저 테스트 완료 - 4가지 문제 모두 해결 확인 -

7. 참고 문서

  • 빠른 시작: docs/quickstart/quick-start.md
  • 품질 체크리스트: docs/standards/quality-checklist.md
  • API 규칙: docs/standards/api-rules.md

8. 검증 결과

브라우저 자동화 테스트 완료 (2026-01-26)

8.1 테스트 케이스

입력값 예상 결과 실제 결과 상태
DevFill 후 자동 견적 산출 제품 리스트 표시 볼트 M10×40, 너트 M10, 볼트 M8×30 등 6개 품목 표시
개소 선택 개소별 합계 표시 1F / SS-01 상세소계: 3,119,555.94원
그룹별 합계 상세별 합계 표시 절곡 공정: 735,891.24원, 철재 공정: 2,383,364.7원
전체 금액 예상 견적금액 > 0 예상 견적금액: 3,119,555.94원

8.2 테스트 환경

  • URL: http://dev.sam.kr/sales/quote-management/test-new
  • 테스트 방법: Claude-in-Chrome 브라우저 자동화
  • 데이터: DevFill로 생성된 테스트 데이터

8.3 추가 발견 및 해결 사항

테스트 중 DevFill이 BOM 없는 제품을 선택하여 계산 결과가 0으로 나오는 문제 발견:

문제 원인 해결
DevFill 후 bomItemsCount: 0 BOM 없는 제품 선택 DevFill에서 BOM 있는 제품만 필터링
has_bom 필드 없음 API 응답에 미포함 ItemService.php에서 계산 필드 추가
getFinishedGoods에서 필드 누락 매핑 시 has_bom, bom 미포함 FinishedGoods 인터페이스 및 매핑 수정

8.4 최종 검증 결과

[DevFill] BOM 있는 제품: 15개 / 전체: 2017개
[BOM 계산 결과]
- bomItemsCount: 6
- bomGrandTotal: 3,119,555.94
- 공정별 그룹: 절곡, 철재

모든 4가지 UI 문제 해결 확인 완료


이 문서는 /sc:plan 스킬로 생성되었습니다.