# 품목기준관리 API 구조 변경 대응 작업

## 작업 일자: 2025-11-27

---

## 1. 백엔드 API 변경 요약

### 1.1 핵심 구조 변경: 독립 엔티티 + 링크 테이블

**Before (CASCADE FK)**:
```
item_pages
  ↓ page_id FK (CASCADE) - 삭제 시 연쇄 삭제
item_sections
  ↓ section_id FK (CASCADE) - 삭제 시 연쇄 삭제
item_fields / item_bom_items
```

**After (독립 + 링크)**:
```
item_pages (독립)
item_sections (독립)     → entity_relationships (링크 테이블)
item_fields (독립)
item_bom_items (독립)
```

### 1.2 `item_master_fields` 테이블 통합 → DROP

- `item_master_fields` 테이블 삭제됨
- `item_fields` 테이블에 통합:
  - `section_id` → nullable (독립 필드는 NULL)
  - `category`, `description`, `is_common` 컬럼 추가

**결과**: 마스터 항목 = `item_fields` WHERE `section_id IS NULL`

### 1.3 `entity_relationships` 테이블 구조

```sql
CREATE TABLE entity_relationships (
  id BIGINT PRIMARY KEY,
  tenant_id BIGINT,
  group_id INT DEFAULT 1,           -- 1: 품목관리
  parent_type ENUM('page', 'section'),
  parent_id BIGINT,
  child_type ENUM('section', 'field', 'bom'),
  child_id BIGINT,
  order_no INT DEFAULT 0,
  metadata JSON,
  created_at, updated_at
);
```

### 1.4 새 API 엔드포인트 (14개)

**페이지-섹션 연결**:
- `POST /pages/{pageId}/link-section` - { child_id, order_no? }
- `DELETE /pages/{pageId}/unlink-section/{sectionId}`

**페이지-필드 직접 연결**:
- `POST /pages/{pageId}/link-field` - { child_id, order_no? }
- `DELETE /pages/{pageId}/unlink-field/{fieldId}`

**페이지 관계 조회**:
- `GET /pages/{pageId}/relationships`
- `GET /pages/{pageId}/structure` ⭐ 전체 구조 조회

**섹션-필드 연결**:
- `POST /sections/{sectionId}/link-field` - { child_id, order_no? }
- `DELETE /sections/{sectionId}/unlink-field/{fieldId}`

**섹션-BOM 연결**:
- `POST /sections/{sectionId}/link-bom` - { child_id, order_no? }
- `DELETE /sections/{sectionId}/unlink-bom/{bomId}`

**섹션 관계 조회**:
- `GET /sections/{sectionId}/relationships`

**순서 변경**:
- `POST /relationships/reorder`
  ```json
  {
    "parent_type": "page",
    "parent_id": 1,
    "ordered_items": [
      { "child_type": "section", "child_id": 1 },
      { "child_type": "section", "child_id": 2 }
    ]
  }
  ```

### 1.5 독립 엔티티 API

**섹션**:
- `GET /sections` - 독립 섹션 목록 (is_template 필터 가능)
- `POST /sections` - 독립 섹션 생성
- `POST /sections/{id}/clone` - 섹션 복제
- `GET /sections/{id}/usage` - 섹션 사용처 조회

**필드**:
- `GET /fields` - 독립 필드 목록
- `POST /fields` - 독립 필드 생성
- `POST /fields/{id}/clone` - 필드 복제
- `GET /fields/{id}/usage` - 필드 사용처 조회

**BOM**:
- `GET /bom-items` - 독립 BOM 목록
- `POST /bom-items` - 독립 BOM 생성

---

## 2. 프론트엔드 수정 계획

### 2.1 타입 정의 수정 (item-master-api.ts) ✅ 완료

**제거 또는 수정**:
- [x] `ItemMasterField` → `ItemField`로 통합 (section_id = null) ✅
- [x] `MasterFieldRequest`, `MasterFieldResponse` deprecated 표시 ✅

**추가**:
- [x] `EntityRelationship` 타입 추가 (`EntityRelationshipResponse`) ✅
- [x] `LinkEntityRequest` 타입 추가 ✅
- [x] `ReorderRelationshipsRequest` 타입 추가 ✅
- [x] `PageStructureResponse` 타입 추가 ✅
- [x] `LinkBomRequest` 타입 추가 ✅

**수정**:
- [x] `ItemFieldResponse`에 `category`, `description`, `is_common` 추가 ✅
- [x] `IndependentFieldRequest`에 `category`, `description`, `is_common` 추가 ✅
- [x] `InitResponse`에 `fields` 필드 추가, `masterFields` deprecated ✅

### 2.2 API 함수 수정 (lib/api/item-master.ts) ✅ 완료

