51 KiB
생산계획관리 (Production Plan Management)
Screen ID: /screens/{TBD} 메뉴 경로: 생산관리 > 생산계획관리
⚠️ 구현 상태 안내
- 간소화 버전 (패턴 A): ✅ 즉시 구현 가능
- 정식 버전 (복합 레이아웃): ⚠️ 컴포넌트 개발 후 구현 가능
✅ 구현 완료v2-split-panel-layout커스텀 모드 확장v2-table-grouped,v2-timeline-scheduler신규 개발 (2개)
1. 화면 개요
| 항목 | 내용 |
|---|---|
| 화면명 | 생산계획관리 |
| 영문명 | Production Plan Management |
| Screen ID | /screens/{TBD} |
| 메뉴 경로 | 생산관리 > 생산계획관리 |
| 화면 유형 (전체) | 복합형 (좌우 분할 패널 + 타임라인 스케줄러) - ⚠️ 컴포넌트 확장 후 구현 |
| 화면 유형 (간소화) | 패턴 A (기본 마스터 화면) - ✅ 즉시 구현 가능 |
| 메인 테이블 | production_plan_mng |
| 관련 테이블 | sales_order_mng, item_info, equipment_info, bom_info |
| 주요 기능 | 수주 기반 생산계획 수립, 타임라인 스케줄러, 자동 스케줄 생성, 반제품 계획 연동 |
| 필요 작업 | v2-split-panel-layout 확장v2-table-grouped 개발 / 3. v2-timeline-scheduler 개발 |
2. 테이블 선택 및 화면 구조
2.1 사용 테이블
| 테이블명 | 용도 | 비고 |
|---|---|---|
production_plan_mng |
생산계획 마스터 | 주 테이블 |
sales_order_mng |
수주 정보 | 참조 (수주 기반 계획) |
item_info |
품목 정보 | 참조 (품목코드, 품명) |
equipment_info |
설비 정보 | 참조 (설비 할당) |
bom_info |
BOM 정보 | 참조 (반제품 계획 생성) |
2.2 테이블 관계
┌──────────────────────┐ ┌──────────────────────┐
│ sales_order_mng │ │ production_plan_mng │
├──────────────────────┤ ├──────────────────────┤
│ order_no (PK) │──N:1──│ order_no (FK) │
│ item_code │ │ id (PK) │
│ ... │ │ plan_no │
└──────────────────────┘ │ item_code │
│ equipment_id (FK) │
┌──────────────────────┐ │ parent_plan_id (FK) │
│ item_info │ │ ... │
├──────────────────────┤ └──────────────────────┘
│ item_code (PK) │──1:N── │
│ item_name │ │
│ ... │ │
└──────────────────────┘ │
│
┌──────────────────────┐ │
│ equipment_info │ │
├──────────────────────┤ │
│ id (PK) │──1:N──────────┘
│ equipment_code │
│ equipment_name │
│ ... │
└──────────────────────┘
2.3 화면 구조 분석 (전체 버전)
2.3.1 레이아웃 구조
┌─────────────────────────────────────────────────────────────────────────────┐
│ 검색 섹션 │
│ [검색필드들...] [사용자옵션] [엑셀업로드] [엑셀다운로드] │
├────────────────────────────────┬──┬──────────────────────────────────────────┤
│ 왼쪽 패널 (50%, 리사이즈) │ │ 오른쪽 패널 (50%) │
│ ┌────────────────────────────┐ │리│ ┌──────────────────────────────────────┐ │
│ │ [수주데이터] [안전재고부족] │ │사│ │ [완제품 생산계획] [반제품 생산계획] │ │
│ ├────────────────────────────┤ │이│ ├──────────────────────────────────────┤ │
│ │ │ │즈│ │ │ │
│ │ 수주 목록 테이블 │ │핸│ │ 타임라인 스케줄러 │
│ │ (그룹화된 품목별 수주) │ │들│ │ (간트차트 형태) │
│ │ │ │ │ │ │ │
│ │ - 체크박스 │ │ │ │ - 날짜별 그리드 │
│ │ - 접기/펼치기 토글 │ │ │ │ - 생산계획 바 (드래그 가능) │
│ │ - 품목별 그룹 행 │ │ │ │ - 납기일 마커 │
│ │ - 수주 상세 행 │ │ │ │ │
│ │ │ │ │ │ │
│ └────────────────────────────┘ │ │ └──────────────────────────────────────┘ │
│ [계획에 없는 품목만] [선택품목 불러오기] [새로고침] │ [자동스케줄] [저장] [초기화] │
└────────────────────────────────┴──┴──────────────────────────────────────────┘
2.3.2 탭 구조
왼쪽 패널 탭:
- 수주데이터: 수주 목록 (품목별 그룹핑)
- 안전재고 부족분: 안전재고 미달 품목 목록
오른쪽 패널 탭:
- 완제품 생산계획: 완제품 타임라인 스케줄러
- 반제품 생산계획: 반제품 타임라인 스케줄러
3. 테이블 정의
3.1 메인 테이블: production_plan_mng
| 컬럼명 | 타입 | NULL | 설명 |
|---|---|---|---|
| id | SERIAL | NO | PK |
| company_code | VARCHAR(20) | NO | 회사 코드 |
| plan_no | VARCHAR(50) | NO | 생산계획번호 |
| plan_date | DATE | NO | 계획일자 |
| item_code | VARCHAR(50) | NO | 품목코드 |
| item_name | VARCHAR(200) | YES | 품명 |
| plan_qty | NUMERIC(15,3) | NO | 계획수량 |
| start_date | DATE | NO | 시작일 |
| end_date | DATE | NO | 종료일 |
| due_date | DATE | YES | 납기일 |
| equipment_id | INTEGER | YES | 설비 ID (FK) |
| equipment_name | VARCHAR(100) | YES | 설비명 |
| status | VARCHAR(20) | YES | 상태 (계획/지시/진행/완료) |
| priority | VARCHAR(20) | YES | 우선순위 |
| work_shift | VARCHAR(20) | YES | 작업조 (주간/야간/주야) |
| manager_name | VARCHAR(100) | YES | 담당자 |
| work_order_no | VARCHAR(50) | YES | 작업지시번호 |
| remarks | TEXT | YES | 비고 |
| order_no | VARCHAR(50) | YES | 관련 수주번호 |
| partner_id | VARCHAR(50) | YES | 거래처 ID |
| hourly_capacity | NUMERIC(15,3) | YES | 시간당 생산능력 |
| daily_capacity | NUMERIC(15,3) | YES | 일일 생산능력 |
| lead_time | INTEGER | YES | 리드타임 (일) |
| product_type | VARCHAR(20) | YES | 제품유형 (완제품/반제품) |
| parent_plan_id | INTEGER | YES | 모품목 계획 ID (반제품용) |
| created_date | TIMESTAMPTZ | YES | 생성일시 |
| created_by | VARCHAR(50) | YES | 생성자 |
| updated_date | TIMESTAMPTZ | YES | 수정일시 |
| updated_by | VARCHAR(50) | YES | 수정자 |
3.2 관련 테이블
equipment_info (설비 정보)
| 컬럼명 | 타입 | 설명 |
|---|---|---|
| id | SERIAL | PK |
| equipment_code | VARCHAR(50) | 설비코드 |
| equipment_name | VARCHAR(100) | 설비명 |
| equipment_type | VARCHAR(50) | 설비유형 |
| capacity_per_hour | NUMERIC(15,3) | 시간당 생산능력 |
| status | VARCHAR(20) | 상태 |
4. 구현 가능 여부 분석
4.1 현재 V2 컴포넌트로 구현 가능한 기능
| 기능 | 가능 여부 | 사용 컴포넌트 | 비고 |
|---|---|---|---|
| 검색 필터 | ✅ | v2-table-search-widget |
|
| 기본 버튼 (엑셀, 사용자옵션) | ✅ | v2-button-primary |
|
| 단일 테이블 목록 | ✅ | v2-table-list |
|
| 기본 모달 폼 | ✅ | 모달 화면 | |
| 좌우 분할 패널 (커스텀 모드) | ✅ | v2-split-panel-layout |
displayMode: "custom" 지원 |
| 탭 컴포넌트 (기본) | ⚠️ | v2-tabs-widget |
디자인 모드에서 컴포넌트 배치 |
4.2 현재 V2 컴포넌트의 제한 사항 및 확장 방안
v2-split-panel-layout 현재 기능
| 기능 | 지원 | 설명 |
|---|---|---|
| 좌우 분할 패널 | ✅ | 리사이즈 가능 |
| 테이블/리스트 표시 | ✅ | displayMode: "list" | "table" |
| 마스터-디테일 관계 | ✅ | relation 설정 |
우측 추가 탭 (additionalTabs) |
⚠️ | 타입만 정의, 렌더링 미구현 |
| 패널 내 임의 컴포넌트 배치 | ✅ | displayMode: "custom" - 구현 완료! |
✅ 커스텀 모드 (구현 완료)
v2-tabs-widget과 동일한 구조로 패널 안에 컴포넌트를 자유롭게 배치:
leftPanel: {
displayMode: "list" | "table" | "custom", // ✅ 커스텀 모드 지원
// 기존 모드 (list, table)
tableName?: string,
columns?: [...],
// ✅ 커스텀 모드 - 패널 안에 자유롭게 컴포넌트 배치
components?: PanelInlineComponent[],
}
// PanelInlineComponent 구조
interface PanelInlineComponent {
id: string;
componentType: string;
label?: string;
position?: { x: number; y: number };
size?: { width: number; height: number };
componentConfig?: Record<string, any>;
}
커스텀 모드 기능:
- ✅ 드래그앤드롭으로 컴포넌트 이동
- ✅ 리사이즈 핸들로 크기 조절
- ✅ 컴포넌트 클릭 시 좌측 설정 패널에서 속성 편집
- ✅ 디자인 모드에서 실제 컴포넌트 미리보기 렌더링
- ✅ 탭, 테이블, 버튼 등 모든 V2 컴포넌트 배치 가능
v2-tabs-widget 현재 기능
| 기능 | 지원 | 설명 |
|---|---|---|
| 탭별 컴포넌트 배치 | ✅ | components[] |
| 디자인 모드 드래그&드롭 | ✅ | 위치/크기 조정 |
| 런타임 렌더링 | ✅ | DynamicComponentRenderer 사용 |
v2-tabs-widget 구조 (참고용):
interface TabItem {
id: string;
label: string;
components?: TabInlineComponent[]; // 탭 안에 배치된 컴포넌트들
}
interface TabInlineComponent {
id: string;
componentType: string; // "v2-table-list", "v2-timeline-scheduler" 등
position?: { x: number; y: number };
size?: { width: number; height: number };
componentConfig?: Record<string, any>;
}
4.3 생산계획관리에 필요한 기능 vs 현재 지원
| 필요 기능 | 현재 지원 | 해결 방안 |
|---|---|---|
| 좌우 분할 패널 | ✅ | v2-split-panel-layout |
| 왼쪽 패널 탭 (수주/안전재고) | ✅ | 커스텀 모드 + v2-tabs-widget 조합 (구현 완료) |
| 오른쪽 패널 탭 (완제품/반제품) | ✅ | 커스텀 모드 + v2-tabs-widget 조합 (구현 완료) |
| 그룹화된 테이블 (품목별 접기/펼치기) | ❌ | 신규 개발 필요 |
| 타임라인 스케줄러 (간트차트) | ❌ | 신규 개발 필요 |
| 드래그&드롭 스케줄 이동 | ❌ | v2-timeline-scheduler에 포함 |
| 복잡한 상세 모달 | ✅ | 기존 모달 화면으로 충분 |
4.4 향후 개발 필요 사항
기존 컴포넌트 확장 (1개)
| 컴포넌트 | 작업 내용 | 상태 |
|---|---|---|
v2-split-panel-layout |
displayMode: "custom" 추가 + components[] 지원 |
✅ 완료 |
신규 컴포넌트 개발 (2개) - 대체 불가
| 컴포넌트 | 필요 이유 | 상태 |
|---|---|---|
v2-table-grouped |
품목별 접기/펼치기 그룹화 테이블 | ✅ 완료 |
v2-timeline-scheduler |
간트차트 형태의 타임라인 스케줄러 | ⏳ 대기 |
불필요한 컴포넌트 (이전 분석에서 제외)
| 컴포넌트 | 제외 이유 |
|---|---|
v2-split-panel-enhanced |
커스텀 모드로 대체 가능 |
v2-modal-complex |
기존 모달 화면으로 충분 |
최종 필요 작업:
1. ✅ v2-split-panel-layout 확장 - displayMode: "custom" 추가 [완료]
2. ✅ v2-table-grouped 신규 개발 - 그룹화 테이블 (접기/펼치기) [완료]
3. v2-timeline-scheduler 신규 개발 - 타임라인/간트차트 (핵심!)
4.5 현재 구현 가능한 최대 범위
현재 V2 컴포넌트로 구현 가능한 최대 범위:
┌──────────────────────────────────────────────────────────────┐
│ 검색 섹션 (v2-table-search-widget) │
├──────────────────────────────────────────────────────────────┤
│ │
│ 생산계획 테이블 (v2-table-list) - 단일 테이블, 그룹화 없음 │
│ │
├──────────────────────────────────────────────────────────────┤
│ [등록] [수정] [삭제] (v2-button-primary) │
└──────────────────────────────────────────────────────────────┘
구현 불가능한 핵심 기능:
- 품목별 그룹핑 (접기/펼치기)
- 간트차트 타임라인
- 자동 스케줄 생성
- 드래그로 스케줄 이동
4.6 정식 버전 구현 구조 (확장 후)
v2-split-panel-layout에 커스텀 모드를 추가한 후의 정식 버전 구현 구조:
┌──────────────────────────────────────────────────────────────────────┐
│ v2-split-panel-layout (양쪽 패널 displayMode: "custom") │
├────────────────────────────────┬─────────────────────────────────────┤
│ leftPanel.components: [ │ rightPanel.components: [ │
│ v2-tabs-widget { │ v2-tabs-widget { │
│ tabs: [ │ tabs: [ │
│ { │ { │
│ label: "수주데이터", │ label: "완제품 생산계획", │
│ components: [ │ components: [ │
│ v2-table-grouped │ v2-timeline-scheduler │
│ ] │ ] │
│ }, │ }, │
│ { │ { │
│ label: "안전재고부족", │ label: "반제품 생산계획", │
│ components: [ │ components: [ │
│ v2-table-grouped │ v2-timeline-scheduler │
│ ] │ ] │
│ } │ } │
│ ] │ ] │
│ } │ } │
│ ] │ ] │
└────────────────────────────────┴─────────────────────────────────────┘
컴포넌트 중첩 구조:
v2-split-panel-layout (displayMode: "custom")
├── leftPanel.components[]
│ └── v2-tabs-widget
│ ├── tabs[0]: "수주데이터"
│ │ └── components[]
│ │ └── v2-table-grouped (품목별 그룹화)
│ └── tabs[1]: "안전재고부족"
│ └── components[]
│ └── v2-table-grouped
│
└── rightPanel.components[]
└── v2-tabs-widget
├── tabs[0]: "완제품 생산계획"
│ └── components[]
│ └── v2-timeline-scheduler (간트차트)
└── tabs[1]: "반제품 생산계획"
└── components[]
└── v2-timeline-scheduler
장점:
- 기존
v2-tabs-widget로직 100% 재사용 - 패널 안에 어떤 컴포넌트든 배치 가능
- 별도
v2-split-panel-enhanced개발 불필요 - 확장성 뛰어남 (향후 다른 복합 화면에도 적용 가능)
5. 단순화된 구현 방안 (임시)
현재 V2 컴포넌트만으로 간소화된 버전을 구현할 수 있습니다.
5.1 간소화 버전 레이아웃
┌──────────────────────────────────────────────────────────────┐
│ 검색 섹션 │
│ [품목코드] [품명] [계획기간] [상태] [사용자옵션] [엑셀다운로드] │
├──────────────────────────────────────────────────────────────┤
│ │
│ 생산계획 목록 테이블 │
│ (단일 테이블, 그룹화 없음) │
│ │
├──────────────────────────────────────────────────────────────┤
│ [신규등록] [수정] [삭제] │
└──────────────────────────────────────────────────────────────┘
5.2 컴포넌트 배치도 (간소화 버전)
┌─────────────────────────────────────────────────────────────────────────────┐
│ v2-table-search-widget (comp_search) │
│ [품목코드] [품명] [계획기간: 시작~종료] [상태] [조회] [엑셀다운로드] │
├─────────────────────────────────────────────────────────────────────────────┤
│ 생산계획 목록 [신규등록] [수정] [삭제] [작업지시 생성] │
│ ─────────────────────────────────────────────────────────────────────────── │
│ v2-table-list (comp_table) │
│ □ | 계획번호 | 계획일자 | 품목코드 | 품명 | 계획수량 | 시작일 | 종료일 | ... │
│ □ | PP-001 | 2026-01 | ITEM001 | 제품A| 1,000 | 01-30 | 02-05 | ... │
│ □ | PP-002 | 2026-01 | ITEM002 | 제품B| 500 | 02-01 | 02-10 | ... │
│ │
│ [1] [2] [3] ... [10] 페이지당: [20] ▼ │
└─────────────────────────────────────────────────────────────────────────────┘
5.3 컴포넌트 목록 (간소화 버전)
| 컴포넌트 ID | 컴포넌트 타입 | 역할 |
|---|---|---|
comp_search |
v2-table-search-widget | 검색 필터 |
comp_table |
v2-table-list | 생산계획 목록 |
comp_btn_register |
v2-button-primary | 신규 등록 |
comp_btn_edit |
v2-button-primary | 수정 |
comp_btn_delete |
v2-button-primary | 삭제 |
comp_btn_work_order |
v2-button-primary | 작업지시 생성 |
5.4 간소화 버전 테이블 컬럼
| 순서 | 컬럼명 | 표시명 | 정렬 | 형식 | 너비 |
|---|---|---|---|---|---|
| 1 | plan_no | 계획번호 | left | text | 120 |
| 2 | plan_date | 계획일자 | center | date | 100 |
| 3 | item_code | 품목코드 | left | text | 100 |
| 4 | item_name | 품명 | left | text | 150 |
| 5 | plan_qty | 계획수량 | right | number | 100 |
| 6 | start_date | 시작일 | center | date | 100 |
| 7 | end_date | 종료일 | center | date | 100 |
| 8 | due_date | 납기일 | center | date | 100 |
| 9 | equipment_name | 설비 | left | text | 120 |
| 10 | status | 상태 | center | badge | 80 |
| 11 | manager_name | 담당자 | left | text | 100 |
| 12 | product_type | 제품유형 | center | text | 80 |
5.5 간소화 버전 모달 필드
| 필드명 | 라벨 | 타입 | 필수 | 비고 |
|---|---|---|---|---|
| plan_no | 계획번호 | text (readonly) | ✅ | 자동채번: PP-YYYYMMDD-0001 |
| plan_date | 계획일자 | date | ✅ | 기본값: 오늘 |
| item_code | 품목코드 | select (품목 검색) | ✅ | 엔티티: item_info |
| item_name | 품명 | text (readonly) | 자동 입력 | |
| plan_qty | 계획수량 | number | ✅ | min: 1 |
| start_date | 시작일 | date | ✅ | |
| end_date | 종료일 | date | ✅ | start_date 이후 |
| due_date | 납기일 | date | ||
| equipment_id | 설비 | select | 엔티티: equipment_info | |
| equipment_name | 설비명 | text (readonly) | 자동 입력 | |
| status | 상태 | select | ✅ | 공통코드: PROD_PLAN_STATUS |
| priority | 우선순위 | select | 공통코드: PRIORITY | |
| work_shift | 작업조 | select | 공통코드: WORK_SHIFT | |
| manager_name | 담당자 | text | ||
| product_type | 제품유형 | select | 공통코드: PRODUCT_TYPE | |
| remarks | 비고 | textarea |
5.6 상태 배지 및 공통코드
상태 (PROD_PLAN_STATUS)
| 코드 | 표시명 | 배경색 | 글자색 |
|---|---|---|---|
| 계획 | 계획 | #dbeafe | #1e40af |
| 지시 | 지시 | #fef3c7 | #92400e |
| 진행 | 진행 | #d1fae5 | #065f46 |
| 완료 | 완료 | #f3f4f6 | #4b5563 |
우선순위 (PRIORITY)
| 코드 | 표시명 |
|---|---|
| 긴급 | 긴급 |
| 높음 | 높음 |
| 보통 | 보통 |
| 낮음 | 낮음 |
작업조 (WORK_SHIFT)
| 코드 | 표시명 |
|---|---|
| 주간 | 주간 |
| 야간 | 야간 |
| 주야 | 주야 |
제품유형 (PRODUCT_TYPE)
| 코드 | 표시명 |
|---|---|
| 완제품 | 완제품 |
| 반제품 | 반제품 |
6. 원본 HTML 기능 상세 분석
6.1 수주데이터 탭 (왼쪽 패널)
테이블 구조:
- 품목별 그룹 행 (접기/펼치기 가능)
- 수주 상세 행 (그룹 행 하위)
품목 그룹 행 컬럼:
| 컬럼 | 설명 |
|---|---|
| 체크박스 | 품목 그룹 선택 |
| 토글 | 상세 접기/펼치기 |
| 품목코드 | |
| 품목명 | |
| 총수주량 | 해당 품목의 모든 수주 합계 |
| 출고량 | |
| 잔량 | 총수주량 - 출고량 |
| 현재고 | |
| 안전재고 | |
| 출하계획량 | |
| 기생산계획량 | 이미 등록된 생산계획 수량 |
| 생산진행 | 현재 생산 중인 수량 |
| 필요생산계획 | 추가로 계획해야 할 수량 (빨간색 강조) |
수주 상세 행:
- 수주번호, 거래처, 상태 배지
- 수주량, 출고량, 잔량
- 납기일
버튼:
계획에 없는 품목만체크박스 필터선택 품목 불러오기: 선택한 품목을 생산계획으로 등록새로고침
6.2 안전재고 부족분 탭 (왼쪽 패널)
테이블 컬럼:
| 컬럼 | 설명 |
|---|---|
| 체크박스 | |
| 품목코드 | |
| 품목명 | |
| 현재고 | |
| 안전재고 | |
| 부족수량 | 빨간색 (마이너스) |
| 권장생산량 | 녹색 |
| 최종입고일 |
6.3 완제품 생산계획 탭 (오른쪽 패널)
스케줄 옵션:
- 안전리드타임 (일)
- 표시 기간 (주)
- 미진행 계획 재계산 체크박스
범례:
- 계획 (파란색)
- 지시 (주황색)
- 진행 (녹색)
- 완료 (회색)
- 납기일 (빨간 테두리)
- 긴급 (빨간 아이콘)
타임라인 구조:
- 날짜별 헤더 (일/월 표시, 주말 강조, 오늘 강조)
- 품목별 행
- 생산계획 바 (드래그로 이동 가능)
- 클릭 시 상세 모달 오픈
버튼:
새로고침자동 스케줄 생성: 선택된 품목에 대해 자동으로 생산계획 생성선택 계획 병합: 같은 품목의 계획을 하나로 병합선택 품목 → 반제품 계획: BOM 기반 반제품 계획 생성저장초기화
6.4 반제품 생산계획 탭 (오른쪽 패널)
옵션:
- 현재고 및 안전재고 감안
- 진행중인 계획 유지하고 재계산
- 투입 완료된 반제품 제외
안내:
- 완제품 생산계획 기준으로 필요한 반제품 계획 자동 생성
- 모품목 생산 시작일 고려하여 납기일 설정
- BOM(자재명세서) 정보 기반 필요 수량 계산
6.5 생산 스케줄 상세 모달
기본 정보:
- 품목코드 (읽기전용)
- 품목명 (읽기전용)
근거 정보:
- 수주번호, 안전재고, 재고부족 등 표시
생산 정보:
- 총 생산수량
- 납기일 (읽기전용)
- 계획 시작일 (수정 가능)
- 계획 종료일 (수정 가능)
- 생산 기간 (자동 계산)
과거 계획 경고:
- 시작일이 과거인 경우 경고 표시
오늘부터 재조정버튼작업지시 즉시 생성버튼
계획 분할:
- 분할 개수 선택 (2~4개)
- 각 분할 수량 입력
- 분할 실행
설비 할당:
- 설비 선택 버튼
- 선택된 설비 목록
생산 상태:
- 상태 (자동 관리): 계획됨/작업지시/진행중/완료
추가 정보:
- 담당자
- 작업지시번호
- 비고
버튼:
- 삭제
- 취소
- 저장
7. 구현 우선순위
Phase 1: 간소화 버전 (현재 구현 가능)
V2 컴포넌트로 기본 CRUD 화면 구현:
- 검색 위젯
- 단일 테이블 (그룹화 없음)
- 기본 모달 폼
- 상태 배지
Phase 2: 컴포넌트 확장 및 개발
-
✅ 완료v2-split-panel-layout확장- ✅
displayMode: "custom"추가 - ✅
components[]필드 지원 (탭 컴포넌트와 동일한 구조) - ✅ 디자인 모드에서 컴포넌트 드래그&드롭 지원
- ✅ 컴포넌트 클릭 시 좌측 설정 패널에서 속성 편집
- ✅
-
✅ 완료v2-table-grouped신규 개발- ✅ 품목별 그룹핑 (접기/펼치기)
- ✅ 그룹 행과 상세 행 구분
- ✅ 체크박스 선택 (그룹 단위 / 개별 단위)
- ✅ 그룹 요약 (개수, 합계, 평균 등)
Phase 3: 타임라인 스케줄러
-
v2-timeline-scheduler신규 개발- 간트차트 형태 타임라인
- 날짜 그리드 (일/주/월 단위)
- 생산계획 바 렌더링
-
드래그&드롭 기능
- 계획 바 드래그로 날짜 이동
- 계획 바 크기 조정 (기간 변경)
-
비즈니스 로직
- 자동 스케줄 생성 API
- BOM 기반 반제품 계획 연동
- 설비별 용량 체크
8. 참고 사항
8.1 상태 배지 스타일
| 상태 | 배경색 | 글자색 | 설명 |
|---|---|---|---|
| 계획 | #dbeafe | #1e40af | 파란색 |
| 지시 | #fef3c7 | #92400e | 주황색 |
| 진행 | #d1fae5 | #065f46 | 녹색 |
| 완료 | #f3f4f6 | #4b5563 | 회색 |
| 긴급 | #fee2e2 | #991b1b | 빨간색 |
8.2 자동 스케줄 생성 로직
1. 선택된 품목의 필요 생산수량 계산
- 필요수량 = 잔량 + 안전재고 - 현재고 - 기생산계획량
2. 납기일에서 안전리드타임 차감하여 완료일 계산
3. 일일 생산능력으로 필요 생산일수 계산
4. 완료일에서 역산하여 시작일 계산
5. 설비 가용성 확인 및 자동 할당
6. 반제품이 필요한 경우 BOM 기반 반제품 계획 생성
8.3 계획 분할 로직
1. 원본 계획의 총 수량 확인
2. 분할 개수 선택 (2~4개)
3. 각 분할 수량 입력 (합계 = 원본 수량)
4. 분할 실행 시:
- 원본 계획 삭제
- 새로운 N개의 계획 생성
- 각각 별도의 시작일/종료일 설정 가능
9. DB INSERT JSON (간소화 버전)
⚠️ 이 JSON은 간소화 버전입니다. 전체 기능 구현 시 별도 개발이 필요합니다.
9.1 screen_definitions
{
"screen_name": "생산계획관리",
"screen_code": "{COMPANY_CODE}_PP_MAIN",
"table_name": "production_plan_mng",
"company_code": "{COMPANY_CODE}",
"description": "생산계획 관리 화면 (간소화 버전)",
"is_active": "Y",
"db_source_type": "internal",
"data_source_type": "database"
}
9.2 screen_layouts_v2.layout_data (간소화 버전)
{
"version": "2.0",
"components": [
{
"id": "comp_search",
"url": "@/lib/registry/components/v2-table-search-widget",
"size": { "width": 1920, "height": 80 },
"position": { "x": 0, "y": 20, "z": 1 },
"overrides": {
"type": "v2-table-search-widget",
"label": "검색 필터",
"searchFields": [
{ "field": "item_code", "label": "품목코드", "type": "text" },
{ "field": "item_name", "label": "품명", "type": "text" },
{ "field": "plan_date", "label": "계획기간", "type": "daterange" },
{
"field": "status",
"label": "상태",
"type": "select",
"options": [
{ "value": "", "label": "전체" },
{ "value": "계획", "label": "계획" },
{ "value": "지시", "label": "지시" },
{ "value": "진행", "label": "진행" },
{ "value": "완료", "label": "완료" }
]
}
],
"targetTableId": "comp_table"
},
"displayOrder": 0
},
{
"id": "comp_table",
"url": "@/lib/registry/components/v2-table-list",
"size": { "width": 1920, "height": 700 },
"position": { "x": 0, "y": 120, "z": 1 },
"overrides": {
"type": "v2-table-list",
"label": "생산계획 목록",
"columns": [
{ "columnName": "plan_no", "displayName": "계획번호", "order": 0, "visible": true, "sortable": true, "format": "text", "align": "left", "width": 120 },
{ "columnName": "plan_date", "displayName": "계획일자", "order": 1, "visible": true, "sortable": true, "format": "date", "align": "center", "width": 100 },
{ "columnName": "item_code", "displayName": "품목코드", "order": 2, "visible": true, "sortable": true, "format": "text", "align": "left", "width": 100 },
{ "columnName": "item_name", "displayName": "품명", "order": 3, "visible": true, "sortable": true, "format": "text", "align": "left", "width": 150 },
{ "columnName": "plan_qty", "displayName": "계획수량", "order": 4, "visible": true, "sortable": true, "format": "number", "align": "right", "width": 100 },
{ "columnName": "start_date", "displayName": "시작일", "order": 5, "visible": true, "sortable": true, "format": "date", "align": "center", "width": 100 },
{ "columnName": "end_date", "displayName": "종료일", "order": 6, "visible": true, "sortable": true, "format": "date", "align": "center", "width": 100 },
{ "columnName": "due_date", "displayName": "납기일", "order": 7, "visible": true, "sortable": true, "format": "date", "align": "center", "width": 100 },
{ "columnName": "equipment_name", "displayName": "설비", "order": 8, "visible": true, "sortable": true, "format": "text", "align": "left", "width": 120 },
{
"columnName": "status",
"displayName": "상태",
"order": 9,
"visible": true,
"sortable": true,
"format": "badge",
"align": "center",
"width": 80,
"badgeConfig": {
"계획": { "background": "#dbeafe", "color": "#1e40af" },
"지시": { "background": "#fef3c7", "color": "#92400e" },
"진행": { "background": "#d1fae5", "color": "#065f46" },
"완료": { "background": "#f3f4f6", "color": "#4b5563" }
}
},
{ "columnName": "product_type", "displayName": "제품유형", "order": 10, "visible": true, "sortable": true, "format": "text", "align": "center", "width": 80 },
{ "columnName": "manager_name", "displayName": "담당자", "order": 11, "visible": true, "sortable": true, "format": "text", "align": "left", "width": 100 }
],
"selectedTable": "production_plan_mng",
"pagination": { "enabled": true, "pageSize": 20, "pageSizeOptions": [10, 20, 50, 100] },
"checkbox": { "enabled": true, "multiple": true },
"horizontalScroll": { "enabled": true, "minColumnWidth": 80, "maxColumnWidth": 200 },
"defaultSort": { "field": "plan_date", "order": "desc" }
},
"displayOrder": 1
},
{
"id": "comp_btn_register",
"url": "@/lib/registry/components/v2-button-primary",
"size": { "width": 100, "height": 40 },
"position": { "x": 1480, "y": 70, "z": 1 },
"overrides": {
"text": "신규 등록",
"type": "v2-button-primary",
"action": { "type": "modal", "modalTitle": "생산계획 등록", "targetScreenId": null },
"variant": "success"
},
"displayOrder": 2
},
{
"id": "comp_btn_edit",
"url": "@/lib/registry/components/v2-button-primary",
"size": { "width": 80, "height": 40 },
"position": { "x": 1590, "y": 70, "z": 1 },
"overrides": {
"text": "수정",
"type": "v2-button-primary",
"action": { "type": "edit", "modalTitle": "생산계획 수정", "targetScreenId": null },
"variant": "secondary",
"requireSelection": true
},
"displayOrder": 3
},
{
"id": "comp_btn_delete",
"url": "@/lib/registry/components/v2-button-primary",
"size": { "width": 80, "height": 40 },
"position": { "x": 1680, "y": 70, "z": 1 },
"overrides": {
"text": "삭제",
"type": "v2-button-primary",
"action": { "type": "delete" },
"variant": "danger",
"requireSelection": true,
"enableDataflowControl": true,
"dataflowDiagramId": null
},
"displayOrder": 4
},
{
"id": "comp_btn_work_order",
"url": "@/lib/registry/components/v2-button-primary",
"size": { "width": 120, "height": 40 },
"position": { "x": 1770, "y": 70, "z": 1 },
"overrides": {
"text": "작업지시 생성",
"type": "v2-button-primary",
"action": { "type": "custom" },
"variant": "primary",
"requireSelection": true,
"enableDataflowControl": true,
"dataflowDiagramId": null,
"confirmMessage": "선택한 계획에 대해 작업지시를 생성하시겠습니까?"
},
"displayOrder": 5
}
]
}
10. 비즈니스 로직 요청서 (간소화 버전)
중요: 이 섹션은 표준 양식에 따라 작성되었습니다.
=== 비즈니스 로직 요청서 ===
【화면 정보】
- 화면명: 생산계획관리 (간소화 버전)
- 회사코드: {COMPANY_CODE}
- 메뉴ID: {TBD}
【테이블 정보】
- 메인 테이블: production_plan_mng
- 디테일 테이블: 없음 (간소화 버전)
- 관계 FK: 없음
【버튼 목록】
버튼1:
- 버튼명: 신규 등록
- 동작 유형: 모달 열기 (insert)
- 조건: 없음
- 대상 테이블: production_plan_mng
- 추가 동작:
1. plan_no 자동채번 (PP-YYYYMMDD-0001)
2. plan_date 기본값 = 오늘
3. status 기본값 = '계획'
버튼2:
- 버튼명: 수정
- 동작 유형: 모달 열기 (update)
- 조건: 행 선택 필수
- 대상 테이블: production_plan_mng
- 추가 동작: 없음
버튼3:
- 버튼명: 삭제
- 동작 유형: 삭제 (delete)
- 조건:
1. 행 선택 필수
2. status != '진행' AND status != '완료'
- 대상 테이블: production_plan_mng
- 추가 동작: 삭제 확인 다이얼로그
버튼4:
- 버튼명: 작업지시 생성
- 동작 유형: 수정 (update)
- 조건:
1. 행 선택 필수 (다중 선택 가능)
2. status = '계획'
- 대상 테이블: production_plan_mng
- 추가 동작:
1. status를 '지시'로 변경
2. work_order_no 자동채번 (WO-YYYYMMDD-0001)
3. work_order_mng에 INSERT (작업지시 테이블)
【추가 요구사항】
- 진행/완료 상태의 계획은 수정/삭제 불가
- 계획번호(plan_no) 자동채번: PP-YYYYMMDD-0001
- 품목코드 선택 시 품명 자동 입력
- 설비 선택 시 시간당 생산능력 자동 입력
- 시작일/종료일 기반 생산기간 자동 계산
11. 제어관리 설정 (dataflow_diagrams)
11.1 신규 등록 버튼 (기본 저장)
기본 INSERT 액션은 화면 디자이너에서 처리되므로 별도 dataflow 불필요
11.2 삭제 버튼 (조건부 삭제)
{
"diagram_name": "생산계획관리_삭제",
"company_code": "{COMPANY_CODE}",
"control": {
"actionType": "delete",
"triggerType": "before",
"conditions": [
{
"id": "cond-status-not-in-progress",
"type": "condition",
"field": "status",
"operator": "!=",
"value": "진행",
"dataType": "string"
},
{
"id": "cond-status-not-completed",
"type": "condition",
"field": "status",
"operator": "!=",
"value": "완료",
"dataType": "string"
}
],
"conditionLogic": "AND",
"errorMessage": "진행 중이거나 완료된 계획은 삭제할 수 없습니다."
},
"plan": {
"actions": [
{
"id": "action-delete",
"actionType": "delete",
"targetTable": "production_plan_mng"
}
]
}
}
11.3 작업지시 생성 버튼
{
"diagram_name": "생산계획관리_작업지시생성",
"company_code": "{COMPANY_CODE}",
"control": {
"actionType": "update",
"triggerType": "after",
"conditions": [
{
"id": "cond-status-plan",
"type": "condition",
"field": "status",
"operator": "=",
"value": "계획",
"dataType": "string"
}
],
"errorMessage": "계획 상태인 항목만 작업지시를 생성할 수 있습니다."
},
"plan": {
"actions": [
{
"id": "action-update-status",
"actionType": "update",
"targetTable": "production_plan_mng",
"fieldMappings": [
{ "targetField": "status", "defaultValue": "지시" },
{ "targetField": "updated_date", "defaultValue": "#NOW" },
{ "targetField": "updated_by", "defaultValue": "#USER" }
]
},
{
"id": "action-insert-workorder",
"actionType": "insert",
"targetTable": "work_order_mng",
"fieldMappings": [
{ "sourceField": "plan_no", "targetField": "plan_no" },
{ "sourceField": "item_code", "targetField": "item_code" },
{ "sourceField": "item_name", "targetField": "item_name" },
{ "sourceField": "plan_qty", "targetField": "order_qty" },
{ "sourceField": "start_date", "targetField": "work_start_date" },
{ "sourceField": "end_date", "targetField": "work_end_date" },
{ "sourceField": "equipment_id", "targetField": "equipment_id" },
{ "sourceField": "equipment_name", "targetField": "equipment_name" },
{ "targetField": "status", "defaultValue": "대기" },
{ "targetField": "company_code", "defaultValue": "#COMPANY" },
{ "targetField": "created_date", "defaultValue": "#NOW" },
{ "targetField": "created_by", "defaultValue": "#USER" }
]
}
]
}
}
12. 컴포넌트 연동 설정 (간소화 버전)
12.1 이벤트 흐름
[화면 진입]
│
▼
v2-table-search-widget (검색 필터)
│ onFilterChange
▼
v2-table-list (생산계획 목록)
│ onRowSelect
▼
[버튼 활성화/비활성화]
│
├── [신규 등록] 클릭 → 등록 모달 오픈
│ │ onSave
│ ▼
│ INSERT → 테이블 Refresh
│
├── [수정] 클릭 → 수정 모달 오픈
│ │ onSave
│ ▼
│ UPDATE → 테이블 Refresh
│
├── [삭제] 클릭 → 조건 체크
│ │ 통과 시
│ ▼
│ DELETE → 테이블 Refresh
│
└── [작업지시 생성] 클릭 → 조건 체크
│ 통과 시
▼
UPDATE + INSERT → 테이블 Refresh
12.2 연동 설정 테이블
| 소스 컴포넌트 | 이벤트 | 대상 컴포넌트 | 동작 |
|---|---|---|---|
| search-widget | onFilterChange | main-table | 필터 적용 후 재조회 |
| main-table | onRowSelect | btn-edit, btn-delete | 버튼 활성화 |
| main-table | onRowDoubleClick | modal-edit | 수정 모달 오픈 |
| btn-register | onClick | modal-register | 등록 모달 오픈 |
| btn-edit | onClick | modal-edit | 수정 모달 오픈 |
| btn-delete | onClick | dataflow | 삭제 실행 |
| btn-work-order | onClick | dataflow | 작업지시 생성 실행 |
| modal-* | onSave | main-table | 테이블 새로고침 |
13. 사용자 사용 예시 시나리오 (간소화 버전)
시나리오 1: 생산계획 조회
| 단계 | 사용자 동작 | 기대 결과 |
|---|---|---|
| 1 | 화면 진입 | 전체 생산계획 목록 표시 (최근순) |
| 2 | 품목코드 입력 후 [조회] 클릭 | 해당 품목의 생산계획만 필터링 |
| 3 | 상태 드롭다운에서 '계획' 선택 | 계획 상태인 항목만 표시 |
| 4 | 컬럼 헤더 클릭 | 해당 컬럼 기준 정렬 |
시나리오 2: 생산계획 등록
| 단계 | 사용자 동작 | 기대 결과 |
|---|---|---|
| 1 | [신규 등록] 버튼 클릭 | 등록 모달 오픈 |
| 2 | 품목코드 검색/선택 | 품명 자동 입력 |
| 3 | 계획수량, 시작일, 종료일 입력 | 입력 필드 채움 |
| 4 | 설비 선택 | 시간당 생산능력 표시 |
| 5 | [저장] 버튼 클릭 | 저장 완료, 목록에 신규 행 표시 |
시나리오 3: 생산계획 수정
| 단계 | 사용자 동작 | 기대 결과 |
|---|---|---|
| 1 | 목록에서 행 선택 | 행 하이라이트 |
| 2 | [수정] 버튼 클릭 (또는 더블클릭) | 수정 모달 오픈 (기존 값 로드) |
| 3 | 필요한 필드 수정 | 값 변경 |
| 4 | [저장] 버튼 클릭 | 저장 완료, 목록 갱신 |
시나리오 4: 생산계획 삭제
| 단계 | 사용자 동작 | 기대 결과 |
|---|---|---|
| 1 | 삭제할 행 체크박스 선택 | 선택 표시 |
| 2 | [삭제] 버튼 클릭 | 삭제 확인 다이얼로그 표시 |
| 3-a | (상태가 계획/지시) 확인 클릭 | 삭제 완료, 목록에서 제거 |
| 3-b | (상태가 진행/완료) 확인 클릭 | "삭제할 수 없습니다" 오류 메시지 |
시나리오 5: 작업지시 생성
| 단계 | 사용자 동작 | 기대 결과 |
|---|---|---|
| 1 | 계획 상태인 행 체크박스 선택 (다중 가능) | 선택 표시 |
| 2 | [작업지시 생성] 버튼 클릭 | 확인 다이얼로그 표시 |
| 3-a | (상태가 계획) 확인 클릭 | 상태가 '지시'로 변경, 작업지시번호 생성 |
| 3-b | (상태가 계획 아님) 확인 클릭 | "계획 상태만 가능합니다" 오류 메시지 |
14. 검증 체크리스트
14.1 기능 테스트
- 데이터 조회가 정상 동작하는가?
- 검색 필터가 정상 동작하는가?
- 신규 등록이 정상 동작하는가?
- 수정이 정상 동작하는가?
- 삭제가 정상 동작하는가? (조건 포함)
- 작업지시 생성이 정상 동작하는가? (조건 포함)
- 페이지네이션이 정상 동작하는가?
- 정렬이 정상 동작하는가?
14.2 데이터 검증
- 계획번호(plan_no) 자동채번이 중복 없이 생성되는가?
- 품목코드 선택 시 품명이 자동 입력되는가?
- 설비 선택 시 시간당 생산능력이 표시되는가?
- company_code 필터링이 적용되는가? (멀티테넌시)
14.3 비즈니스 룰 검증
- 진행/완료 상태는 삭제 불가한가?
- 계획 상태만 작업지시 생성 가능한가?
- 작업지시 생성 시 work_order_mng에 데이터가 INSERT되는가?
15. 구현 체크리스트
15.1 간소화 버전 (현재 구현 가능)
| 체크 | 항목 | 설명 |
|---|---|---|
| ☐ | 테이블 생성 | production_plan_mng 테이블 생성 |
| ☐ | 화면 정의 | screen_definitions INSERT |
| ☐ | 모달 화면 생성 | 등록/수정 모달 화면 생성 |
| ☐ | 메인 화면 생성 | screen_layouts_v2 INSERT |
| ☐ | 제어관리 설정 | dataflow_diagrams INSERT (삭제, 작업지시 생성) |
| ☐ | 메뉴 연결 | 대상 메뉴에 화면 할당 |
| ☐ | 기본 CRUD 테스트 | 등록/수정/삭제/조회 테스트 |
| ☐ | 비즈니스 룰 테스트 | 조건부 삭제, 작업지시 생성 테스트 |
15.2 전체 버전 (향후 구현)
| 체크 | 항목 | 설명 |
|---|---|---|
| ✅ | displayMode: "custom" + components[] 추가 완료 |
|
| ✅ | 그룹화 테이블 컴포넌트 완료 | |
| ☐ | v2-timeline-scheduler 개발 | 타임라인/간트차트 스케줄러 |
| ☐ | 드래그&드롭 기능 | 타임라인 바 드래그 이동/크기 조정 |
| ☐ | 자동 스케줄 로직 | 자동 스케줄 생성 백엔드 API |
| ☐ | 반제품 연동 | BOM 기반 반제품 계획 생성 |
| ☐ | 정식 버전 화면 구성 | 커스텀 모드로 탭+테이블+타임라인 조합 |
16. 자동 스케줄 생성 기능
상세 가이드: 스케줄 자동 생성 기능 구현 가이드
16.1 개요
좌측 수주 테이블에서 품목을 선택하고 "자동 스케줄 생성" 버튼을 클릭하면, 선택된 품목들에 대한 생산 스케줄이 자동으로 생성되어 우측 타임라인에 표시됩니다.
16.2 데이터 흐름
1. 좌측 v2-table-grouped에서 품목 선택 (그룹 선택 시 자식 포함)
2. "자동 스케줄 생성" 버튼 클릭
3. 백엔드 API에서 미리보기 생성 (생성/삭제/수정될 스케줄)
4. 변경사항 확인 다이얼로그 표시
5. 확인 시 스케줄 적용 및 타임라인 새로고침
6. 다음 방문 시: 좌측 선택 → linkedFilter로 우측 자동 필터링
16.3 스케줄 생성 설정
{
"scheduleType": "PRODUCTION",
"source": {
"componentId": "order_table",
"tableName": "sales_order_mng",
"groupByField": "part_code",
"quantityField": "balance_qty",
"dueDateField": "due_date"
},
"resource": {
"type": "ITEM",
"idField": "part_code",
"nameField": "part_name"
},
"rules": {
"leadTimeDays": 3,
"dailyCapacity": 100,
"workingDays": [1, 2, 3, 4, 5],
"considerStock": true,
"stockTableName": "inventory_mng",
"stockQtyField": "current_qty"
},
"target": {
"tableName": "production_plan_mng",
"timelineComponentId": "production_timeline"
}
}
16.4 버튼 설정
{
"componentType": "v2-button-primary",
"componentId": "btn_auto_schedule",
"componentConfig": {
"label": "자동 스케줄 생성",
"variant": "default",
"icon": "Calendar",
"action": {
"type": "custom",
"customAction": "autoGenerateSchedule",
"scheduleConfig": { /* 위 설정 */ }
}
}
}
16.5 연결 필터 설정 (linkedFilters)
좌측 테이블 선택 시 우측 타임라인 자동 필터링:
{
"linkedFilters": [
{
"sourceComponentId": "order_table",
"sourceField": "part_code",
"targetColumn": "resource_id"
}
]
}
16.6 구현 상태
| 항목 | 상태 | 비고 |
|---|---|---|
| schedule_mng 테이블 | ⏳ 대기 | 범용 스케줄 테이블 |
| /api/schedule/preview API | ⏳ 대기 | 미리보기 |
| /api/schedule/apply API | ⏳ 대기 | 적용 |
| autoGenerateSchedule 버튼 액션 | ⏳ 대기 | buttonActions.ts |
| 확인 다이얼로그 | ⏳ 대기 | 기존 AlertDialog 활용 |
| linkedFilter 연동 | ⏳ 대기 | 타임라인 필터링 |