# 견적 관리 8개 이슈 수정 계획 > **작성일**: 2026-01-06 > **목적**: 견적 관리 화면 8개 이슈 수정 (리스트/상세/수정 화면) > **기준 문서**: react/src/components/quotes/ 컴포넌트 > **상태**: 🔄 진행중 --- ## 📍 현재 진행 상태 | 항목 | 내용 | |------|------| | **마지막 완료 작업** | 이슈 #1 분석 완료 (백엔드 API 정상 확인) | | **다음 작업** | 이슈 #1 분석 결과 사용자 컨펌 대기 | | **진행률** | 0/8 (0%) - 이슈 #1 분석 완료, 컨펌 대기 | | **마지막 업데이트** | 2026-01-06 | --- ## 1. 개요 ### 1.1 배경 견적 관리 시스템에서 담당자, 연락처, 비고, 단위 등의 필드가 제대로 표시되지 않거나 잘못된 값이 표시되는 8개 이슈 발견 ### 1.2 핵심 원칙 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 🎯 핵심 원칙 │ ├─────────────────────────────────────────────────────────────────┤ │ - 한 이슈씩 순차적으로 수정 (사용자 컨펌 후 다음 진행) │ │ - 프론트엔드 필드 매핑 일관성 유지 │ │ - 백엔드 API 응답 데이터 확인 후 프론트엔드 수정 │ │ - 커밋은 모든 작업 완료 후 일괄 진행 │ └─────────────────────────────────────────────────────────────────┘ ``` ### 1.3 🔴 작업 진행 절차 (필수) ``` ┌─────────────────────────────────────────────────────────────────┐ │ 📋 각 이슈별 작업 흐름 │ ├─────────────────────────────────────────────────────────────────┤ │ 1. 분석 → 분석 결과 보고 │ │ 2. 사용자 컨펌 대기 (테스트 가능한 정보 제공) │ │ 3. 컨펌 후 → 수정 작업 진행 │ │ 4. 수정 완료 → 결과 보고 (테스트 방법 포함) │ │ 5. 사용자 테스트 & 컨펌 │ │ 6. 컨펌 완료 → 다음 이슈 진행 │ │ │ │ ⚠️ 사용자 승인 없이 다음 단계 진행 금지! │ └─────────────────────────────────────────────────────────────────┘ ``` **각 이슈 완료 보고 형식:** ```markdown ## 이슈 #N 완료 보고 **작업 내용:** - 수정한 파일과 라인 - 변경 전/후 코드 **테스트 방법:** - 테스트 URL - 확인 포인트 **기대 결과:** - 변경 전: [문제 상황] - 변경 후: [예상 결과] **다음 작업 진행할까요?** ``` ### 1.4 핵심 발견: 필드명 불일치 문제 **Quote 인터페이스 (types.ts:85-115):** ```typescript export interface Quote { managerName?: string; // ← 담당자 managerContact?: string; // ← 연락처 description?: string; // ← 비고 // ... } ``` **문제점:** - `QuoteDocument.tsx`, `QuoteCalculationReport.tsx`에서 `quote.manager`, `quote.contact` 사용 - Quote 인터페이스에는 `managerName`, `managerContact`로 정의됨 - **필드명 불일치로 인해 항상 undefined → '-' 표시** --- ## 2. 대상 범위 ### 2.1 이슈 목록 | # | 이슈 | 화면 | 상태 | 근본 원인 | |---|------|------|:----:|----------| | 1 | 담당자, 비고 컬럼 미표시 | 리스트 | ⏳ | API 응답 확인 필요 | | 2 | 담당자, 연락처 미표시 + 단위 "set" | 상세 (/8) | ⏳ | 필드명 불일치 | | 3 | 담당자, 연락처 미표시 + 총 수량 계산 | 상세 견적서 (/9) | ⏳ | 필드명 불일치 + 하드코딩 | | 4 | 단위가 모두 "개소"로 표시 | 품목내역 | ⏳ | item.unit 누락 | | 5 | 담당자/연락처/단위/수량 이슈 | 산출 내역서 | ⏳ | 필드명 불일치 + 하드코딩 | | 6 | 세부산출 vs 소요자재 동일 | 산출 내역서 | ⏳ | leaf 노드 분리 미적용 | | 7 | 작성자/담당자/연락처/비고 미표시 | 수정 (/edit) | ⏳ | 데이터 로딩 확인 | | 8 | 1개 → 14개 견적 표시 | 자동 견적 산출 | ⏳ | state 초기화 누락 | --- ## 3. 상세 분석 및 수정 코드 ### 3.1 이슈 #1: 리스트 화면 담당자/비고 미표시 **파일**: `react/src/components/quotes/QuoteManagementClient.tsx` **현재 코드 (Line 421, 424):** ```typescript {quote.managerName || '-'} // ...
{quote.description || '-'}
``` **분석:** - 코드 자체는 정확함 (`managerName`, `description` 사용) - API 응답에서 `manager` → `managerName` 변환 확인 필요 **변환 함수 (types.ts:254-256, 266):** ```typescript // transformApiToFrontend 함수 managerName: apiData.manager || apiData.manager_name || undefined, managerContact: apiData.contact || apiData.manager_contact || undefined, // ... description: apiData.remarks || apiData.description || undefined, ``` **확인 필요:** - API 응답에 `manager`, `contact`, `remarks` 필드가 포함되는지 확인 - 백엔드 QuoteResource에서 해당 필드 반환 여부 확인 --- ### 3.2 이슈 #2: 상세 화면 담당자/연락처 미표시 + 단위 "set" **파일**: `react/src/components/quotes/QuoteDocument.tsx` **현재 코드 (Line 271-278):** ```typescript 담당자 {quote.manager || '-'} // ❌ 잘못된 필드명 // ... 연락처 {quote.contact || '-'} // ❌ 잘못된 필드명 ``` **수정 코드:** ```typescript 담당자 {quote.managerName || '-'} // ✅ 올바른 필드명 // ... 연락처 {quote.managerContact || '-'} // ✅ 올바른 필드명 ``` **단위 문제 (Line 34-42):** ```typescript // 현재 코드 - 이미 올바름 const quoteItems = quote.items?.map((item, index) => ({ // ... unit: item.unit || '', // ✅ 각 품목의 단위 사용 })) || []; ``` --- ### 3.3 이슈 #3: 상세 견적서 총 수량 계산 **파일**: `react/src/components/quotes/QuoteDocument.tsx` **현재 코드 (Line 345):** ```typescript 총 수량 {quote.items.reduce((sum, item) => sum + (item.quantity || 0), 0)}개소 // ❌ "개소" 하드코딩 ``` **수정 코드:** ```typescript 총 수량 {quote.items.reduce((sum, item) => sum + (item.quantity || 0), 0)} {quote.items[0]?.unit || 'EA'} // ✅ 첫 번째 품목의 단위 사용 또는 기본값 EA ``` --- ### 3.4 이슈 #4: 품목내역 단위 "개소" 고정 **파일**: `react/src/components/quotes/QuoteDocument.tsx` **현재 코드 (Line 383):** ```typescript {item.unit} ``` **분석:** - 코드는 `item.unit`을 사용하고 있어 올바름 - 문제는 `item.unit` 값이 API에서 오지 않거나 비어 있음 - **확인 필요**: API 응답의 `unit` 필드 확인 --- ### 3.5 이슈 #5: 산출 내역서 담당자/연락처/단위/수량 **파일**: `react/src/components/quotes/QuoteCalculationReport.tsx` **현재 코드 (Line 307-314):** ```typescript 담당자 {quote.manager || '-'} // ❌ 잘못된 필드명 // ... 연락처 {quote.contact || '-'} // ❌ 잘못된 필드명 ``` **수정 코드:** ```typescript 담당자 {quote.managerName || '-'} // ✅ 올바른 필드명 // ... 연락처 {quote.managerContact || '-'} // ✅ 올바른 필드명 ``` **단위 하드코딩 (Line 394):** ```typescript // 현재 코드 SET // ❌ 하드코딩 // 수정 코드 {item.unit || 'SET'} // ✅ 동적 + 기본값 ``` **수량 기준 문제:** - 현재: 1개 기준 수량 표시 - 필요: 세트 수량(예: 10개) 기준 표시 - **확인 필요**: 비즈니스 로직 명확화 --- ### 3.6 이슈 #6: 세부산출내역 vs 소요자재내역 분리 **파일**: `react/src/components/quotes/QuoteCalculationReport.tsx` **현재 상태 (Line 45-55):** ```typescript // 소요자재 내역 - 실제 BOM 자재 데이터 사용 const materialItems = quote.bomMaterials?.map((material, index) => ({ // ... })) || []; ``` **문제:** - 세부산출내역과 소요자재내역이 동일한 `bomMaterials` 사용 - 소요자재는 leaf 노드만 표시해야 함 **수정 방향:** ```typescript // 세부산출내역: 전체 BOM 항목 const detailItems = quote.bomMaterials || []; // 소요자재내역: leaf 노드만 (has_children = false 또는 별도 필드) const materialItems = quote.bomMaterials?.filter(m => !m.hasChildren) || []; // 또는 백엔드에서 별도 필드로 제공 (leafMaterials) ``` **참고**: 이전 세션에서 백엔드 `getBomLeafMaterials()` 함수 추가됨 --- ### 3.7 이슈 #7: 수정 화면 필드 미표시 **파일**: `react/src/components/quotes/QuoteRegistration.tsx` **폼 필드 코드 (Line 593-683):** ```typescript // 작성자 (Line 593-600) // 담당자 (Line 644-651) // 연락처 (Line 653-659) // 비고 (Line 675-683)