**deprecated 표시**:
- [x] `masterFields.list()` - deprecated, `fields.list()` 사용 권장 ✅
- [x] `masterFields.create()` - deprecated, `fields.createIndependent()` 사용 권장 ✅
- [x] `masterFields.update()` - deprecated, `fields.update()` 사용 권장 ✅
- [x] `masterFields.delete()` - deprecated, `fields.delete()` 사용 권장 ✅

**추가 (link/unlink API)**:
- [x] `pages.linkSection()` ✅ (기존)
- [x] `pages.unlinkSection()` ✅ (기존)
- [x] `pages.linkField()` ✅
- [x] `pages.unlinkField()` ✅
- [x] `sections.linkField()` ✅ (기존)
- [x] `sections.unlinkField()` ✅ (기존)
- [x] `sections.linkBom()` ✅
- [x] `sections.unlinkBom()` ✅
- [x] `pages.getRelationships()` ✅
- [x] `pages.getStructure()` ✅ (기존)
- [x] `sections.getRelationships()` ✅
- [x] `relationships.reorder()` ✅

**추가 (독립 엔티티 API)** - 기존 구현됨:
- [x] `sections.list()` ✅
- [x] `sections.createIndependent()` ✅
- [x] `sections.clone()` ✅
- [x] `sections.getUsage()` ✅
- [x] `fields.list()` ✅
- [x] `fields.createIndependent()` ✅
- [x] `fields.clone()` ✅
- [x] `fields.getUsage()` ✅

### 2.3 Context 수정 (ItemMasterContext.tsx) ✅ 완료

**상태 변경**:
- [x] `itemMasterFields` → deprecated 표시 (기존 유지, `independentFields` 병행) ✅
- [x] 독립 필드 = `independentFields` state 이미 존재 ✅

**함수 변경 (API 마이그레이션 + deprecated 표시)**:
- [x] `addItemMasterField` → `fields.createIndependent()` 사용 ✅
- [x] `updateItemMasterField` → `fields.update()` 사용 ✅
- [x] `deleteItemMasterField` → `fields.delete()` 사용 ✅
- [x] `loadItemMasterFields` → deprecated 표시 추가 ✅

**신규 함수 (이미 구현됨)**:
- [x] `linkSectionToPage(pageId, sectionId)` ✅ (line 2225)
- [x] `unlinkSectionFromPage(pageId, sectionId)` ✅ (line 2294)
- [x] `linkFieldToSection(sectionId, fieldId)` ✅ (line 2328)
- [x] `unlinkFieldFromSection(sectionId, fieldId)` ✅ (line 2366)

### 2.4 UI 컴포넌트 수정

**계층구조 탭 (HierarchyTab)**: ✅ 완료
- [x] 섹션 추가 시 → link-section API 사용 ✅ (기존 구현)
- [x] 섹션 제거 시 → unlink-section API 사용 ✅ (기존 구현)
- [x] 필드 제거 시 → unlinkFieldFromSection API 사용 ✅
- [x] confirm/toast 메시지 "연결 해제"로 변경 ✅
- [x] ItemMasterDataManagement.tsx에서 handleUnlinkFieldWithTracking 사용 ✅

**섹션 탭 (SectionsTab)**: ✅ 완료 (2025-11-27)
- [x] handleDeleteTemplateField → unlinkFieldFromSection API 호출로 변경 ✅
- [x] SectionsTab.tsx 필드 삭제 아이콘 → Unlink 아이콘 (orange) ✅
- [x] 버튼 title "삭제" → "연결 해제" 변경 ✅
- [x] confirm 메시지 "연결을 해제하시겠습니까?" 변경 ✅
- [x] toast 메시지 "항목 연결이 해제되었습니다" 변경 ✅
- [x] useTemplateManagement.ts에 linkFieldToSection, unlinkFieldFromSection import 추가 ✅

**항목 탭 (MasterFieldTab → FieldTab)**: ✅ 완료
- [x] 데이터 소스: Context에서 `fields.*` API 사용 (2025-11-27)
- [x] CRUD → 독립 필드 API 사용 (`fields.createIndependent()`, `fields.update()`, `fields.delete()`)
- [x] useMasterFieldManagement.ts에 deprecated 표시 추가
- [x] MasterFieldTab/index.tsx UI 텍스트 "항목"으로 변경
- [x] MasterFieldDialog 제목/설명 변경
- [x] toast 메시지 "마스터 항목" → "항목" 변경
- [x] 다이얼로그 텍스트 변경 완료 (FieldDialog, FieldDrawer, TemplateFieldDialog, ImportFieldDialog)

