+```
+
+#### 2.2 item-detail.blade.php에 메타 데이터 추가
+
+**수정 파일**: `mng/resources/views/item-management/partials/item-detail.blade.php`
+
+**파일 맨 위에 추가** (기존 `
` 앞):
+```html
+
+
+```
+
+#### 2.3 JS 추가 (index.blade.php @push('scripts'))
+
+**기존 IIFE 내부에 추가할 변수와 함수**:
+
+```javascript
+// ── 추가 변수 ──
+let currentBomTab = 'static'; // 'static' | 'formula'
+let currentItemId = null;
+let currentItemCode = null;
+
+// ── 탭 전환 ──
+window.switchBomTab = function(tab) {
+ currentBomTab = tab;
+
+ // 탭 버튼 스타일
+ document.querySelectorAll('.bom-tab').forEach(btn => {
+ btn.classList.remove('bg-blue-100', 'text-blue-800');
+ btn.classList.add('bg-gray-100', 'text-gray-600');
+ });
+ const activeBtn = document.getElementById(tab === 'static' ? 'tab-static-bom' : 'tab-formula-bom');
+ if (activeBtn) {
+ activeBtn.classList.remove('bg-gray-100', 'text-gray-600');
+ activeBtn.classList.add('bg-blue-100', 'text-blue-800');
+ }
+
+ // 콘텐츠 영역 전환
+ document.getElementById('bom-tree-container').style.display = (tab === 'static') ? '' : 'none';
+ document.getElementById('formula-input-panel').style.display = (tab === 'formula') ? '' : 'none';
+ document.getElementById('formula-result-container').style.display = (tab === 'formula') ? '' : 'none';
+};
+
+// ── 가변사이즈 탭 표시/숨김 ──
+function showFormulaTab() {
+ document.getElementById('tab-formula-bom').style.display = '';
+ switchBomTab('formula'); // 자동으로 수식 산출 탭으로 전환
+}
+
+function hideFormulaTab() {
+ document.getElementById('tab-formula-bom').style.display = 'none';
+ document.getElementById('formula-input-panel').style.display = 'none';
+ document.getElementById('formula-result-container').style.display = 'none';
+ switchBomTab('static');
+}
+
+// ── 상세 로드 완료 후 가변사이즈 감지 ──
+document.body.addEventListener('htmx:afterSwap', function(event) {
+ if (event.detail.target.id === 'item-detail') {
+ const meta = document.getElementById('item-meta-data');
+ if (meta) {
+ currentItemId = meta.dataset.itemId;
+ currentItemCode = meta.dataset.itemCode;
+ if (meta.dataset.isVariableSize === 'true') {
+ showFormulaTab();
+ } else {
+ hideFormulaTab();
+ }
+ }
+ }
+});
+
+// ── 수식 산출 API 호출 ──
+window.calculateFormula = function() {
+ if (!currentItemId) return;
+
+ const width = parseInt(document.getElementById('input-width').value) || 1000;
+ const height = parseInt(document.getElementById('input-height').value) || 1000;
+ const qty = parseInt(document.getElementById('input-qty').value) || 1;
+
+ // 입력값 범위 검증
+ if (width < 100 || width > 10000 || height < 100 || height > 10000) {
+ alert('폭과 높이는 100~10000 범위로 입력하세요.');
+ return;
+ }
+
+ const container = document.getElementById('formula-result-container');
+ container.innerHTML = '
';
+
+ fetch(`/api/admin/items/${currentItemId}/calculate-formula`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-TOKEN': csrfToken,
+ },
+ body: JSON.stringify({ width, height, qty }),
+ })
+ .then(res => res.json())
+ .then(data => {
+ if (data.success === false) {
+ container.innerHTML = `
+
+
${data.error || '산출 실패'}
+
다시 시도
+
`;
+ return;
+ }
+ renderFormulaTree(data, container);
+ })
+ .catch(err => {
+ container.innerHTML = `
+
`;
+ });
+};
+
+// ── 수식 산출 결과 트리 렌더링 ──
+function renderFormulaTree(data, container) {
+ container.innerHTML = '';
+
+ // 카테고리 그룹 한글 매핑
+ const groupLabels = { steel: '강재', part: '부품', motor: '모터/컨트롤러' };
+ const groupIcons = { steel: '🏗️', part: '🔧', motor: '⚡' };
+ const groupedItems = data.grouped_items || {};
+
+ // 합계 영역
+ if (data.grand_total) {
+ const totalDiv = document.createElement('div');
+ totalDiv.className = 'mb-4 p-3 bg-blue-50 rounded-lg flex justify-between items-center';
+ totalDiv.innerHTML = `
+
+ ${data.finished_goods?.name || ''} (${data.finished_goods?.code || ''})
+ W:${data.variables?.W0} H:${data.variables?.H0}
+
+
합계: ${Number(data.grand_total).toLocaleString()}원
+ `;
+ container.appendChild(totalDiv);
+ }
+
+ // 카테고리 그룹별 렌더링
+ Object.entries(groupedItems).forEach(([group, items]) => {
+ if (!items || items.length === 0) return;
+
+ const groupDiv = document.createElement('div');
+ groupDiv.className = 'mb-3';
+
+ const subtotal = data.subtotals?.[group] || 0;
+
+ // 그룹 헤더
+ const header = document.createElement('div');
+ header.className = 'flex items-center gap-2 py-2 px-3 bg-gray-50 rounded-t-lg cursor-pointer';
+ header.innerHTML = `
+
▼
+
${groupIcons[group] || '📦'}
+
${groupLabels[group] || group}
+
(${items.length}건)
+
소계: ${Number(subtotal).toLocaleString()}원
+ `;
+
+ const listDiv = document.createElement('div');
+ listDiv.className = 'border border-gray-100 rounded-b-lg divide-y divide-gray-50';
+
+ // 그룹 접기/펼치기
+ header.onclick = function() {
+ const toggle = header.querySelector('.text-gray-400');
+ if (listDiv.style.display === 'none') {
+ listDiv.style.display = '';
+ toggle.textContent = '▼';
+ } else {
+ listDiv.style.display = 'none';
+ toggle.textContent = '▶';
+ }
+ };
+
+ // 아이템 목록
+ items.forEach(item => {
+ const row = document.createElement('div');
+ row.className = 'flex items-center gap-2 py-1.5 px-3 hover:bg-gray-50 cursor-pointer text-sm';
+ row.innerHTML = `
+
PT
+
${item.item_code || ''}
+
${item.item_name || ''}
+
${item.quantity || 0} ${item.unit || ''}
+
${Number(item.total_price || 0).toLocaleString()}원
+ `;
+ // 아이템 클릭 시 items 테이블에서 해당 코드로 검색하여 상세 표시
+ row.onclick = function() {
+ // item_code로 좌측 검색 → 해당 품목 상세 로드
+ const searchInput = document.getElementById('item-search');
+ searchInput.value = item.item_code;
+ loadItemList();
+ };
+ listDiv.appendChild(row);
+ });
+
+ groupDiv.appendChild(header);
+ groupDiv.appendChild(listDiv);
+ container.appendChild(groupDiv);
+ });
+
+ if (Object.keys(groupedItems).length === 0) {
+ container.innerHTML = '
산출된 자재가 없습니다.
';
+ }
+}
+```
+
+---
+
+## 5. 컨펌 대기 목록
+
+| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
+|---|------|----------|----------|------|
+| 1 | ~~API 인증 방식~~ | X-API-KEY 필수 (FLOW_TESTER_API_KEY) | MNG→API 통신 | ✅ 확인 완료 |
+| 2 | API 라우트 추가 | POST /api/admin/items/{id}/calculate-formula | mng/routes/api.php | ✅ 즉시 가능 |
+
+---
+
+## 6. 변경 이력
+
+| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
+|------|------|----------|------|------|
+| 2026-02-19 | - | 계획 문서 초안 작성 | - | - |
+| 2026-02-19 | - | 자기완결성 보강 (기존 코드 현황, API 인증 분석, 트러블슈팅) | - | - |
+| 2026-02-19 | 1.1~1.3 | Phase 1 백엔드 구현 완료 (FormulaApiService, Controller, Route) | FormulaApiService.php, ItemManagementApiController.php, api.php | ✅ |
+| 2026-02-19 | 2.1~2.5 | Phase 2 프론트엔드 구현 완료 (탭 UI, 입력 폼, 트리 렌더링, 감지, 에러) | index.blade.php, item-detail.blade.php | ✅ |
+
+---
+
+## 7. 참고 문서
+
+- **기존 품목관리 계획**: `docs/plans/mng-item-management-plan.md`
+- **FormulaEvaluatorService**: `api/app/Services/Quote/FormulaEvaluatorService.php`
+ - 메서드: `calculateBomWithDebug(string $finishedGoodsCode, array $inputVariables, ?int $tenantId): array`
+ - tenant_id=287 자동 감지 → KyungdongFormulaHandler 라우팅
+- **KyungdongFormulaHandler**: `api/app/Services/Quote/Handlers/KyungdongFormulaHandler.php`
+ - `calculateDynamicItems(array $inputs)` → steel(10종), part(3종), motor/controller 산출
+- **API 라우트**: `api/routes/api/v1/sales.php:64` → `QuoteController::calculateBom`
+- **QuoteBomCalculateRequest**: `api/app/Http/Requests/V1/QuoteBomCalculateRequest.php`
+ - `finished_goods_code` (required|string)
+ - `variables` (required|array), `variables.W0` (required|numeric), `variables.H0` (required|numeric)
+ - `tenant_id` (nullable|integer)
+- **MNG-API HTTP 패턴**: `mng/app/Services/FlowTester/HttpClient.php`
+- **API Key 설정**: `mng/config/api-explorer.php:26` → `env('FLOW_TESTER_API_KEY')`
+- **현재 품목관리 뷰**: `mng/resources/views/item-management/index.blade.php`
+- **MNG 프로젝트 규칙**: `mng/CLAUDE.md`
+
+---
+
+## 8. 세션 및 메모리 관리 정책
+
+### 8.1 세션 시작 시 (Load Strategy)
+```
+1. 이 문서 읽기 (docs/plans/mng-item-formula-integration-plan.md)
+2. 📍 현재 진행 상태 확인 → 다음 작업 파악
+3. 섹션 3 "이미 구현된 코드" 확인 → 수정 대상 파일 파악
+4. 필요시 Serena 메모리 로드:
+ read_memory("item-formula-state")
+ read_memory("item-formula-snapshot")
+ read_memory("item-formula-active-symbols")
+```
+
+### 8.2 작업 중 관리 (Context Defense)
+| 컨텍스트 잔량 | Action | 내용 |
+|--------------|--------|------|
+| **30% 이하** | Snapshot | `write_memory("item-formula-snapshot", "코드변경+논의요약")` |
+| **20% 이하** | Context Purge | `write_memory("item-formula-active-symbols", "주요 수정 파일/함수")` |
+| **10% 이하** | Stop & Save | 최종 상태 저장 후 세션 교체 권고 |
+
+---
+
+## 9. 검증 결과
+
+### 9.1 테스트 케이스
+
+| # | 테스트 | 입력 | 예상 결과 | 실제 결과 | 상태 |
+|---|--------|------|----------|----------|------|
+| 1 | FG 가변사이즈 품목 선택 | FG-KQTS01 클릭 | 수식 산출 탭 자동 표시, 입력 폼 노출 | | ⏳ |
+| 2 | 오픈사이즈 입력 후 산출 | W:3000, H:3000, QTY:1 | 17종 자재 트리 (steel/part/motor 그룹별), 소계/합계 표시 | | ⏳ |
+| 3 | 비가변사이즈 품목 선택 | PT 품목 클릭 | 수식 산출 탭 숨김, 정적 BOM만 표시 | | ⏳ |
+| 4 | 정적 BOM ↔ 수식 산출 탭 전환 | 탭 클릭 | 각 탭 콘텐츠 전환, 입력 폼 표시/숨김 | | ⏳ |
+| 5 | 산출 결과에서 품목 클릭 | 트리 노드 클릭 | 좌측 검색에 품목코드 입력 → 품목 리스트 필터링 | | ⏳ |
+| 6 | API Key 미설정 | FLOW_TESTER_API_KEY 없음 | 에러 메시지 "API 응답 오류: HTTP 401" + 재시도 버튼 | | ⏳ |
+| 7 | 입력값 범위 초과 | W:0, H:-1 | alert 표시, API 호출 안 함 | | ⏳ |
+| 8 | 서버 연결 실패 | nginx 중지 상태 | 에러 메시지 "서버 연결 실패" + 재시도 버튼 | | ⏳ |
+
+### 9.2 성공 기준 달성 현황
+
+| 기준 | 달성 | 비고 |
+|------|------|------|
+| FG 가변사이즈 품목에서 수식 산출 가능 | ⏳ | |
+| 산출 결과가 견적관리와 동일한 17종 자재 표시 | ⏳ | |
+| 정적 BOM과 수식 산출 탭 전환 작동 | ⏳ | |
+| 비가변사이즈 품목은 기존 정적 BOM만 표시 | ⏳ | |
+| 에러 처리 및 로딩 상태 표시 | ⏳ | |
+
+---
+
+## 10. 자기완결성 점검 결과
+
+### 10.1 체크리스트 검증
+
+| # | 검증 항목 | 상태 | 비고 |
+|---|----------|:----:|------|
+| 1 | 작업 목적이 명확한가? | ✅ | 가변사이즈 FG 품목의 동적 자재 산출 표시 |
+| 2 | 성공 기준이 정의되어 있는가? | ✅ | 9.2 성공 기준 5개 항목 |
+| 3 | 작업 범위가 구체적인가? | ✅ | Phase 1 백엔드 3건, Phase 2 프론트 5건 |
+| 4 | 의존성이 명시되어 있는가? | ✅ | API 엔드포인트 인증 분석 완료, Docker 라우팅 패턴 |
+| 5 | 참고 파일 경로가 정확한가? | ✅ | 모든 파일 경로 검증 완료 |
+| 6 | 단계별 절차가 실행 가능한가? | ✅ | 전체 구현 코드 포함 |
+| 7 | 검증 방법이 명시되어 있는가? | ✅ | 9.1 테스트 케이스 8개 |
+| 8 | 모호한 표현이 없는가? | ✅ | 구체적 수치/코드로 기술 |
+| 9 | 기존 코드 현황이 명시되어 있는가? | ✅ | 섹션 3에 전체 파일 구조 + 핵심 코드 인라인 |
+| 10 | API 인증 방식이 확정되었는가? | ✅ | X-API-KEY 필수 (FLOW_TESTER_API_KEY) |
+| 11 | 트러블슈팅 가이드가 있는가? | ✅ | 4.1 FormulaApiService 트러블슈팅 섹션 |
+
+### 10.2 새 세션 시뮬레이션 테스트
+
+| 질문 | 답변 가능 | 참조 섹션 |
+|------|:--------:|----------|
+| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
+| Q2. 어디서부터 시작해야 하는가? | ✅ | 📍 현재 진행 상태 + 4.1 Phase 1 |
+| Q3. 어떤 파일을 수정/생성해야 하는가? | ✅ | 3.1 파일 구조 + 2. 대상 범위 |
+| Q4. 현재 코드 상태는 어떤가? | ✅ | 3.2~3.6 기존 코드 현황 |
+| Q5. API 인증은 어떻게 하는가? | ✅ | 4.1 FormulaApiService (인증 테이블) |
+| Q6. 테넌트 필터링은 어떻게 동작하는가? | ✅ | 3.6 테넌트 필터링 패턴 |
+| Q7. 작업 완료 확인 방법은? | ✅ | 9. 검증 결과 |
+| Q8. 막혔을 때 참고 문서는? | ✅ | 7. 참고 문서 + 4.1 트러블슈팅 |
+
+**결과**: 8/8 통과 → ✅ 자기완결성 확보
+
+---
+
+*이 문서는 /sc:plan 스킬로 생성되었습니다. 자기완결성 보강: 2026-02-19*
diff --git a/plans/archive/mng-item-management-plan.md b/plans/archive/mng-item-management-plan.md
new file mode 100644
index 0000000..172f216
--- /dev/null
+++ b/plans/archive/mng-item-management-plan.md
@@ -0,0 +1,1447 @@
+# MNG 품목관리 페이지 계획
+
+> **작성일**: 2026-02-19
+> **목적**: MNG 관리자 패널에 3-Panel 품목관리 페이지 추가 (좌측 리스트 + 중앙 BOM 트리 + 우측 상세)
+> **기준 문서**: docs/rules/item-policy.md, docs/specs/item-master-integration.md
+> **상태**: ✅ 기본 구현 완료 (미커밋) → Phase 3 수식 연동은 별도 계획
+
+---
+
+## 📍 현재 진행 상태
+
+| 항목 | 내용 |
+|------|------|
+| **마지막 완료 작업** | Phase 1~2 전체 구현 완료 (미커밋 상태) |
+| **다음 작업** | 수식 엔진 연동 → `docs/plans/mng-item-formula-integration-plan.md` 참조 |
+| **진행률** | 12/12 (100%) - 기본 3-Panel 구현 완료 |
+| **마지막 업데이트** | 2026-02-19 |
+| **후속 작업** | FormulaEvaluatorService 연동 (별도 계획 문서) |
+
+---
+
+## 1. 개요
+
+### 1.1 배경
+
+MNG 관리자 패널에 품목(Items)을 관리하고 BOM 연결관계를 시각적으로 파악할 수 있는 페이지가 필요하다.
+현재 items 테이블은 products + materials 통합 구조로, `items.bom` JSON 필드에 BOM 구성을 저장한다.
+
+### 1.2 기준 원칙
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ 🎯 핵심 원칙 │
+├─────────────────────────────────────────────────────────────────┤
+│ - MNG에서 마이그레이션 파일 생성 금지 (API에서만) │
+│ - Service-First (비즈니스 로직은 Service 클래스에만) │
+│ - FormRequest 필수 (Controller 검증 금지) │
+│ - BelongsToTenant (테넌트 격리) │
+│ - Blade + HTMX + Tailwind (Alpine.js 미사용) │
+│ - 세션 기반 테넌트 필터링: session('selected_tenant_id') │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+### 1.3 변경 승인 정책
+
+| 분류 | 예시 | 승인 |
+|------|------|------|
+| ✅ 즉시 가능 | 모델/서비스/뷰/컨트롤러/라우트 생성 | 불필요 |
+| ⚠️ 컨펌 필요 | 기존 라우트 수정, 사이드바 메뉴 추가 | **필수** |
+| 🔴 금지 | mng에서 마이그레이션 생성, 테이블 구조 변경 | 별도 협의 |
+
+### 1.4 MNG 절대 금지 규칙 (인라인)
+
+```
+❌ mng/database/migrations/ 에 파일 생성 금지
+❌ docker exec sam-mng-1 php artisan migrate 실행 금지
+❌ php artisan db:seed --class=*MenuSeeder 실행 금지
+❌ 메뉴 시더 파일 생성/실행 금지 (부서별 권한 초기화됨)
+❌ Controller에서 직접 DB 쿼리 금지 (Service-First)
+❌ Controller에서 직접 validate() 금지 (FormRequest 필수)
+```
+
+---
+
+## 2. 기능 설계
+
+### 2.1 3-Panel 레이아웃
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ Header (64px) - 테넌트 선택 (session 기반 필터링) │
+├──────────┬─────────────────────────────┬────────────────────────────┤
+│ 좌측 │ 중앙 │ 우측 │
+│ (280px) │ (flex-1) │ (380px) │
+│ │ │ │
+│ [검색] │ │ ┌──────────────────────┐ │
+│ ________│ │ │ 기본정보 │ │
+│ │ BOM 재귀 트리 │ │ 코드: P-001 │ │
+│ 품목 1 ◀│ ┌ 완제품A │ │ 이름: 스크린 제품 │ │
+│ 품목 2 │ ├─ 부품B │ │ 유형: FG │ │
+│ 품목 3 │ │ ├─ 원자재C │ │ 단위: EA │ │
+│ 품목 4 │ │ └─ 부자재D │ │ 카테고리: ... │ │
+│ 품목 5 │ ├─ 부품E │ ├──────────────────────┤ │
+│ ... │ │ ├─ 원자재F │ │ BOM 구성 (1depth) │ │
+│ │ │ └─ 소모품G │ │ - 부품B (2ea) │ │
+│ │ └─ 원자재H │ │ - 부품E (1ea) │ │
+│ │ │ │ - 원자재H (0.5kg) │ │
+│ │ ← 전체 재귀 트리 → │ ├──────────────────────┤ │
+│ │ (좌측 선택 품목 기준) │ │ 절곡 정보 │ │
+│ │ │ │ (bending_details) │ │
+│ │ │ ├──────────────────────┤ │
+│ │ │ │ 이미지/파일 │ │
+│ │ │ │ 📎 도면.pdf │ │
+│ │ │ │ 📎 인증서.pdf │ │
+│ │ │ └──────────────────────┘ │
+├──────────┴─────────────────────────────┴────────────────────────────┤
+│ ← 클릭 시 어디서든 → 우측 상세 갱신 │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+### 2.2 패널별 상세 동작
+
+#### 좌측 패널 (품목 리스트)
+- **상단 검색**: `
` debounce 300ms, 코드+이름 동시 검색
+- **리스트**: 스크롤 가능, 선택된 항목 하이라이트
+- **표시 정보**: 품목코드, 품목명, 유형(FG/PT/SM/RM/CS) 뱃지
+- **테넌트 필터**: 헤더에서 선택된 테넌트 자동 적용 (BelongsToTenant)
+- **클릭 시**: 중앙 트리 갱신 + 우측 상세 갱신
+
+#### 중앙 패널 (BOM 재귀 트리)
+- **데이터 소스**: `items.bom` JSON → child_item_id 재귀 탐색
+- **트리 깊이**: 전체 재귀 (BOM → BOM → BOM ...)
+- **노드 표시**: 품목코드 + 품목명 + 수량 + 유형 뱃지
+- **펼침/접힘**: 노드별 토글 가능
+- **클릭 시**: 해당 품목으로 우측 상세 갱신 (좌측 선택은 변경 안 함)
+
+#### 우측 패널 (선택 품목 상세)
+- **기본정보**: 코드, 이름, 유형, 단위, 카테고리, 활성 여부, options
+- **BOM 구성 (1depth)**: 직접 연결된 자식 품목만 (재귀 X)
+- **절곡 정보**: item_details.bending_details JSON (해당 시)
+- **파일/이미지**: 연결된 files 목록
+- **scope**: 선택된 품목에 직접 연결된 정보만 (1depth)
+
+### 2.3 데이터 흐름
+
+```
+[좌측 검색/선택]
+ │
+ ├──→ HTMX GET /api/admin/items?search=xxx
+ │ → 좌측 리스트 갱신
+ │
+ ├──→ fetch GET /api/admin/items/{id}/bom-tree
+ │ → 중앙 트리 갱신 (재귀 JSON 반환 → Vanilla JS 렌더링)
+ │
+ └──→ HTMX GET /api/admin/items/{id}/detail
+ → 우측 상세 갱신
+
+[중앙 트리 노드 클릭]
+ │
+ └──→ HTMX GET /api/admin/items/{id}/detail
+ → 우측 상세만 갱신 (중앙 트리 유지)
+```
+
+---
+
+## 3. 기술 설계
+
+### 3.1 DB 스키마 (기존 테이블 활용, 변경 없음)
+
+```sql
+-- items (통합 품목) - 이미 존재하는 테이블
+-- item_type: FG(완제품), PT(부품), SM(부자재), RM(원자재), CS(소모품)
+-- item_category: SCREEN, STEEL, BENDING, ALUMINUM 등
+CREATE TABLE items (
+ id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+ tenant_id BIGINT UNSIGNED NOT NULL,
+ item_type VARCHAR(10) NOT NULL, -- FG/PT/SM/RM/CS
+ item_category VARCHAR(50) NULL, -- SCREEN/STEEL/BENDING/ALUMINUM 등
+ code VARCHAR(50) NOT NULL,
+ name VARCHAR(200) NOT NULL,
+ unit VARCHAR(20) NULL,
+ category_id BIGINT UNSIGNED NULL, -- FK → categories.id
+ bom JSON NULL, -- [{child_item_id: 5, quantity: 2.5}, ...]
+ attributes JSON NULL, -- 동적 필드 (migration 등에서 가져온 데이터)
+ attributes_archive JSON NULL, -- 아카이브
+ options JSON NULL, -- {lot_managed, consumption_method, ...}
+ description TEXT NULL,
+ is_active TINYINT(1) DEFAULT 1,
+ created_by BIGINT UNSIGNED NULL,
+ updated_by BIGINT UNSIGNED NULL,
+ deleted_at TIMESTAMP NULL,
+ created_at TIMESTAMP NULL,
+ updated_at TIMESTAMP NULL,
+ INDEX (tenant_id), INDEX (item_type), INDEX (code), INDEX (category_id)
+);
+
+-- item_details (1:1 확장) - 이미 존재하는 테이블
+CREATE TABLE item_details (
+ id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+ item_id BIGINT UNSIGNED NOT NULL UNIQUE, -- FK → items.id (1:1)
+ -- Products 전용
+ is_sellable TINYINT(1) DEFAULT 0,
+ is_purchasable TINYINT(1) DEFAULT 0,
+ is_producible TINYINT(1) DEFAULT 0,
+ safety_stock DECIMAL(10,2) NULL,
+ lead_time INT NULL,
+ is_variable_size TINYINT(1) DEFAULT 0,
+ product_category VARCHAR(50) NULL,
+ part_type VARCHAR(50) NULL,
+ bending_diagram VARCHAR(255) NULL, -- 절곡 도면 파일 경로
+ bending_details JSON NULL, -- 절곡 상세 정보 JSON
+ specification_file VARCHAR(255) NULL,
+ specification_file_name VARCHAR(255) NULL,
+ certification_file VARCHAR(255) NULL,
+ certification_file_name VARCHAR(255) NULL,
+ certification_number VARCHAR(100) NULL,
+ certification_start_date DATE NULL,
+ certification_end_date DATE NULL,
+ -- Materials 전용
+ is_inspection CHAR(1) NULL, -- 'Y'/'N'
+ item_name VARCHAR(200) NULL,
+ specification VARCHAR(500) NULL,
+ search_tag VARCHAR(500) NULL,
+ remarks TEXT NULL,
+ created_at TIMESTAMP NULL,
+ updated_at TIMESTAMP NULL
+);
+
+-- files (폴리모픽) - 이미 존재하는 테이블
+-- 품목 파일: document_id = items.id, document_type = '1' (ITEM_GROUP_ID)
+CREATE TABLE files (
+ id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+ tenant_id BIGINT UNSIGNED NULL,
+ document_id BIGINT UNSIGNED NOT NULL, -- 연결 대상 ID (items.id)
+ document_type VARCHAR(10) NOT NULL, -- '1' = ITEM_GROUP_ID
+ original_name VARCHAR(255) NOT NULL,
+ stored_name VARCHAR(255) NOT NULL,
+ path VARCHAR(500) NOT NULL,
+ mime_type VARCHAR(100) NULL,
+ size BIGINT UNSIGNED NULL,
+ created_at TIMESTAMP NULL,
+ updated_at TIMESTAMP NULL
+);
+
+-- categories - 이미 존재하는 테이블
+-- 품목 카테고리 (code_group으로 구분, 계층 구조)
+CREATE TABLE categories (
+ id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+ tenant_id BIGINT UNSIGNED NOT NULL,
+ parent_id BIGINT UNSIGNED NULL, -- 자기 참조 (트리)
+ code_group VARCHAR(50) NOT NULL, -- 카테고리 그룹
+ profile_code VARCHAR(50) NULL,
+ code VARCHAR(50) NOT NULL,
+ name VARCHAR(200) NOT NULL,
+ is_active TINYINT(1) DEFAULT 1,
+ sort_order INT DEFAULT 0,
+ description TEXT NULL,
+ created_by BIGINT UNSIGNED NULL,
+ updated_by BIGINT UNSIGNED NULL,
+ deleted_by BIGINT UNSIGNED NULL,
+ deleted_at TIMESTAMP NULL,
+ created_at TIMESTAMP NULL,
+ updated_at TIMESTAMP NULL
+);
+```
+
+### 3.2 BOM 트리 재귀 로직
+
+```php
+// ItemManagementService::getBomTree(int $itemId, int $maxDepth = 10): array
+public function getBomTree(int $itemId, int $maxDepth = 10): array
+{
+ $item = Item::with('details')->findOrFail($itemId);
+ return $this->buildBomNode($item, 0, $maxDepth, []);
+}
+
+private function buildBomNode(Item $item, int $depth, int $maxDepth, array $visited): array
+{
+ // 순환 참조 방지: visited 배열 + maxDepth 이중 안전장치
+ if (in_array($item->id, $visited) || $depth >= $maxDepth) {
+ return $this->formatNode($item, $depth, []);
+ }
+
+ $visited[] = $item->id;
+ $children = [];
+
+ $bomData = $item->bom ?? [];
+ if (!empty($bomData)) {
+ $childIds = array_column($bomData, 'child_item_id');
+ $childItems = Item::whereIn('id', $childIds)->get()->keyBy('id');
+
+ foreach ($bomData as $bom) {
+ $childItem = $childItems->get($bom['child_item_id']);
+ if ($childItem) {
+ $childNode = $this->buildBomNode($childItem, $depth + 1, $maxDepth, $visited);
+ $childNode['quantity'] = $bom['quantity'] ?? 1;
+ $children[] = $childNode;
+ }
+ }
+ }
+
+ return $this->formatNode($item, $depth, $children);
+}
+
+private function formatNode(Item $item, int $depth, array $children): array
+{
+ return [
+ 'id' => $item->id,
+ 'code' => $item->code,
+ 'name' => $item->name,
+ 'item_type' => $item->item_type,
+ 'unit' => $item->unit,
+ 'depth' => $depth,
+ 'has_children' => count($children) > 0,
+ 'children' => $children,
+ ];
+}
+```
+
+### 3.3 API 엔드포인트 설계
+
+| Method | Endpoint | 설명 | 반환 |
+|--------|----------|------|------|
+| GET | `/api/admin/items` | 품목 목록 (검색, 페이지네이션) | HTML partial |
+| GET | `/api/admin/items/{id}/bom-tree` | BOM 재귀 트리 | JSON |
+| GET | `/api/admin/items/{id}/detail` | 품목 상세 (1depth BOM, 파일, 절곡) | HTML partial |
+
+#### GET /api/admin/items
+
+| 파라미터 | 타입 | 설명 |
+|---------|------|------|
+| search | string | 코드+이름 검색 (LIKE) |
+| item_type | string | 유형 필터 (FG,PT,SM,RM,CS 쉼표 구분) |
+| per_page | int | 페이지 크기 (default: 50) |
+| page | int | 페이지 번호 |
+
+#### GET /api/admin/items/{id}/bom-tree
+
+| 파라미터 | 타입 | 설명 |
+|---------|------|------|
+| max_depth | int | 최대 재귀 깊이 (default: 10) |
+
+**응답 (JSON)**:
+```json
+{
+ "id": 1,
+ "code": "SCREEN-001",
+ "name": "스크린 제품",
+ "item_type": "FG",
+ "unit": "EA",
+ "depth": 0,
+ "has_children": true,
+ "children": [
+ {
+ "id": 5,
+ "code": "SLAT-001",
+ "name": "슬랫",
+ "item_type": "PT",
+ "quantity": 2.5,
+ "depth": 1,
+ "has_children": true,
+ "children": [
+ {
+ "id": 12,
+ "code": "STEEL-001",
+ "name": "강판",
+ "item_type": "RM",
+ "quantity": 1.0,
+ "depth": 2,
+ "has_children": false,
+ "children": []
+ }
+ ]
+ }
+ ]
+}
+```
+
+#### GET /api/admin/items/{id}/detail
+
+**응답 (HTML partial)**: 기본정보 + BOM 1depth + 절곡정보 + 파일 목록
+
+### 3.4 파일 구조
+
+```
+mng/
+├── app/
+│ ├── Http/
+│ │ └── Controllers/
+│ │ ├── ItemManagementController.php # Web (Blade 화면)
+│ │ └── Api/Admin/
+│ │ └── ItemManagementApiController.php # API (HTMX)
+│ ├── Models/
+│ │ ├── Category.php # ⚠️ 이미 존재 (수정 불필요)
+│ │ └── Items/
+│ │ ├── Item.php # ⚠️ 이미 존재 → 보완 필요
+│ │ └── ItemDetail.php # 신규 생성
+│ ├── Services/
+│ │ └── ItemManagementService.php # BOM 트리, 검색, 상세
+│ └── Traits/
+│ └── BelongsToTenant.php # ⚠️ 이미 존재 (수정 불필요)
+├── resources/
+│ └── views/
+│ └── item-management/
+│ ├── index.blade.php # 메인 (3-Panel)
+│ └── partials/
+│ ├── item-list.blade.php # 좌측 리스트
+│ ├── bom-tree.blade.php # 중앙 트리 (JS 렌더링)
+│ └── item-detail.blade.php # 우측 상세
+└── routes/
+ ├── web.php # + items 라우트 추가
+ └── api.php # + items API 라우트 추가
+```
+
+### 3.5 트리 렌더링 방식
+
+**Vanilla JS + Tailwind (라이브러리 미사용)** - MNG 기존 패턴 유지
+
+```javascript
+// BOM 트리 JSON → HTML 변환
+function renderBomTree(node, container) {
+ const li = document.createElement('li');
+ li.className = 'ml-4';
+
+ // 노드 렌더링
+ const nodeEl = document.createElement('div');
+ nodeEl.className = 'flex items-center gap-2 py-1 px-2 rounded cursor-pointer hover:bg-blue-50';
+ nodeEl.onclick = () => selectTreeNode(node.id);
+
+ // 펼침/접힘 토글
+ if (node.has_children) {
+ const toggle = document.createElement('span');
+ toggle.className = 'text-gray-400 cursor-pointer';
+ toggle.textContent = '▶';
+ toggle.onclick = (e) => { e.stopPropagation(); toggleNode(toggle, childList); };
+ nodeEl.appendChild(toggle);
+ } else {
+ // 빈 공간 (들여쓰기 맞춤)
+ const spacer = document.createElement('span');
+ spacer.className = 'w-4 inline-block';
+ nodeEl.appendChild(spacer);
+ }
+
+ // 유형 뱃지 + 코드 + 이름 + 수량
+ nodeEl.innerHTML += `
+
${node.item_type}
+
${node.code}
+
${node.name}
+ ${node.quantity ? `
(${node.quantity}) ` : ''}
+ `;
+ li.appendChild(nodeEl);
+
+ // 자식 노드 재귀 렌더링
+ if (node.children && node.children.length > 0) {
+ const childList = document.createElement('ul');
+ childList.className = 'border-l border-gray-200';
+ node.children.forEach(child => renderBomTree(child, childList));
+ li.appendChild(childList);
+ }
+
+ container.appendChild(li);
+}
+
+// 트리 노드 펼침/접힘
+function toggleNode(toggle, childList) {
+ if (childList.style.display === 'none') {
+ childList.style.display = '';
+ toggle.textContent = '▼';
+ } else {
+ childList.style.display = 'none';
+ toggle.textContent = '▶';
+ }
+}
+```
+
+---
+
+## 4. 대상 범위
+
+### Phase 1: 백엔드 (모델 + 서비스 + API)
+
+| # | 작업 항목 | 상태 | 비고 |
+|---|----------|:----:|------|
+| 1.1 | Item 모델 보완 (mng/app/Models/Items/Item.php) | ✅ | BelongsToTenant, 관계, 스코프, 상수, 헬퍼 추가 |
+| 1.2 | ItemDetail 모델 생성 (mng/app/Models/Items/ItemDetail.php) | ✅ | 1:1 관계, is_variable_size 포함 |
+| 1.3 | ItemManagementService 생성 | ✅ | getItemList, getBomTree(재귀), getItemDetail |
+| 1.4 | ItemManagementApiController 생성 | ✅ | index(HTML), bomTree(JSON), detail(HTML) |
+| 1.5 | API 라우트 등록 (routes/api.php) | ✅ | /api/admin/items/* (3개 라우트) |
+| 1.6 | File 모델 생성 (mng/app/Models/Commons/File.php) | ✅ | Item.files() 관계용 |
+
+### Phase 2: 프론트엔드 (Blade + JS)
+
+| # | 작업 항목 | 상태 | 비고 |
+|---|----------|:----:|------|
+| 2.1 | 메인 페이지 (index.blade.php) - 3-Panel 레이아웃 | ✅ | Tailwind flex, 3-Panel |
+| 2.2 | 좌측 패널 (item-list.blade.php) + 실시간 검색 | ✅ | HTMX + debounce 300ms + 유형 필터 |
+| 2.3 | 중앙 패널 (bom-tree.blade.php) + JS 트리 렌더링 | ✅ | Vanilla JS 재귀 렌더링 |
+| 2.4 | 우측 패널 (item-detail.blade.php) | ✅ | 기본정보+BOM 1depth+절곡+파일 |
+| 2.5 | ItemManagementController (Web) 생성 | ✅ | HX-Redirect 패턴 |
+| 2.6 | Web 라우트 등록 (routes/web.php) | ✅ | GET /item-management |
+| 2.7 | 유형별 뱃지 스타일 + 트리 라인 CSS | ✅ | Tailwind inline + JS getTypeBadgeClass |
+
+### Phase 3: 수식 엔진 연동 (후속 작업)
+
+> 별도 계획 문서: `docs/plans/mng-item-formula-integration-plan.md`
+>
+> 가변사이즈 FG 품목 선택 시 오픈사이즈(W,H) 입력 → FormulaEvaluatorService 동적 산출 → 중앙 패널 탭 전환 표시
+
+---
+
+## 5. 작업 절차
+
+### Step 1: 모델 보완/생성 (Phase 1.1, 1.2)
+```
+├── mng/app/Models/Items/Item.php 보완 (기존 파일 존재)
+│ 현재 상태: SoftDeletes만 있음, BelongsToTenant 없음, 관계 없음
+│ 추가 필요:
+│ - use App\Traits\BelongsToTenant 추가
+│ - $fillable에 category_id, bom, attributes, options, description 추가
+│ - $casts에 bom→array, options→array 추가
+│ - 관계: details(), category(), files()
+│ - 스코프: type(), active(), search()
+│ - 상수: TYPE_FG 등, PRODUCT_TYPES, MATERIAL_TYPES
+│ - 헬퍼: isProduct(), isMaterial(), getBomChildIds()
+│
+└── mng/app/Models/Items/ItemDetail.php 생성 (신규)
+ - item() belongsTo 관계
+ - $fillable: 전체 필드 (섹션 A.3 참고)
+ - $casts: bending_details→array, is_sellable→boolean 등
+```
+
+### Step 2: 서비스 생성 (Phase 1.3)
+```
+├── mng/app/Services/ItemManagementService.php 생성
+│ - getItemList(array $filters): LengthAwarePaginator
+│ └ Item::query()->search($search)->active()->orderBy('code')->paginate($perPage)
+│ - getBomTree(int $itemId, int $maxDepth = 10): array
+│ └ 재귀 buildBomNode() (섹션 3.2 코드)
+│ - getItemDetail(int $itemId): array
+│ └ Item::with(['details', 'category', 'files'])->findOrFail($id)
+│ └ BOM 1depth: items.bom JSON에서 child_item_id 추출 → Item::whereIn()
+│
+└── 테넌트 스코프 자동 적용 (BelongsToTenant가 글로벌 스코프 등록)
+```
+
+### Step 3: API 컨트롤러 + 라우트 (Phase 1.4, 1.5)
+```
+├── mng/app/Http/Controllers/Api/Admin/ItemManagementApiController.php
+│ - __construct(private readonly ItemManagementService $service)
+│ - index(Request $request): View
+│ └ HTMX 요청 시 HTML partial 반환 (Blade view render)
+│ - bomTree(int $id): JsonResponse
+│ └ JSON 반환 (JS에서 트리 렌더링)
+│ - detail(int $id): View
+│ └ HTML partial 반환 (item-detail.blade.php)
+│
+└── routes/api.php에 라우트 추가 (기존 그룹 내)
+ // 기존 Route::middleware(['web', 'auth', 'hq.member'])
+ // ->prefix('admin')->name('api.admin.')->group(function () { ... });
+ // 내부에 추가:
+ Route::prefix('items')->name('items.')->group(function () {
+ Route::get('/', [ItemManagementApiController::class, 'index'])->name('index');
+ Route::get('/{id}/bom-tree', [ItemManagementApiController::class, 'bomTree'])->name('bom-tree');
+ Route::get('/{id}/detail', [ItemManagementApiController::class, 'detail'])->name('detail');
+ });
+```
+
+### Step 4: Blade 뷰 생성 (Phase 2.1~2.4)
+```
+├── index.blade.php: 3-Panel 메인 레이아웃
+│ @extends('layouts.app'), @section('content'), @push('scripts')
+│ HTMX 페이지이므로 HX-Redirect 필요 (JS가 @push('scripts')에 있음)
+│
+├── partials/item-list.blade.php: 좌측 품목 리스트
+│ @foreach($items as $item) → 품목코드, 품목명, 유형 뱃지
+│ data-item-id="{{ $item->id }}" onclick="selectItem({{ $item->id }})"
+│
+├── partials/bom-tree.blade.php: 중앙 트리 (빈 컨테이너)
+│
품목을 선택하세요
+│
+└── partials/item-detail.blade.php: 우측 상세정보
+ 기본정보 테이블 + BOM 1depth 리스트 + 절곡 정보 + 파일 목록
+```
+
+### Step 5: Web 컨트롤러 + 라우트 (Phase 2.5, 2.6)
+```
+├── mng/app/Http/Controllers/ItemManagementController.php
+│ - __construct(private readonly ItemManagementService $service)
+│ - index(Request $request): View|Response
+│ └ HX-Request 체크 → HX-Redirect (JS 포함 페이지이므로)
+│ └ return view('item-management.index')
+│
+└── routes/web.php에 라우트 추가
+ // 기존 인증 미들웨어 그룹 내에 추가:
+ Route::get('/item-management', [ItemManagementController::class, 'index'])
+ ->name('item-management.index');
+```
+
+### Step 6: 스타일 + 트리 인터랙션 (Phase 2.7)
+```
+├── 유형별 뱃지 색상 (Tailwind inline)
+│ FG: bg-blue-100 text-blue-800 (완제품)
+│ PT: bg-green-100 text-green-800 (부품)
+│ SM: bg-yellow-100 text-yellow-800 (부자재)
+│ RM: bg-orange-100 text-orange-800 (원자재)
+│ CS: bg-gray-100 text-gray-800 (소모품)
+│
+└── 트리 라인 CSS (border-l + ml-4 indent)
+```
+
+---
+
+## 6. 상세 구현 명세
+
+### 6.1 Item 모델 보완 (기존 파일 수정)
+
+**기존 파일**: `mng/app/Models/Items/Item.php`
+
+**현재 상태 (보완 전)**:
+```php
+ 'boolean',
+ 'attributes' => 'array',
+ ];
+}
+```
+
+**보완 후 (목표 상태)**:
+```php
+ 'array',
+ 'attributes' => 'array',
+ 'attributes_archive' => 'array',
+ 'options' => 'array',
+ 'is_active' => 'boolean',
+ ];
+
+ // 유형 상수
+ const TYPE_FG = 'FG'; // 완제품
+ const TYPE_PT = 'PT'; // 부품
+ const TYPE_SM = 'SM'; // 부자재
+ const TYPE_RM = 'RM'; // 원자재
+ const TYPE_CS = 'CS'; // 소모품
+
+ const PRODUCT_TYPES = ['FG', 'PT'];
+ const MATERIAL_TYPES = ['SM', 'RM', 'CS'];
+
+ // ── 관계 ──
+
+ public function details()
+ {
+ return $this->hasOne(ItemDetail::class, 'item_id');
+ }
+
+ public function category()
+ {
+ return $this->belongsTo(Category::class, 'category_id');
+ }
+
+ /**
+ * 파일 (document_id/document_type 기반)
+ * document_id = items.id, document_type = '1' (ITEM_GROUP_ID)
+ */
+ public function files()
+ {
+ return $this->hasMany(\App\Models\Commons\File::class, 'document_id')
+ ->where('document_type', '1');
+ }
+
+ // ── 스코프 ──
+
+ public function scopeType($query, string $type)
+ {
+ return $query->where('items.item_type', strtoupper($type));
+ }
+
+ public function scopeActive($query)
+ {
+ return $query->where('is_active', true);
+ }
+
+ public function scopeSearch($query, ?string $search)
+ {
+ if (!$search) return $query;
+ return $query->where(function ($q) use ($search) {
+ $q->where('code', 'like', "%{$search}%")
+ ->orWhere('name', 'like', "%{$search}%");
+ });
+ }
+
+ // ── 헬퍼 ──
+
+ public function isProduct(): bool
+ {
+ return in_array($this->item_type, self::PRODUCT_TYPES);
+ }
+
+ public function isMaterial(): bool
+ {
+ return in_array($this->item_type, self::MATERIAL_TYPES);
+ }
+
+ public function getBomChildIds(): array
+ {
+ return collect($this->bom ?? [])->pluck('child_item_id')->filter()->toArray();
+ }
+}
+```
+
+> **주의**: files() 관계에서 `\App\Models\Commons\File::class` 경로를 사용한다.
+> 만약 mng에 File 모델이 없다면, 단순 모델로 신규 생성해야 한다.
+> 확인 필요: `mng/app/Models/Commons/File.php` 존재 여부. 없으면 생성.
+
+### 6.2 ItemDetail 모델 (신규 생성)
+
+```php
+ 'boolean',
+ 'is_purchasable' => 'boolean',
+ 'is_producible' => 'boolean',
+ 'is_variable_size' => 'boolean',
+ 'bending_details' => 'array',
+ 'certification_start_date' => 'date',
+ 'certification_end_date' => 'date',
+ ];
+
+ public function item()
+ {
+ return $this->belongsTo(Item::class);
+ }
+}
+```
+
+### 6.3 좌측 검색 - Debounce + HTMX
+
+```javascript
+// index.blade.php @push('scripts')
+let searchTimer = null;
+const searchInput = document.getElementById('item-search');
+
+searchInput.addEventListener('input', function() {
+ clearTimeout(searchTimer);
+ searchTimer = setTimeout(() => {
+ const search = this.value.trim();
+ htmx.ajax('GET', `/api/admin/items?search=${encodeURIComponent(search)}&per_page=50`, {
+ target: '#item-list',
+ swap: 'innerHTML',
+ headers: {'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content}
+ });
+ }, 300); // 300ms debounce
+});
+```
+
+### 6.4 품목 선택 시 중앙+우측 갱신
+
+```javascript
+// 품목 선택 함수 (좌측/중앙 공용)
+function selectItem(itemId, updateTree = true) {
+ // 선택 하이라이트
+ document.querySelectorAll('.item-row').forEach(el => el.classList.remove('bg-blue-50', 'border-blue-300'));
+ const selected = document.querySelector(`[data-item-id="${itemId}"]`);
+ if (selected) selected.classList.add('bg-blue-50', 'border-blue-300');
+
+ // 중앙 트리 갱신 (좌측에서 클릭 시에만)
+ if (updateTree) {
+ fetch(`/api/admin/items/${itemId}/bom-tree`, {
+ headers: {'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content}
+ })
+ .then(res => res.json())
+ .then(tree => {
+ const container = document.getElementById('bom-tree-container');
+ container.innerHTML = '';
+ if (tree.has_children) {
+ const ul = document.createElement('ul');
+ renderBomTree(tree, ul);
+ container.appendChild(ul);
+ } else {
+ container.innerHTML = '
BOM 구성이 없습니다.
';
+ }
+ });
+ }
+
+ // 우측 상세 갱신 (항상)
+ htmx.ajax('GET', `/api/admin/items/${itemId}/detail`, {
+ target: '#item-detail',
+ swap: 'innerHTML',
+ headers: {'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content}
+ });
+}
+
+// 중앙 트리 노드 클릭 (트리는 유지, 우측만 갱신)
+function selectTreeNode(itemId) {
+ selectItem(itemId, false); // updateTree = false
+}
+```
+
+---
+
+## 7. 컨펌 대기 목록
+
+| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
+|---|------|----------|----------|------|
+| 1 | 사이드바 메뉴 추가 | "품목관리" 메뉴 항목 추가 | menus 테이블 (DB) | ⏳ tinker 안내 필요 |
+
+---
+
+## 8. 변경 이력
+
+| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
+|------|------|----------|------|------|
+| 2026-02-19 | - | 문서 초안 작성 | - | - |
+| 2026-02-19 | - | 자기완결성 보강 (Appendix A~C 추가) | - | - |
+| 2026-02-19 | Phase 1 | Item 모델 보완, ItemDetail/File 모델 생성 | Item.php, ItemDetail.php, File.php | ✅ |
+| 2026-02-19 | Phase 1 | ItemManagementService 생성 | ItemManagementService.php | ✅ |
+| 2026-02-19 | Phase 1 | ItemManagementApiController 생성 + API 라우트 | ItemManagementApiController.php, api.php | ✅ |
+| 2026-02-19 | Phase 2 | 3-Panel Blade 뷰 전체 생성 | index.blade.php + 3 partials | ✅ |
+| 2026-02-19 | Phase 2 | Web 컨트롤러 + 라우트 등록 | ItemManagementController.php, web.php | ✅ |
+| 2026-02-19 | - | Phase 1~2 완료, Phase 3 수식 연동 계획 별도 문서 분리 | mng-item-formula-integration-plan.md | - |
+
+---
+
+## 9. 참고 문서
+
+- **품목 정책**: `docs/rules/item-policy.md`
+- **품목 연동 설계**: `docs/specs/item-master-integration.md`
+- **MNG 절대 규칙**: `mng/docs/MNG_CRITICAL_RULES.md`
+- **MNG 프로젝트 문서**: `mng/docs/INDEX.md`
+- **DB 스키마**: `docs/specs/database-schema.md`
+- **API Item 모델**: `api/app/Models/Items/Item.php`
+- **API ItemDetail 모델**: `api/app/Models/Items/ItemDetail.php`
+
+---
+
+## 10. 검증 결과
+
+### 10.1 테스트 케이스
+
+| 입력값 | 예상 결과 | 실제 결과 | 상태 |
+|--------|----------|----------|------|
+| 좌측 검색: "스크린" | "스크린" 포함 품목만 표시 | 정상 동작 | ✅ |
+| FG 품목 클릭 | 중앙에 BOM 트리, 우측에 상세 | 정상 동작 (정적 BOM 2개 표시) | ✅ |
+| BOM 없는 품목 클릭 | 중앙 "BOM 없음", 우측 상세 표시 | 정상 동작 | ✅ |
+| 중앙 트리 노드 클릭 | 우측 상세만 변경 (트리 유지) | 정상 동작 | ✅ |
+| 테넌트 전환 | 좌측 리스트가 해당 테넌트 품목으로 변경 | 확인 필요 | ⏳ |
+| 순환 참조 BOM | 무한 루프 없이 maxDepth에서 중단 | 로직 구현 완료, 실제 데이터 미검증 | ⏳ |
+
+### 10.2 성공 기준
+
+| 기준 | 달성 | 비고 |
+|------|------|------|
+| 3-Panel 레이아웃 정상 렌더링 | ✅ | 좌측 280px + 중앙 flex-1 + 우측 384px |
+| 실시간 검색 (debounce 300ms) | ✅ | 코드+이름 동시 검색 |
+| BOM 재귀 트리 정상 표시 (전체 depth) | ✅ | 펼침/접힘 토글 포함 |
+| 어디서든 클릭 → 우측 상세 갱신 | ✅ | selectItem + selectTreeNode |
+| 테넌트 필터링 정상 동작 | ⏳ | withoutGlobalScopes + session 패턴 사용 |
+| 순환 참조 방지 (maxDepth) | ✅ | visited 배열 + maxDepth 이중 안전장치 |
+
+---
+
+## 11. 자기완결성 점검 결과
+
+### 11.1 체크리스트 검증
+
+| # | 검증 항목 | 상태 | 비고 |
+|---|----------|:----:|------|
+| 1 | 작업 목적이 명확한가? | ✅ | 3-Panel 품목관리 페이지 |
+| 2 | 성공 기준이 정의되어 있는가? | ✅ | 섹션 10.2 |
+| 3 | 작업 범위가 구체적인가? | ✅ | 섹션 4 (12개 작업 항목) |
+| 4 | 의존성이 명시되어 있는가? | ✅ | items 테이블 존재 전제 |
+| 5 | 참고 파일 경로가 정확한가? | ✅ | 섹션 9 + Appendix |
+| 6 | 단계별 절차가 실행 가능한가? | ✅ | 섹션 5 (6 Step) |
+| 7 | 검증 방법이 명시되어 있는가? | ✅ | 섹션 10.1 |
+| 8 | 모호한 표현이 없는가? | ✅ | 구체적 코드/구조 명시 |
+
+### 11.2 새 세션 시뮬레이션 테스트
+
+| 질문 | 답변 가능 | 참조 섹션 |
+|------|:--------:|----------|
+| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
+| Q2. 어디서부터 시작해야 하는가? | ✅ | 5. 작업 절차 Step 1 |
+| Q3. 어떤 파일을 수정해야 하는가? | ✅ | 3.4 파일 구조 + 6.1 기존 파일 현황 |
+| Q4. 작업 완료 확인 방법은? | ✅ | 10. 검증 결과 |
+| Q5. 막혔을 때 참고 문서는? | ✅ | 9. 참고 문서 + Appendix A~C |
+| Q6. MNG 코딩 패턴은 무엇인가? | ✅ | Appendix A (인라인 패턴) |
+| Q7. 테넌트 필터링은 어떻게 동작하는가? | ✅ | Appendix B (BelongsToTenant 전문) |
+| Q8. API 모델의 정확한 필드는? | ✅ | Appendix C (API 모델 전문) |
+
+**결과**: 8/8 통과 → ✅ 자기완결성 확보
+
+---
+
+## Appendix A: MNG 코딩 패턴 레퍼런스
+
+> 새 세션에서 외부 파일을 읽지 않고도 MNG 패턴을 따를 수 있도록 인라인화한 레퍼런스.
+
+### A.1 Web Controller 패턴
+
+Web Controller는 Blade 뷰 렌더링만 담당한다. 비즈니스 로직은 Service에 위임.
+
+```php
+header('HX-Request')) {
+ return response('', 200)->header('HX-Redirect', route('item-management.index'));
+ }
+ return view('item-management.index');
+}
+```
+
+### A.2 API Controller 패턴
+
+API Controller는 HTMX 요청 시 HTML partial, 일반 요청 시 JSON 반환.
+
+```php
+departmentService->getDepartments(
+ $request->all(),
+ $request->integer('per_page', 10)
+ );
+
+ // HTMX 요청 시 HTML partial 반환
+ if ($request->header('HX-Request')) {
+ return view('departments.partials.table', compact('departments'));
+ }
+
+ // 일반 요청 시 JSON
+ return response()->json([
+ 'success' => true,
+ 'data' => $departments->items(),
+ 'meta' => [
+ 'current_page' => $departments->currentPage(),
+ 'last_page' => $departments->lastPage(),
+ 'per_page' => $departments->perPage(),
+ 'total' => $departments->total(),
+ ],
+ ]);
+ }
+}
+```
+
+### A.3 Service 패턴
+
+모든 DB 쿼리 로직은 Service에서 처리. `session('selected_tenant_id')`로 테넌트 격리.
+
+```php
+with('parent');
+
+ // 검색 필터
+ if (!empty($filters['search'])) {
+ $search = $filters['search'];
+ $query->where(function ($q) use ($search) {
+ $q->where('name', 'like', "%{$search}%")
+ ->orWhere('code', 'like', "%{$search}%");
+ });
+ }
+
+ return $query->orderBy('sort_order')->paginate($perPage);
+ }
+}
+```
+
+> **중요**: BelongsToTenant trait이 모델에 있으면 tenant_id 필터가 자동 적용된다.
+> Service에서 수동으로 `where('tenant_id', ...)` 할 필요 없음.
+
+### A.4 Blade + HTMX 패턴
+
+Index 페이지는 빈 셸이고, 데이터는 HTMX `hx-get` + `hx-trigger="load"`로 로드.
+
+```blade
+{{-- 참고: mng/resources/views/departments/index.blade.php 패턴 --}}
+@extends('layouts.app')
+
+@section('title', '부서 관리')
+
+@section('content')
+
+
부서 관리
+
+
+ {{-- HTMX 테이블: 초기 로드 + 이벤트 재로드 --}}
+
+@endsection
+
+@push('scripts')
+
+@endpush
+```
+
+### A.5 라우트 패턴
+
+**routes/web.php** 구조:
+```php
+// 인증 필요 라우트 그룹
+Route::middleware(['auth', 'hq.member', 'password.changed'])->group(function () {
+ // ... 기존 라우트들 ...
+
+ // 품목관리 (신규 추가할 위치)
+ Route::get('/item-management', [ItemManagementController::class, 'index'])
+ ->name('item-management.index');
+});
+```
+
+**routes/api.php** 구조:
+```php
+// MNG API는 세션 기반 (token 아님)
+Route::middleware(['web', 'auth', 'hq.member'])
+ ->prefix('admin')
+ ->name('api.admin.')
+ ->group(function () {
+ // ... 기존 API 라우트들 ...
+
+ // 품목관리 API (신규 추가할 위치)
+ Route::prefix('items')->name('items.')->group(function () {
+ Route::get('/', [ItemManagementApiController::class, 'index'])->name('index');
+ Route::get('/{id}/bom-tree', [ItemManagementApiController::class, 'bomTree'])->name('bom-tree');
+ Route::get('/{id}/detail', [ItemManagementApiController::class, 'detail'])->name('detail');
+ });
+ });
+```
+
+> **주의**: MNG API는 `['web', 'auth', 'hq.member']` 미들웨어 사용 (세션 기반, Sanctum 아님).
+> 고정 라우트(`/all`, `/summary`)를 `/{id}` 파라미터 라우트보다 먼저 정의해야 충돌 방지.
+
+### A.6 모델 패턴
+
+```php
+// 참고: mng/app/Models/Category.php 패턴
+use App\Traits\BelongsToTenant;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
+class Category extends Model
+{
+ use BelongsToTenant, SoftDeletes;
+
+ protected $fillable = [
+ 'tenant_id', 'parent_id', 'code_group', 'profile_code',
+ 'code', 'name', 'is_active', 'sort_order', 'description',
+ 'created_by', 'updated_by', 'deleted_by',
+ ];
+
+ protected $casts = [
+ 'is_active' => 'boolean',
+ 'sort_order' => 'integer',
+ ];
+
+ // 자기 참조 트리
+ public function parent() { return $this->belongsTo(self::class, 'parent_id'); }
+ public function children() { return $this->hasMany(self::class, 'parent_id')->orderBy('sort_order'); }
+
+ // 스코프
+ public function scopeActive($query) { return $query->where('is_active', true); }
+}
+```
+
+---
+
+## Appendix B: BelongsToTenant 동작 방식
+
+### B.1 Trait (mng/app/Traits/BelongsToTenant.php)
+
+```php
+runningInConsole()) {
+ return;
+ }
+
+ // 요청당 1회만 tenant_id 조회 (캐시)
+ if (!self::$cacheInitialized) {
+ $request = app(Request::class);
+ self::$cachedTenantId = $request->attributes->get('tenant_id')
+ ?? $request->header('X-TENANT-ID')
+ ?? auth()->user()?->tenant_id;
+ self::$cacheInitialized = true;
+ }
+
+ if (self::$cachedTenantId !== null) {
+ $builder->where($model->getTable() . '.tenant_id', self::$cachedTenantId);
+ }
+ }
+
+ public static function clearCache(): void
+ {
+ self::$cachedTenantId = null;
+ self::$cacheInitialized = false;
+ }
+}
+```
+
+**동작 요약**:
+1. 모델에 `use BelongsToTenant` 선언하면 자동으로 TenantScope 등록
+2. 모든 쿼리에 `WHERE items.tenant_id = ?` 조건 자동 추가
+3. tenant_id 결정 우선순위: request attributes → X-TENANT-ID 헤더 → auth user
+4. console 환경(migrate 등)에서는 스킵
+5. **Service에서 수동 tenant_id 필터 불필요** (자동 적용)
+
+---
+
+## Appendix C: API 모델 전문 (참조용)
+
+> 구현 시 API 모델의 정확한 필드 목록과 관계를 참고하기 위한 인라인 전문.
+
+### C.1 api/app/Models/Items/Item.php (전체)
+
+```php
+ 'array',
+ 'attributes' => 'array',
+ 'attributes_archive' => 'array',
+ 'options' => 'array',
+ 'is_active' => 'boolean',
+ ];
+
+ const TYPE_FINISHED_GOODS = 'FG';
+ const TYPE_PARTS = 'PT';
+ const TYPE_SUB_MATERIALS = 'SM';
+ const TYPE_RAW_MATERIALS = 'RM';
+ const TYPE_CONSUMABLES = 'CS';
+ const PRODUCT_TYPES = ['FG', 'PT'];
+ const MATERIAL_TYPES = ['SM', 'RM', 'CS'];
+
+ public function details() { return $this->hasOne(ItemDetail::class); }
+ public function stock() { return $this->hasOne(\App\Models\Tenants\Stock::class); }
+ public function category() { return $this->belongsTo(Category::class, 'category_id'); }
+
+ // files: document_id = item_id, document_type = '1' (ITEM_GROUP_ID)
+ public function files()
+ {
+ return $this->hasMany(File::class, 'document_id')->where('document_type', '1');
+ }
+
+ public function tags() { return $this->morphToMany(Tag::class, 'taggable'); }
+
+ // BOM 자식 조회 (JSON bom 필드에서 child_item_id 추출)
+ public function bomChildren()
+ {
+ $childIds = collect($this->bom ?? [])->pluck('child_item_id')->filter()->toArray();
+ return self::whereIn('id', $childIds);
+ }
+
+ // 스코프
+ public function scopeType($query, string $type)
+ {
+ return $query->where('items.item_type', strtoupper($type));
+ }
+ public function scopeProducts($query) { return $query->whereIn('items.item_type', self::PRODUCT_TYPES); }
+ public function scopeMaterials($query) { return $query->whereIn('items.item_type', self::MATERIAL_TYPES); }
+ public function scopeActive($query) { return $query->where('is_active', true); }
+
+ // 헬퍼
+ public function isProduct(): bool { return in_array($this->item_type, self::PRODUCT_TYPES); }
+ public function isMaterial(): bool { return in_array($this->item_type, self::MATERIAL_TYPES); }
+ public function getBomChildIds(): array
+ {
+ return collect($this->bom ?? [])->pluck('child_item_id')->filter()->toArray();
+ }
+}
+```
+
+### C.2 api/app/Models/Items/ItemDetail.php (전체)
+
+```php
+ 'boolean',
+ 'is_purchasable' => 'boolean',
+ 'is_producible' => 'boolean',
+ 'is_variable_size' => 'boolean',
+ 'bending_details' => 'array',
+ 'certification_start_date' => 'date',
+ 'certification_end_date' => 'date',
+ ];
+
+ public function item() { return $this->belongsTo(Item::class); }
+ public function isSellable(): bool { return $this->is_sellable ?? false; }
+ public function isPurchasable(): bool { return $this->is_purchasable ?? false; }
+ public function isProducible(): bool { return $this->is_producible ?? false; }
+ public function isCertificationValid(): bool
+ {
+ return $this->certification_end_date?->isFuture() ?? false;
+ }
+ public function requiresInspection(): bool { return $this->is_inspection === 'Y'; }
+}
+```
+
+---
+
+## Appendix D: 구현 시 확인 사항
+
+### D.1 File 모델 존재 여부 확인
+
+구현 시작 전 `mng/app/Models/Commons/File.php` 존재 여부를 확인해야 한다.
+없으면 다음과 같이 간단한 모델 생성 필요:
+
+```php
+ 1,
+ 'parent_id' => <부모메뉴ID>,
+ 'name' => '품목관리',
+ 'url' => '/item-management',
+ 'icon' => 'heroicon-o-cube',
+ 'sort_order' => 1,
+ 'is_active' => true,
+]);
+"
+```
+
+### D.3 품목 유형 정리
+
+| 코드 | 이름 | 설명 | BOM 자식 가능 |
+|------|------|------|:------------:|
+| FG | 완제품 (Finished Goods) | 최종 판매 제품 | ✅ 주로 있음 |
+| PT | 부품 (Parts) | 조립/가공 부품 | ✅ 있을 수 있음 |
+| SM | 부자재 (Sub Materials) | 보조 자재 | ❌ 일반적으로 없음 |
+| RM | 원자재 (Raw Materials) | 원재료 | ❌ 리프 노드 |
+| CS | 소모품 (Consumables) | 소모성 자재 | ❌ 리프 노드 |
+
+### D.4 items.bom JSON 구조
+
+```json
+// items.bom 필드 예시 (FG 완제품)
+[
+ {"child_item_id": 5, "quantity": 2.5},
+ {"child_item_id": 8, "quantity": 1},
+ {"child_item_id": 12, "quantity": 0.5}
+]
+// child_item_id는 같은 items 테이블의 다른 행을 참조
+// quantity는 소수점 가능 (단위에 따라 kg, m, EA 등)
+```
+
+### D.5 items.options JSON 구조
+
+```json
+{
+ "lot_managed": true, // LOT 추적 여부
+ "consumption_method": "auto", // auto/manual/none
+ "production_source": "self_produced", // purchased/self_produced/both
+ "input_tracking": true // 원자재 투입 추적
+}
+```
+
+---
+
+*이 문서는 /plan 스킬로 생성되었습니다. 자기완결성 보강: 2026-02-19*
\ No newline at end of file
diff --git a/plans/order-location-management-plan.md b/plans/archive/order-location-management-plan.md
similarity index 100%
rename from plans/order-location-management-plan.md
rename to plans/archive/order-location-management-plan.md
diff --git a/plans/order-workorder-shipment-integration-plan.md b/plans/archive/order-workorder-shipment-integration-plan.md
similarity index 100%
rename from plans/order-workorder-shipment-integration-plan.md
rename to plans/archive/order-workorder-shipment-integration-plan.md
diff --git a/plans/quote-v2-auto-calculation-fix-plan.md b/plans/archive/quote-v2-auto-calculation-fix-plan.md
similarity index 100%
rename from plans/quote-v2-auto-calculation-fix-plan.md
rename to plans/archive/quote-v2-auto-calculation-fix-plan.md
diff --git a/plans/sam-stat-database-design-plan.md b/plans/archive/sam-stat-database-design-plan.md
similarity index 100%
rename from plans/sam-stat-database-design-plan.md
rename to plans/archive/sam-stat-database-design-plan.md
diff --git a/plans/simulator-calculation-logic-mapping.md b/plans/archive/simulator-calculation-logic-mapping.md
similarity index 100%
rename from plans/simulator-calculation-logic-mapping.md
rename to plans/archive/simulator-calculation-logic-mapping.md
diff --git a/plans/stock-integration-plan.md b/plans/archive/stock-integration-plan.md
similarity index 100%
rename from plans/stock-integration-plan.md
rename to plans/archive/stock-integration-plan.md
diff --git a/plans/welfare-section-plan.md b/plans/archive/welfare-section-plan.md
similarity index 100%
rename from plans/welfare-section-plan.md
rename to plans/archive/welfare-section-plan.md
diff --git a/plans/index_plans.md b/plans/index_plans.md
index fc4fedb..9cd0f4d 100644
--- a/plans/index_plans.md
+++ b/plans/index_plans.md
@@ -1,7 +1,7 @@
# 기획 문서 인덱스
> SAM 시스템 개발 계획 및 기획 문서 모음
-> **최종 업데이트**: 2026-01-20
+> **최종 업데이트**: 2026-02-22
---
@@ -9,14 +9,12 @@
| 분류 | 개수 | 설명 |
|------|------|------|
-| 진행중/대기 계획서 | 16개 | 기능별 API 개발 계획 |
-| 완료 아카이브 | 15개 | `archive/` 폴더에 보관 |
+| 진행중/대기 계획서 | 44개 | 기능별 개발 계획 |
+| 완료 아카이브 | 37개 | `archive/` 폴더에 보관 |
| 스토리보드 | 1개 | ERP 화면 설계 (D1.0) |
| 플로우 테스트 | 32개 | API 검증용 JSON 테스트 케이스 |
-> **Note**: D0.8 스토리보드는 `docs/history/2025-12/`로 아카이브됨
-> **Note**: E2E 버그 수정 계획은 `docs/history/2026-01/`로 아카이브됨 (2026-01-15 완료)
-> **Note**: 완료된 계획 15개는 `archive/` 폴더로 이동됨 (2026-01-20)
+> **Note**: 완료된 계획 37개는 `archive/` 폴더로 이동됨 (최종 정리: 2026-02-22)
---
@@ -24,72 +22,138 @@
### ERP API 개발
-| 문서 | 상태 | 설명 |
-|------|------|------|
-| [erp-api-development-plan.md](./erp-api-development-plan.md) | 🟡 Phase 3 진행중 | SAM ERP API 전체 개발 계획 (D0.8 기준) |
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [erp-api-development-plan.md](./erp-api-development-plan.md) | 🟡 진행중 | Phase 3/L | SAM ERP API 전체 개발 계획, L-2 React 연동 대기 |
-### 기능별 계획
+### 견적/수주 (Quote/Order)
-| 문서 | 상태 | 설명 |
-|------|------|------|
-| [simulator-calculation-logic-mapping.md](./simulator-calculation-logic-mapping.md) | 📚 참조 | 견적 시뮬레이터 계산 로직 매핑 분석 |
-| [mng-item-field-management-plan.md](./mng-item-field-management-plan.md) | ⚪ 계획수립 | 품목 필드 관리 (미착수) |
-| [items-table-unification-plan.md](./items-table-unification-plan.md) | ⚪ 계획수립 | items 테이블 통합 (롤백 후 대기) |
-| [mng-menu-system-plan.md](./mng-menu-system-plan.md) | 🔵 계획수립 | mng 메뉴 시스템 (설계 완료, 구현 대기) |
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [kd-quote-logic-plan.md](./kd-quote-logic-plan.md) | 🟡 진행중 | 4/5 (80%) | 경동 견적 로직, Phase 5 통합 테스트 미완 |
+| [quote-management-url-migration-plan.md](./quote-management-url-migration-plan.md) | 🟡 진행중 | 11/12 (92%) | URL 마이그레이션, 사용자 테스트 잔여 |
+| [quote-management-8issues-plan.md](./quote-management-8issues-plan.md) | ⚪ 대기 | 0/8 (0%) | 견적관리 8개 이슈, 컨펌 대기 |
+| [quote-calculation-api-plan.md](./quote-calculation-api-plan.md) | ⚪ 대기 | 0/12 (0%) | 견적 계산 API, 미착수 |
+| [quote-order-sync-improvement-plan.md](./quote-order-sync-improvement-plan.md) | ⚪ 대기 | 0/4 (0%) | 견적-수주 동기화 개선, 미착수 |
+| [quote-system-development-plan.md](./quote-system-development-plan.md) | ⚪ 대기 | - | 견적 시스템 개발, 계획 수립 |
+
+### 생산/절곡 (Production/Bending)
+
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [bending-preproduction-stock-plan.md](./bending-preproduction-stock-plan.md) | 🟡 진행중 | 14/14 코드 | 선재고, 마이그레이션 실행/검증 잔여 |
+| [bending-info-auto-generation-plan.md](./bending-info-auto-generation-plan.md) | ⚪ 대기 | 0/7 (0%) | 절곡 정보 자동 생성, 분석만 완료 |
+| [bending-material-input-mapping-plan.md](./bending-material-input-mapping-plan.md) | ⚪ 대기 | 분석 | 절곡 자재투입 매핑, GAP 분석 완료 |
+
+### 품목/BOM (Item/BOM)
+
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [bom-item-mapping-plan.md](./bom-item-mapping-plan.md) | 🟡 진행중 | 2/3 (66%) | BOM 품목 매핑, Phase 3 검증 잔여 |
+| [item-master-data-alignment-plan.md](./item-master-data-alignment-plan.md) | 🟡 진행중 | - | 품목 마스터 정합, 섀도잉 정리 잔여 |
+| [mng-item-field-management-plan.md](./mng-item-field-management-plan.md) | ⚪ 대기 | 0% | 품목 필드 관리, 미착수 |
+| [item-inventory-management-plan.md](./item-inventory-management-plan.md) | ⚪ 대기 | 설계 | 품목 재고 관리, 설계 확정/구현 대기 |
+| [fg-code-consolidation-plan.md](./fg-code-consolidation-plan.md) | ⚪ 대기 | 0/8 (0%) | FG 코드 통합, 미착수 |
+
+### 문서/서식 (Document System)
+
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [document-management-system-plan.md](./document-management-system-plan.md) | 🟡 진행중 | 16/20 (80%) | 문서관리 시스템, Phase 4.4 잔여 |
+| [document-system-master.md](./document-system-master.md) | 🟡 진행중 | Phase 4-5 | 마스터 문서, 일부 Phase 잔여 |
+| [document-system-mid-inspection.md](./document-system-mid-inspection.md) | 🟡 진행중 | 5/6 | 중간검사, 1개 미완 |
+| [document-system-work-log.md](./document-system-work-log.md) | 🟡 진행중 | 3/4+α | 작업일지, React 연동 잔여 |
+| [incoming-inspection-document-integration-plan.md](./incoming-inspection-document-integration-plan.md) | ⚪ 대기 | 0/8 (0%) | 수입검사 서류 연동, 분석만 완료 |
+| [incoming-inspection-templates-plan.md](./incoming-inspection-templates-plan.md) | 🟡 진행중 | 19/23 (83%) | 수입검사 템플릿, 4종 품목 대기 |
+| [intermediate-inspection-report-plan.md](./intermediate-inspection-report-plan.md) | ⚪ 대기 | 0/14 (0%) | 중간검사 보고서, 검토 대기 |
### 마이그레이션 & 연동
-| 문서 | 상태 | 설명 |
-|------|------|------|
-| [5130-to-mng-migration-plan.md](./5130-to-mng-migration-plan.md) | 🟡 진행중 | 5130 → mng 마이그레이션 (5/38 완료) |
-| [react-api-integration-plan.md](./react-api-integration-plan.md) | 🟡 진행중 | React ↔ API 연동 테스트 |
-| [react-mock-to-api-migration-plan.md](./react-mock-to-api-migration-plan.md) | 🟡 진행중 | Mock → API 전환 (Phase A 부분 완료) |
-| [dashboard-api-integration-plan.md](./dashboard-api-integration-plan.md) | 🟡 Phase 1 대기 | CEO Dashboard API 연동 |
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [5130-to-mng-migration-plan.md](./5130-to-mng-migration-plan.md) | 🟡 진행중 | 5/38 (13%) | 5130→mng 마이그레이션 |
+| [react-api-integration-plan.md](./react-api-integration-plan.md) | 🟡 진행중 | - | React↔API 연동 |
+| [react-mock-to-api-migration-plan.md](./react-mock-to-api-migration-plan.md) | 🟡 진행중 | - | Mock→API 전환, 별도 문서 추적 |
+| [dashboard-api-integration-plan.md](./dashboard-api-integration-plan.md) | 🟡 진행중 | 5/11 (45%) | CEO Dashboard API 연동 |
+| [kd-orders-migration-plan.md](./kd-orders-migration-plan.md) | ⚪ 대기 | 0/2 (0%) | 경동 수주 마이그레이션, 선행조건 미충족 |
+| [items-migration-kyungdong-plan.md](./items-migration-kyungdong-plan.md) | 📚 참조 | ARCHIVED | 후속 문서로 이관됨 |
-### 영업/생산 (Sales/Production)
+### 시스템/인프라
-| 문서 | 상태 | 설명 |
-|------|------|------|
-| [quote-management-8issues-plan.md](./quote-management-8issues-plan.md) | 🟡 진행중 | 견적관리 8개 이슈 |
-| [quote-calculation-api-plan.md](./quote-calculation-api-plan.md) | 🟡 진행중 | 견적 계산 API |
-| [order-workorder-shipment-integration-plan.md](./order-workorder-shipment-integration-plan.md) | 🔵 계획수립 | 수주-작업지시-출하 연동 |
-| [quote-system-development-plan.md](./quote-system-development-plan.md) | 🟡 진행중 | 견적 시스템 개발 |
-| [simulator-ui-enhancement-plan.md](./simulator-ui-enhancement-plan.md) | 🔵 계획수립 | 시뮬레이터 UI 개선 |
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [db-trigger-audit-system-plan.md](./db-trigger-audit-system-plan.md) | 🟡 진행중 | 15/16 (94%) | DB 트리거 감사, 옵션 3건 잔여 |
+| [db-backup-system-plan.md](./db-backup-system-plan.md) | 🟡 진행중 | 11/14 (79%) | DB 백업, 서버 작업 3건 잔여 |
+| [tenant-id-compliance-plan.md](./tenant-id-compliance-plan.md) | ⚪ 대기 | 0/4 (0%) | 테넌트 ID 정합, 실행 대기 |
+| [tenant-numbering-system-plan.md](./tenant-numbering-system-plan.md) | ⚪ 대기 | 0/8 (0%) | 테넌트 채번, 미착수 |
+| [mng-numbering-rule-management-plan.md](./mng-numbering-rule-management-plan.md) | ⚪ 대기 | 0% | 채번 규칙 관리, 미착수 |
-### 시스템/기타
+### 프론트엔드 & UI
-| 문서 | 상태 | 설명 |
-|------|------|------|
-| [dummy-data-seeding-plan.md](./dummy-data-seeding-plan.md) | ⚪ 계획수립 | 더미 데이터 시딩 (2025-12-23 작성) |
-| [api-explorer-development-plan.md](./api-explorer-development-plan.md) | 🔵 계획수립 | API Explorer 개발 (설계 완료, 구현 대기) |
-| [employee-user-linkage-plan.md](./employee-user-linkage-plan.md) | 🔵 계획수립 | 사원-회원 연결 기능 (2025-12-25 작성) |
-| [docs-update-plan.md](./docs-update-plan.md) | 🟡 진행중 | 문서 업데이트 계획 (Phase 4 진행중) |
-| [react-mock-remaining-tasks.md](./react-mock-remaining-tasks.md) | 📚 참조 | Mock 전환 잔여 작업 목록 |
-| [hotfix-20260119-action-plan.md](./hotfix-20260119-action-plan.md) | 🟡 진행중 | Hotfix 액션 플랜 (2026-01-19) |
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [simulator-ui-enhancement-plan.md](./simulator-ui-enhancement-plan.md) | 🟡 진행중 | 6/10 (60%) | 시뮬레이터 UI 개선 |
+| [card-management-section-plan.md](./card-management-section-plan.md) | 🟡 진행중 | 6/12 (50%) | 카드 관리 섹션 |
+| [dev-toolbar-plan.md](./dev-toolbar-plan.md) | 🟡 진행중 | 3/8 (38%) | 개발 툴바 |
+
+### 기타
+
+| 문서 | 상태 | 진행률 | 설명 |
+|------|------|--------|------|
+| [hotfix-20260119-action-plan.md](./hotfix-20260119-action-plan.md) | 🟡 진행중 | API 완료 | Hotfix, React P0 2건 대기 |
+| [mng-menu-system-plan.md](./mng-menu-system-plan.md) | 🟡 진행중 | 구현 완료 | 메뉴 시스템, Phase 3 테스트 잔여 |
+| [monthly-expense-integration-plan.md](./monthly-expense-integration-plan.md) | ⚪ 대기 | 0/8 (0%) | 월별 경비 연동, 미착수 |
+| [receiving-management-analysis-plan.md](./receiving-management-analysis-plan.md) | ⚪ 대기 | 분석 | 입고 관리, 분석 완료/개발 대기 |
+| [api-explorer-development-plan.md](./api-explorer-development-plan.md) | ⚪ 대기 | 0% | API Explorer, 미착수 |
+| [employee-user-linkage-plan.md](./employee-user-linkage-plan.md) | ⚪ 대기 | 0% | 사원-회원 연결, 미착수 |
+| [dummy-data-seeding-plan.md](./dummy-data-seeding-plan.md) | ⚪ 대기 | - | 더미 데이터 시딩, 미착수 |
+| [react-mock-remaining-tasks.md](./react-mock-remaining-tasks.md) | 📚 참조 | - | Mock 전환 잔여 작업 목록 |
---
-## 완료 아카이브 (archive/)
+## 완료 아카이브 (archive/) - 37개
> 완료된 계획 문서들 - 참조용으로 보관
| 문서 | 완료일 | 설명 |
|------|--------|------|
-| [erp-api-development-plan-d1.0-changes.md](./archive/erp-api-development-plan-d1.0-changes.md) | 2025-12 | D1.0 변경사항 (Phase 5-8) |
+| [bending-lot-pipeline-dev-plan.md](./archive/bending-lot-pipeline-dev-plan.md) | 2026-02 | 절곡 LOT 매핑 파이프라인 |
+| [bending-worklog-reimplementation-plan.md](./archive/bending-worklog-reimplementation-plan.md) | 2026-02 | 절곡 작업일지 재구현 |
+| [document-system-product-inspection.md](./archive/document-system-product-inspection.md) | 2026-02 | 제품검사 서식 |
+| [formula-engine-real-data-plan.md](./archive/formula-engine-real-data-plan.md) | 2026-02 | 수식 엔진 실데이터 |
+| [material-input-per-item-mapping-plan.md](./archive/material-input-per-item-mapping-plan.md) | 2026-02 | 품목별 자재투입 매핑 |
+| [mng-item-formula-integration-plan.md](./archive/mng-item-formula-integration-plan.md) | 2026-02 | mng 품목 수식 연동 |
+| [mng-item-management-plan.md](./archive/mng-item-management-plan.md) | 2026-02 | mng 품목 관리 |
+| [fcm-user-targeted-notification-plan.md](./archive/fcm-user-targeted-notification-plan.md) | 2026-01 | 사용자 타겟 FCM 알림 |
+| [docs-update-plan.md](./archive/docs-update-plan.md) | 2026-01 | 문서 업데이트 계획 |
+| [order-location-management-plan.md](./archive/order-location-management-plan.md) | 2026-01 | 수주 현장 관리 |
+| [quote-v2-auto-calculation-fix-plan.md](./archive/quote-v2-auto-calculation-fix-plan.md) | 2026-01 | 견적 V2 자동계산 수정 |
+| [sam-stat-database-design-plan.md](./archive/sam-stat-database-design-plan.md) | 2026-01 | 통계 DB 설계 |
+| [stock-integration-plan.md](./archive/stock-integration-plan.md) | 2026-01 | 재고 연동 |
+| [welfare-section-plan.md](./archive/welfare-section-plan.md) | 2026-01 | 복리후생 섹션 |
+| [order-workorder-shipment-integration-plan.md](./archive/order-workorder-shipment-integration-plan.md) | 2026-01 | 수주-작업지시-출하 연동 |
+| [document-management-system-changelog.md](./archive/document-management-system-changelog.md) | 2026-01 | 문서관리 변경 이력 |
+| [items-table-unification-plan.md](./archive/items-table-unification-plan.md) | 2025-12 | items 테이블 통합 |
+| [kd-items-migration-plan.md](./archive/kd-items-migration-plan.md) | 2025-12 | 경동 품목 마이그레이션 |
+| [simulator-calculation-logic-mapping.md](./archive/simulator-calculation-logic-mapping.md) | 2025-12 | 시뮬레이터 로직 매핑 |
+| [AI_리포트_키워드_색상체계_가이드_v1.4.md](./archive/AI_리포트_키워드_색상체계_가이드_v1.4.md) | 2025-12 | AI 리포트 색상 가이드 |
+| [SEEDERS_LIST.md](./archive/SEEDERS_LIST.md) | 2025-12 | 시더 참조 목록 |
+| [api-analysis-report.md](./archive/api-analysis-report.md) | 2025-12 | API 분석 보고서 |
+| [erp-api-development-plan-d1.0-changes.md](./archive/erp-api-development-plan-d1.0-changes.md) | 2025-12 | D1.0 변경사항 |
| [mng-quote-formula-development-plan.md](./archive/mng-quote-formula-development-plan.md) | 2025-12 | mng 견적 수식 관리 |
-| [quote-auto-calculation-development-plan.md](./archive/quote-auto-calculation-development-plan.md) | 2025-12-22 | 견적 자동 계산 |
-| [order-management-plan.md](./archive/order-management-plan.md) | 2025-01-09 | 수주관리 API 연동 |
-| [work-order-plan.md](./archive/work-order-plan.md) | 2025-01-11 | 작업지시 검증 |
+| [quote-auto-calculation-development-plan.md](./archive/quote-auto-calculation-development-plan.md) | 2025-12 | 견적 자동 계산 |
+| [order-management-plan.md](./archive/order-management-plan.md) | 2025-01 | 수주관리 API 연동 |
+| [work-order-plan.md](./archive/work-order-plan.md) | 2025-01 | 작업지시 검증 |
| [process-management-plan.md](./archive/process-management-plan.md) | 2025-12 | 공정관리 API 연동 |
| [construction-api-integration-plan.md](./archive/construction-api-integration-plan.md) | 2026-01 | 시공사 API 연동 |
-| [notification-sound-system-plan.md](./archive/notification-sound-system-plan.md) | 2025-01-07 | 알림음 시스템 |
+| [notification-sound-system-plan.md](./archive/notification-sound-system-plan.md) | 2025-01 | 알림음 시스템 |
| [l2-permission-management-plan.md](./archive/l2-permission-management-plan.md) | 2025-12 | L2 권한 관리 |
| [react-fcm-push-notification-plan.md](./archive/react-fcm-push-notification-plan.md) | 2025-12 | FCM 푸시 알림 |
| [react-server-component-audit-plan.md](./archive/react-server-component-audit-plan.md) | 2025-12 | Server Component 점검 |
| [5130-bom-migration-plan.md](./archive/5130-bom-migration-plan.md) | 2025-12 | 5130 BOM 마이그레이션 |
| [5130-sam-data-migration-plan.md](./archive/5130-sam-data-migration-plan.md) | 2025-12 | 5130 데이터 마이그레이션 |
| [bidding-api-implementation-plan.md](./archive/bidding-api-implementation-plan.md) | 2025-12 | 입찰 API 구현 |
-| [mes-integration-analysis-plan.md](./archive/mes-integration-analysis-plan.md) | 2025-01-09 | MES 연동 분석 |
+| [mes-integration-analysis-plan.md](./archive/mes-integration-analysis-plan.md) | 2025-01 | MES 연동 분석 |
---
@@ -103,8 +167,6 @@
**내용**: D0.8 대비 변경/추가된 화면 (D1.0 버전)
-**변경 사항**: [erp-api-development-plan-d1.0-changes.md](./erp-api-development-plan-d1.0-changes.md) 참조
-
---
## 플로우 테스트
@@ -175,55 +237,14 @@
---
-## 디렉토리 구조
-
-```
-docs/plans/
-├── index_plans.md # 이 파일
-│
-├── erp-api-development-plan.md # ERP API 개발 계획 (D0.8)
-├── erp-api-development-plan-d1.0-changes.md # D1.0 변경사항
-├── mng-quote-formula-development-plan.md # 견적 수식 관리
-├── quote-auto-calculation-development-plan.md # 견적 자동 계산
-├── simulator-calculation-logic-mapping.md # 시뮬레이터 로직 매핑
-├── mng-item-field-management-plan.md # 품목 필드 관리
-├── items-table-unification-plan.md # items 테이블 통합
-├── mng-menu-system-plan.md # mng 메뉴 시스템
-├── 5130-to-mng-migration-plan.md # 5130 마이그레이션
-├── react-api-integration-plan.md # React-API 연동
-├── react-mock-to-api-migration-plan.md # Mock→API 전환
-├── dummy-data-seeding-plan.md # 더미 데이터 시딩
-├── api-explorer-development-plan.md # API Explorer
-├── employee-user-linkage-plan.md # 사원-회원 연결
-├── docs-update-plan.md # 문서 업데이트 계획
-│
-├── SAM_ERP_Storyboard_D1.0_251218/ # 스토리보드 D1.0 (38장)
-│ └── 슬라이드*.jpeg
-│
-└── flow-tests/ # 플로우 테스트 JSON (32개)
- ├── auth-*.json
- ├── items-*.json
- ├── client-*.json
- └── ...
-
-# 아카이브됨
-# docs/history/2025-12/SAM_ERP_Storyboard_D0.8_251216/ # D0.8 (113장)
-```
-
----
-
## 관련 문서
- [docs/INDEX.md](../INDEX.md) - 전체 문서 인덱스
- [docs/projects/index_projects.md](../projects/index_projects.md) - 프로젝트 문서 인덱스
-- [docs/specs/erp-analysis/](../specs/erp-analysis/) - ERP 분석 명세서
-- [CURRENT_WORKS.md](../../CURRENT_WORKS.md) - 현재 작업
---
**범례**:
-- 🟢 완료: 구현 완료
-- 🟡 진행중: 현재 작업 중
-- 🔵 계획수립: 설계/계획 완료, 구현 대기
-- ⚪ 미착수: 계획만 수립, 작업 대기
-- 📚 참조: 분석/참조용 문서
\ No newline at end of file
+- 🟡 진행중: 현재 작업 중 또는 일부 완료
+- ⚪ 대기: 미착수 또는 선행조건 대기
+- 📚 참조: 분석/참조용 문서