Files
sam-docs/plans/item-master-data-alignment-plan.md
권혁성 925e8f13ff docs: 품목 기준 데이터 정비 Phase 2 완료
Phase 1 분석 + Phase 2 실행 결과를 포함한 계획 문서.

DB 변경 사항 (tenant_id=287):
- item_fields 4건 생성 (id:177-180, FG attributes 매핑)
- item_fields 10건 비활성화 (섀도잉/null key/미연결 정리)
- item_fields 9건 options 갱신 (RM/SM/PT 실데이터)
- entity_relationships 7건 삭제, 8건 추가 (is_active 통합 + FG 필드 연결)
- item_details 18건 생성 (id:524-541, FG 제품 상세)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 02:41:29 +09:00

41 KiB
Raw Blame History

품목 기준 데이터 정비 계획

작성일: 2026-01-31 목적: 5130 레거시 시스템에서 이관된 품목 데이터가 SAM 품목기준관리(item-master-data-management)에서 올바르게 표시되고, 견적 문서에 정확히 반영되도록 설정을 정비한다. 기준 문서: docs/specs/database-schema.md, docs/rules/item-policy.md 상태: 🔄 진행중


📍 현재 진행 상태

항목 내용
마지막 완료 작업 Phase 2 전체 완료 (6/6)
다음 작업 프론트엔드 표시 검증
진행률 Phase 1 완료, Phase 2 완료 (6/6)
마지막 업데이트 2026-01-31

1. 개요

1.1 배경

5130 레거시 시스템(chandj DB)의 품목 데이터를 SAM으로 이관 완료하였으나, SAM의 품목기준관리(item-master-data-management) 설정이 이관된 데이터 구조와 맞지 않아 프론트엔드에서 품목 정보가 올바르게 표시되지 않는다. 품목 데이터가 정확히 표시되어야 견적 문서에 데이터를 뿌려줄 수 있다.

핵심 문제:

  • item_pages/item_sections/item_fields의 현재 필드 정의가 이관된 데이터의 실제 attributes JSON 구조와 불일치
  • item_details 테이블에 FG 18개 품목의 상세 정보가 없음 (PT 129개만 존재)
  • 드롭다운 필드의 options 값이 실제 데이터와 매핑되지 않음
  • setting_field_defstenant_field_settings 테이블이 비어있음

1.2 기준 원칙

┌─────────────────────────────────────────────────────────────────┐
│  🎯 핵심 원칙                                                     │
├─────────────────────────────────────────────────────────────────┤
│  1. 견적 로직(FormulaEvaluatorService)에 영향 없는 범위에서만 수정  │
│  2. items.bom JSON 구조, items.code 체계는 변경 금지                │
│  3. item_pages/sections/fields 설정만 조정하여 데이터 표시 정합성 확보│
│  4. 5130 데이터와 SAM 데이터 간 매핑 관계를 명확히 문서화           │
└─────────────────────────────────────────────────────────────────┘

1.3 변경 승인 정책

분류 예시 승인
즉시 가능 item_fields options 값 수정, field_name 변경, 필드 순서 변경 불필요
⚠️ 컨펌 필요 item_fields 추가/삭제, item_sections 구조 변경, entity_relationships 변경 필수
🔴 금지 items.bom JSON 구조 변경, items.code 체계 변경, FormulaEvaluatorService 수정 별도 협의

1.4 준수 규칙

  • docs/specs/database-schema.md - DB 스키마 참조
  • docs/rules/item-policy.md - 품목 정책
  • docs/standards/quality-checklist.md - 품질 체크리스트

2. 대상 범위

2.1 Phase 1: 분석 (4단계)

# 작업 항목 상태 비고
1.1 품목기준관리 구조 파악 아래 섹션 4.1 참조
1.2 현재 설정 현황 분석 아래 섹션 4.2 참조
1.3 이관된 제품 데이터 구조 분석 아래 섹션 4.3 참조
1.4 BOM 관계 구조 분석 아래 섹션 4.4 참조

2.2 Phase 2: 설정 수정 (견적 영향 없는 범위)

# 작업 항목 상태 비고
2.1 FG(제품) 필드 설정 정비 완료: 4개 필드 추가(id:177-180), section 102 연결, order_no 정렬
2.2 PT(부품) 필드 설정 정비 완료: Part_type options 갱신(BD부품 추가, 라벨 간소화). display_condition은 5.6.4로 이관
2.3 SM/RM/CS 필드 설정 정비 완료: RM options 실데이터(SUS/EGI/두께/폭/길이), SM 11개 카테고리, SM규격 빈 배열
2.4 FG item_details 데이터 보완 완료: 18건 INSERT (id:524-541), product_category/item_name/specification 설정
2.5 드롭다운 options 실데이터 매핑 완료: 2.1~2.3에서 함께 처리 (FG 4개, PT Part_type, RM 5개, SM 3개)
2.6 고정컬럼-동적필드 섀도잉 정리 완료: null key 1건, 미연결 5건 비활성화, is_active 중복 4건 통합

3. 작업 절차

3.1 단계별 절차

