From 3bfe30ee1c4bdcacc4eb92eb62eeafeeb11a9e39 Mon Sep 17 00:00:00 2001 From: kent Date: Tue, 6 Jan 2026 21:00:56 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EA=B2=AC=EC=A0=81=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=EC=9D=B4=EC=8A=88=20=EA=B3=84=ED=9A=8D=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8B=9C=EB=8D=94=20=EB=AA=A9=EB=A1=9D=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - plans/quote-management-8issues-plan.md: 견적 관리 8개 이슈 수정 계획 - plans/SEEDERS_LIST.md: SAM API 시더 목록 및 실행 방법 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- plans/SEEDERS_LIST.md | 128 ++++++ plans/quote-management-8issues-plan.md | 529 +++++++++++++++++++++++++ 2 files changed, 657 insertions(+) create mode 100644 plans/SEEDERS_LIST.md create mode 100644 plans/quote-management-8issues-plan.md diff --git a/plans/SEEDERS_LIST.md b/plans/SEEDERS_LIST.md new file mode 100644 index 0000000..b8a90b2 --- /dev/null +++ b/plans/SEEDERS_LIST.md @@ -0,0 +1,128 @@ +# SAM API 시더 목록 + +> 생성일: 2025-01-05 +> 대상 테넌트: ID 287 + +## 개별 실행 방법 + +```bash +# Docker 컨테이너 접속 후 +php artisan db:seed --class=시더클래스명 + +# Dummy 폴더 시더는 네임스페이스 포함 +php artisan db:seed --class=Dummy\\DummyClientSeeder +``` + +--- + +## 1. 메인 시더 + +| # | 시더 | 설명 | 실행 명령어 | +|---|------|------|-------------| +| 1 | `DatabaseSeeder` | 기본 시더 (테스트 유저 + 메뉴) | `php artisan db:seed` | +| 2 | `DummyDataSeeder` | 전체 더미 데이터 (모든 Dummy 호출) | `php artisan db:seed --class=DummyDataSeeder` | + +--- + +## 2. 기본 데이터 시더 (Dummy) + +| # | 시더 | 테이블 | 수량 | 실행 명령어 | +|---|------|--------|------|-------------| +| 3 | `DummyUserSeeder` | users | 15 | `php artisan db:seed --class=Dummy\\DummyUserSeeder` | +| 4 | `DummyDepartmentSeeder` | departments | 11 | `php artisan db:seed --class=Dummy\\DummyDepartmentSeeder` | +| 5 | `DummyClientGroupSeeder` | client_groups | 5 | `php artisan db:seed --class=Dummy\\DummyClientGroupSeeder` | +| 6 | `DummyBankAccountSeeder` | bank_accounts | 5 | `php artisan db:seed --class=Dummy\\DummyBankAccountSeeder` | +| 7 | `DummyClientSeeder` | clients | 20 | `php artisan db:seed --class=Dummy\\DummyClientSeeder` | + +--- + +## 3. 회계 데이터 시더 (Dummy) + +| # | 시더 | 테이블 | 수량 | 실행 명령어 | +|---|------|--------|------|-------------| +| 8 | `DummyDepositSeeder` | deposits | 60 | `php artisan db:seed --class=Dummy\\DummyDepositSeeder` | +| 9 | `DummyWithdrawalSeeder` | withdrawals | 60 | `php artisan db:seed --class=Dummy\\DummyWithdrawalSeeder` | +| 10 | `DummySaleSeeder` | sales | 80 | `php artisan db:seed --class=Dummy\\DummySaleSeeder` | +| 11 | `DummyPurchaseSeeder` | purchases | 70 | `php artisan db:seed --class=Dummy\\DummyPurchaseSeeder` | +| 12 | `DummyBadDebtSeeder` | bad_debts | 18 | `php artisan db:seed --class=Dummy\\DummyBadDebtSeeder` | +| 13 | `DummyBillSeeder` | bills | 30 | `php artisan db:seed --class=Dummy\\DummyBillSeeder` | + +--- + +## 4. HR 데이터 시더 (Dummy) + +| # | 시더 | 테이블 | 수량 | 실행 명령어 | +|---|------|--------|------|-------------| +| 14 | `DummyWorkSettingSeeder` | work_settings | 1 | `php artisan db:seed --class=Dummy\\DummyWorkSettingSeeder` | +| 15 | `DummyAttendanceSettingSeeder` | attendance_settings | 1 | `php artisan db:seed --class=Dummy\\DummyAttendanceSettingSeeder` | +| 16 | `DummyAttendanceSeeder` | attendances | ~300 | `php artisan db:seed --class=Dummy\\DummyAttendanceSeeder` | +| 17 | `DummyLeaveGrantSeeder` | leave_grants | ~200 | `php artisan db:seed --class=Dummy\\DummyLeaveGrantSeeder` | +| 18 | `DummyLeaveSeeder` | leaves | ~50 | `php artisan db:seed --class=Dummy\\DummyLeaveSeeder` | +| 19 | `DummyCardSeeder` | cards | 5 | `php artisan db:seed --class=Dummy\\DummyCardSeeder` | +| 20 | `DummySalarySeeder` | salaries | 15 | `php artisan db:seed --class=Dummy\\DummySalarySeeder` | + +--- + +## 5. 기타 더미 시더 (Dummy) + +| # | 시더 | 테이블 | 수량 | 실행 명령어 | +|---|------|--------|------|-------------| +| 21 | `DummyItemSeeder` | items | 10,000 | `php artisan db:seed --class=Dummy\\DummyItemSeeder` | +| 22 | `DummyPopupSeeder` | popups | 8 | `php artisan db:seed --class=Dummy\\DummyPopupSeeder` | +| 23 | `DummyPaymentSeeder` | payments | 13 | `php artisan db:seed --class=Dummy\\DummyPaymentSeeder` | +| 24 | `ApprovalTestDataSeeder` | approvals | ~60 | `php artisan db:seed --class=ApprovalTestDataSeeder` | + +--- + +## 6. 시스템/설정 시더 + +| # | 시더 | 설명 | 실행 명령어 | +|---|------|------|-------------| +| 25 | `GlobalMenuTemplateSeeder` | 글로벌 메뉴 템플릿 | `php artisan db:seed --class=GlobalMenuTemplateSeeder` | +| 26 | `ReactMenuSeeder` | React 메뉴 | `php artisan db:seed --class=ReactMenuSeeder` | +| 27 | `CategorySeeder` | 카테고리 | `php artisan db:seed --class=CategorySeeder` | +| 28 | `ItemTypeSeeder` | 품목 유형 | `php artisan db:seed --class=ItemTypeSeeder` | +| 29 | `ItemMasterSeeder` | 품목 마스터 | `php artisan db:seed --class=ItemMasterSeeder` | +| 30 | `PositionSeeder` | 직급 | `php artisan db:seed --class=PositionSeeder` | +| 31 | `FolderSeeder` | 폴더 | `php artisan db:seed --class=FolderSeeder` | +| 32 | `CapabilityProfileSeeder` | 역량 프로필 | `php artisan db:seed --class=CapabilityProfileSeeder` | +| 33 | `StockReceivingSeeder` | 입고 | `php artisan db:seed --class=StockReceivingSeeder` | +| 34 | `ComprehensiveAnalysisSeeder` | 종합분석 | `php artisan db:seed --class=ComprehensiveAnalysisSeeder` | +| 35 | `SystemFieldDefinitionSeeder` | 시스템 필드 정의 | `php artisan db:seed --class=SystemFieldDefinitionSeeder` | +| 36 | `DemoSystemSeeder` | 데모 시스템 | `php artisan db:seed --class=DemoSystemSeeder` | +| 37 | `BpMesCategoryFieldsSeeder` | MES 카테고리 필드 | `php artisan db:seed --class=BpMesCategoryFieldsSeeder` | +| 38 | `BpMesTenantStatFieldsSeeder` | MES 테넌트 통계 필드 | `php artisan db:seed --class=BpMesTenantStatFieldsSeeder` | + +--- + +## 7. 견적 관련 시더 + +| # | 시더 | 설명 | 실행 명령어 | +|---|------|------|-------------| +| 39 | `QuoteFormulaSeeder` | 견적 계산식 | `php artisan db:seed --class=QuoteFormulaSeeder` | +| 40 | `QuoteFormulaCategorySeeder` | 견적 계산 카테고리 | `php artisan db:seed --class=QuoteFormulaCategorySeeder` | +| 41 | `QuoteFormulaItemSeeder` | 견적 계산 품목 | `php artisan db:seed --class=QuoteFormulaItemSeeder` | +| 42 | `QuoteFormulaMappingSeeder` | 견적 계산 매핑 | `php artisan db:seed --class=QuoteFormulaMappingSeeder` | + +--- + +## 요약 + +| 카테고리 | 개수 | +|----------|------| +| 메인 시더 | 2 | +| 기본 데이터 (Dummy) | 5 | +| 회계 데이터 (Dummy) | 6 | +| HR 데이터 (Dummy) | 7 | +| 기타 더미 (Dummy) | 4 | +| 시스템/설정 | 14 | +| 견적 관련 | 4 | +| **총계** | **42** | + +--- + +## 주의사항 + +1. **Dummy 시더**는 `TENANT_ID = 287` 하드코딩 +2. **의존성 순서**: 기본 데이터 → 회계 → HR → 기타 순서로 실행 권장 +3. **중복 주의**: 이미 데이터가 있는 경우 중복 생성됨 (특히 `DummyItemSeeder` 10,000개) \ No newline at end of file diff --git a/plans/quote-management-8issues-plan.md b/plans/quote-management-8issues-plan.md new file mode 100644 index 0000000..7ef7b47 --- /dev/null +++ b/plans/quote-management-8issues-plan.md @@ -0,0 +1,529 @@ +# 견적 관리 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) + +