**속성 탭 (AttributesTab)**: ✅ 분석 완료 - itemMasterFields 양방향 연동 (2025-11-27)
- [x] 데이터 소스: `itemMasterFields` (Context) + 로컬 옵션 state ✅
- [x] 양방향 연동: 항목탭 ⇄ 속성탭 (같은 itemMasterFields 참조)
- [x] 항목 추가/수정/삭제 → 속성탭에도 반영 ✅
- [x] 속성 옵션 변경 → 해당 필드의 dropdown options 자동 업데이트 (useAttributeManagement.ts:131-161)

**ImportFieldDialog**: ✅ 탭 통합 완료 (2025-11-27)
- [x] 항목/독립필드 탭 → 단일 필드 목록으로 통합 ✅
- [x] `fields` prop 추가, `independentFields`/`itemMasterFields` deprecated ✅
- [x] `onImport` 시그니처 단순화: `(source?: ImportSource)` → `()` ✅
- [x] `handleImportField` 함수: source 분기 제거 → `linkFieldToSection` 단일 호출 ✅

---

## 3. 삭제 동작 변경

### 3.1 기존 (CASCADE 삭제)

```
페이지 삭제 → 연결된 섹션도 삭제 → 연결된 필드도 삭제
```

### 3.2 변경 후 (unlink만)

```
페이지 삭제 → entity_relationships에서 링크만 제거
             → 섹션은 섹션 탭에 유지
             → 필드는 항목 탭에 유지
```

**UI에서 "삭제" vs "연결 해제" 구분**:
- 연결 해제: 현재 페이지/섹션에서만 제거, 원본 유지
- 실제 삭제: 엔티티 자체를 삭제 (모든 곳에서 사라짐)

---

## 4. 데이터 통일

### 4.1 필드 속성 공유

**현재 문제**:
- 마스터 항목에서 `is_required` 설정
- 계층구조/섹션에서는 복사본이라 반영 안됨

**해결**:
- 이제 같은 `item_fields` 레코드를 링크로 참조
- 한 곳에서 수정 → 모든 곳에 반영

### 4.2 UI 표시 통일

| 탭 | 데이터 소스 | 용도 |
|---|---|---|
| 항목 탭 | `itemMasterFields` (Context) | 독립 필드 CRUD |
| 속성 탭 | `itemMasterFields` + 로컬 옵션 state | 단위/재질/표면처리 + 필드 연동 |
| 계층구조 탭 | `entity_relationships` → `item_fields` | 페이지-섹션-필드 구조 |
| 섹션 탭 | `entity_relationships` → `item_fields` | 섹션-필드 연결 관리 |

**핵심**: 모든 탭이 `item_fields`를 공유 → 어디서 수정해도 전체 반영!

---

## 5. 작업 체크리스트

### Phase 1: 타입 및 API 수정 ✅ 완료
- [x] `item-master-api.ts` 타입 정의 수정 ✅
- [x] `lib/api/item-master.ts` API 함수 추가 ✅

### Phase 2: Context 수정 ✅ 완료
- [x] `ItemMasterContext.tsx` 상태 및 함수 수정 ✅

### Phase 3: UI 컴포넌트 수정 ✅ 완료
- [x] 계층구조 탭 - 필드 삭제 → unlink 변경 ✅
- [x] 섹션 탭 - handleDeleteTemplateField → unlinkFieldFromSection API 호출 ✅ (2025-11-27)
- [x] 항목 탭 - 데이터 소스 변경 + UI 텍스트 변경 ✅ (다이얼로그 포함 완료)
- [x] 속성 탭 - 동일 데이터 소스 사용 (통합됨) ✅
- [x] ImportFieldDialog - 탭 통합 완료 (항목/독립필드 → 필드) ✅ (2025-11-27)

### Phase 4: 테스트
- [ ] 페이지 삭제 시 섹션 유지 확인
- [ ] 섹션에서 필드 제거 시 항목 탭에 유지 확인
- [ ] 필드 속성 변경 시 모든 탭에 반영 확인

---

## 6. 관련 파일

### 프론트엔드
- `src/types/item-master-api.ts`
- `src/lib/api/item-master.ts`
- `src/contexts/ItemMasterContext.tsx`
- `src/components/items/ItemMasterDataManagement.tsx`
- `src/components/items/ItemMasterDataManagement/tabs/HierarchyTab/`
- `src/components/items/ItemMasterDataManagement/tabs/SectionsTab.tsx`
- `src/components/items/ItemMasterDataManagement/tabs/MasterFieldTab/`
- `src/components/items/ItemMasterDataManagement/dialogs/ImportFieldDialog.tsx`

### 백엔드 (참조)
- `app/Models/ItemMaster/EntityRelationship.php`
- `app/Swagger/v1/EntityRelationshipApi.php`
- `routes/api.php`