Step 1: 구조 분석 (Phase 1.1)
├── item_pages → item_sections → item_fields 계층 구조 파악
├── entity_relationships 연결 관계 매핑
└── React 프론트엔드 렌더링 로직 확인

Step 2: 현재 설정 현황 (Phase 1.2)
├── 5개 item_pages (CS/RM/SM/PT/FG) 설정 현황
├── 26개 page→section, 66개 section→field 관계 확인
└── 각 필드의 options, validation_rules 점검

Step 3: 이관 데이터 구조 (Phase 1.3)
├── items 테이블 780건 (FG:18, PT:669, SM:61, RM:28, CS:4)
├── items.attributes JSON 구조 분석
├── item_details 129건 (PT만 존재) 분석
└── 5130 원본 데이터와 대조

Step 4: BOM 관계 구조 (Phase 1.4)
├── FG→PT BOM JSON 관계 매핑
├── 5130 models→parts→parts_sub 3계층 대응
├── BD계열(가이드레일, 하단마감재, L-BAR) 매핑
└── 견적 FormulaEvaluatorService 의존성 확인

Step 5: 설정 수정 (Phase 2)
├── FG 필드: attributes 키와 item_fields 매핑
├── PT 필드: part_type별 분기 필드 정의
├── 드롭다운 options: 실제 사용 값으로 갱신
├── FG item_details 18건 생성
├── 고정컬럼-동적필드 섀도잉 정리 (is_active 중복 통합, null key, 미연결 필드)
└── 프론트엔드 표시 검증

4. 상세 분석 결과

4.1 Phase 1.1: 품목기준관리 구조

아키텍처 개요

┌─────────────────────────────────────────────────────────────────┐
│  item_pages (품목유형별 폼 정의)                                   │
│  - CS/RM/SM/PT/FG 각 1개 페이지                                   │
│  - tenant_id=287, group_id=1                                     │
├─────────────────────────────────────────────────────────────────┤
│  entity_relationships (parent_type='page' → child_type='section')│
│  - 26개 관계 (페이지→섹션)                                        │
│  - 66개 관계 (섹션→필드)                                          │
├─────────────────────────────────────────────────────────────────┤
│  item_sections (섹션)                                             │
│  - type: 'fields' (일반 필드 그룹)                                │
│  - type: 'bom' (BOM 구성 섹션)                                    │
├─────────────────────────────────────────────────────────────────┤
│  item_fields (필드 정의)                                          │
│  - field_type: textbox/number/dropdown/checkbox/date/textarea    │
│  - storage_type: 'column' (items 컬럼) / 'json' (attributes)    │
│  - options: JSON [{label, value}] (드롭다운용)                    │
└─────────────────────────────────────────────────────────────────┘

테이블 스키마

item_pages: id, tenant_id, group_id, page_name, item_type(ENUM), source_table, absolute_path, is_active

item_sections: id, tenant_id, group_id, title, type(ENUM: fields/bom), order_no, is_template, is_default, description

item_fields: id, tenant_id, group_id, field_name, field_key, field_type(ENUM), order_no, is_required, default_value, placeholder, display_condition(JSON), validation_rules(JSON), options(JSON), properties(JSON), source_table, source_column, storage_type(ENUM: column/json), json_path, category, description, is_common, is_active, is_locked

entity_relationships: id, tenant_id, group_id, parent_type, parent_id, child_type, child_id, order_no, metadata(JSON), is_locked


4.2 Phase 1.2: 현재 설정 현황

4.2.1 페이지별 구조

CS (소모품) - page id:1015

└ Section: 기본정보 (id:92, type:fields)
    ├ 품목명 (key:item_name, textbox)
    ├ 규격(사양) (key:specification, textbox)
    ├ 단위 (key:unit, dropdown)
    └ 비고 (key:note1, textbox)

RM (원자재) - page id:1016

└ Section: 기본 정보 (id:93, type:fields)
    ├ 품목명 (key:100_item_name, dropdown) → options: [철판, 알루미늄, 스테인리스, 아연도금강판]
    ├ 규격 (key:101_specification_1, dropdown) → options: [옵션1-1, 옵션1-2, 옵션1-3, 옵션120]
    ├ 규격 (key:102_specification_2, dropdown) → options: [옵션2-1, 옵션2-2]
    ├ 규격 (key:103_specification_3, dropdown) → options: [옵션3-1, 옵션3-2, 옵션3-3]
    ├ 규격 (key:104_specification_4, dropdown)
    ├ 활성 여부 (key:is_active, dropdown)
    ├ 단위 (key:unit, dropdown)
    └ 비고 (key:note1, textbox)

SM (부자재) - page id:1017

└ Section: 기본 정보 (id:94, type:fields)
    ├ 품목명 (key:107_item_name, dropdown)
    ├ 규격 (key:108_specification_1, dropdown)
    ├ 규격 (key:109_specification_2, dropdown)
    ├ 활성 여부 (key:field_163, dropdown)
    ├ 단위 (key:unit, dropdown)
    └ 비고 (key:note1, textbox)

PT (부품) - page id:1018

