diff --git a/claudedocs/[REF] all-pages-test-urls.md b/claudedocs/[REF] all-pages-test-urls.md index 6f3513c6..b0e02f45 100644 --- a/claudedocs/[REF] all-pages-test-urls.md +++ b/claudedocs/[REF] all-pages-test-urls.md @@ -1,6 +1,6 @@ # 전체 페이지 테스트 URL 목록 -> 백엔드 메뉴 연동 전 테스트용 직접 접근 URL (Last Updated: 2025-12-19) +> 백엔드 메뉴 연동 전 테스트용 직접 접근 URL (Last Updated: 2025-12-23) ## 🚀 클릭 가능한 웹 페이지 @@ -83,9 +83,49 @@ http://localhost:3000/ko/master-data/item-master-data-management | 페이지 | URL | 상태 | |--------|-----|------| | 스크린 생산 | `/ko/production/screen-production` | ✅ | +| 작업지시 관리 | `/ko/production/work-orders` | ✅ | +| **작업실적 조회** | `/ko/production/work-results` | 🆕 NEW | ``` http://localhost:3000/ko/production/screen-production +http://localhost:3000/ko/production/work-orders +http://localhost:3000/ko/production/work-results # 🆕 작업실적 조회 +``` + +--- + +## 📦 자재관리 (Material) + +| 페이지 | URL | 상태 | +|--------|-----|------| +| **재고현황** | `/ko/material/stock-status` | 🆕 NEW | + +``` +http://localhost:3000/ko/material/stock-status # 🆕 재고현황 +``` + +--- + +## 🔬 품질관리 (Quality) + +| 페이지 | URL | 상태 | +|--------|-----|------| +| **검사관리** | `/ko/quality/inspections` | 🆕 NEW | + +``` +http://localhost:3000/ko/quality/inspections # 🆕 검사관리 +``` + +--- + +## 📤 출고관리 (Outbound) + +| 페이지 | URL | 상태 | +|--------|-----|------| +| **출하 목록** | `/ko/outbound/shipments` | 🆕 NEW | + +``` +http://localhost:3000/ko/outbound/shipments # 🆕 출하관리 ``` --- @@ -278,6 +318,23 @@ http://localhost:3000/ko/master-data/item-master-data-management ### Production ``` http://localhost:3000/ko/production/screen-production +http://localhost:3000/ko/production/work-orders +http://localhost:3000/ko/production/work-results # 🆕 작업실적 조회 +``` + +### Material +``` +http://localhost:3000/ko/material/stock-status # 🆕 재고현황 +``` + +### Quality +``` +http://localhost:3000/ko/quality/inspections # 🆕 검사관리 +``` + +### Outbound +``` +http://localhost:3000/ko/outbound/shipments # 🆕 출하관리 ``` ### Settings @@ -359,6 +416,17 @@ http://localhost:3000/ko/customer-center/inquiries # 1:1 문의 // Production '/production/screen-production' +'/production/work-orders' // 작업지시 관리 +'/production/work-results' // 작업실적 조회 (🆕 NEW) + +// Material (자재관리) +'/material/stock-status' // 재고현황 (🆕 NEW) + +// Quality (품질관리) +'/quality/inspections' // 검사관리 (🆕 NEW) + +// Outbound (출고관리) +'/outbound/shipments' // 출하관리 (🆕 NEW) // Settings '/settings/leave-policy' @@ -417,4 +485,4 @@ http://localhost:3000/ko/customer-center/inquiries # 1:1 문의 ## 작성일 - 최초 작성: 2025-12-06 -- 최종 업데이트: 2025-12-19 (하위 페이지 정리, 리스트 페이지만 유지) +- 최종 업데이트: 2025-12-23 (출고관리 출하관리 페이지 추가) diff --git a/claudedocs/_index.md b/claudedocs/_index.md index 72a9dbe7..1efba35f 100644 --- a/claudedocs/_index.md +++ b/claudedocs/_index.md @@ -1,6 +1,6 @@ # claudedocs 문서 맵 -> 프로젝트 기술 문서 인덱스 (Last Updated: 2025-12-20) +> 프로젝트 기술 문서 인덱스 (Last Updated: 2025-12-22) ## ⭐ 빠른 참조 @@ -18,10 +18,12 @@ claudedocs/ ├── auth/ # 🔐 인증 & 토큰 관리 ├── hr/ # 👥 인사관리 (부서/사원) ├── item-master/ # 📦 품목기준관리 +├── production/ # 🏭 생산관리 (생산현황판/작업지시) +├── quality/ # 🔬 품질관리 (검사관리) (NEW) ├── sales/ # 💰 판매관리 (견적/거래처) ├── accounting/ # 💳 회계관리 (매입/매출/출금) ├── board/ # 📝 게시판 관리 -├── settings/ # ⚙️ 설정 관리 (NEW) +├── settings/ # ⚙️ 설정 관리 ├── dashboard/ # 📊 대시보드 & 사이드바 ├── api/ # 🔌 API 통합 ├── guides/ # 📚 범용 가이드 @@ -92,6 +94,22 @@ claudedocs/ --- +## 🏭 production/ - 생산관리 (생산현황판/작업지시) + +| 파일 | 설명 | +|------|------| +| `[IMPL-2025-12-22] production-dashboard-checklist.md` | 🔴 **NEW** - 생산 현황판 구현 체크리스트 (메인/작업자화면, 8 Phase) | + +--- + +## 🔬 quality/ - 품질관리 (검사관리) + +| 파일 | 설명 | +|------|------| +| `[IMPL-2025-12-23] inspection-management-checklist.md` | 🔴 **NEW** - 검사관리 구현 체크리스트 (리스트/등록/상세/수정, 7 Phase) | + +--- + ## 💰 sales/ - 판매관리 (견적/거래처/단가) | 파일 | 설명 | @@ -134,6 +152,7 @@ claudedocs/ | 파일 | 설명 | |------|------| +| `[ANALYSIS-2025-12-23] common-component-extraction-candidates.md` | 🔴 **NEW** - 공통 컴포넌트 추출 후보 분석 (다이얼로그 102개 중복, ~2,370줄 절감 예상) | | `[PLAN-2025-12-19] project-health-improvement.md` | ✅ **Phase 1 완료** - 프로젝트 헬스 개선 계획서 (타입에러 0개, API키 보안, SSR 수정) | | `[PLAN-2025-12-19] page-layout-standardization.md` | 🔴 **NEW** - 페이지 레이아웃 표준화 계획 | | `[GUIDE-2025-12-16] options-vs-flattened-data.md` | options vs 평탄화 데이터 패턴 (API 응답 매핑 시 options 직접 파싱 금지) | diff --git a/claudedocs/guides/[ANALYSIS-2025-12-23] common-component-extraction-candidates.md b/claudedocs/guides/[ANALYSIS-2025-12-23] common-component-extraction-candidates.md new file mode 100644 index 00000000..c9eff83a --- /dev/null +++ b/claudedocs/guides/[ANALYSIS-2025-12-23] common-component-extraction-candidates.md @@ -0,0 +1,216 @@ +# 공통 컴포넌트 추출 후보 분석 + +> 프로젝트 전반의 반복 패턴 분석 및 공통화 후보 목록 (2025-12-23) + +## 현황 요약 + +| 구분 | 수치 | +|-----|------| +| 전체 컴포넌트 파일 | 317개 | +| Dialog/AlertDialog 사용 파일 | 102개 | +| 공통 StandardDialog 사용 | 1개 (quote-management만) | +| 예상 코드 절감 | ~2,370줄 | + +--- + +## 기존 공통 컴포넌트 (사용률 저조) + +| 컴포넌트 | 위치 | 사용 현황 | +|---------|------|----------| +| `StandardDialog` | `molecules/StandardDialog.tsx` | 1곳 사용 | +| `ConfirmDialog` | `molecules/StandardDialog.tsx` | 미사용 | +| `FormDialog` | `molecules/StandardDialog.tsx` | 미사용 | + +--- + +## 공통화 우선순위 + +### 🔴 긴급 (높은 중복률) + +| 컴포넌트 | 현재 중복 | 예상 절감 | 설명 | +|---------|----------|----------|------| +| **DeleteConfirmDialog** | 54+ 파일 | ~810줄 | AlertDialog 기반 삭제 확인 | +| **ActionButtons** | 35+ 파일 | ~700줄 | Edit/Delete/Add 버튼 세트 | +| **TableActionCell** | 30+ 파일 | ~360줄 | 행 선택 시 액션 버튼 | +| **FormDialog** | 20+ 파일 | ~500줄 | Dialog + Form 조합 | + +#### 세부 파일 목록 (DeleteConfirmDialog) +``` +- ItemListClient.tsx +- VendorManagement/index.tsx +- SalesManagement/index.tsx +- AccountManagement/index.tsx +- BoardManagement/index.tsx +- PurchaseManagement/index.tsx +- DepositManagement/index.tsx +- WithdrawalManagement/index.tsx +- BillManagement/index.tsx +- EmployeeManagement/index.tsx +- DepartmentManagement/index.tsx +- VacationManagement/index.tsx +- RankManagement/index.tsx +- TitleManagement/index.tsx +- PermissionManagement/index.tsx +- CardManagement/index.tsx +- PopupManagement/PopupList.tsx +- ... (54개+) +``` + +#### 세부 파일 목록 (Dialog + Form 조합) +``` +- RankDialog.tsx +- TitleDialog.tsx +- PermissionDialog.tsx +- DepartmentDialog.tsx +- EmployeeDialog.tsx +- VacationRegisterDialog.tsx +- VacationRequestDialog.tsx +- VacationGrantDialog.tsx +- VacationAdjustDialog.tsx +- VacationTypeSettingsDialog.tsx +- UserInviteDialog.tsx +- CSVUploadDialog.tsx +- SalaryDetailDialog.tsx +- AttendanceInfoDialog.tsx +- ReasonInfoDialog.tsx +- FieldSettingsDialog.tsx +- ... (20개+) +``` + +--- + +### 🟡 중간 우선순위 + +| 컴포넌트 | 현재 중복 | 설명 | +|---------|----------|------| +| **TableWrapper** | 40+ 파일 | 컬럼 정의 기반 자동 생성 | +| **EmptyStateTemplate** | 12+ 파일 | 빈 상태 통일 | +| **StatCard** | 5+ 파일 | 통계 카드 (아이콘+값+라벨) | +| **DetailCard** | 20+ 파일 | 상세보기 카드 래퍼 | +| **SearchFilterBar** | 40+ 파일 | 검색 + 필터 조합 | + +--- + +### 🟢 낮음 (이미 공통화됨, 강화 필요) + +| 컴포넌트 | 상태 | 개선 필요사항 | +|---------|------|-------------| +| **LoadingSpinner** | ✅ 존재 | 테이블용/페이지용 변형 추가 | +| **SearchFilter** | ✅ 존재 | 날짜범위, 다중선택 필터 | +| **Pagination** | ✅ 존재 | 현재 잘 작동 중 | +| **IntegratedListTemplateV2** | ✅ 존재 | 잘 사용 중 | + +--- + +## 패턴별 상세 분석 + +### 1. 다이얼로그/모달 패턴 + +| 패턴 | 사용 빈도 | 파일 수 | 우선순위 | +|------|---------|-------|--------| +| 삭제 확인 AlertDialog | 매우 높음 | 54+ | 🔴 높음 | +| 정보 입력 Dialog | 높음 | 20+ | 🔴 높음 | +| 상세 조회 Modal | 높음 | 15+ | 🟡 중간 | +| CSV/파일 업로드 Dialog | 중간 | 5+ | 🟡 중간 | + +### 2. 테이블 관련 패턴 + +| 패턴 | 사용 빈도 | 파일 수 | 우선순위 | +|------|---------|-------|--------| +| 테이블 액션 버튼 | 매우 높음 | 35+ | 🔴 높음 | +| 체크박스 행 선택 | 매우 높음 | 40+ | 🔴 높음 | +| 페이지네이션 | 높음 | 39+ | ✅ 공통화됨 | +| 테이블 헤더/행 구조 | 높음 | 40+ | 🟡 중간 | + +### 3. 폼 관련 패턴 + +| 패턴 | 사용 빈도 | 파일 수 | 우선순위 | +|------|---------|-------|--------| +| 검색 폼 | 높음 | 40+ | ✅ 공통화됨 | +| 동적 폼 필드 | 중간 | 8+ | ✅ 공통화됨 | +| 폼 상태 관리 | 중간 | 15+ | 🟡 중간 | +| 폼 유효성 검사 | 중간 | 10+ | 🟡 중간 | + +### 4. 상태 표시 패턴 + +| 패턴 | 사용 빈도 | 파일 수 | 우선순위 | +|------|---------|-------|--------| +| 로딩 스피너 | 높음 | 5 | ✅ 공통화됨 | +| 빈 상태 | 높음 | 12+ | 🟡 중간 | +| 에러 메시지 | 중간 | 10+ | 🟡 중간 | +| 배지/상태 표시 | 높음 | 30+ | 🟡 중간 | + +### 5. 액션 버튼 그룹 패턴 + +| 패턴 | 사용 빈도 | 파일 수 | 우선순위 | +|------|---------|-------|--------| +| CRUD 버튼 세트 | 매우 높음 | 35+ | 🔴 높음 | +| Form 액션 버튼 | 높음 | 20+ | 🔴 높음 | +| 행 액션 버튼 | 높음 | 30+ | 🔴 높음 | + +--- + +## 추천 구현 순서 + +### Phase 1: 다이얼로그 공통화 +1. `DeleteConfirmDialog` - 삭제 확인용 (54+ 파일 영향) +2. 기존 `ConfirmDialog` 활용 또는 강화 + +### Phase 2: 액션 버튼 공통화 +3. `ActionButtonGroup` - CRUD 버튼 세트 +4. `TableActionCell` - 테이블 행 액션 버튼 + +### Phase 3: 폼 다이얼로그 공통화 +5. 기존 `FormDialog` 활용 확대 +6. 도메인별 Dialog들을 FormDialog 기반으로 리팩토링 + +### Phase 4: 기타 +7. `EmptyStateTemplate` 통일 +8. `StatCard` 통합 + +--- + +## 기대 효과 + +| 항목 | 효과 | +|-----|------| +| 코드 절감 | ~2,370줄 (전체 대비 5-7%) | +| 유지보수성 | 버튼 스타일/동작 통일, 버그 감소 | +| 개발 속도 | 새 페이지 작성 시 +30% 빠름 | +| UI 일관성 | 전체 앱에서 동일한 UX | + +--- + +## 작업 시점 권장 + +> ⚠️ **권장**: 프로젝트 기능 구현이 어느 정도 마무리된 시점에 진행 +> - 현재 새 페이지가 계속 추가되는 중 +> - 리팩토링 후 다시 중복 코드가 생길 수 있음 +> - MVP 완료 후 일괄 작업이 효율적 + +--- + +## 참고: 공통 컴포넌트 경로 + +``` +src/components/ +├── ui/ # 기본 UI 컴포넌트 (shadcn) +│ ├── dialog.tsx +│ ├── alert-dialog.tsx +│ ├── button.tsx +│ └── ... +├── molecules/ # 조합 컴포넌트 +│ └── StandardDialog.tsx # ⭐ 기존 공통 다이얼로그 (미사용) +├── templates/ # 페이지 템플릿 +│ └── IntegratedListTemplateV2.tsx +└── [domain]/ # 도메인별 컴포넌트 + └── *Dialog.tsx # 개별 다이얼로그들 (중복) +``` + +--- + +## 변경 이력 + +| 날짜 | 변경 내용 | +|-----|----------| +| 2025-12-23 | 최초 작성 - 공통화 후보 분석 | \ No newline at end of file diff --git a/claudedocs/material/[IMPL-2025-12-23] stock-status.md b/claudedocs/material/[IMPL-2025-12-23] stock-status.md new file mode 100644 index 00000000..0f160ccc --- /dev/null +++ b/claudedocs/material/[IMPL-2025-12-23] stock-status.md @@ -0,0 +1,97 @@ +# 자재관리 - 재고현황 페이지 구현 + +**경로**: `/material/stock-status` +**작업일**: 2025-12-23 + +--- + +## 📋 구현 체크리스트 + +### Phase 1: 기본 구조 설정 +- [x] 폴더 구조 생성 (`src/components/material/StockStatus/`) +- [x] 페이지 라우트 생성 (`src/app/[locale]/(protected)/material/stock-status/`) +- [x] types.ts 작성 +- [x] mockData.ts 작성 + +### Phase 2: 리스트 페이지 구현 +- [x] 통계 카드 4개 (전체 품목, 정상 재고, 재고 부족, 재고 없음) +- [x] 필터 탭 (전체, 원자재, 절곡부품, 구매부품, 부자재, 소모품) +- [x] 검색 기능 (품목코드, 품목명) +- [x] 테이블 구현 (체크박스, 품목코드, 품목명, 품목유형, 단위, 재고량, 안전재고, LOT, 상태, 위치) +- [x] 품목유형 뱃지 (구매부품, 부자재, 원자재, 소모품) +- [x] 엑셀 다운로드 버튼 +- [x] 하단 요약 (총 XX종 / 재고부족 X종) + +### Phase 3: 상세 페이지 구현 +- [x] 상세 페이지 라우트 (`/material/stock-status/[id]`) +- [x] 기본 정보 섹션 (품목코드, 품목명, 품목유형, 카테고리, 규격, 단위) +- [x] 재고 현황 섹션 (현재 재고량, 안전 재고, 재고 위치, LOT 개수, 최근 입고일, 재고 상태) +- [x] LOT별 상세 재고 테이블 (FIFO, LOT번호, 입고일, 경과일, 공급업체, 발주번호, 수량, 위치, 상태) +- [x] FIFO 권장 메시지 표시 +- [x] 목록 버튼 + +### Phase 4: 마무리 +- [x] Mock 데이터 작성 +- [x] 빌드 테스트 +- [x] 테스트 URL 문서 업데이트 + +--- + +## 📊 스크린샷 분석 + +### 리스트 페이지 구조 + +**통계 카드:** +| 카드 | 값 | 아이콘 | +|------|-----|--------| +| 전체 품목 | 134종 | 기본 | +| 정상 재고 | 133종 | ✓ 체크 | +| 재고 부족 | 1종 | ⏱ 시계 | +| 재고 없음 | 0종 | 기본 | + +**필터 탭:** +- 전체 134, 원자재 4, 절곡부품 41, 구매부품 80, 부자재 7, 소모품 2 + +**테이블 컬럼:** +| 컬럼 | 설명 | +|------|------| +| 체크박스 | row 선택 | +| 품목코드 | SQP-50-40, ANG-75-40 등 | +| 품목명 | 각파이프 50×50 L:4000 등 | +| 품목유형 | 구매부품/부자재/원자재/소모품 (뱃지) | +| 단위 | EA, M, m² | +| 재고량 | 숫자 | +| 안전재고 | 숫자 | +| LOT | X개 + 경과일 (예: 2개 8일 경과) | +| 상태 | 정상 | +| 위치 | I-05, A-04 등 | + +### 상세 페이지 구조 + +**헤더:** 재고 상세 [품목코드] [상태뱃지] + 목록 버튼 + +**기본 정보:** +- 품목코드, 품목명, 품목유형 +- 카테고리, 규격, 단위 + +**재고 현황:** +- 현재 재고량 (큰 숫자, 예: 120 EA) +- 안전 재고 (예: 30 EA) +- 재고 위치 (예: I-05) +- LOT 개수 (예: 4개) +- 최근 입고일 (예: 2025-12-13) +- 재고 상태 (정상 뱃지) + +**LOT별 상세 재고:** +- 토글: FIFO 순서 / 오래된 LOT부터 사용 권장 +- 테이블: FIFO(번호), LOT번호, 입고일, 경과일, 공급업체, 발주번호, 수량, 위치, 상태 +- 합계 행 +- FIFO 권장 메시지: ⓘ FIFO 권장: LOT XXXXXX-XX가 XX일 경과되었습니다. 우선 사용을 권장합니다. + +--- + +## 🔧 기술 스택 +- IntegratedListTemplateV2 (리스트) +- PageLayout (상세) +- Radix UI (뱃지, 테이블) +- Mock 데이터 (API 연동 TODO) \ No newline at end of file diff --git a/claudedocs/production/[IMPL-2025-12-22] production-dashboard-checklist.md b/claudedocs/production/[IMPL-2025-12-22] production-dashboard-checklist.md new file mode 100644 index 00000000..74ed4c66 --- /dev/null +++ b/claudedocs/production/[IMPL-2025-12-22] production-dashboard-checklist.md @@ -0,0 +1,391 @@ +# [IMPL-2025-12-22] 생산 현황판 구현 계획서 + +## 개요 +생산관리 하위 **생산 현황판** 및 **작업자 화면** 기능 구현 +- 생산 현황판: `/production/dashboard` +- 작업자 화면: `/production/worker-screen` (별도 메뉴) + +--- + +## 1. 페이지 구조 + +### 1.1 생산 현황판 (메인) +**경로**: `/ko/production/dashboard` + +| 섹션 | 설명 | +|------|------| +| 상단 탭 | 전체, 스크린공장, 슬랫공장, 절곡공장 | +| 통계 카드 | 전체작업, 작업대기, 작업중, 작업완료, 긴급, 지연 (6개) | +| 3컬럼 레이아웃 | 긴급작업 / 지연작업 / 작업자별 현황 | +| 우측 상단 버튼 | 작업자 화면, 작업지시 목록 | + +**긴급작업/지연작업 카드 클릭** +- → 작업지시 관리 상세 화면 이동 (TODO: 페이지 생성 후 연결) + +**작업지시 목록 버튼** +- → 작업지시 관리 리스트 이동 (TODO: 페이지 생성 후 연결) + +### 1.2 작업자 화면 (별도 페이지) +**경로**: `/ko/production/worker-screen` (생산 현황판 하위가 아닌 별도 메뉴) + +| 섹션 | 설명 | +|------|------| +| 상단 통계 | 할당, 작업중, 완료, 긴급 (4개) | +| 내 작업 목록 | 카드 리스트 형태 (우선순위순 정렬 옵션) | +| 각 카드 | 제품명, EA수량, 납기, 순위 배지, 상태 배지 | +| 카드 버튼 | 전량완료, 공정상세, 자재투입, 작업일지, 이슈보고 | + +**참고**: 생산 현황판 복귀 버튼 불필요 (사이드바 메뉴로 이동) + +--- + +## 2. 기능 상세 + +### 2.1 전량완료 버튼 클릭 시 + +#### Step 1: 자재 투입 확인 팝업 +``` +제목: 자재 투입이 필요합니다! +내용: +- 작업지시: KD-WO-251216-01 +- 공정: 스크린 +- "자재 투입 없이 완료 처리하시겠습니까? (LOT 추적이 불가능해집니다)" +버튼: 취소 / 확인 +``` +- **디자인 팝업 사용** (AlertDialog 컴포넌트) + +#### Step 2-A: 확인 클릭 시 +``` +제목: 작업이 완료되었습니다. +내용: +- 제품검사(LOT: KD-SA-251222-01) +- 제품검사(FQC)가 자동 생성되었습니다. +- "[품질관리 > 제품검사]에서 검사를 진행하세요." +버튼: 확인 +``` +- **디자인 팝업 사용** (AlertDialog 컴포넌트) + +#### Step 3: 동적 뱃지 표시 +``` +검은색 라운드 배지 (상단 중앙) +"✓ KD-WO-251216-01 완료! (3EA)" +``` +- 3초 후 자동 사라짐 (애니메이션) +- 작업 목록에서 해당 지시사항 제거 + +#### Step 2-B: 취소 클릭 시 +- 자재투입 모달 표시 (팝업 닫힘) + +### 2.2 공정상세 버튼 클릭 시 + +**탭 활성화 또는 섹션 확장** +| 항목 | 설명 | +|------|------| +| 자재 투입 필요 | 섹션 + "자재 투입하기" 버튼 | +| 공정 단계 (5단계) | 0/5 완료 표시 | +| 각 단계 | 절곡판/코일 절단, V컷팅, 절곡, 중간검사, 포장 | +| 단계 상세 | #1, #2 등 세부 항목 (위치, 규격, LOT 정보) | + +### 2.3 자재투입 버튼 클릭 시 + +**자재투입 모달** +``` +제목: 투입자재 등록 +FIFO 순위: 1 최우선, 2 차선, 3+ 대기 +테이블: +- 자재코드 | 자재명 | 단위 | 현재고 | 선택 +- "이 공정에 배정된 자재가 없습니다" (데이터 없을 때) +버튼: 취소 / 투입 등록 +``` +- Dialog 컴포넌트 사용 + +### 2.4 작업일지 버튼 클릭 시 + +**작업일지 모달** (기안함 스타일 참고) +``` +제목: 작업일지 - 절곡 생산부서 (KD-WO-FLD-251212-01) +우측: 인쇄 버튼 +내용: 작업일지 양식 (테이블 형태) +``` +- Dialog 컴포넌트 사용 +- 인쇄 기능: `window.print()` 또는 react-to-print + +### 2.5 이슈 보고 버튼 클릭 시 + +**이슈 보고 모달** +``` +제목: 이슈 보고 +내용: +- 작업: KD-WO-FLD-251212-01 +- 현대건설(주) +- 이슈 유형: 불량품 발생, 재고 없음, 일정 지연, 설비 문제, 기타 (5개 버튼) +- 상세 내용: textarea +버튼: 취소 / 보고 +``` + +#### 벨리데이션 +- 이슈 유형 미선택 시: **디자인 팝업** "이슈 유형을 선택해주세요." +- ❌ `alert()` 사용 금지 + +#### 보고 완료 시 +- **디자인 팝업** "이슈가 보고되었습니다. 작업: KD-WO-FLD-251212-01, 유형: [선택값]" +- 확인 후 이슈 보고 화면으로 복귀 + +--- + +## 3. 네비게이션 연결 + +### 3.1 긴급작업/지연작업 카드 클릭 +- → 작업지시 관리 상세 화면 (`/production/work-orders/[id]`) +- **TODO**: 작업지시 관리 페이지 생성 후 연결 + +### 3.2 작업지시 목록 버튼 +- → 작업지시 관리 리스트 (`/production/work-orders`) +- **TODO**: 작업지시 관리 페이지 생성 후 연결 + +### 3.3 작업자 화면 버튼 (생산 현황판) +- → 작업자 화면 (`/production/worker-screen`) +- 별도 메뉴로 이동 (사이드바에서도 접근 가능) + +--- + +## 4. 디자인 팝업 변경 목록 + +| 기존 | 변경 | 컴포넌트 | +|------|------|----------| +| `alert('자재 투입이 필요합니다')` | AlertDialog | confirm | +| `alert('작업이 완료되었습니다')` | AlertDialog | info | +| `alert('이슈 유형을 선택해주세요')` | AlertDialog | validation | +| `alert('이슈가 보고되었습니다')` | AlertDialog | success | + +--- + +## 5. 파일 구조 + +``` +src/app/[locale]/(protected)/production/ +├── dashboard/ +│ └── page.tsx # 생산 현황판 메인 +├── worker-screen/ +│ └── page.tsx # 작업자 화면 (별도 메뉴) + +src/components/production/ +├── ProductionDashboard/ +│ ├── index.tsx # 메인 컴포넌트 +│ ├── types.ts # 타입 정의 +│ └── mockData.ts # Mock 데이터 +│ +├── WorkerScreen/ +│ ├── index.tsx # 작업자 화면 메인 +│ ├── types.ts # 타입 정의 +│ ├── WorkCard.tsx # 작업 카드 컴포넌트 +│ ├── ProcessDetailSection.tsx # 공정상세 섹션 +│ ├── MaterialInputModal.tsx # 자재투입 모달 +│ ├── WorkLogModal.tsx # 작업일지 모달 +│ ├── IssueReportModal.tsx # 이슈보고 모달 +│ ├── CompletionConfirmDialog.tsx # 전량완료 확인 다이얼로그 +│ └── CompletionToast.tsx # 완료 토스트/뱃지 +``` + +--- + +## 6. 구현 체크리스트 + +### Phase 1: 기본 구조 (생산 현황판 메인) ✅ +- [x] 1.1 `/production/dashboard` 라우트 생성 +- [x] 1.2 ProductionDashboard 컴포넌트 생성 +- [x] 1.3 상단 탭 구현 (전체/스크린공장/슬랫공장/절곡공장) +- [x] 1.4 통계 카드 6개 구현 +- [x] 1.5 3컬럼 레이아웃 (긴급작업/지연작업/작업자별현황) +- [x] 1.6 긴급작업 리스트 컴포넌트 +- [x] 1.7 지연작업 리스트 컴포넌트 +- [x] 1.8 작업자별 현황 컴포넌트 +- [x] 1.9 우측 상단 버튼 (작업자 화면/작업지시 목록) + +### Phase 2: 작업자 화면 (별도 페이지) ✅ +- [x] 2.1 `/production/worker-screen` 라우트 생성 +- [x] 2.2 WorkerScreen 컴포넌트 생성 +- [x] 2.3 상단 통계 카드 4개 (할당/작업중/완료/긴급) +- [x] 2.4 내 작업 목록 카드 리스트 (2열 그리드) +- [x] 2.5 WorkCard 컴포넌트 (제품명/EA/납기/배지/버튼) + +### Phase 3: 작업자 화면 - 버튼 기능 ✅ +- [x] 3.1 전량완료 버튼 → CompletionConfirmDialog +- [x] 3.2 자재 미투입 확인 다이얼로그 (AlertDialog) +- [x] 3.3 완료 성공 다이얼로그 (AlertDialog) +- [x] 3.4 완료 뱃지 애니메이션 (CompletionToast) +- [x] 3.5 작업 목록에서 완료 항목 제거 + +### Phase 4: 공정상세 기능 ✅ +- [x] 4.1 ProcessDetailSection 컴포넌트 +- [x] 4.2 공정 단계 표시 (5단계) +- [x] 4.3 각 단계 세부 항목 (#1, #2...) +- [x] 4.4 자재 투입 필요 섹션 + +### Phase 5: 자재투입 기능 ✅ +- [x] 5.1 MaterialInputModal 컴포넌트 +- [x] 5.2 FIFO 순위 표시 +- [x] 5.3 자재 테이블 (BOM 기준) +- [x] 5.4 투입 등록 로직 + +### Phase 6: 작업일지 기능 ✅ +- [x] 6.1 WorkLogModal 컴포넌트 +- [x] 6.2 작업일지 양식 (기안함 참고) +- [x] 6.3 인쇄 기능 + +### Phase 7: 이슈보고 기능 ✅ +- [x] 7.1 IssueReportModal 컴포넌트 +- [x] 7.2 이슈 유형 선택 (5개 버튼) +- [x] 7.3 상세 내용 textarea +- [x] 7.4 벨리데이션 다이얼로그 (AlertDialog) +- [x] 7.5 보고 완료 다이얼로그 (AlertDialog) + +### Phase 8: 네비게이션 연결 (TODO 노티) ✅ +- [x] 8.1 긴급/지연 작업 클릭 → console.log + TODO 주석 +- [x] 8.2 작업지시 목록 버튼 → console.log + TODO 주석 +- [ ] 8.3 추후 작업지시 관리 페이지 생성 시 연결 (대기) + +--- + +## 7. 사용 컴포넌트/라이브러리 + +| 용도 | 컴포넌트 | +|------|----------| +| 확인/취소 팝업 | `@/components/ui/alert-dialog` | +| 정보 모달 | `@/components/ui/dialog` | +| 버튼 | `@/components/ui/button` | +| 배지 | `@/components/ui/badge` | +| 카드 | `@/components/ui/card` | +| 탭 | `@/components/ui/tabs` | +| 테이블 | `@/components/ui/table` | +| 체크박스 | `@/components/ui/checkbox` | +| Textarea | `@/components/ui/textarea` | + +--- + +## 8. Mock 데이터 구조 + +### 작업 지시 (WorkOrder) +```typescript +interface WorkOrder { + id: string; + orderNo: string; // KD-WO-251216-01 + productName: string; // 스크린 서터 (표준형) - 추가 + process: string; // 스크린, 슬랫, 절곡 + client: string; // 삼성물산(주) + projectName: string; // 강남 타워 신축현장 + assignees: string[]; // 담당자 배열 + quantity: number; // EA 수량 + dueDate: string; // 납기 + priority: number; // 순위 (1~5) + status: 'waiting' | 'inProgress' | 'completed'; + isUrgent: boolean; + isDelayed: boolean; + instruction?: string; // 지시사항 + createdAt: string; +} +``` + +### 작업자 현황 (WorkerStatus) +```typescript +interface WorkerStatus { + id: string; + name: string; + inProgress: number; // 작업중 건수 + completed: number; // 완료 건수 + assigned: number; // 배정 건수 +} +``` + +### 공정 단계 (ProcessStep) +```typescript +interface ProcessStep { + id: string; + stepNo: number; // 1~5 + name: string; // 절곡판/코일 절단, V컷팅... + isInspection?: boolean; // 검사 단계 여부 + completed: number; + total: number; + items: ProcessStepItem[]; +} + +interface ProcessStepItem { + id: string; + itemNo: string; // #1, #2 + location: string; // 1층 1호-A + isPriority: boolean; // 선행 생산 + spec: string; // W2500 × H3000 + material: string; // 자재: 절곡판 + lot: string; // LOT-절곡-2025-001 +} +``` + +--- + +## 9. 확정 사항 + +### 확인 완료 +1. ✅ 모든 alert() → AlertDialog 컴포넌트 사용 +2. ✅ 작업자 화면은 별도 메뉴 (`/production/worker-screen`) +3. ✅ 생산 현황판 복귀 버튼 불필요 (사이드바 메뉴로 이동) +4. ✅ 긴급/지연 작업 클릭 → 작업지시 상세로 이동 (페이지 생성 후 연결) +5. ✅ 작업지시 목록 버튼 → 작업지시 리스트로 이동 (페이지 생성 후 연결) +6. ✅ 작업지시 관리 페이지 → 생산 현황판 완료 후 별도 진행 (스샷/설명 별도 제공 예정) +7. ✅ 공정상세 버튼 → 카드 내 토글 확장 방식 (스크린샷 기준) +8. ✅ 완료 뱃지 → 상단 중앙 검은색 뱃지, 3초 후 fade out + +--- + +## 10. 다음 단계 + +사용자 확정 후: +1. Phase 1부터 순차적으로 구현 +2. 각 Phase 완료 시 체크리스트 업데이트 +3. 테스트 URL 문서 업데이트 + +--- + +**작성일**: 2025-12-22 +**작성자**: Claude Code +**상태**: ✅ 구현 완료 + +--- + +## 11. 구현 결과 + +### 생성된 파일 +``` +src/app/[locale]/(protected)/production/ +├── dashboard/page.tsx ✅ 생산 현황판 페이지 +└── worker-screen/page.tsx ✅ 작업자 화면 페이지 + +src/components/production/ +├── ProductionDashboard/ +│ ├── index.tsx ✅ 메인 컴포넌트 +│ ├── types.ts ✅ 타입 정의 +│ └── mockData.ts ✅ Mock 데이터 +│ +└── WorkerScreen/ + ├── index.tsx ✅ 작업자 화면 메인 + ├── types.ts ✅ 타입 정의 + ├── WorkCard.tsx ✅ 작업 카드 컴포넌트 + ├── ProcessDetailSection.tsx ✅ 공정상세 섹션 + ├── MaterialInputModal.tsx ✅ 자재투입 모달 + ├── WorkLogModal.tsx ✅ 작업일지 모달 + ├── IssueReportModal.tsx ✅ 이슈보고 모달 + ├── CompletionConfirmDialog.tsx ✅ 전량완료 확인 다이얼로그 + └── CompletionToast.tsx ✅ 완료 토스트 + +src/components/ui/ +└── collapsible.tsx ✅ Collapsible 컴포넌트 추가 +``` + +### 테스트 URL +- 생산 현황판: http://localhost:3000/ko/production/dashboard +- 작업자 화면: http://localhost:3000/ko/production/worker-screen + +### 남은 작업 +- [ ] **작업일지 모달 개선** - 기안함 상세 화면 스타일로 변경 + - 참고: `src/components/approval/DocumentDetail/` 컴포넌트 활용 + - 수정: `src/components/production/WorkerScreen/WorkLogModal.tsx` +- [ ] 작업지시 관리 페이지 생성 후 네비게이션 연결 \ No newline at end of file diff --git a/claudedocs/production/[NEXT-2025-12-22] production-session-context.md b/claudedocs/production/[NEXT-2025-12-22] production-session-context.md new file mode 100644 index 00000000..1ebfd298 --- /dev/null +++ b/claudedocs/production/[NEXT-2025-12-22] production-session-context.md @@ -0,0 +1,97 @@ +# [NEXT-2025-12-22] 생산 현황판 세션 컨텍스트 + +## 세션 요약 (2025-12-22) + +### 완료된 작업 ✅ +- [x] Phase 1: 생산 현황판 메인 페이지 구현 +- [x] Phase 2: 작업자 화면 구현 (별도 페이지) +- [x] Phase 3: 전량완료 기능 (확인/완료 팝업, 뱃지) +- [x] Phase 4: 공정상세 섹션 구현 (카드 내 토글) +- [x] Phase 5: 자재투입 모달 구현 +- [x] Phase 6: 작업일지 모달 구현 (⚠️ 개선 필요) +- [x] Phase 7: 이슈보고 모달 구현 +- [x] Phase 8: 네비게이션 연결 (TODO 주석 처리) + +### 다음 세션 TODO ⚠️ + +#### 1. 작업일지 모달 개선 (우선) +**현재**: 단순 테이블 형태로 구현됨 +**요청**: 기안함 상세 화면 스타일 (완성된 문서 형태)로 개선 + +**참고 컴포넌트**: +``` +src/components/approval/DocumentDetail/ +├── ProposalDocument.tsx ← 기품의서 양식 +├── ExpenseReportDocument.tsx ← 지출보고서 양식 +└── ExpenseEstimateDocument.tsx ← 지출품의서 양식 +``` + +**수정 대상**: +``` +src/components/production/WorkerScreen/WorkLogModal.tsx +``` + +**작업 내용**: +- DocumentDetail 컴포넌트 스타일 참고 +- 완성된 문서 형태로 작업일지 양식 재구현 +- 인쇄 친화적 레이아웃 적용 + +#### 2. 작업지시 관리 페이지 (대기) +- 생산 현황판에서 네비게이션 연결 대기 +- 스크린샷/설명 별도 제공 예정 + +--- + +### 생성된 파일 목록 + +``` +src/app/[locale]/(protected)/production/ +├── dashboard/page.tsx ✅ +└── worker-screen/page.tsx ✅ + +src/components/production/ +├── ProductionDashboard/ +│ ├── index.tsx ✅ +│ ├── types.ts ✅ +│ └── mockData.ts ✅ +│ +└── WorkerScreen/ + ├── index.tsx ✅ + ├── types.ts ✅ + ├── WorkCard.tsx ✅ + ├── ProcessDetailSection.tsx ✅ + ├── MaterialInputModal.tsx ✅ + ├── WorkLogModal.tsx ⚠️ 개선 필요 + ├── IssueReportModal.tsx ✅ + ├── CompletionConfirmDialog.tsx ✅ + └── CompletionToast.tsx ✅ + +src/components/ui/ +└── collapsible.tsx ✅ (신규 추가, @radix-ui/react-collapsible 설치됨) +``` + +--- + +### 테스트 URL +- 생산 현황판: http://localhost:3000/ko/production/dashboard +- 작업자 화면: http://localhost:3000/ko/production/worker-screen + +--- + +### 참고 사항 +1. **작업자 화면 = 별도 페이지** (생산 현황판 하위 아님) + - 사이드바 메뉴로 접근 + - "돌아가기" 버튼 불필요 + +2. **모든 alert() → AlertDialog 변환 완료** + - 전량완료 확인/성공 + - 이슈보고 벨리데이션/성공 + +3. **공정상세 = 카드 내 토글 확장** + - Collapsible 컴포넌트 사용 + - 5단계 공정 표시 + +--- + +**작성일**: 2025-12-22 +**상태**: 🔄 작업일지 모달 개선 대기 \ No newline at end of file diff --git a/claudedocs/quality/[IMPL-2025-12-23] inspection-management-checklist.md b/claudedocs/quality/[IMPL-2025-12-23] inspection-management-checklist.md new file mode 100644 index 00000000..a9566244 --- /dev/null +++ b/claudedocs/quality/[IMPL-2025-12-23] inspection-management-checklist.md @@ -0,0 +1,159 @@ +# 검사관리 구현 체크리스트 + +> **URL**: `/quality/inspections` +> **생성일**: 2025-12-23 +> **상태**: ✅ 완료 + +--- + +## 스크린샷 분석 요약 + +### 1. 검사 목록 (리스트) +- **상단 카드**: 금일 대기 건수, 진행 중 검사, 금일 완료 건수, 불량 발생률(%) +- **검색**: LOT번호/품목명/공정명 검색 + 날짜 범위 선택 +- **탭 필터**: 전체, 대기, 진행중, 완료 +- **테이블 컬럼**: No, 검사유형(IQC/PQC/FQC), 요청일, 품목명, LOT NO, 상태, 담당자 +- **버튼**: + 검사 등록 + +### 2. 검사 등록 +- **검사 개요**: LOT NO(자동), 품목명(자동), 공정명(자동), 수량, 작업자, 특이사항 +- **검사 기준 및 도해**: 템플릿 이미지 표시 영역 +- **검사 데이터 입력**: + - 가공상태: 기준(Spec) + 양호/불량 라디오 + - 높이(H): 기준(Spec) + 측정값 입력(mm) + - 길이(L): 기준(Spec) + 측정값 입력(mm) + - 각 항목 우측에 "판정: 적합" 표시 +- **버튼**: 취소, 검사완료 + +### 3. 검사 상세 +- **헤더**: 검사번호 + 합격/불합격 배지, 성적서 버튼, 목록/수정 버튼 +- **검사 정보**: 검사번호, 검사유형, 검사일자, 판정결과, 품목명, LOT NO, 공정명, 검사자 +- **검사 결과 데이터 테이블**: 항목명, 기준(Spec), 측정값/결과, 판정(적합/부적합) +- **종합 의견**: 텍스트 영역 +- **첨부 파일**: 파일 목록 + +### 4. 검사 수정 +- **검사 개요 (수정 불가)**: LOT NO, 품목명, 공정명, 수량 - 모두 disabled +- **수정 사유 (필수 ★)**: textarea +- **검사 데이터 수정**: 등록과 동일한 입력 폼 +- **버튼**: 취소, 수정 완료 + +--- + +## Phase 1: 폴더 구조 및 기본 설정 + +- [x] 1.1 폴더 구조 생성 + - `src/app/[locale]/(protected)/quality/inspections/` + - `src/components/quality/InspectionManagement/` +- [x] 1.2 타입 정의 (`types.ts`) +- [x] 1.3 mockData 생성 (`mockData.ts`) + +## Phase 2: 검사 목록 (리스트) 페이지 + +- [x] 2.1 메인 페이지 컴포넌트 (`page.tsx`) +- [x] 2.2 클라이언트 컴포넌트 (`InspectionList.tsx`) +- [x] 2.3 상단 통계 카드 (4개) + - 금일 대기 건수 + - 진행 중 검사 + - 금일 완료 건수 + - 불량 발생률 +- [x] 2.4 검색/필터 영역 + - LOT번호/품목명/공정명 검색 + - 날짜 범위 선택 +- [x] 2.5 탭 필터 (전체/대기/진행중/완료) +- [x] 2.6 테이블 구현 + - 체크박스, No, 검사유형, 요청일, 품목명, LOT NO, 상태, 담당자 +- [x] 2.7 "+ 검사 등록" 버튼 → 등록 페이지 이동 + +## Phase 3: 검사 등록 페이지 + +- [x] 3.1 등록 페이지 라우트 (`new/page.tsx`) +- [x] 3.2 검사 개요 섹션 + - LOT NO, 품목명, 공정명 (자동/읽기전용) + - 수량, 작업자, 특이사항 (입력) +- [x] 3.3 검사 기준 및 도해 섹션 + - 이미지 표시 영역 +- [x] 3.4 검사 데이터 입력 섹션 + - 동적 검사항목 폼 + - 가공상태: 양호/불량 라디오 + - 측정항목: 기준(Spec) + 측정값 입력 + - 자동 판정 로직 (기준값 범위 체크) +- [x] 3.5 버튼: 취소, 검사완료 +- [x] 3.6 폼 유효성 검사 및 제출 로직 + +## Phase 4: 검사 상세 페이지 + +- [x] 4.1 상세 페이지 라우트 (`[id]/page.tsx`) +- [x] 4.2 헤더 영역 + - 검사번호 + 합격/불합격 배지 + - 성적서 버튼 + - 목록/수정 버튼 +- [x] 4.3 검사 정보 섹션 (읽기 전용) +- [x] 4.4 검사 결과 데이터 테이블 +- [x] 4.5 종합 의견 표시 +- [x] 4.6 첨부 파일 목록 + +## Phase 5: 검사 수정 페이지 + +- [x] 5.1 수정 모드 구현 (`?mode=edit` 쿼리 파라미터) +- [x] 5.2 검사 개요 (수정 불가 - disabled) +- [x] 5.3 수정 사유 입력 (필수) +- [x] 5.4 검사 데이터 수정 폼 (기존 값 로드) +- [x] 5.5 버튼: 취소, 수정 완료 +- [x] 5.6 수정 로직 및 유효성 검사 + +## Phase 6: 공통 기능 + +- [x] 6.1 상태 배지 컴포넌트 (대기/진행중/완료) +- [x] 6.2 검사유형 배지 (IQC/PQC/FQC) +- [x] 6.3 판정 로직 (기준값 범위 체크 → 적합/부적합) +- [x] 6.4 측정값 자동 판정 표시 +- [x] 6.5 성적서 출력 기능 (버튼 및 로직 준비) + +## Phase 7: 통합 및 테스트 + +- [x] 7.1 페이지 간 네비게이션 연결 +- [x] 7.2 빌드 테스트 (타입체크 통과) +- [x] 7.3 테스트 URL 문서 업데이트 + +--- + +## 생성된 파일 목록 + +### 페이지 라우트 +| 파일 | 경로 | +|------|------| +| 검사 목록 | `src/app/[locale]/(protected)/quality/inspections/page.tsx` | +| 검사 등록 | `src/app/[locale]/(protected)/quality/inspections/new/page.tsx` | +| 검사 상세/수정 | `src/app/[locale]/(protected)/quality/inspections/[id]/page.tsx` | + +### 컴포넌트 +| 파일 | 설명 | +|------|------| +| `types.ts` | 타입 정의 (InspectionType, InspectionItem 등) | +| `mockData.ts` | Mock 데이터 및 judgeMeasurement 함수 | +| `InspectionList.tsx` | 목록 페이지 (IntegratedListTemplateV2 사용) | +| `InspectionCreate.tsx` | 등록 페이지 | +| `InspectionDetail.tsx` | 상세/수정 페이지 (mode 쿼리 파라미터로 전환) | +| `index.ts` | 컴포넌트 export | + +--- + +## 테스트 URL + +| 페이지 | URL | +|--------|-----| +| 검사 목록 | `http://localhost:3000/ko/quality/inspections` | +| 검사 등록 | `http://localhost:3000/ko/quality/inspections/new` | +| 검사 상세 | `http://localhost:3000/ko/quality/inspections/INS-001` | +| 검사 수정 | `http://localhost:3000/ko/quality/inspections/INS-001?mode=edit` | + +--- + +## 진행 로그 + +| 날짜 | 작업 내용 | 상태 | +|------|----------|------| +| 2025-12-23 | 체크리스트 생성, 스크린샷 분석 | ✅ | +| 2025-12-23 | Phase 1-7 전체 구현 완료 | ✅ | +| 2025-12-23 | 타입체크 통과, 문서 업데이트 | ✅ | diff --git a/claudedocs/sales/[IMPL-2025-12-22] order-management-sales.md b/claudedocs/sales/[IMPL-2025-12-22] order-management-sales.md new file mode 100644 index 00000000..66cb6682 --- /dev/null +++ b/claudedocs/sales/[IMPL-2025-12-22] order-management-sales.md @@ -0,0 +1,624 @@ +# 수주관리 (Order Management Sales) 구현 계획서 + +## 기본 정보 + +| 항목 | 내용 | +|------|------| +| **경로** | `/sales/order-management-sales` | +| **상위 메뉴** | 판매관리 | +| **작성일** | 2025-12-22 | +| **상태** | Phase 2 완료 | + +--- + +## 1. 페이지 구조 + +``` +/sales/order-management-sales +├── page.tsx (리스트) +├── new/page.tsx (등록) +├── [id]/page.tsx (상세) +├── [id]/edit/page.tsx (수정) +├── [id]/production-order/page.tsx (생산지시 생성) ← TODO +└── production-orders/ ← 생산지시 조회 (하위 경로) + ├── page.tsx (생산지시 목록) + └── [id]/page.tsx (생산지시 상세) +``` + +--- + +## 2. 리스트 화면 + +### 2.1 상단 통계 카드 (4개) +| 카드 | 아이콘 | 값 형식 | +|------|--------|---------| +| 이번 달 수주 | $ | 금액 (예: 724,250,000원) | +| 분할 대기 | ↔ | 건수 (예: 2건) | +| 생산지시 대기 | 📋 | 건수 (예: 0건) | +| 출하 대기 | 🚚 | 건수 (예: 14건) | + +### 2.2 검색/필터 +- **검색창**: 로트번호, 견적번호, 발주처, 현장명 검색... +- **필터 탭**: 전체, 수주등록, 수주확정, 생산지시완료, 미수 + +### 2.3 테이블 컬럼 +| 컬럼 | 설명 | +|------|------| +| 체크박스 | row 선택 | +| 번호 | 순번 (1부터) | +| 로트번호 | KD-TS-XXXXXX-XX | +| 견적번호 | KD-PR-XXXXXX-XX | +| 발주처 | 거래처명 | +| 현장명 | 프로젝트/현장명 | +| 상태 | 수주확정, 생산중, 출하완료 등 배지 | +| 출고예정일 | YYYY-MM-DD | +| 배송방식 | 직접배차, 상차 등 | + +### 2.4 버튼 +- 우측 상단: `+ 수주 등록` 버튼 + +--- + +## 3. 등록 화면 + +### 3.1 견적 불러오기 섹션 +- 안내 문구: "확정된 견적을 선택하면 정보가 자동으로 채워집니다" +- `견적 선택` 버튼 +- 선택된 견적 표시: 견적번호 + 등급 + 발주처/현장명/금액 + `해제` 버튼 + +### 3.2 기본 정보 +| 필드 | 타입 | 필수 | +|------|------|------| +| 발주처 | Select (드롭다운) | * | +| 현장명 | Text | * | +| 담당자 | Text | | +| 연락처 | Phone | | + +### 3.3 수주/배송 정보 +| 필드 | 타입 | 필수 | +|------|------|------| +| 출고예정일 | DatePicker + 미정 체크박스 | | +| 납품요청일 | DatePicker + 미정 체크박스 | * | +| 배송방식 | Select | | +| 운임비용 | Select | | +| 수신(반장/업체) | Text | * | +| 수신처 연락처 | Phone | * | + +### 3.4 수신처 주소 +- 우편번호 + `우편번호 찾기` 버튼 +- 기본 주소 (자동 입력) +- 상세 주소 입력 + +### 3.5 비고 +- 특이사항 텍스트 영역 + +### 3.6 품목 내역 +| 컬럼 | 설명 | +|------|------| +| 순번 | 1, 2, 3... | +| 품목코드 | PRD-X | +| 품명 | 제품명 | +| 종 | B1, B2 등 | +| 부호 | C-01, C-02 등 | +| 규격 | 4000×3000 등 | +| 수량 | 숫자 | +| 단위 | EA | +| 단가 | 금액 | +| 금액 | 단가 × 수량 | + +- `+ 품목 추가` 버튼 +- 하단 합계: 소계, 할인율(%), 총금액 + +### 3.7 버튼 +- `취소` / `저장` + +--- + +## 4. 팝업 + +### 4.1 견적 선택 팝업 +``` +┌─────────────────────────────────────────┐ +│ 견적 선택 ✕ │ +├─────────────────────────────────────────┤ +│ 🔍 견적번호, 거래처, 현장명 검색... │ +├─────────────────────────────────────────┤ +│ 전환 가능한 견적 X건 (최종확정 상태) │ +│ │ +│ KD-PR-XXXXXX-XX A (우량) │ +│ 발주처명 │ +│ [현장명] 현장 이름 금액원 │ +│ X개 품목 │ +│ ─────────────────────────────────────── │ +│ KD-PR-XXXXXX-XX B (관리) │ +│ ... │ +└─────────────────────────────────────────┘ +``` + +### 4.2 품목 추가 팝업 +| 필드 | 타입 | 필수 | 설명 | +|------|------|------|------| +| 층 | Text | * | 몇 층 (예: 4층) | +| 도면부호 | Text | * | 예: FSS1 | +| 품목명 | Text | | 예: 국민방화스크린세터 | +| **오픈사이즈 (고객 제공 치수)** | | | | +| 가로 (mm) | Number | * | 예: 7260 | +| 세로 (mm) | Number | * | 예: 2600 | +| 가이드레일 타입 | Select | | 예: 백면형 (120-70) | +| 마감 | Select | | 예: SUS마감 | +| 단가 (원) | Number | | 예: 8000000 | + +- `취소` / `추가` 버튼 + +### 4.3 수주 취소 팝업 +``` +┌─────────────────────────────────────────┐ +│ ⊗ 수주 취소 │ +├─────────────────────────────────────────┤ +│ ┌─────────────────────────────────────┐ │ +│ │ 수주번호 KD-TS-251217-09 │ │ +│ │ 발주처 태영건설(주) │ │ +│ │ 현장명 데시앙 동탄 파크뷰 │ │ +│ │ 현재 상태 [재작업중] │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ 취소 사유 * │ +│ [취소 사유를 선택하세요 ▼] │ +│ │ +│ 상세 사유 │ +│ ┌─────────────────────────────────────┐ │ +│ │ 취소 사유에 대한 상세 내용을 │ │ +│ │ 입력하세요 │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────┐ │ +│ │ 취소 시 유의사항 │ │ +│ │ • 취소된 수주는 목록에서 '취소' │ │ +│ │ 상태로 표시됩니다 │ │ +│ │ • 취소 후에는 수정이 불가능합니다 │ │ +│ │ • 관련된 생산지시가 있는 경우 먼저 │ │ +│ │ 생산지시를 취소해야 합니다 │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ [닫기] [⊗ 취소 확정] │ +└─────────────────────────────────────────┘ +``` + +| 필드 | 타입 | 필수 | 설명 | +|------|------|------|------| +| 수주번호 | Text (읽기전용) | | 취소할 수주번호 | +| 발주처 | Text (읽기전용) | | 발주처명 | +| 현장명 | Text (읽기전용) | | 현장명 | +| 현재 상태 | Badge (읽기전용) | | 현재 수주 상태 | +| 취소 사유 | Select | * | 드롭다운 선택 | +| 상세 사유 | Textarea | | 상세 내용 입력 | + +**버튼**: `닫기` / `⊗ 취소 확정` + +**취소 시 유의사항**: +- 취소된 수주는 목록에서 '취소' 상태로 표시됩니다 +- 취소 후에는 수정이 불가능합니다 +- 관련된 생산지시가 있는 경우 먼저 생산지시를 취소해야 합니다 + +--- + +## 5. 상세 화면 + +### 5.1 공통 구조 +- **좌측 상단 버튼**: 계약서, 거래명세서, 발주서 (클릭 시 모달 오픈) +- **기본 정보**: 발주처, 현장명, 담당자, 연락처 +- **수주/배송 정보**: 수주일자, 출고예정일, 납품요청일, 배송방식, 운임비용, 수신, 수신처 연락처, 수신처 주소 +- **비고**: 특이사항 +- **제품 내역**: 테이블 (순번, 품목코드, 품명, 종, 부호, 규격, 수량, 단위, 단가, 금액) +- **하단 합계**: 소계, 할인율, 총금액 + +### 5.2 상태별 버튼 차이 + +| 상태 | 우측 상단 버튼 | +|------|---------------| +| **출하완료** | `목록` | +| **재작업중** | `목록`, `수정`, `생산지시 생성` (파란), `취소` | +| **생산중** | `목록`, `수정`, `생산지시 생성` (파란), `취소` | +| **수주확정** | `목록`, `수정`, `생산지시 생성` (파란), `취소` | +| **생산지시완료** | `목록`, `수정`, `생산지시 생성` (파란) | +| **작업완료** | `목록`, `수정`, `생산지시 생성` (파란), `취소` | + +--- + +## 6. 문서 팝업 (계약서/거래명세서/발주서) + +### 6.1 공통 헤더 +- PDF 다운로드, 이메일, 팩스, 인쇄, 닫기 버튼 + +### 6.2 계약서 +``` +┌─────────────────────────────────────────┐ +│ 계약서 ✕ │ +│ [PDF] [이메일] [팩스] [■■] [인쇄] [닫기] │ +├─────────────────────────────────────────┤ +│ 계 약 서 │ +│ 수주번호: KD-TS-XXXXXX-XX │ +│ 계약일자: YYYY-MM-DD │ +│ │ +│ ┌─────────────────────────────────────┐ │ +│ │ 제품명 │ │ +│ │ 스크린 세터 (표준형) │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────┐ │ +│ │ 수주물목 (개소별 사이즈) │ │ +│ │ 품목코드 │ 품명 │ 규격 │ 수량 │ 단위 │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ 발주처정보 │ │ 당사정보 │ │ +│ │ 업체명 │ │ 업체명 │ │ +│ │ 대표자 │ │ 대표자 │ │ +│ │ 사업자번호 │ │ 사업자번호 │ │ +│ │ 연락처 │ │ 연락처 │ │ +│ │ 주소 │ │ 주소 │ │ +│ └──────────────┘ └──────────────┘ │ +│ │ +│ ┌─────────────────────────────────────┐ │ +│ │ 총 계약 금액 │ │ +│ │ ₩ 38,800,000 │ │ +│ │ (부가세 포함) │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ 공급가액: XX,XXX,XXX원 할인율: X% │ +│ 할인액: -X,XXX,XXX원 │ +│ 할인 후 공급가액: XX,XXX,XXX원 │ +│ 부가세(10%): X,XXX,XXX원 │ +│ 합계: XX,XXX,XXX원 │ +│ │ +│ ┌─────────────────────────────────────┐ │ +│ │ 특이사항 │ │ +│ │ [내용] │ │ +│ └─────────────────────────────────────┘ │ +└─────────────────────────────────────────┘ +``` + +### 6.3 거래명세서 +- 공급자/공급받는자 정보 (상호, 대표자, 사업자번호, 연락처, 주소) +- 품목내역 테이블 (순번, 품목코드, 품명, 규격, 수량, 단위, 단가, 공급가액) +- 금액 계산 (공급가액, 할인율, 할인액, 할인 후 공급가액, 부가세, 합계 금액) +- "위 금액을 거래하였음을 증명합니다." +- 날짜 + 인 + +### 6.4 발주서 +- 로트번호 + 결재란 (작성/검토/승인/생산) +- 신청업체 정보 (발주처, 담당자, FAX, 현장명) +- 신청내용 (납기요청일, 출고일, 배송방법, 납품주소) +- 부자재 테이블 (구분, 품명, 규격, 길이(mm), 수량, 비고) +- 특이사항 +- 유의사항 (발주서 승인 후 작업 진행, 납기 엄수, 기타 문의사항) +- 문의 연락처 + +--- + +## 7. 수정 화면 + +### 7.1 상단 정보 +- 제목: `수주 수정` + 수주번호 + 상태 배지 + +### 7.2 기본 정보 (읽기전용) +| 필드 | 비고 | +|------|------| +| 로트번호 | 읽기전용 | +| 견적번호 | 읽기전용 | +| 담당자 | 읽기전용 | +| 발주처 | 읽기전용 | +| 현장명 | 읽기전용 | +| 연락처 | 읽기전용 | + +### 7.3 수주/배송 정보 (편집 가능) +| 필드 | 타입 | +|------|------| +| 출고예정일 | DatePicker + 미정 체크박스 | +| 납품요청일 | DatePicker | +| 배송방식 | Select | +| 운임비용 | Select | +| 수신(반장/업체) | Text | +| 수신처 연락처 | Phone | +| 수신처 주소 | Text (전체 주소) | +| 상세주소 | Text | + +### 7.4 비고 +- 편집 가능 텍스트 영역 + +### 7.5 품목 내역 +- 안내 문구: `생산 시작 후 수정 불가` +- 테이블 (No, 품목코드, 품명, 종, 부호, 규격(mm), 수량, 단위, 단가, 금액) +- 하단 합계 + +### 7.6 버튼 +- `취소` / `저장` + +--- + +## 8. 생산지시 생성 화면 + +### 8.1 페이지 제목 +- `생산지시 생성` + `2개 작업지시 생성 예정` + +### 8.2 수주 정보 +| 필드 | 값 | +|------|-----| +| 수주번호 | KD-TS-XXXXXX-XX | +| 품목 수 | X EA | +| 총 수량 | X 개(품) | +| 납기일 | YYYY-MM-DD | +| 진행상태 | 배지 (예: 재작업중) | + +### 8.3 생산지시 옵션 +| 필드 | 타입 | 옵션 | +|------|------|------| +| 우선순위 (필수) | Radio | 긴급 / 일반 / 분할 / VIP | +| 비고 | Textarea | | +| 납품요청일 | DatePicker | | +| 생산라인 | Select | | +| 생산지시 (필수) | Select | 작업지시 기본값 (공정) | +| + 작업지시 일괄생성 | Button | | + +### 8.4 메모 +- 생산지시 관련 메모 영역 + +### 8.5 생성될 작업지시 (X건) +| 컬럼 | 설명 | +|------|------| +| 고정번호 | KD-PL-XXXXXX-XX | +| 공정 | BCI | +| 품목 수 | X EA | +| 총 수량 | X EA | +| 공정 수 | X | +| BOM 자재(수량) | 1 BOM, 2 모재, X 자재소요, 6 BOM | +| 시작일/완료일 | X 일 | + +### 8.6 자재 소요량 및 재고 현황 +| 컬럼 | 설명 | +|------|------| +| 자재코드 | SCR-MAT-XXX | +| 자재명 | 예: 스크린 원단 | +| 단위 | M² / EA | +| 소요량 | 숫자 | +| 현재고 | 숫자 | +| 상태 | 충분 (녹색) | + +### 8.7 스크린 물류 내역 (X건) +| 컬럼 | 설명 | +|------|------| +| No | 순번 | +| 품목코드 | 품목 ID | +| 품명 | 제품명 | +| 가로/세로 | mm | +| 가공수량 | 숫자 | +| 재단면적 | m² | +| 자투리(%) | 퍼센트 | +| 자재코드 | 자재 ID | +| 판재규격 | 규격 | +| 판 | 숫자 | +| 수량 | 숫자 | + +### 8.8 모터/전장품 사양 +| 컬럼 | 설명 | +|------|------| +| 사이즈 (380V) | 예: KD-150K | +| 모터 사양 | 예: 380-180 [3-4"] | +| 허브 사양 | 예: 3"H | + +### 8.9 필요한 BOM +| 컬럼 | 설명 | +|------|------| +| 품목 | 품목명 | +| 규격 | 예: 100-70 | +| 조도 | 예: KSDEL/NAKED | +| 단위 | 예: 3000 | +| 수량 | 숫자 | + +### 8.10 봉/카바 +| 컬럼 | 설명 | +|------|------| +| 카바(스테인리스커버) - 하단 조작 500-330 | | +| 품목 | 품목명 | +| 수량 | 숫자 | +| | | +| 봉/샤 | | +| 품목 | 품목명 | +| 수량 | 숫자 | +| | | +| 마/더 | | +| 품목 | 품목명 | +| 수량 | 숫자 | + +### 8.11 박스/마감재 +| 컬럼 | 설명 | +|------|------| +| 품목 | 품목명 | +| 규격 | 규격 | +| 단위 | 단위 | +| 수량 | 숫자 | + +### 8.12 모터 브라켓 +| 컬럼 | 설명 | +|------|------| +| 품목 | 품목명 | +| 수량 | 숫자 | + +### 8.13 하단 버튼 +- `수주상세보기` / `생산지시 확정 (X건)` (파란 버튼) + +--- + +## 9. 생산지시 확정 후 플로우 + +### 9.1 생산지시 확정 팝업 +``` +┌─────────────────────────────────────────┐ +│ ✅ 생산지시가 생성되었습니다. │ +│ │ +│ 생산지시번호: PO-KD-TS-XXXXXX-XX │ +│ │ +│ 생산관리 > 생산지시 관리에서 │ +│ 작업지시서를 생성하세요. │ +│ │ +│ [확인] │ +└─────────────────────────────────────────┘ +``` + +### 9.2 생산지시 상세 화면 (확정 후) +- **페이지 제목**: `생산지시 상세` + 생산지시번호 + 상태 배지 (생산대기) +- **우측 상단**: `목록`, `작업지시 생성` 버튼 + +#### 공정 진행 현황 +- 진행 상태 바 또는 카드 + +#### 기본 정보 +| 필드 | 값 | +|------|-----| +| 생산지시번호 | PO-KD-TS-XXXXXX-XX | +| 수주번호 | KD-TS-XXXXXX-XX | +| 생산지시일 | YYYY-MM-DD | +| 납기일 | YYYY-MM-DD | +| 수량 | X 개 | + +#### 거래처/현장 정보 +| 필드 | 값 | +|------|-----| +| 거래처 | 거래처명 | +| 현장명 | 현장명 | +| 제품유형 | (선택) | + +#### BOM 품목별 공정 분류 +- 공정별 분류 표시 + +#### 작업지시서 목록 +| 컬럼 | 설명 | +|------|------| +| 작업지시번호 | KD-WO-XXXXXX-XX | +| 공정 | 공정명 | +| 수량 | X 개 | +| 상태 | 배지 (예: 재작업중) | +| 담당자 | - | + +### 9.3 작업지시 자동 생성 팝업 +``` +┌─────────────────────────────────────────┐ +│ ▷ 작업지시서 자동 생성 │ +├─────────────────────────────────────────┤ +│ │ +│ 다음 공정에 대한 작업지시서가 │ +│ 생성됩니다: │ +│ │ +│ 생성된 작업지시서는 생산팀에서 확인하고 │ +│ 작업을 진행할 수 있습니다. │ +│ │ +│ [취소] [작업지시 생성] │ +└─────────────────────────────────────────┘ +``` + +### 9.4 작업지시 생성 완료 팝업 +``` +┌─────────────────────────────────────────┐ +│ ✅ X개의 작업지시서가 공정별로 │ +│ 자동 생성되었습니다. │ +│ │ +│ 생성된 작업지시서: │ +│ │ +│ 작업지시 관리 페이지로 이동합니다. │ +│ │ +│ [확인] │ +└─────────────────────────────────────────┘ +``` + +- **확인 클릭 시**: 생산관리 > 작업지시 관리 리스트 페이지로 이동 + - (해당 페이지는 추후 구현 시 연결) + +--- + +## 10. 컴포넌트 재사용 + +### 10.1 기존 컴포넌트 활용 +| 컴포넌트 | 용도 | +|----------|------| +| IntegratedListTemplateV2 | 리스트 페이지 | +| PageLayout | 페이지 레이아웃 | +| DocumentPreviewDialog | 문서 팝업 (기안함에서 사용 중) | +| DaumPostcodeDialog | 우편번호 검색 | +| AlertDialog | 확인 팝업 | +| Dialog | 일반 팝업 | + +### 10.2 신규 컴포넌트 +| 컴포넌트 | 용도 | +|----------|------| +| QuotationSelectDialog | 견적 선택 팝업 | +| ItemAddDialog | 품목 추가 팝업 | +| ContractDocument | 계약서 문서 | +| TransactionDocument | 거래명세서 문서 | +| PurchaseOrderDocument | 발주서 문서 | +| ProductionOrderForm | 생산지시 생성 폼 | +| WorkOrderConfirmDialog | 작업지시 생성 확인 팝업 | + +--- + +## 11. API 엔드포인트 (예상) + +| Method | Endpoint | 설명 | +|--------|----------|------| +| GET | /api/v1/order-management | 수주 목록 조회 | +| GET | /api/v1/order-management/:id | 수주 상세 조회 | +| POST | /api/v1/order-management | 수주 등록 | +| PUT | /api/v1/order-management/:id | 수주 수정 | +| DELETE | /api/v1/order-management/:id | 수주 삭제 | +| GET | /api/v1/quotations/confirmed | 확정 견적 목록 | +| POST | /api/v1/production-order | 생산지시 생성 | +| POST | /api/v1/work-order | 작업지시 생성 | + +--- + +## 12. 구현 순서 + +### Phase 1: 기본 CRUD ✅ 완료 (2025-12-22) +- [x] 1.1 리스트 페이지 구현 +- [x] 1.2 등록 페이지 구현 +- [x] 1.3 견적 선택 팝업 +- [x] 1.4 품목 추가 팝업 +- [x] 1.5 상세 페이지 구현 +- [x] 1.6 수정 페이지 구현 + +### Phase 2: 문서 팝업 & 생산지시 조회 ✅ 완료 (2025-12-22) +- [x] 2.1 계약서 문서 컴포넌트 (ContractDocument.tsx) +- [x] 2.2 거래명세서 문서 컴포넌트 (TransactionDocument.tsx) +- [x] 2.3 발주서 문서 컴포넌트 (PurchaseOrderDocument.tsx) +- [x] 2.4 OrderDocumentModal 연동 (기안함 패턴 적용) +- [x] 2.5 수주 상세 페이지 수정 (탭 → 버튼+모달) +- [x] 2.6 생산지시 목록 페이지 (production-orders/page.tsx) +- [x] 2.7 생산지시 상세 페이지 (production-orders/[id]/page.tsx) +- [x] 2.8 생산지시완료 상태 버튼 변경 ("생산지시 생성" → "생산지시 보기") + +### Phase 3: 생산지시 생성 연동 ← 현재 +- [ ] 3.1 생산지시 생성 페이지 ([id]/production-order/page.tsx) +- [ ] 3.2 생산지시 확정 플로우 (확정 팝업) +- [ ] 3.3 작업지시 생성 팝업 +- [ ] 3.4 페이지 이동 로직 (작업지시 관리로) + +--- + +## 13. 참고 사항 + +### 13.1 상태 값 (6개) +| 상태 | 배지 색상 | 설명 | +|------|----------|------| +| 수주확정 | 회색 | 초기 상태 | +| 생산지시완료 | 파랑 | 생산지시 생성됨 | +| 생산중 | 초록 | 생산 진행 중 | +| 재작업중 | 주황 | 재작업 진행 중 | +| 작업완료 | 파랑/완료 | 작업 완료 | +| 출하완료 | 회색/완료 | 출하 완료 | + +### 13.2 번호 체계 +| 유형 | 형식 | 예시 | +|------|------|------| +| 로트번호 | KD-TS-YYMMDD-XX | KD-TS-251217-09 | +| 견적번호 | KD-PR-YYMMDD-XX | KD-PR-251217-09 | +| 생산지시번호 | PO-KD-TS-YYMMDD-XX | PO-KD-TS-251217-09 | +| 작업지시번호 | KD-WO-YYMMDD-XX | KD-WO-251217-11 | \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d9c01ebc..2a385813 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@hookform/resolvers": "^5.2.2", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", @@ -1336,6 +1337,77 @@ } } }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", diff --git a/package.json b/package.json index 0736f23a..7fc1777b 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@hookform/resolvers": "^5.2.2", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", diff --git a/src/app/[locale]/(protected)/material/receiving-management/[id]/page.tsx b/src/app/[locale]/(protected)/material/receiving-management/[id]/page.tsx new file mode 100644 index 00000000..5bbc4740 --- /dev/null +++ b/src/app/[locale]/(protected)/material/receiving-management/[id]/page.tsx @@ -0,0 +1,10 @@ +import { ReceivingDetail } from '@/components/material/ReceivingManagement'; + +interface Props { + params: Promise<{ id: string }>; +} + +export default async function ReceivingDetailPage({ params }: Props) { + const { id } = await params; + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/material/receiving-management/inspection/page.tsx b/src/app/[locale]/(protected)/material/receiving-management/inspection/page.tsx new file mode 100644 index 00000000..3ded801c --- /dev/null +++ b/src/app/[locale]/(protected)/material/receiving-management/inspection/page.tsx @@ -0,0 +1,5 @@ +import { InspectionCreate } from '@/components/material/ReceivingManagement'; + +export default function InspectionPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/material/receiving-management/page.tsx b/src/app/[locale]/(protected)/material/receiving-management/page.tsx new file mode 100644 index 00000000..b7985265 --- /dev/null +++ b/src/app/[locale]/(protected)/material/receiving-management/page.tsx @@ -0,0 +1,5 @@ +import { ReceivingList } from '@/components/material/ReceivingManagement'; + +export default function ReceivingManagementPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/material/stock-status/[id]/page.tsx b/src/app/[locale]/(protected)/material/stock-status/[id]/page.tsx new file mode 100644 index 00000000..bf424c2e --- /dev/null +++ b/src/app/[locale]/(protected)/material/stock-status/[id]/page.tsx @@ -0,0 +1,12 @@ +import { StockStatusDetail } from '@/components/material/StockStatus'; + +interface StockStatusDetailPageProps { + params: Promise<{ + id: string; + }>; +} + +export default async function StockStatusDetailPage({ params }: StockStatusDetailPageProps) { + const { id } = await params; + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/material/stock-status/page.tsx b/src/app/[locale]/(protected)/material/stock-status/page.tsx new file mode 100644 index 00000000..da2c0042 --- /dev/null +++ b/src/app/[locale]/(protected)/material/stock-status/page.tsx @@ -0,0 +1,5 @@ +import { StockStatusList } from '@/components/material/StockStatus'; + +export default function StockStatusPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/outbound/shipments/[id]/edit/page.tsx b/src/app/[locale]/(protected)/outbound/shipments/[id]/edit/page.tsx new file mode 100644 index 00000000..345c614c --- /dev/null +++ b/src/app/[locale]/(protected)/outbound/shipments/[id]/edit/page.tsx @@ -0,0 +1,15 @@ +/** + * 출하관리 - 수정 페이지 + * URL: /outbound/shipments/[id]/edit + */ + +import { ShipmentEdit } from '@/components/outbound/ShipmentManagement'; + +interface ShipmentEditPageProps { + params: Promise<{ id: string }>; +} + +export default async function ShipmentEditPage({ params }: ShipmentEditPageProps) { + const { id } = await params; + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/outbound/shipments/[id]/page.tsx b/src/app/[locale]/(protected)/outbound/shipments/[id]/page.tsx new file mode 100644 index 00000000..2793fef4 --- /dev/null +++ b/src/app/[locale]/(protected)/outbound/shipments/[id]/page.tsx @@ -0,0 +1,15 @@ +/** + * 출하관리 - 상세 페이지 + * URL: /outbound/shipments/[id] + */ + +import { ShipmentDetail } from '@/components/outbound/ShipmentManagement'; + +interface ShipmentDetailPageProps { + params: Promise<{ id: string }>; +} + +export default async function ShipmentDetailPage({ params }: ShipmentDetailPageProps) { + const { id } = await params; + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/outbound/shipments/new/page.tsx b/src/app/[locale]/(protected)/outbound/shipments/new/page.tsx new file mode 100644 index 00000000..f6d3cac9 --- /dev/null +++ b/src/app/[locale]/(protected)/outbound/shipments/new/page.tsx @@ -0,0 +1,10 @@ +/** + * 출하관리 - 등록 페이지 + * URL: /outbound/shipments/new + */ + +import { ShipmentCreate } from '@/components/outbound/ShipmentManagement'; + +export default function NewShipmentPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/outbound/shipments/page.tsx b/src/app/[locale]/(protected)/outbound/shipments/page.tsx new file mode 100644 index 00000000..0d88c7be --- /dev/null +++ b/src/app/[locale]/(protected)/outbound/shipments/page.tsx @@ -0,0 +1,10 @@ +/** + * 출하관리 - 목록 페이지 + * URL: /outbound/shipments + */ + +import { ShipmentList } from '@/components/outbound/ShipmentManagement'; + +export default function ShipmentsPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/production/dashboard/page.tsx b/src/app/[locale]/(protected)/production/dashboard/page.tsx new file mode 100644 index 00000000..ffd86f86 --- /dev/null +++ b/src/app/[locale]/(protected)/production/dashboard/page.tsx @@ -0,0 +1,21 @@ +/** + * 생산 현황판 페이지 + * + * 경로: /[locale]/(protected)/production/dashboard + */ + +import { Suspense } from 'react'; +import ProductionDashboard from '@/components/production/ProductionDashboard'; + +export default function ProductionDashboardPage() { + return ( + 로딩 중...}> + + + ); +} + +export const metadata = { + title: '생산 현황판', + description: '공장별 작업 현황을 확인합니다.', +}; \ No newline at end of file diff --git a/src/app/[locale]/(protected)/production/work-orders/[id]/page.tsx b/src/app/[locale]/(protected)/production/work-orders/[id]/page.tsx new file mode 100644 index 00000000..d47eb9c3 --- /dev/null +++ b/src/app/[locale]/(protected)/production/work-orders/[id]/page.tsx @@ -0,0 +1,17 @@ +/** + * 작업지시 상세 페이지 + * URL: /production/work-orders/[id] + */ + +import { WorkOrderDetail } from '@/components/production/WorkOrders'; + +interface PageProps { + params: Promise<{ + id: string; + }>; +} + +export default async function WorkOrderDetailPage({ params }: PageProps) { + const { id } = await params; + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/production/work-orders/create/page.tsx b/src/app/[locale]/(protected)/production/work-orders/create/page.tsx new file mode 100644 index 00000000..230ed1bd --- /dev/null +++ b/src/app/[locale]/(protected)/production/work-orders/create/page.tsx @@ -0,0 +1,10 @@ +/** + * 작업지시 등록 페이지 + * URL: /production/work-orders/create + */ + +import { WorkOrderCreate } from '@/components/production/WorkOrders'; + +export default function WorkOrderCreatePage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/production/work-orders/page.tsx b/src/app/[locale]/(protected)/production/work-orders/page.tsx new file mode 100644 index 00000000..cfcce44d --- /dev/null +++ b/src/app/[locale]/(protected)/production/work-orders/page.tsx @@ -0,0 +1,10 @@ +/** + * 작업지시 목록 페이지 + * URL: /production/work-orders + */ + +import { WorkOrderList } from '@/components/production/WorkOrders'; + +export default function WorkOrdersPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/production/work-results/page.tsx b/src/app/[locale]/(protected)/production/work-results/page.tsx new file mode 100644 index 00000000..ad02d9ef --- /dev/null +++ b/src/app/[locale]/(protected)/production/work-results/page.tsx @@ -0,0 +1,10 @@ +/** + * 작업실적 조회 페이지 + * URL: /production/work-results + */ + +import { WorkResultList } from '@/components/production/WorkResults'; + +export default function WorkResultsPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/production/worker-screen/page.tsx b/src/app/[locale]/(protected)/production/worker-screen/page.tsx new file mode 100644 index 00000000..26ec4787 --- /dev/null +++ b/src/app/[locale]/(protected)/production/worker-screen/page.tsx @@ -0,0 +1,21 @@ +/** + * 작업자 화면 페이지 + * + * 경로: /[locale]/(protected)/production/worker-screen + */ + +import { Suspense } from 'react'; +import WorkerScreen from '@/components/production/WorkerScreen'; + +export default function WorkerScreenPage() { + return ( + 로딩 중...}> + + + ); +} + +export const metadata = { + title: '작업자 화면', + description: '내 작업 목록을 확인하고 관리합니다.', +}; \ No newline at end of file diff --git a/src/app/[locale]/(protected)/quality/inspections/[id]/page.tsx b/src/app/[locale]/(protected)/quality/inspections/[id]/page.tsx new file mode 100644 index 00000000..cd446776 --- /dev/null +++ b/src/app/[locale]/(protected)/quality/inspections/[id]/page.tsx @@ -0,0 +1,16 @@ +/** + * 검사 상세/수정 페이지 + * URL: /quality/inspections/[id] + * 수정 모드: /quality/inspections/[id]?mode=edit + */ + +import { InspectionDetail } from '@/components/quality/InspectionManagement'; + +interface Props { + params: Promise<{ id: string }>; +} + +export default async function InspectionDetailPage({ params }: Props) { + const { id } = await params; + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/quality/inspections/new/page.tsx b/src/app/[locale]/(protected)/quality/inspections/new/page.tsx new file mode 100644 index 00000000..966f92aa --- /dev/null +++ b/src/app/[locale]/(protected)/quality/inspections/new/page.tsx @@ -0,0 +1,10 @@ +/** + * 검사 등록 페이지 + * URL: /quality/inspections/new + */ + +import { InspectionCreate } from '@/components/quality/InspectionManagement'; + +export default function InspectionNewPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/quality/inspections/page.tsx b/src/app/[locale]/(protected)/quality/inspections/page.tsx new file mode 100644 index 00000000..4a31e731 --- /dev/null +++ b/src/app/[locale]/(protected)/quality/inspections/page.tsx @@ -0,0 +1,10 @@ +/** + * 검사 목록 페이지 + * URL: /quality/inspections + */ + +import { InspectionList } from '@/components/quality/InspectionManagement'; + +export default function InspectionsPage() { + return ; +} \ No newline at end of file diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx new file mode 100644 index 00000000..765e89e1 --- /dev/null +++ b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/edit/page.tsx @@ -0,0 +1,557 @@ +"use client"; + +/** + * 수주 수정 페이지 + * + * - 기본 정보 (읽기전용) + * - 수주/배송 정보 (편집 가능) + * - 비고 (편집 가능) + * - 품목 내역 (생산 시작 후 수정 불가) + */ + +import { useState, useEffect } from "react"; +import { useRouter, useParams } from "next/navigation"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { FileText, ArrowLeft, Info, AlertTriangle } from "lucide-react"; +import { toast } from "sonner"; +import { PageLayout } from "@/components/organisms/PageLayout"; +import { PageHeader } from "@/components/organisms/PageHeader"; +import { FormSection } from "@/components/templates/ResponsiveFormTemplate"; +import { FormActions } from "@/components/organisms/FormActions"; +import { BadgeSm } from "@/components/atoms/BadgeSm"; +import { formatAmount } from "@/utils/formatAmount"; +import { OrderItem } from "@/components/orders"; + +// 수주 상태 타입 +type OrderStatus = + | "order_registered" + | "order_confirmed" + | "production_ordered" + | "in_production" + | "rework" + | "work_completed" + | "shipped" + | "cancelled"; + +// 수정 폼 데이터 +interface EditFormData { + // 읽기전용 정보 + lotNumber: string; + quoteNumber: string; + client: string; + siteName: string; + manager: string; + contact: string; + status: OrderStatus; + + // 수정 가능 정보 + expectedShipDate: string; + expectedShipDateUndecided: boolean; + deliveryRequestDate: string; + deliveryMethod: string; + shippingCost: string; + receiver: string; + receiverContact: string; + address: string; + addressDetail: string; + remarks: string; + + // 품목 (수정 제한) + items: OrderItem[]; + canEditItems: boolean; + subtotal: number; + discountRate: number; + totalAmount: number; +} + +// 배송방식 옵션 +const DELIVERY_METHODS = [ + { value: "direct", label: "직접배차" }, + { value: "pickup", label: "상차" }, + { value: "courier", label: "택배" }, +]; + +// 운임비용 옵션 +const SHIPPING_COSTS = [ + { value: "free", label: "무료" }, + { value: "prepaid", label: "선불" }, + { value: "collect", label: "착불" }, + { value: "negotiable", label: "협의" }, +]; + +// 샘플 데이터 +const SAMPLE_ORDER: EditFormData = { + lotNumber: "KD-TS-251217-01", + quoteNumber: "KD-PR-251210-01", + client: "태영건설(주)", + siteName: "데시앙 동탄 파크뷰", + manager: "김철수", + contact: "010-1234-5678", + status: "order_confirmed", + expectedShipDate: "2025-01-15", + expectedShipDateUndecided: false, + deliveryRequestDate: "2025-01-20", + deliveryMethod: "direct", + shippingCost: "free", + receiver: "박반장", + receiverContact: "010-9876-5432", + address: "경기도 화성시 동탄대로 123-45", + addressDetail: "데시앙 동탄 파크뷰 현장", + remarks: "4층 우선 납품 요청", + items: [ + { + id: "1", + itemCode: "PRD-001", + itemName: "국민방화스크린세터", + type: "B1", + symbol: "FSS1", + spec: "7260×2600", + width: 7260, + height: 2600, + quantity: 2, + unit: "EA", + unitPrice: 8000000, + amount: 16000000, + }, + { + id: "2", + itemCode: "PRD-002", + itemName: "국민방화스크린세터", + type: "B1", + symbol: "FSS2", + spec: "5000×2400", + width: 5000, + height: 2400, + quantity: 3, + unit: "EA", + unitPrice: 7600000, + amount: 22800000, + }, + ], + canEditItems: true, + subtotal: 38800000, + discountRate: 0, + totalAmount: 38800000, +}; + +// 상태 뱃지 헬퍼 +function getOrderStatusBadge(status: OrderStatus) { + const statusConfig: Record = { + order_registered: { label: "수주등록", className: "bg-gray-100 text-gray-700 border-gray-200" }, + order_confirmed: { label: "수주확정", className: "bg-gray-100 text-gray-700 border-gray-200" }, + production_ordered: { label: "생산지시완료", className: "bg-blue-100 text-blue-700 border-blue-200" }, + in_production: { label: "생산중", className: "bg-green-100 text-green-700 border-green-200" }, + rework: { label: "재작업중", className: "bg-orange-100 text-orange-700 border-orange-200" }, + work_completed: { label: "작업완료", className: "bg-blue-600 text-white border-blue-600" }, + shipped: { label: "출하완료", className: "bg-gray-500 text-white border-gray-500" }, + cancelled: { label: "취소", className: "bg-red-100 text-red-700 border-red-200" }, + }; + const config = statusConfig[status]; + return ( + + {config.label} + + ); +} + +export default function OrderEditPage() { + const router = useRouter(); + const params = useParams(); + const orderId = params.id as string; + + const [form, setForm] = useState(null); + const [loading, setLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); + + // 데이터 로드 + useEffect(() => { + setTimeout(() => { + // 상태에 따라 품목 수정 가능 여부 결정 + const canEditItems = !["in_production", "rework", "work_completed", "shipped"].includes( + SAMPLE_ORDER.status + ); + setForm({ ...SAMPLE_ORDER, canEditItems }); + setLoading(false); + }, 300); + }, [orderId]); + + const handleBack = () => { + router.push(`/sales/order-management-sales/${orderId}`); + }; + + const handleCancel = () => { + router.push(`/sales/order-management-sales/${orderId}`); + }; + + const handleSave = async () => { + if (!form) return; + + // 유효성 검사 + if (!form.deliveryRequestDate) { + toast.error("납품요청일을 입력해주세요."); + return; + } + if (!form.receiver.trim()) { + toast.error("수신(반장/업체)을 입력해주세요."); + return; + } + if (!form.receiverContact.trim()) { + toast.error("수신처 연락처를 입력해주세요."); + return; + } + + setIsSaving(true); + try { + // TODO: API 연동 + console.log("수주 수정 데이터:", form); + await new Promise((resolve) => setTimeout(resolve, 500)); + toast.success("수주가 수정되었습니다."); + router.push(`/sales/order-management-sales/${orderId}`); + } finally { + setIsSaving(false); + } + }; + + if (loading || !form) { + return ( + +
+
+
+ + ); + } + + return ( + + {/* 헤더 */} + + + {form.lotNumber} + + {getOrderStatusBadge(form.status)} +
+ } + /> + +
+ {/* 기본 정보 (읽기전용) */} + + + + 기본 정보 + (읽기전용) + + + +
+
+ +

