diff --git a/INDEX.md b/INDEX.md index 16dcb30..f991b9f 100644 --- a/INDEX.md +++ b/INDEX.md @@ -20,6 +20,7 @@ | Blade+React | `dev/standards/blade-react-policy.md` | Blade JSX 이중 중괄호 충돌 방지 | | 이메일 연동 | `dev/guides/tenant-email-integration-guide.md` | 테넌트 메일 연동, SMTP 프리셋, MNG 관리 | | 품목관리 | `rules/item-policy.md` | 품목 정책 | +| BOM V2 설계 | `plans/bom-v2-universal-architecture-plan.md` | 범용 멀티테넌트 BOM V2 아키텍처 | | 단가관리 | `rules/pricing-policy.md` | 6 Depth 단가 체계, 흐름도, 계산공식, 버전관리 개선방향 | | 단가 버전관리 기획 | `dev/dev_plans/price-version-management-plan.md` | 단가 버전 그룹, 일괄변경, 영향분석, 적용 워크플로우 | | 견적관리 | `features/quotes/README.md` | 견적 시스템, BOM 계산 | @@ -375,6 +376,7 @@ DB 도메인별: | [bom-tree-3level-react-request.md](plans/bom-tree-3level-react-request.md) | BOM 트리 3단계 그룹 표시 React 구현 요청 (API 완료, 카테고리 접힘/펼침) | | [item-list-search-state-preservation.md](plans/item-list-search-state-preservation.md) | 품목관리 검색 상태 보존 UX 개선 요청 (router.back + URL searchParams 동기화) | | [optimal-stock-management-plan.md](plans/optimal-stock-management-plan.md) | 적정재고 관리 기능 기획 (안전재고+최대재고 범위 기반, 상태 확장) | +| [bom-v2-universal-architecture-plan.md](plans/bom-v2-universal-architecture-plan.md) | BOM V2 범용 멀티테넌트 아키텍처 설계 (V1 한계 분석, 관계형 BOM, 버전/팬텀/대체/공정 연동) | ### frontend/integration/ — 프론트엔드 개발 가이드 diff --git a/plans/bom-v2-universal-architecture-plan.md b/plans/bom-v2-universal-architecture-plan.md new file mode 100644 index 0000000..7e4fdb7 --- /dev/null +++ b/plans/bom-v2-universal-architecture-plan.md @@ -0,0 +1,824 @@ +# BOM V2 범용 멀티테넌트 아키텍처 설계 + +> **작성일**: 2026-03-22 +> **상태**: 설계 중 +> **담당**: R&D실 +> **목표**: 어떤 업종/회사도 수용 가능한 확장형 BOM 시스템 + +--- + +## 1. V1 현황 진단 + +### 1.1 현재 구조 (3중 병렬) + +``` +V1 BOM 시스템 +├── Product BOM (product_components) ← 레거시, 폐기 진행 중 +├── Design BOM (bom_templates) ← 수식 산출용 (활성) +└── Item BOM (items.bom JSON) ← 현재 표준 +``` + +| 시스템 | 저장 방식 | 계층 | 버전 | 상태 | +|--------|---------|:----:|:----:|------| +| Product BOM | 관계형 (product_components) | N-Level | 없음 | 폐기 중 | +| Design BOM | 관계형 (bom_template_items) | 1-Level | 모델 버전 | 수식 전용 | +| Item BOM | JSON (items.bom) | 1-Level* | 없음 | **표준** | + +> *Item BOM은 저장이 1-Level이지만, 자식의 BOM을 재귀 탐색하여 트리를 구성한다. + +### 1.2 V1 한계점 + +| 분류 | 한계 | 영향 | +|------|------|------| +| **구조** | BOM이 JSON 평탄 저장 → 다단계 재귀 탐색 필요 | 성능 저하, 순환 참조 위험 | +| **구조** | 3개 BOM 시스템 병렬 → 데이터 일관성 유지 어려움 | 유지보수 비용 | +| **버전** | BOM 버전/리비전 없음 (덮어쓰기) | 변경 이력 추적 불가 | +| **유형** | item_type 5종 고정 (FG/PT/SM/RM/CS) | 반제품(WIP), 팬텀 등 미지원 | +| **수식** | 산출 수식이 경동기업 제품에 하드코딩 | 다른 업종 적용 불가 | +| **공정** | BOM-공정(Routing) 연동 없음 | 공정별 자재 투입 관리 불가 | +| **대체** | 대체품목(Substitute) 미지원 | 자재 부족 시 대응 불가 | +| **유효** | BOM 유효기간(Effectivity) 없음 | 설계 변경 시점 관리 불가 | +| **수율** | 수율/로스율이 Design BOM에만 존재 | Item BOM에서 로스 관리 불가 | +| **원가** | BOM 기반 원가 계산 구조 없음 | 표준원가 산출 불가 | +| **승인** | BOM 승인 워크플로우 없음 | 무검증 BOM 변경 가능 | +| **비교** | BOM 간 diff/비교 기능 제한적 | 설계 변경 영향 분석 어려움 | + +### 1.3 V1에서 유지할 것 + +| 항목 | 이유 | +|------|------| +| `items` 통합 테이블 | Products+Materials 단일화 완료, 역행 불필요 | +| `tenant_id` + `BelongsToTenant` | 멀티테넌시 기반 확립 | +| `options` JSON 정책 | 확장성 확보 | +| `BomTemplate` 수식 엔진 | 파라미터 기반 산출 유지 | +| Category 계층 분류 | 기존 카테고리 시스템 활용 | + +--- + +## 2. V2 설계 원칙 + +### 2.1 핵심 원칙 + +``` +P1. 모든 업종 수용 — 이산/공정/조립/혼합 제조 전부 지원 +P2. 테넌트별 자율 — BOM 깊이, 유형, 수식을 테넌트가 정의 +P3. 단일 BOM 엔진 — 3중 병렬 → 1개 통합 BOM 테이블 +P4. 버전 필수 — 모든 BOM 변경은 리비전으로 관리 +P5. 하위 호환 — V1 JSON BOM 데이터 무손실 마이그레이션 +``` + +### 2.2 지원 대상 업종 + +| 업종 | BOM 특성 | V2 대응 | +|------|---------|---------| +| **블라인드/스크린** (현재) | 수식 기반, 가변 사이즈 | 수식 엔진 유지 | +| **기계 부품** | 다단계 조립, 가공 공정 | N-Level + Routing | +| **전자/반도체** | 대체품목, ECN 관리 | Substitute + Effectivity | +| **식품/화학** | 배합비, 수율, 부산물 | Formula BOM + Co-product | +| **건설/플랜트** | 프로젝트별 BOM, 대량 자재 | Project BOM + Bulk | +| **가구/인테리어** | 옵션 조합, 커스텀 | Configurable BOM | +| **의류/섬유** | 사이즈별 BOM, 색상별 원단 | Variant BOM | + +--- + +## 3. V2 데이터 모델 + +### 3.1 핵심 테이블 설계 + +``` +V2 BOM 테이블 구조 + +items (기존 유지 + 확장) + ├── item_type 확장: FG, SA, PT, WIP, PH, SM, RM, CS, BP, SV + └── bom 컬럼: 제거 (관계형으로 이관) + +bom_headers (신규 — BOM 헤더/버전) + ├── item_id → items + ├── revision (REV.01, REV.02 ...) + ├── status (DRAFT → PENDING → APPROVED → ACTIVE → OBSOLETE) + ├── effective_from / effective_to + └── bom_type (STANDARD | ENGINEERING | CONFIGURABLE | FORMULA) + +bom_lines (신규 — BOM 라인/구성품) + ├── bom_header_id → bom_headers + ├── child_item_id → items + ├── quantity + quantity_formula + ├── waste_rate (로스율) + ├── operation_id → operations (공정 연결) + ├── effective_from / effective_to (라인별 유효기간) + └── options JSON (확장 속성) + +bom_substitutes (신규 — 대체품목) + ├── bom_line_id → bom_lines + ├── substitute_item_id → items + ├── priority (대체 우선순위) + └── conversion_factor (환산 계수) + +operations (신규 — 공정/라우팅) + ├── item_id → items + ├── sequence (공정 순서) + ├── process_id → processes (공정 마스터) + ├── setup_time, run_time, wait_time + └── work_center_id (작업장) +``` + +### 3.2 ERD 관계 + +``` +items ───────────────────────────────────────────────── + │ (1:N) │ + ▼ │ +bom_headers ────────────────────────── │ + │ (1:N) │ │ + ▼ │ │ +bom_lines ─── (N:1) ──→ items ◄─────┘ │ + │ (1:N) │ │ + ▼ │ (N:1) │ +bom_substitutes ▼ │ + operations ─── (N:1) ──→ processes │ + │ │ + └── (N:1) ──→ work_centers │ + │ +bom_templates (기존 유지) │ + └── 수식 산출 → bom_headers 자동 생성 ───────────────┘ +``` + +### 3.3 items.item_type 확장 + +| 코드 | 한글 | 설명 | V1 | V2 | +|------|------|------|:--:|:--:| +| `FG` | 완제품 | 판매 가능한 최종 제품 | O | O | +| `SA` | 반조립품 | 중간 조립품 (재고 관리됨) | - | **신규** | +| `PT` | 부품 | 구성 부품 | O | O | +| `WIP` | 재공품 | 가공 중인 중간 산출물 | - | **신규** | +| `PH` | 팬텀 | 가상 그룹 (재고 없음, BOM 전개 시 투과) | - | **신규** | +| `SM` | 부자재 | 보조 자재 | O | O | +| `RM` | 원자재 | 주요 원료 | O | O | +| `CS` | 소모품 | 일회성 소모 자재 | O | O | +| `BP` | 부산물 | 생산 시 발생하는 부산물 | - | **신규** | +| `SV` | 서비스 | 외주 가공, 검사비 등 비물리 항목 | - | **신규** | + +> 테넌트별로 사용할 유형을 선택할 수 있다. 블라인드 업체는 FG/PT/SM/RM/CS만, 전자업체는 SA/PH까지 활성화. + +### 3.4 bom_headers 상세 + +```sql +CREATE TABLE bom_headers ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + tenant_id BIGINT UNSIGNED NOT NULL, + item_id BIGINT UNSIGNED NOT NULL, -- 부모 품목 + revision VARCHAR(20) NOT NULL DEFAULT 'REV.01', + bom_type VARCHAR(20) NOT NULL DEFAULT 'STANDARD', + -- STANDARD: 일반 BOM + -- ENGINEERING: 설계용 (비생산) + -- CONFIGURABLE: 옵션 조합 BOM + -- FORMULA: 배합/수식 BOM + status VARCHAR(20) NOT NULL DEFAULT 'DRAFT', + -- DRAFT → PENDING → APPROVED → ACTIVE → OBSOLETE + effective_from DATE NULL, -- 유효 시작 + effective_to DATE NULL, -- 유효 종료 + base_qty DECIMAL(18,6) NOT NULL DEFAULT 1, -- 기준 수량 + base_unit VARCHAR(20) NULL, -- 기준 단위 + description TEXT NULL, + approved_by BIGINT UNSIGNED NULL, -- 승인자 + approved_at DATETIME NULL, + source_template_id BIGINT UNSIGNED NULL, -- Design BOM 연결 + options JSON NULL, -- 확장 속성 + created_by BIGINT UNSIGNED NULL, + updated_by BIGINT UNSIGNED NULL, + created_at TIMESTAMP NULL, + updated_at TIMESTAMP NULL, + deleted_at TIMESTAMP NULL, + + UNIQUE KEY uq_bom_tenant_item_rev (tenant_id, item_id, revision, deleted_at), + INDEX idx_bom_tenant_item (tenant_id, item_id), + INDEX idx_bom_tenant_status (tenant_id, status), + INDEX idx_bom_effective (tenant_id, effective_from, effective_to) +); +``` + +### 3.5 bom_lines 상세 + +```sql +CREATE TABLE bom_lines ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + tenant_id BIGINT UNSIGNED NOT NULL, + bom_header_id BIGINT UNSIGNED NOT NULL, + child_item_id BIGINT UNSIGNED NOT NULL, -- 자식 품목 + quantity DECIMAL(18,6) NOT NULL DEFAULT 1, -- 소요량 + quantity_formula VARCHAR(500) NULL, -- 수식 (예: "W1 * H1 / 1000000") + unit VARCHAR(20) NULL, + waste_rate DECIMAL(9,6) NOT NULL DEFAULT 0, -- 로스율 (0.05 = 5%) + category VARCHAR(100) NULL, -- 카테고리 그룹명 + operation_id BIGINT UNSIGNED NULL, -- 공정 연결 + effective_from DATE NULL, -- 라인별 유효 시작 + effective_to DATE NULL, -- 라인별 유효 종료 + is_phantom TINYINT(1) NOT NULL DEFAULT 0, -- 팬텀 여부 (BOM 전개 시 투과) + supply_type VARCHAR(20) DEFAULT 'STOCK', -- STOCK | PURCHASE | SUBCONTRACT + sort_order INT NOT NULL DEFAULT 0, + notes VARCHAR(500) NULL, + options JSON NULL, -- 확장 속성 + created_by BIGINT UNSIGNED NULL, + updated_by BIGINT UNSIGNED NULL, + created_at TIMESTAMP NULL, + updated_at TIMESTAMP NULL, + deleted_at TIMESTAMP NULL, + + INDEX idx_bl_tenant_header (tenant_id, bom_header_id), + INDEX idx_bl_child (child_item_id), + INDEX idx_bl_operation (operation_id), + INDEX idx_bl_effective (effective_from, effective_to) +); +``` + +### 3.6 bom_substitutes 상세 + +```sql +CREATE TABLE bom_substitutes ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + tenant_id BIGINT UNSIGNED NOT NULL, + bom_line_id BIGINT UNSIGNED NOT NULL, + substitute_item_id BIGINT UNSIGNED NOT NULL, -- 대체 품목 + priority INT NOT NULL DEFAULT 1, -- 대체 우선순위 (1=최우선) + conversion_factor DECIMAL(12,6) NOT NULL DEFAULT 1, -- 환산 계수 + effective_from DATE NULL, + effective_to DATE NULL, + notes VARCHAR(255) NULL, + options JSON NULL, + created_at TIMESTAMP NULL, + updated_at TIMESTAMP NULL, + + INDEX idx_bs_tenant_line (tenant_id, bom_line_id), + UNIQUE KEY uq_bs_line_sub (bom_line_id, substitute_item_id) +); +``` + +--- + +## 4. BOM 유형별 동작 + +### 4.1 STANDARD BOM (표준 BOM) + +가장 일반적인 형태. 고정 수량 기반. + +``` +FG-001 (스크린 제품) [REV.02, ACTIVE, 2026-01-01~] +├── [주자재] RM-001 스크린 원단 x10.65 m² (로스 5%) +├── [모터] PT-001 모터 150K x1 EA +├── [제어기] PT-002 제어기 노출형 x1 EA +├── [절곡품] WIP-001 케이스 500*380 x3.22 m → 공정: 절곡 +├── [절곡품] WIP-002 마구리 505*385 x1 EA → 공정: 절곡 +├── [부자재] SM-001 감기샤프트 x1 EA +├── [검사비] SV-001 검사비 x1 EA +└── [대체] PT-001 → PT-001-B 모터 200K (priority=1, factor=1.0) +``` + +### 4.2 FORMULA BOM (수식 BOM) + +파라미터 입력 → 수식 평가 → 수량 자동 계산. 기존 Design BOM의 발전형. + +``` +FG-KSS02 (스크린 SUS 측면형) [FORMULA] +├── 파라미터: W0=3000, H0=3000, QTY=1, MP=single +├── 변수계산: W1=W0+140, H1=H0+350, M=W1*H1/1e6, K=M*2+(W0/1000)*14.17 +│ +├── RM-슬랫 qty_formula="M" → 10.65 m² +├── PT-모터 qty_formula="1" → 1 EA +├── WIP-케이스 qty_formula="W1/1000" → 3.14 m +├── SM-샤프트 qty_formula="CEIL(H1/2000)" → 2 EA +└── SV-검사 qty_formula="1" → 1 EA +``` + +> 수식 평가 후 결과를 STANDARD BOM으로 스냅샷 저장 가능 (V1의 "BOM 저장" 기능 유지). + +### 4.3 CONFIGURABLE BOM (구성형 BOM) + +옵션 조합에 따라 구성이 달라지는 BOM. 가구/의류/맞춤 제품에 적합. + +``` +FG-DESK (사무용 책상) [CONFIGURABLE] +├── [공통] PT-프레임 x1 EA — 항상 포함 +├── [공통] SM-나사세트 x1 SET — 항상 포함 +│ +├── [옵션: 상판 재질] +│ ├── 원목 → RM-원목상판 x1 EA +│ ├── MDF → RM-MDF상판 x1 EA +│ └── 유리 → RM-유리상판 x1 EA + SM-흡착패드 x4 EA +│ +└── [옵션: 다리 높이] + ├── 표준(720mm) → PT-다리-720 x4 EA + └── 높은(900mm) → PT-다리-900 x4 EA +``` + +### 4.4 ENGINEERING BOM (설계 BOM) + +생산 투입 전 설계 단계 BOM. 승인 후 STANDARD로 전환. + +``` +ENGINEERING BOM (설계팀) + │ 검토 → 승인 + ▼ +STANDARD BOM (생산팀) + │ ECN (설계 변경) + ▼ +새 REVISION 생성 (REV.02) +``` + +--- + +## 5. BOM 버전 관리 + +### 5.1 리비전 워크플로우 + +``` +REV.01 (DRAFT) + │ 편집 완료 + ▼ +REV.01 (PENDING) ← 승인 요청 + │ 승인자 확인 + ▼ +REV.01 (APPROVED) ← 승인 완료 + │ 유효기간 도래 + ▼ +REV.01 (ACTIVE) ← 생산에 사용 + │ 설계 변경 발생 + ▼ +REV.01 (OBSOLETE) ← 비활성화 +REV.02 (DRAFT) 생성 ← 새 리비전 +``` + +### 5.2 유효기간 관리 + +``` +REV.01 ────────[2025-01-01 ~ 2026-06-30]──────── +REV.02 [2026-07-01 ~ ]────────────── + ↑ + 설계 변경 적용일 +``` + +- 특정 날짜에 유효한 BOM 조회: `WHERE effective_from <= ? AND (effective_to IS NULL OR effective_to >= ?)` +- 라인별 유효기간: 부품 단종/교체 시 개별 라인 종료 + +### 5.3 BOM 비교 (Diff) + +```json +{ + "comparison": "REV.01 vs REV.02", + "added": [ + { "item": "PT-003 신규부품", "qty": 2 } + ], + "removed": [ + { "item": "PT-002 구부품", "qty": 1 } + ], + "changed": [ + { "item": "RM-001 원단", "qty_before": 10.0, "qty_after": 10.65, "reason": "로스율 반영" } + ] +} +``` + +--- + +## 6. 팬텀(Phantom) 품목 + +### 6.1 개념 + +팬텀 품목은 **재고로 관리하지 않는 가상 그룹**이다. BOM 전개(Explosion) 시 팬텀은 "투과"되어 하위 구성품이 직접 상위로 올라간다. + +### 6.2 V1 → V2 매핑 + +V1의 `item_type: CAT` (카테고리 그룹)가 V2의 팬텀에 해당한다. + +``` +V1 (가상 CAT 노드): +FG-001 + ├── [CAT] 주자재 (가상 — DB에 없음, 코드로 생성) + │ └── RM-001 스크린 원단 + └── [CAT] 모터 (가상) + └── PT-001 모터 + +V2 (팬텀 품목): +FG-001 + ├── PH-주자재 (팬텀 — items 테이블에 실체 있음) + │ └── RM-001 스크린 원단 + └── PH-모터 (팬텀) + └── PT-001 모터 + +BOM 전개 결과 (MRP): +FG-001 → RM-001, PT-001 (팬텀 투과) +``` + +### 6.3 팬텀 활용 + +| 용도 | 설명 | +|------|------| +| **그룹화** | V1의 카테고리 그룹을 구조화 | +| **중간조립 생략** | 재고 불필요한 중간 단계 | +| **공통 부품군** | 여러 FG에서 공유하는 부품 묶음 | + +--- + +## 7. 공정-BOM 연동 (Routing) + +### 7.1 공정 마스터 + +```sql +CREATE TABLE processes ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + tenant_id BIGINT UNSIGNED NOT NULL, + code VARCHAR(50) NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(50) NULL, -- FABRICATION | ASSEMBLY | INSPECTION | SUBCONTRACT + options JSON NULL, + is_active BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP NULL, + updated_at TIMESTAMP NULL, + deleted_at TIMESTAMP NULL, + + UNIQUE KEY uq_process_tenant_code (tenant_id, code, deleted_at) +); +``` + +### 7.2 공정 라우팅 + +```sql +CREATE TABLE operations ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + tenant_id BIGINT UNSIGNED NOT NULL, + item_id BIGINT UNSIGNED NOT NULL, -- 대상 품목 + bom_header_id BIGINT UNSIGNED NULL, -- BOM과 연결 (선택) + sequence INT NOT NULL, -- 공정 순서 (10, 20, 30...) + process_id BIGINT UNSIGNED NOT NULL, -- 공정 마스터 + work_center_id BIGINT UNSIGNED NULL, -- 작업장/설비 + setup_time DECIMAL(10,2) DEFAULT 0, -- 준비 시간 (분) + run_time DECIMAL(10,2) DEFAULT 0, -- 가동 시간 (분/단위) + wait_time DECIMAL(10,2) DEFAULT 0, -- 대기 시간 (분) + description VARCHAR(500) NULL, + options JSON NULL, + created_at TIMESTAMP NULL, + updated_at TIMESTAMP NULL, + deleted_at TIMESTAMP NULL, + + INDEX idx_op_tenant_item (tenant_id, item_id), + INDEX idx_op_sequence (item_id, sequence) +); +``` + +### 7.3 공정별 자재 투입 + +``` +FG-001 스크린 제품 + 공정 10: 원단 재단 → RM-001 원단 (이 공정에서 투입) + 공정 20: 절곡 가공 → WIP-001 케이스, WIP-002 마구리 + 공정 30: 조립 → PT-001 모터, PT-002 제어기, SM-001 샤프트 + 공정 40: 검사 → SV-001 검사비 + 공정 50: 포장 → SM-002 포장재 +``` + +`bom_lines.operation_id`로 각 자재가 어느 공정에서 투입되는지 연결한다. + +--- + +## 8. 테넌트별 BOM 설정 + +### 8.1 테넌트 BOM 설정 (tenant_bom_settings) + +```sql +CREATE TABLE tenant_bom_settings ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + tenant_id BIGINT UNSIGNED NOT NULL UNIQUE, + -- 활성화할 품목 유형 + enabled_item_types JSON NOT NULL DEFAULT '["FG","PT","SM","RM","CS"]', + -- 활성화할 BOM 유형 + enabled_bom_types JSON NOT NULL DEFAULT '["STANDARD"]', + -- BOM 최대 깊이 + max_bom_depth INT NOT NULL DEFAULT 10, + -- 승인 워크플로우 사용 여부 + require_approval BOOLEAN NOT NULL DEFAULT FALSE, + -- 유효기간 관리 사용 여부 + use_effectivity BOOLEAN NOT NULL DEFAULT FALSE, + -- 대체품목 사용 여부 + use_substitutes BOOLEAN NOT NULL DEFAULT FALSE, + -- 공정(Routing) 연동 여부 + use_routing BOOLEAN NOT NULL DEFAULT FALSE, + -- 로스율 관리 여부 + use_waste_rate BOOLEAN NOT NULL DEFAULT FALSE, + -- 팬텀 품목 사용 여부 + use_phantom BOOLEAN NOT NULL DEFAULT FALSE, + -- 수식 BOM 사용 여부 + use_formula_bom BOOLEAN NOT NULL DEFAULT FALSE, + -- 카테고리 그룹 표시 방식 + category_display VARCHAR(20) DEFAULT 'FOLDER', -- FOLDER | FLAT | NONE + -- 커스텀 BOM 라인 필드 (테넌트별 확장) + custom_line_fields JSON NULL, + options JSON NULL, + created_at TIMESTAMP NULL, + updated_at TIMESTAMP NULL +); +``` + +### 8.2 업종별 프리셋 + +```json +{ + "presets": { + "blind_screen": { + "label": "블라인드/스크린 제조", + "enabled_item_types": ["FG", "PT", "WIP", "SM", "RM", "CS", "SV"], + "enabled_bom_types": ["STANDARD", "FORMULA"], + "max_bom_depth": 5, + "use_formula_bom": true, + "use_waste_rate": true, + "use_routing": true, + "category_display": "FOLDER" + }, + "electronics": { + "label": "전자/반도체", + "enabled_item_types": ["FG", "SA", "PT", "PH", "SM", "RM", "CS"], + "enabled_bom_types": ["STANDARD", "ENGINEERING"], + "max_bom_depth": 15, + "require_approval": true, + "use_effectivity": true, + "use_substitutes": true, + "use_phantom": true + }, + "food_chemical": { + "label": "식품/화학", + "enabled_item_types": ["FG", "PT", "RM", "CS", "BP"], + "enabled_bom_types": ["STANDARD", "FORMULA"], + "use_formula_bom": true, + "use_waste_rate": true, + "category_display": "FLAT" + }, + "furniture": { + "label": "가구/인테리어", + "enabled_item_types": ["FG", "SA", "PT", "SM", "RM"], + "enabled_bom_types": ["STANDARD", "CONFIGURABLE"], + "max_bom_depth": 5 + }, + "simple_assembly": { + "label": "단순 조립", + "enabled_item_types": ["FG", "PT", "SM", "RM", "CS"], + "enabled_bom_types": ["STANDARD"], + "max_bom_depth": 3, + "category_display": "FLAT" + } + } +} +``` + +--- + +## 9. API 설계 + +### 9.1 엔드포인트 구조 + +``` +/api/v2/items/{itemId}/bom/ + ├── GET / BOM 헤더 목록 (리비전 이력) + ├── POST / BOM 헤더 생성 (새 리비전) + ├── GET /{bomId} BOM 상세 (헤더 + 라인) + ├── PUT /{bomId} BOM 헤더 수정 + ├── DELETE /{bomId} BOM 삭제 (DRAFT만) + │ + ├── GET /{bomId}/lines BOM 라인 목록 + ├── POST /{bomId}/lines 라인 추가 + ├── PUT /{bomId}/lines/bulk 라인 일괄 업서트 + ├── PUT /{bomId}/lines/{id} 라인 수정 + ├── DELETE /{bomId}/lines/{id} 라인 삭제 + │ + ├── GET /{bomId}/tree BOM 트리 (재귀, 팬텀 투과 옵션) + ├── GET /{bomId}/flat BOM 전개 (Explosion, 평탄화) + ├── GET /{bomId}/where-used 역전개 (이 품목을 사용하는 BOM) + │ + ├── POST /{bomId}/approve 승인 요청 + ├── POST /{bomId}/activate 활성화 + ├── POST /{bomId}/obsolete 비활성화 + ├── POST /{bomId}/clone 복제 (새 리비전) + ├── GET /{bomId}/diff/{otherId} BOM 비교 + │ + ├── GET /{bomId}/substitutes 대체품목 목록 + ├── POST /{bomId}/lines/{id}/substitutes 대체품목 추가 + │ + └── POST /{bomId}/calculate 수식 BOM 계산 (FORMULA 타입) + +/api/v2/bom/ + ├── GET /settings 테넌트 BOM 설정 조회 + ├── PUT /settings 테넌트 BOM 설정 변경 + ├── GET /search BOM 검색 (품목코드, 구성품 등) + └── POST /mass-replace 품목 일괄 대체 (ECN) +``` + +### 9.2 BOM 트리 응답 (V2) + +```json +{ + "bom_header": { + "id": 1, + "item_id": 100, + "revision": "REV.02", + "status": "ACTIVE", + "bom_type": "STANDARD", + "effective_from": "2026-07-01", + "base_qty": 1 + }, + "tree": { + "id": 100, + "code": "FG-KSS02", + "name": "KSS02 스크린 SUS 측면형", + "item_type": "FG", + "depth": 0, + "children": [ + { + "bom_line_id": 10, + "id": 0, + "name": "주자재", + "item_type": "PH", + "is_phantom": true, + "depth": 1, + "children": [ + { + "bom_line_id": 11, + "id": 201, + "code": "RM-슬랫-방화", + "name": "스크린 실리카", + "item_type": "RM", + "quantity": 10.65, + "unit": "m²", + "waste_rate": 0.05, + "effective_quantity": 11.18, + "operation": { "sequence": 10, "name": "원단 재단" }, + "substitutes": [ + { "item_code": "RM-슬랫-일반", "priority": 1, "factor": 1.0 } + ], + "depth": 2, + "children": [] + } + ] + } + ] + }, + "summary": { + "total_items": 17, + "total_groups": 6, + "max_depth": 3, + "has_substitutes": true, + "has_formulas": false + } +} +``` + +--- + +## 10. V1 → V2 마이그레이션 + +### 10.1 마이그레이션 전략 + +``` +Phase 1: 테이블 생성 (V2 테이블 추가, V1 유지) + │ +Phase 2: 데이터 이관 (items.bom JSON → bom_headers + bom_lines) + │ +Phase 3: API 전환 (V1 API 유지 + V2 API 추가) + │ +Phase 4: 프론트엔드 전환 (MNG/React V2 UI) + │ +Phase 5: V1 폐기 (items.bom 컬럼 제거, V1 API 제거) +``` + +### 10.2 데이터 이관 스크립트 + +```php +// items.bom JSON → bom_headers + bom_lines 변환 +foreach (Item::whereNotNull('bom')->cursor() as $item) { + $header = BomHeader::create([ + 'tenant_id' => $item->tenant_id, + 'item_id' => $item->id, + 'revision' => 'REV.01', + 'bom_type' => 'STANDARD', + 'status' => 'ACTIVE', + 'base_qty' => 1, + ]); + + foreach ($item->bom as $i => $bomLine) { + BomLine::create([ + 'tenant_id' => $item->tenant_id, + 'bom_header_id' => $header->id, + 'child_item_id' => $bomLine['child_item_id'], + 'quantity' => $bomLine['quantity'] ?? 1, + 'unit' => $bomLine['unit'] ?? null, + 'category' => $bomLine['category'] ?? null, + 'sort_order' => $i, + ]); + } +} +``` + +### 10.3 하위 호환 + +| V1 API | V2 대응 | 전환 방식 | +|--------|---------|---------| +| `GET /v1/items/{id}/bom/tree` | `GET /v2/items/{id}/bom/{activeId}/tree` | V1 래퍼 → V2 호출 | +| `POST /v1/items/{id}/save-bom` | `POST /v2/items/{id}/bom` + lines | V1 래퍼 유지 | +| `POST /v1/quotes/calculate/bom` | `POST /v2/items/{id}/bom/{id}/calculate` | V1 래퍼 유지 | + +--- + +## 11. 구현 로드맵 + +### Phase 1: 기반 구축 (2~3주) + +- [ ] `bom_headers`, `bom_lines`, `bom_substitutes` 마이그레이션 생성 +- [ ] `tenant_bom_settings` 테이블 및 프리셋 +- [ ] `BomHeader`, `BomLine`, `BomSubstitute` 모델 생성 +- [ ] `BomService` 핵심 CRUD (생성, 조회, 수정, 삭제) +- [ ] V1 items.bom → V2 데이터 이관 스크립트 +- [ ] V2 BOM API 기본 엔드포인트 + +### Phase 2: 핵심 기능 (2~3주) + +- [ ] BOM 트리 빌더 (재귀, 팬텀 투과, 깊이 제한) +- [ ] BOM 전개 (Explosion) — 평탄화 조회 +- [ ] 역전개 (Where-Used) — 이 부품을 사용하는 상위 BOM +- [ ] BOM 버전 관리 (리비전 생성, 복제) +- [ ] BOM 비교 (Diff) +- [ ] items.item_type 확장 (SA, WIP, PH, BP, SV) + +### Phase 3: 확장 기능 (3~4주) + +- [ ] 수식 BOM (FORMULA) — Design BOM 연동 개선 +- [ ] 대체품목 관리 +- [ ] 유효기간(Effectivity) 관리 +- [ ] 공정(Routing) 테이블 및 BOM-공정 연동 +- [ ] BOM 승인 워크플로우 +- [ ] 원가 계산 연동 (BOM 기반 표준원가) + +### Phase 4: UI 및 통합 (2~3주) + +- [ ] MNG BOM 관리 UI 전환 (V2 API) +- [ ] React BOM 트리 뷰어 V2 연동 +- [ ] 테넌트 BOM 설정 관리 화면 +- [ ] V1 API 래퍼 → V2 전환 완료 +- [ ] V1 items.bom 컬럼 제거 + +--- + +## 12. 업종별 시나리오 검증 + +### 12.1 블라인드/스크린 (현재) + +``` +설정: STANDARD + FORMULA, WIP 사용, 카테고리 FOLDER +검증: + ✓ 수식 산출 → BOM 자동 생성 + ✓ 절곡품(WIP) BOM 트리 + ✓ 카테고리 그룹 표시 + ✓ V1 데이터 100% 호환 +``` + +### 12.2 전자부품 제조 + +``` +설정: STANDARD + ENGINEERING, SA/PH 사용, 승인 필수, 대체품목, ECN +검증: + ✓ 15단계 BOM 깊이 + ✓ 팬텀 품목 투과 전개 + ✓ ECN 시 일괄 품목 대체 + ✓ 리비전별 유효기간 관리 +``` + +### 12.3 식품 제조 + +``` +설정: FORMULA, 수율 관리, 부산물(BP) +검증: + ✓ 배합비 수식 (A원료 30% + B원료 70%) + ✓ 로스율 반영 투입량 + ✓ 부산물 자동 등록 +``` + +### 12.4 가구 주문제작 + +``` +설정: CONFIGURABLE, 옵션 조합 +검증: + ✓ 상판/다리/마감 옵션별 BOM 분기 + ✓ 주문 시 옵션 선택 → BOM 확정 +``` + +--- + +## 관련 문서 + +| 문서 | 경로 | +|------|------| +| 품목 정책 | `rules/item-policy.md` | +| 견적 시스템 | `features/quotes/README.md` | +| 제품/품목/설계 DB | `system/database/products.md` | +| BOM 아이템 매핑 | `dev/dev_plans/bom-item-mapping-plan.md` | +| BOM 트리 3단계 | `changes/20260318_item-management-bom-tree.md` | +| 재공품 생산 정책 | `rules/wip-production-policy.md` | +| options JSON 정책 | `standards/options-column-policy.md` | + +--- + +**최종 업데이트**: 2026-03-22