├ Section: 기본 정보 (id:95, type:fields)
│   ├ 부품 유형 (key:Part_type, dropdown)
│   ├ 품목명 (key:itemNameAssemblyPart, dropdown)
│   ├ 설치유형 (key:119~121_Installation_type_1~3, dropdown x3)
│   ├ 마감 (key:112_deadline, dropdown)
│   ├ 품목명 (key:122_bending_parts, dropdown)
│   ├ 종류 (key:123~125_type_1~3, dropdown x3)
│   ├ 재질 (key:126_texture, dropdown)
│   ├ 폭 합계 (key:127_width_total, number)
│   ├ 모양&길이 (key:128_Shape_Length, dropdown)
│   ├ 비고 (key:note2, textbox)
│   ├ 품목명 (key:132_PurchasedItemName, dropdown)
│   ├ 품목상태 (key:138_state, dropdown)
│   ├ 전원 (key:134_power, dropdown)
│   ├ 용량 (key:135_capacity, dropdown)
│   ├ 비고 (key:note3, textbox)
│   ├ 품목상태 (key:, dropdown) ← ⚠️ key 비어있음
│   └ 단위 (key:unit, dropdown)
├ Section: 측면 규격 및 길이 (id:99, type:fields)
│   ├ 측면 규격 (가로) (key:113_side_dimensions_horizontal, number)
│   ├ 측면 규격 (세로) (key:114_side_dimensions_vertical, number)
│   ├ 길이 (key:115_length, dropdown)
│   ├ 품목 상태 (key:105_state, dropdown)
│   └ 품목상태 (key:133_state, dropdown)
├ Section: BOM (id:100, type:fields)
│   └ 부품구성 (BOM) 필요 (key:118_bom, checkbox)
└ Section: 부품 구성 (BOM) (id:101, type:bom)

FG (제품) - page id:1019

├ Section: 기본 정보 (id:102, type:fields)
│   ├ 상품명 (key:139_productName, textbox)
│   ├ 품목명 (key:140_field_96, textbox)
│   ├ 로트 약자 (key:141_lotNum, textbox)
│   ├ 품목상태 (key:138_state, dropdown)
│   ├ 비고 (key:note3, textbox)
│   ├ 인정번호 (key:142_accreditationNumber, textbox)
│   ├ 인정 유효기간 시작일 (key:143_accreditationStart, date)
│   ├ 인정 유효기간 종료일 (key:144_accreditationEnd, date)
│   └ 비고 (key:145_field_137, textbox)
├ Section: BOM (id:100, type:fields) ← PT와 공유
│   └ 부품구성 (BOM) 필요 (key:118_bom, checkbox)
└ Section: 부품 구성 (BOM) (id:101, type:bom) ← PT와 공유

4.2.2 발견된 문제점

# 문제 영향 심각도
1 FG 필드의 field_key가 이관 데이터의 attributes 키와 불일치 FG 품목 표시 불가 🔴
2 PT 필드에 field_key가 빈 필드 존재 데이터 매핑 실패 🟡
3 RM/SM 드롭다운 options가 플레이스홀더 값 (옵션1-1 등) 실제 데이터와 불일치 🟡
4 FG item_details 0건 (18개 FG 품목 상세 없음) 제품 상세 표시 불가 🔴
5 setting_field_defs, tenant_field_settings 테이블 비어있음 필드 커스터마이징 미설정 🟢
6 FG attributes에 model_name, finishing_type 등 레거시 키 사용 필드 매핑 필요 🟡
7 고정컬럼과 동적필드 간 섀도잉 중복 다수 존재 향후 일괄 기능 오작동 위험 🔴

4.2.3 고정컬럼-동적필드 섀도잉 분석

is_common=1 필드 11개가 items 테이블 고정 컬럼과 직접 매핑됨. is_common=0 동적 필드 중 고정 컬럼과 의미적으로 동일한 필드가 별도 key로 생성되어 있어, 고정 컬럼 기반 기능(필터링, 일괄 변경 등)이 이 동적 필드를 사용하는 품목에 적용되지 않는 위험 존재.

고정 컬럼 매핑 현황 (is_common=1, 정상)
field id field_key source_column 비고
153 item_type items.item_type
154 code items.code
155 name items.name
156 items_unit items.unit
157 category_id items.category_id
158 bom items.bom
159 attributes items.attributes
160 attributes_archive items.attributes_archive
161 options items.options
162 description items.description
163 is_active items.is_active
섀도잉 유형 A: is_active 중복 (6건) — 🔴 이번에 정리
field id field_key field_name 소속 page 섀도잉 대상
163 is_active 활성 여부 공통(is_common=1) items.is_active (정상 매핑)
164 field_163 활성 여부 SM items.is_active 중복
105 105_state 품목 상태 PT (측면규격 섹션) items.is_active 중복
131 131_state 품목 상태 미연결 items.is_active 중복
133 133_state 품목상태 PT (측면규격 섹션) items.is_active 중복
138 138_state 품목상태 PT, FG items.is_active 중복
152 (null) 품목상태 PT items.is_active 중복 + key 없음

위험: items.is_active 기반 비활성 필터링 시 동적 필드 138_state 등을 사용하는 품목은 필터 미적용