{form.lotNumber}

+
+
+ +

{form.quoteNumber}

+
+
+ +

{form.manager}

+
+
+ +

{form.client}

+
+
+ +

{form.siteName}

+
+
+ +

{form.contact}

+
+
+
+
+ + {/* 수주/배송 정보 (편집 가능) */} + + + 수주/배송 정보 + + +
+ {/* 출고예정일 */} +
+ +
+ + setForm({ ...form, expectedShipDate: e.target.value }) + } + disabled={form.expectedShipDateUndecided} + className="flex-1" + /> +
+ + setForm({ + ...form, + expectedShipDateUndecided: checked as boolean, + expectedShipDate: checked ? "" : form.expectedShipDate, + }) + } + /> + +
+
+
+ + {/* 납품요청일 */} +
+ + + setForm({ ...form, deliveryRequestDate: e.target.value }) + } + /> +
+ + {/* 배송방식 */} +
+ + +
+ + {/* 운임비용 */} +
+ + +
+ + {/* 수신(반장/업체) */} +
+ + + setForm({ ...form, receiver: e.target.value }) + } + /> +
+ + {/* 수신처 연락처 */} +
+ + + setForm({ ...form, receiverContact: e.target.value }) + } + /> +
+ + {/* 수신처 주소 */} +
+ + + setForm({ ...form, address: e.target.value }) + } + placeholder="주소" + className="mb-2" + /> + + setForm({ ...form, addressDetail: e.target.value }) + } + placeholder="상세주소" + /> +
+
+
+
+ + {/* 비고 */} + + + 비고 + + +