섀도잉 유형 B: null key 필드 (1건) — 🔴 이번에 정리
field id field_key field_name 소속 page
152 (null) 품목상태 PT

위험: field_key가 없어서 데이터 저장/조회 자체 불가. 폼에 표시는 되지만 값 매핑 실패.

섀도잉 유형 C: 미연결 필드 (5건) — 🟡 이번에 정리

어떤 page에도 entity_relationship으로 연결되지 않아 사용 불가 상태인 필드:

field id field_key field_name 비고
116 116_bending_parts 품목명 미연결, 122와 중복
117 117_purchase_parts 품목명 미연결, 132와 중복
129 unit_2 단위_2 미연결, 98(unit)과 중복
131 131_state 품목 상태 미연결, is_active 중복
136 unit_3 단위_3 미연결, 98(unit)과 중복

위험: 미연결 상태이므로 즉각적 문제는 없으나, 향후 혼동 유발 가능.

섀도잉 유형 D: name/unit/specification/description 중복 — 📌 다음에 정리
고정 컬럼 동적 필드 중복 수 소속 pages 다음에 정리하는 이유
items.name 8건 (id:96,100,107,111,122,132,139,140) CS,RM,SM,PT,FG PT 부품유형별 분기 UI와 맞물림. 렌더링 로직 변경 필요
items.unit 2건 (id:98,129,136) CS,RM,SM,PT + 미연결 unit(id:98)은 4개 page에서 활발히 사용 중
item_details.specification 6건 (id:97,101104,108109) CS,RM,SM 원자재 4단 규격은 의도된 설계. 통합 시 정책 결정 필요
items.description 4건 (id:99,130,137,145) CS,RM,SM,PT,FG 용도별 비고 분리가 의도된 것일 수 있음
item_details.part_type 1건 (id:110) PT 현재 정상 사용 중
item_details.certification_* 3건 (id:142~144) FG FG item_details 생성 후 연계 검토

4.3 Phase 1.3: 이관된 제품 데이터 구조

4.3.1 SAM items 테이블 현황 (tenant_id=287)

item_type 건수 설명
FG (완제품) 18 5130 models 18개와 1:1 매핑
PT (부품) 669 5130 parts/parts_sub + BDmodels 이관
SM (부자재) 61 5130 item_list 중 부자재
RM (원자재) 28 5130 item_list 중 원자재
CS (소모품) 4 소모품
합계 780

4.3.2 FG 품목 attributes 구조

FG 18개 품목의 attributes JSON 구조 (예: FG-KSS01-벽면형-SUS):

{
    "model_name": "KSS01",        // 5130 모델명
    "legacy_source": "models",     // 원본 출처
    "finishing_type": "SUS마감",    // 마감 유형
    "guiderail_type": "벽면형",    // 가이드레일 유형 (설치유형)
    "major_category": "스크린",    // 대분류 (스크린/철재)
    "legacy_model_id": 12         // 5130 model_id
}

FG attributes 키 ↔ FG item_fields 매핑 현황:

attributes 키 현재 FG field_key 매핑 상태
model_name 139_productName (상품명) 불일치 - textbox로 직접 입력
major_category 없음 필드 없음
finishing_type 없음 필드 없음
guiderail_type 없음 필드 없음
legacy_model_id 없음 내부 참조용, 표시 불필요
legacy_source 없음 내부 참조용, 표시 불필요

4.3.3 PT 품목 attributes 구조

PT 품목의 attributes JSON (예: PT-가이드레일):

{
    "base_price": "25000.00",      // 기본 단가
    "legacy_num": 6,               // 5130 번호
    "legacy_source": "item_list"   // 원본 출처
}

4.3.4 item_details 현황

item_type item_details 건수 비고
FG 0 ⚠️ 없음 - 생성 필요
PT 129 BD계열 부품 (마구리, 케이스 등)
SM 0
RM 0
CS 0

PT item_details 예시 (BD-마구리-505*355):

part_type: 마구리
item_name: 마구리 505*355
specification: 505*355
is_sellable: 1, is_purchasable: 1, is_producible: 0

4.4 Phase 1.4: BOM 관계 구조

4.4.1 SAM BOM 구조

FG 품목의 bom JSON 형태:

// FG-KSE01-벽면형-EGI (스크린, bom_items: 3)
[
    {"quantity": 2, "child_item_id": 13170},  // PT-가이드레일
    {"quantity": 1, "child_item_id": 13174},  // PT-하단마감재
    {"quantity": 2, "child_item_id": 13175}   // PT-L-BAR
]

BOM 패턴 요약:

대분류 FG 품목 수 BOM 구성
스크린 (KSS01/KSE01/KWE01/KSS02) 12 PT 3개 (가이드레일×2 + 하단마감재×1 + L-BAR×2)
철재 (KQTS01/KTE01) 6 PT 2개 (가이드레일×2 + 하단마감재×1)

4.4.2 5130 레거시 구조 비교

5130 models (18개 활성):

모델명 대분류 마감 유형 가이드레일
KSS01 스크린 SUS마감 벽면형/측면형
KSE01 스크린 SUS마감/EGI마감 벽면형/측면형
KWE01 스크린 SUS마감/EGI마감 벽면형/측면형
KQTS01 철재 SUS마감 벽면형/측면형
KTE01 철재 SUS마감/EGI마감 벽면형/측면형
KSS02 스크린 SUS마감 벽면형/측면형

5130 BDmodels (59개 활성):

model_name 건수 설명
KSS01 4 가이드레일/하단마감재/L-BAR 등
KSE01 8
KWE01 7
KQTS01 3
KTE01 6
KSS02 4
KDSS01 4
(빈값) 23 공용 부품

4.4.3 견적 의존성 분석

FormulaEvaluatorService가 의존하는 데이터:

  1. items.bom JSON → child_item_id로 PT 품목 조회 → PT의 item_categoryCategoryGroup 매핑
  2. items.code → 품목 식별에 사용
  3. items.item_category → 카테고리 그룹 가격 산출에 사용

⚠️ 수정 금지 영역:

  • items.bom JSON 구조 ([{child_item_id, quantity}])
  • items.code 체계 (FG-모델명-가이드레일-마감, PT-부품명)
  • items.item_category 값 (스크린, 철재)
  • FormulaEvaluatorService 로직

안전한 수정 영역:

  • item_pages/item_sections/item_fields (폼 표시 설정)
  • entity_relationships (폼 구성 관계)
  • item_fields.options (드롭다운 선택 값)
  • item_details (표시용 상세 정보)
  • items.attributes JSON (프론트엔드 표시용, 견적 미사용)

5. Phase 2 수정 계획

5.1 FG(제품) 필드 설정 정비

현재 문제: FG의 attributes 키(model_name, finishing_type, guiderail_type, major_category)와 FG page의 item_fields field_key가 매핑되지 않음

수정 방안:

순서 작업 field_key field_type options
1 모델명 필드 추가/수정 model_name dropdown KSS01, KSE01, KWE01, KQTS01, KTE01, KSS02
2 대분류 필드 추가 major_category dropdown 스크린, 철재
3 마감유형 필드 추가 finishing_type dropdown SUS마감, EGI마감
4 설치유형 필드 추가 guiderail_type dropdown 벽면형, 측면형
5 기존 필드 유지 139_productName → 상품명 textbox -
6 기존 필드 유지 141_lotNum → 로트 약자 textbox -
7 인정 관련 필드 유지 142~145_* textbox/date -

storage_type 설정: json (attributes JSON에서 읽기)

5.2 PT(부품) 필드 설정 정비

현재 문제: 빈 field_key 필드 존재, 부품유형별 조건부 필드가 복잡

수정 방안:

  • 빈 field_key 필드 수정 또는 비활성화
  • Part_type 드롭다운 options를 실제 부품 유형으로 갱신
  • 부품유형별 display_condition JSON 설정으로 조건부 표시

5.3 RM/SM/CS 필드 설정 정비

현재 문제: 드롭다운 options가 플레이스홀더 값

수정 방안:

  • RM: 100_item_name options → 실제 원자재명 (철판, 알루미늄, 스테인리스, 아연도금강판 등)
  • RM: 101~104_specification_* options → 실제 규격 값으로 교체
  • SM: 107_item_name options → 실제 부자재명
  • SM: 108~109_specification_* options → 실제 규격 값

5.4 FG item_details 데이터 보완

현재 문제: FG 18개 품목의 item_details 레코드 없음

수정 방안: FG 18개 품목에 대해 item_details 생성

item_id: (각 FG item id)
is_sellable: 1
is_purchasable: 0
is_producible: 1
product_category: (스크린/철재)
item_name: (SAM name)
specification: (마감유형-가이드레일유형)

5.5 드롭다운 options 실데이터 매핑

5130 데이터 기반으로 매핑할 값:

필드 현재 options 목표 options
FG model_name 없음 KSS01, KSE01, KWE01, KQTS01, KTE01, KSS02
FG major_category 없음 스크린, 철재
FG finishing_type 없음 SUS마감, EGI마감
FG guiderail_type 없음 벽면형, 측면형
PT Part_type 확인 필요 조립부품, 벤딩부품, 구매부품, BD부품
RM 100_item_name 기존값 유지 철판, 알루미늄, 스테인리스, 아연도금강판
RM 규격 101~104 옵션1-1 등 (임시값) 실제 규격 값으로 교체 필요

5.6 고정컬럼-동적필드 섀도잉 정리

상세 분석: 섹션 4.2.3 참조

5.6.1 is_active 중복 정리 (⚠️ 컨펌 필요)

목표: items.is_active 고정 컬럼만으로 활성/비활성 상태를 관리하도록 통합

방안 A (권장): 동적 필드를 is_common=1 공통필드(id:163)로 교체

각 page에서 중복 동적 필드를 제거하고, 공통 필드 is_active(id:163)를 entity_relationship으로 연결:

대상 page 제거할 동적 필드 대체 작업 내용
SM (id:1017) id:164 (field_163) id:163 (is_active) 1) section(id:94)→field(id:164) 관계 삭제 2) section(id:94)→field(id:163) 관계 추가
PT 측면규격 (id:99) id:105 (105_state) id:163 (is_active) 1) section(id:99)→field(id:105) 관계 삭제 2) section(id:99)→field(id:163) 관계 추가
PT 측면규격 (id:99) id:133 (133_state) id:163 (is_active) 1) section(id:99)→field(id:133) 관계 삭제 (id:163 이미 추가됨)
PT 기본정보 (id:95) id:138 (138_state) id:163 (is_active) 1) section(id:95)→field(id:138) 관계 삭제 2) section(id:95)→field(id:163) 관계 추가
FG 기본정보 (id:102) id:138 (138_state) id:163 (is_active) 1) section(id:102)→field(id:138) 관계 삭제 2) section(id:102)→field(id:163) 관계 추가
PT 기본정보 (id:95) id:152 (null key) id:163 (is_active) 1) section(id:95)→field(id:152) 관계 삭제 (id:163 이미 추가됨)

추가 작업:

  • 제거된 동적 필드(id:105,131,133,138,152,164)는 is_active=0으로 비활성화 (삭제 대신 비활성화하여 안전)
  • 기존 items.attributes JSON에 105_state, 138_state 등의 키로 저장된 값이 있다면, 해당 값을 items.is_active 컬럼과 동기화 필요 여부 확인

방안 B (보수적): 동적 필드의 field_key를 is_active로 변경만

동적 필드를 유지하되, source_columnis_active로, storage_typecolumn으로 변경하여 같은 컬럼을 가리키게 함. 관계 변경 없이 안전하지만, 불필요한 필드가 잔존함.

실행 전 확인 사항:

-- 동적 필드에 실제 데이터가 저장되어 있는지 확인
SELECT id, code, name,
  JSON_EXTRACT(attributes, '$.105_state') as s105,
  JSON_EXTRACT(attributes, '$.131_state') as s131,
  JSON_EXTRACT(attributes, '$.133_state') as s133,
  JSON_EXTRACT(attributes, '$.138_state') as s138,
  JSON_EXTRACT(attributes, '$.field_163') as f163
FROM items
WHERE tenant_id = 287 AND deleted_at IS NULL
AND (
  JSON_EXTRACT(attributes, '$.105_state') IS NOT NULL
  OR JSON_EXTRACT(attributes, '$.131_state') IS NOT NULL
  OR JSON_EXTRACT(attributes, '$.133_state') IS NOT NULL
  OR JSON_EXTRACT(attributes, '$.138_state') IS NOT NULL
  OR JSON_EXTRACT(attributes, '$.field_163') IS NOT NULL
);

5.6.2 null key 필드 비활성화 ( 즉시 가능)

-- item_fields id:152 (field_key=NULL, 품목상태, PT page)
-- key가 없어서 데이터 매핑 불가. 비활성화 처리.
UPDATE item_fields SET is_active = 0 WHERE id = 152 AND tenant_id = 287;

5.6.3 미연결 필드 비활성화 ( 즉시 가능)

entity_relationship에 연결되지 않아 어떤 폼에도 표시되지 않는 필드:

-- 미연결 필드 5건 비활성화
UPDATE item_fields SET is_active = 0
WHERE id IN (116, 117, 129, 131, 136) AND tenant_id = 287;

-- 확인: 이 필드들이 실제 미연결인지 재검증
SELECT f.id, f.field_key, f.field_name, er.id as rel_id
FROM item_fields f
LEFT JOIN entity_relationships er
  ON er.child_type = 'field' AND er.child_id = f.id AND er.tenant_id = 287
WHERE f.id IN (116, 117, 129, 131, 136) AND f.tenant_id = 287;
-- rel_id가 모두 NULL이면 확실히 미연결
field id field_key 비활성화 이유
116 116_bending_parts 미연결. id:122(122_bending_parts)와 중복
117 117_purchase_parts 미연결. id:132(132_PurchasedItemName)와 중복
129 unit_2 미연결. id:98(unit)과 중복
131 131_state 미연결. is_active 중복
136 unit_3 미연결. id:98(unit)과 중복

5.6.4 다음에 정리할 항목 (이번 범위 밖)

유형 건수 다음에 정리하는 이유
name (품목명) 중복 8건 PT 부품유형별 분기 UI(조립부품명/벤딩부품명/구매부품명)와 맞물림. display_condition 기반 렌더링 로직 변경 필요
unit (단위) 중복 2건 (활성) id:98이 4개 page에서 사용 중. 공통필드(id:156)와의 역할 분담 정책 결정 필요
specification (규격) 중복 6건 원자재 4단 규격은 의도된 설계. item_details.specification과의 동기화 정책 필요
description (비고) 중복 4건 note1/note2/note3 용도별 분리가 의도일 수 있음
certification_* 중복 3건 FG item_details 생성(5.4) 후 연계 검토
part_type 중복 1건 PT에서 정상 사용 중

6. 컨펌 대기 목록

# 항목 변경 내용 영향 범위 상태
1 FG 필드 추가 model_name, major_category, finishing_type, guiderail_type 4개 필드 추가 item_fields, entity_relationships 대기
2 PT 빈 field_key 처리 id:152 비활성화 item_fields 대기
3 RM/SM options 교체 플레이스홀더 → 실제 값 item_fields.options 대기
4 FG item_details 생성 18건 INSERT item_details 대기
5 is_active 중복 필드 통합 6개 동적필드 → 공통필드(id:163)로 교체 entity_relationships, item_fields 대기
6 미연결 필드 비활성화 id:116,117,129,131,136 비활성화 item_fields 대기

7. 변경 이력

날짜 항목 변경 내용 파일 승인
2026-01-31 - 문서 초안 작성 및 Phase 1 분석 완료 - -
2026-01-31 4.2.3 고정컬럼-동적필드 섀도잉 분석 추가 (is_active 6건, null key 1건, 미연결 5건) - -
2026-01-31 5.6 Phase 2에 섀도잉 정리 작업(2.6) 추가. 구체적 SQL, field id, entity_relationship 변경 계획 명시 - -
2026-01-31 2.6 Phase 2.6 실행 완료: null key(id:152) 비활성화, 미연결 5건(id:116,117,129,131,136) 비활성화, is_active 중복 통합(rel 7건 삭제, 공통필드 163을 section 94/95/99/102에 연결, 동적필드 105/133/138/164 비활성화). id:116,117은 계획과 달리 고아 section(97,98)에 연결 확인됨 -
2026-01-31 2.1 FG 필드 4개 추가(id:177-180: model_name/major_category/finishing_type/guiderail_type), section 102 연결, order_no 정렬 item_fields, entity_relationships
2026-01-31 2.2 PT Part_type options 갱신: BD부품 추가, 라벨 간소화 (4개: 조립/벤딩/구매/BD) item_fields id:110
2026-01-31 2.3 RM options 실데이터 교체(재질4종, 두께7종, 폭1종, 길이6종), SM options 11개 카테고리. SM 규격 빈 배열 설정 item_fields id:100-104,107-109
2026-01-31 2.5 드롭다운 options 매핑 2.1~2.3에서 함께 완료 -
2026-01-31 2.4 FG item_details 18건 생성(id:524-541). is_sellable=1, is_producible=1, product_category/item_name/specification 설정 item_details

8. 참고 문서

  • DB 스키마: docs/specs/database-schema.md
  • 품목 정책: docs/rules/item-policy.md
  • 품질 체크리스트: docs/standards/quality-checklist.md
  • 빠른 시작: docs/quickstart/quick-start.md
  • API 규칙: docs/standards/api-rules.md
  • 기존 이관 계획: docs/plans/items-migration-kyungdong-plan.md
  • MNG 필드 관리 계획: docs/plans/mng-item-field-management-plan.md

9. 새 세션 작업 시작 가이드

9.0 이 문서만으로 작업을 시작하는 방법

1단계: 현재 상태 확인

  • 이 문서의 "📍 현재 진행 상태" 섹션에서 마지막 완료 작업과 다음 작업 확인
  • Phase 2 대상 범위(섹션 2.2) 테이블에서 / 상태 확인

2단계: 환경 확인

# Docker 컨테이너 실행 확인
docker ps | grep sam

# 테넌트 데이터 접근 확인 (tenant_id=287)
docker exec sam-api-1 php artisan tinker --execute="echo DB::table('items')->where('tenant_id', 287)->count();"
# 기대값: 780

3단계: 작업 실행 순서 (Phase 2)

┌─────────────────────────────────────────────────────────────────┐
│  Phase 2 실행 순서 (권장)                                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  2.6 섀도잉 정리 (안전, 선행 작업)                                │
│   ├─ 5.6.2 null key 비활성화 (즉시 가능)                         │
│   ├─ 5.6.3 미연결 필드 비활성화 (즉시 가능)                      │
│   └─ 5.6.1 is_active 중복 통합 (⚠️ 컨펌 필요)                   │
│       └─ 사전: 5.6.1 확인 SQL 실행하여 기존 데이터 유무 확인     │
│                                                                  │
│  2.1 FG 필드 설정 정비 (⚠️ 컨펌 필요)                            │
│   └─ 섹션 5.1 참조: 4개 필드 추가 + entity_relationship 연결     │
│                                                                  │
│  2.2 PT 필드 설정 정비 (⚠️ 컨펌 필요)                            │
│   └─ 섹션 5.2 참조                                               │
│                                                                  │
│  2.3 SM/RM/CS 필드 설정 정비                                      │
│   └─ 섹션 5.3 참조                                               │
│                                                                  │
│  2.5 드롭다운 options 실데이터 매핑                               │
│   └─ 섹션 5.5 참조: FG 4개 + PT/RM 교체                         │
│                                                                  │
│  2.4 FG item_details 데이터 보완                                  │
│   └─ 섹션 5.4 참조: 18건 INSERT                                  │
│                                                                  │
│  검증                                                             │
│   └─ 섹션 10 테스트 케이스 실행                                   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4단계: 작업 대상 테이블/ID 빠른 참조

테이블 tenant_id 주요 ID 범위 용도
item_pages 287 1015~1019 (CS/RM/SM/PT/FG) 품목유형별 폼
item_sections 287 92~102 섹션 그룹
item_fields 287 96~164 필드 정의
entity_relationships 287 page→section 26건, section→field 66건 계층 연결
items 287 13147~13164 (FG 18건) 품목 데이터
item_details - PT 129건, FG 0건 품목 상세

5단계: 수정 금지 영역 (반드시 확인)

  • items.bom JSON 구조 변경 금지
  • items.code 체계 변경 금지
  • items.item_category 값 변경 금지
  • FormulaEvaluatorService 수정 금지
  • 위 항목은 견적 로직에 직접 영향. 상세: 섹션 4.4.3

10. Serena 메모리 관리 정책

10.1 세션 시작 시 (Load Strategy)

read_memory("item-data-alignment-state")     // 1. 상태 파악
read_memory("item-data-alignment-snapshot")  // 2. 사고 흐름 복구
read_memory("item-data-alignment-active-symbols") // 3. 작업 대상 파악

10.2 작업 중 관리 (Context Defense)

컨텍스트 잔량 Action 내용
30% 이하 Snapshot write_memory("item-data-alignment-snapshot", "코드변경+논의요약")
20% 이하 Context Purge write_memory("item-data-alignment-active-symbols", "주요 수정 파일/함수")
10% 이하 Stop & Save 최종 상태 저장 후 세션 교체 권고

10.3 Serena 메모리 구조

  • item-data-alignment-state: { phase, progress, next_step, last_decision } (JSON 구조)
  • item-data-alignment-snapshot: 현재까지의 논의 및 코드 변경점 요약 (Text)
  • item-data-alignment-rules: 견적 영향 금지 등 불변 규칙 (Text)
  • item-data-alignment-active-symbols: 현재 수정 중인 파일/심볼 리스트 (List)

11. 검증 결과

작업 완료 후 이 섹션에 검증 결과 추가

11.1 테스트 케이스

입력값 예상 결과 실제 결과 상태
FG-KSE01-벽면형-EGI 조회 model_name=KSE01, finishing_type=EGI마감 등 표시 -
PT-가이드레일 조회 base_price, 부품유형 등 표시 -
FG BOM 표시 가이드레일×2, 하단마감재×1, L-BAR×2 표시 -
견적 생성 (수정 후) 기존과 동일한 견적 금액 산출 -
SM 품목 활성 여부 items.is_active 컬럼 값 표시 (field_163 아님) -
PT 품목상태 필드 items.is_active 공통 필드로 통합 표시 -
FG 품목상태 필드 items.is_active 공통 필드로 통합 표시 -
id:152 (null key) 폼에 표시되지 않음 (비활성화) -
미연결 필드 5건 폼에 표시되지 않음 (비활성화) -

11.2 성공 기준 달성 현황

기준 달성 비고
FG 18개 품목이 모든 필드 정상 표시
PT 부품유형별 조건부 필드 정상 작동
RM/SM 드롭다운 실제 값 표시
견적 금액 변동 없음 (회귀 테스트)
품목 목록 → 상세 → 문서 데이터 흐름 정상
is_active 중복 필드 통합 완료 (6건 → 공통필드 1개)
null key 필드(id:152) 비활성화
미연결 필드(id:116,117,129,131,136) 비활성화

12. 자기완결성 점검 결과

12.1 체크리스트 검증

# 검증 항목 상태 비고
1 작업 목적이 명확한가? 섹션 1.1 배경
2 성공 기준이 정의되어 있는가? 섹션 11.2
3 작업 범위가 구체적인가? 섹션 2 대상 범위
4 의존성이 명시되어 있는가? 견적 금지 영역 명시 (4.4.3), 수정금지 (9.0 5단계)
5 참고 파일 경로가 정확한가? 섹션 8
6 단계별 절차가 실행 가능한가? 섹션 9.0 (새 세션 가이드), 섹션 5 (상세 수정 계획)
7 검증 방법이 명시되어 있는가? 섹션 11.1
8 모호한 표현이 없는가? 구체적 테이블/필드/ID, SQL 쿼리 명시

12.2 새 세션 시뮬레이션 테스트

질문 답변 가능 참조 섹션
Q1. 이 작업의 목적은 무엇인가? 1.1 배경
Q2. 어디서부터 시작해야 하는가? 9.0 3단계 (실행 순서 다이어그램)
Q3. 어떤 데이터를 수정해야 하는가? 5.1~5.6 (상세 수정 계획 + SQL)
Q4. 절대 건드리면 안 되는 것은? 9.0 5단계 + 4.4.3 (수정 금지 영역)
Q5. 작업 완료 확인 방법은? 11.1 테스트 케이스, 11.2 성공 기준
Q6. 막혔을 때 참고 문서는? 8. 참고 문서
Q7. DB 접속/환경 세팅은? 9.0 2단계 (환경 확인 명령어)
Q8. 테이블/ID 범위는? 9.0 4단계 (빠른 참조 테이블)

결과: 8/8 통과 → 자기완결성 확보


이 문서는 /sc:plan 스킬로 생성되었습니다.