Files
sam-react-prod/claudedocs/_ITEM_MASTER_API_STRUCTURE.md
byeongcheolryu df3db155dd [feat]: Item Master 데이터 관리 기능 구현 및 타입 에러 수정
- ItemMasterDataManagement 컴포넌트 구조화 (tabs, dialogs, components 분리)
- HierarchyTab 타입 에러 수정 (BOMItem section_id, updated_at 추가)
- API 클라이언트 구현 (item-master.ts, 13개 엔드포인트)
- ItemMasterContext 구현 (상태 관리 및 데이터 흐름)
- 백엔드 요구사항 문서 작성 (CORS 설정, API 스펙 등)
- SSR 호환성 수정 (navigator API typeof window 체크)
- 미사용 변수 ESLint 에러 해결
- Context 리팩토링 (AuthContext, RootProvider 추가)
- API 유틸리티 추가 (error-handler, logger, transformers)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 16:10:27 +09:00

31 KiB

품목기준관리 API 구조

목차

  1. 최초 화면 접근 시 필요한 API
  2. 각 항목별 저장 API
  3. API 응답 구조
  4. 에러 처리

최초 화면 접근 시 필요한 API

페이지 로드 시 tenant.id 기준으로 모든 기준정보를 조회합니다.

1. 전체 설정 조회 (통합 API)

엔드포인트: GET /api/tenants/{tenantId}/item-master-config

목적: 모든 기준정보를 한 번에 조회 (성능 최적화)

Next.js 프록시: /api/tenants/[tenantId]/item-master-config/route.ts

요청 예시:

GET /api/tenants/282/item-master-config HTTP/1.1
Authorization: Bearer {access_token}
X-API-KEY: {api_key}

PHP 백엔드 엔드포인트:

GET /api/v1/tenants/282/item-master-config

응답 구조:

{
  "success": true,
  "data": {
    "tenantId": 282,
    "itemMasters": [],
    "specificationMasters": [...],
    "materialItemNames": [...],
    "itemCategories": [...],
    "itemUnits": [...],
    "itemMaterials": [...],
    "surfaceTreatments": [...],
    "partTypeOptions": [...],
    "partUsageOptions": [...],
    "guideRailOptions": [...],
    "itemMasterFields": [...],
    "itemPages": [...]
  }
}

2. 개별 조회 API (선택적 사용)

필요 시 개별 항목만 조회할 수 있습니다.

2.1 규격 마스터

GET /api/tenants/{tenantId}/item-master-config/specification-masters

2.2 자재 품목명

GET /api/tenants/{tenantId}/item-master-config/material-item-names

2.3 품목 카테고리

GET /api/tenants/{tenantId}/item-master-config/item-categories

2.4 품목 단위

GET /api/tenants/{tenantId}/item-master-config/item-units

2.5 품목 재질

GET /api/tenants/{tenantId}/item-master-config/item-materials

2.6 표면처리

GET /api/tenants/{tenantId}/item-master-config/surface-treatments

2.7 부품 타입 옵션

GET /api/tenants/{tenantId}/item-master-config/part-type-options

2.8 부품 용도 옵션

GET /api/tenants/{tenantId}/item-master-config/part-usage-options

2.9 가이드레일 옵션

GET /api/tenants/{tenantId}/item-master-config/guide-rail-options

2.10 품목 마스터 필드

GET /api/tenants/{tenantId}/item-master-config/item-master-fields

2.11 품목 페이지

GET /api/tenants/{tenantId}/item-master-config/item-pages

각 항목별 저장 API

각 섹션의 저장 버튼 클릭 시 호출되는 API입니다.

1. 규격 마스터 (Specification Master)

등록

POST /api/tenants/{tenantId}/item-master-config/specification-masters
Content-Type: application/json

{
  "specificationCode": "1219*1200",
  "itemType": "RM",
  "itemName": "SPHC-SD",
  "fieldCount": "1",
  "thickness": "1.6",
  "widthA": "1219",
  "length": "1200",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/specification-masters/{specId}
Content-Type: application/json

{
  "specificationCode": "1219*1200",
  "thickness": "1.8",
  "isActive": true
}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/specification-masters/{specId}

일괄 저장 (추천)

POST /api/tenants/{tenantId}/item-master-config/specification-masters/bulk
Content-Type: application/json

{
  "items": [
    { "specificationCode": "1219*1200", ... },
    { "specificationCode": "1219*2438", ... }
  ]
}

2. 자재 품목명 (Material Item Name)

등록

POST /api/tenants/{tenantId}/item-master-config/material-item-names
Content-Type: application/json

{
  "itemType": "RM",
  "itemName": "SPHC-SD",
  "category": "냉연강판",
  "description": "일반냉연강판",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/material-item-names/{materialId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/material-item-names/{materialId}

일괄 저장

POST /api/tenants/{tenantId}/item-master-config/material-item-names/bulk

3. 품목 카테고리 (Item Category)

등록

POST /api/tenants/{tenantId}/item-master-config/item-categories
Content-Type: application/json

{
  "categoryType": "PRODUCT",
  "category1": "스크린",
  "code": "SC",
  "description": "스크린 셔터",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/item-categories/{categoryId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/item-categories/{categoryId}

4. 품목 단위 (Item Unit)

등록

POST /api/tenants/{tenantId}/item-master-config/item-units
Content-Type: application/json

{
  "unitCode": "EA",
  "unitName": "EA (개)",
  "description": "낱개 단위",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/item-units/{unitId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/item-units/{unitId}

5. 품목 재질 (Item Material)

등록

POST /api/tenants/{tenantId}/item-master-config/item-materials
Content-Type: application/json

{
  "materialCode": "EGI-1.2T",
  "materialName": "EGI 1.2T",
  "materialType": "STEEL",
  "thickness": "1.2T",
  "description": "전기아연도금강판",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/item-materials/{materialId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/item-materials/{materialId}

6. 표면처리 (Surface Treatment)

등록

POST /api/tenants/{tenantId}/item-master-config/surface-treatments
Content-Type: application/json

{
  "treatmentCode": "POWDER",
  "treatmentName": "파우더도장",
  "treatmentType": "PAINTING",
  "description": "분체도장",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/surface-treatments/{treatmentId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/surface-treatments/{treatmentId}

7. 부품 타입 옵션 (Part Type Option)

등록

POST /api/tenants/{tenantId}/item-master-config/part-type-options
Content-Type: application/json

{
  "partType": "ASSEMBLY",
  "optionCode": "ASSY",
  "optionName": "조립품",
  "description": "여러 부품을 조립하는 부품",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/part-type-options/{optionId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/part-type-options/{optionId}

8. 부품 용도 옵션 (Part Usage Option)

등록

POST /api/tenants/{tenantId}/item-master-config/part-usage-options
Content-Type: application/json

{
  "usageCode": "GUIDE_RAIL",
  "usageName": "가이드레일",
  "description": "가이드레일용 부품",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/part-usage-options/{optionId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/part-usage-options/{optionId}

9. 가이드레일 옵션 (Guide Rail Option)

등록

POST /api/tenants/{tenantId}/item-master-config/guide-rail-options
Content-Type: application/json

{
  "optionType": "MODEL_TYPE",
  "optionCode": "SCREEN",
  "optionName": "스크린용",
  "description": "스크린 셔터용 가이드레일",
  "parentOption": null,
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/guide-rail-options/{optionId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/guide-rail-options/{optionId}

10. 품목 마스터 필드 (Item Master Field)

등록

POST /api/tenants/{tenantId}/item-master-config/item-master-fields
Content-Type: application/json

{
  "name": "품목코드",
  "fieldKey": "itemCode",
  "property": {
    "inputType": "textbox",
    "required": true,
    "row": 1,
    "col": 1
  },
  "category": "공통",
  "description": "품목의 고유 코드",
  "isActive": true
}

수정

PUT /api/tenants/{tenantId}/item-master-config/item-master-fields/{fieldId}

삭제

DELETE /api/tenants/{tenantId}/item-master-config/item-master-fields/{fieldId}

11. 품목 페이지 (Item Page)

페이지 조회

GET /api/tenants/{tenantId}/item-master-config/pages/{pageId}

Next.js 프록시: /api/tenants/[tenantId]/item-master-config/pages/[pageId]/route.ts

페이지 생성

POST /api/tenants/{tenantId}/item-master-config/pages
Content-Type: application/json

{
  "pageName": "품목 등록",
  "itemType": "FG",
  "isActive": true,
  "sections": [
    {
      "title": "기본정보",
      "order": 1,
      "isCollapsible": true,
      "isCollapsed": false,
      "fields": [
        {
          "name": "품목코드",
          "fieldKey": "itemCode",
          "property": { "inputType": "textbox", "required": true, "row": 1, "col": 1 }
        }
      ]
    }
  ]
}

페이지 수정

PUT /api/tenants/{tenantId}/item-master-config/pages/{pageId}
Content-Type: application/json

{
  "pageName": "품목 등록 (수정)",
  "isActive": true,
  "sections": [...]
}

Next.js 프록시: /api/tenants/[tenantId]/item-master-config/pages/[pageId]/route.ts

페이지 삭제

DELETE /api/tenants/{tenantId}/item-master-config/pages/{pageId}

Next.js 프록시: /api/tenants/[tenantId]/item-master-config/pages/[pageId]/route.ts


API 응답 샘플 데이터

아래 샘플 데이터는 프론트엔드에서 주석 처리한 Mock 데이터이며, 백엔드 API 응답의 실제 구조 및 데이터 예시입니다.

1. 규격 마스터 (Specification Masters)

샘플 데이터 (27개 중 일부):

[
  {
    "id": "spec-001",
    "specificationCode": "1219*1200",
    "itemType": "RM",
    "itemName": "SPHC-SD",
    "fieldCount": "1",
    "thickness": "1.6",
    "widthA": "1219",
    "length": "1200",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  },
  {
    "id": "spec-002",
    "specificationCode": "1219*2438",
    "itemType": "RM",
    "itemName": "SPHC-SD",
    "fieldCount": "1",
    "thickness": "1.6",
    "widthA": "1219",
    "length": "2438",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  },
  {
    "id": "spec-022",
    "specificationCode": "1219*1200",
    "itemType": "RM",
    "itemName": "STS304",
    "fieldCount": "1",
    "thickness": "1.5",
    "widthA": "1219",
    "length": "1200",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  }
]

데이터 설명:

  • 총 27개 규격: SPHC-SD, SPCC-SD, SECC, SGCC, SPHD, SS330, SS400, STS304, STS430
  • 각 자재별로 3가지 길이 (1200, 2438, 3000mm) 규격 존재

2. 자재 품목명 (Material Item Names)

샘플 데이터 (139개 중 일부):

[
  {
    "id": "mat-001",
    "itemType": "RM",
    "itemName": "SPHC-SD",
    "category": "냉연강판",
    "description": "일반냉연강판",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  },
  {
    "id": "mat-008",
    "itemType": "RM",
    "itemName": "STS304",
    "category": "스테인리스",
    "description": "스테인리스강판 304",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  },
  {
    "id": "mat-101",
    "itemType": "SM",
    "itemName": "육각볼트",
    "category": "체결부품",
    "description": "육각머리볼트",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  },
  {
    "id": "mat-201",
    "itemType": "SM",
    "itemName": "용접봉",
    "category": "용접재료",
    "description": "용접봉",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  },
  {
    "id": "mat-301",
    "itemType": "SM",
    "itemName": "도료(백색)",
    "category": "도장재료",
    "description": "백색도료",
    "isActive": true,
    "createdAt": "2025-01-19T10:00:00Z"
  }
]

데이터 분류:

  • 원자재 (RM): 21개 (냉연강판, 스테인리스, 알루미늄, 파이프류, 형강류, 비철금속)
  • 부자재 (SM): 118개
    • 체결부품 (mat-101~111): 볼트, 너트, 와셔, 나사 등
    • 용접/접착 (mat-201~207): 용접봉, 실리콘, 에폭시 등
    • 도장/표면처리 (mat-301~306): 도료, 프라이머 등
    • 연마/연삭 (mat-401~404): 연마지, 절단석 등
    • 기타 부자재 (mat-501~539): 패킹, 베어링, 모터, 샤프트 등

3. 품목 카테고리 (Item Categories)

샘플 데이터 (14개):

[
  {
    "id": "CAT-001",
    "categoryType": "PRODUCT",
    "category1": "스크린",
    "code": "SC",
    "description": "스크린 셔터",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "CAT-101",
    "categoryType": "PART",
    "category1": "가이드레일",
    "code": "GR",
    "description": "가이드레일 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "CAT-201",
    "categoryType": "MATERIAL",
    "category1": "강판",
    "code": "SP",
    "description": "강판 원자재",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "CAT-301",
    "categoryType": "SUB_MATERIAL",
    "category1": "볼트너트",
    "code": "BN",
    "description": "볼트/너트",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

카테고리 타입 분류:

  • PRODUCT: 완제품 (스크린, 철재문, 블라인드)
  • PART: 부품 (가이드레일, 하단마감재, 케이스, 도어, 브라켓)
  • MATERIAL: 원자재 (강판, 알루미늄, 플라스틱)
  • SUB_MATERIAL: 부자재 (볼트너트, 나사, 페인트)

4. 품목 단위 (Item Units)

샘플 데이터 (7개):

[
  {
    "id": "UNIT-001",
    "unitCode": "EA",
    "unitName": "EA (개)",
    "description": "낱개 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "UNIT-002",
    "unitCode": "SET",
    "unitName": "SET (세트)",
    "description": "세트 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "UNIT-003",
    "unitCode": "M",
    "unitName": "M (미터)",
    "description": "길이 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "UNIT-004",
    "unitCode": "KG",
    "unitName": "KG (킬로그램)",
    "description": "무게 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "UNIT-006",
    "unitCode": "M2",
    "unitName": "㎡ (제곱미터)",
    "description": "면적 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "UNIT-007",
    "unitCode": "BOX",
    "unitName": "BOX (박스)",
    "description": "박스 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

5. 품목 재질 (Item Materials)

샘플 데이터 (7개):

[
  {
    "id": "MAT-001",
    "materialCode": "EGI-1.2T",
    "materialName": "EGI 1.2T",
    "materialType": "STEEL",
    "thickness": "1.2T",
    "description": "전기아연도금강판",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "MAT-002",
    "materialCode": "EGI-1.55T",
    "materialName": "EGI 1.55T",
    "materialType": "STEEL",
    "thickness": "1.55T",
    "description": "전기아연도금강판",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "MAT-004",
    "materialCode": "SUS-1.2T",
    "materialName": "SUS 1.2T",
    "materialType": "STEEL",
    "thickness": "1.2T",
    "description": "스테인리스 강판",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "MAT-006",
    "materialCode": "AL-6063",
    "materialName": "알루미늄 6063",
    "materialType": "ALUMINUM",
    "description": "알루미늄 압출재",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

재질 타입:

  • STEEL: EGI (전기아연도금강판), SUS (스테인리스)
  • ALUMINUM: AL-6063, AL-6061

6. 표면처리 (Surface Treatments)

샘플 데이터 (5개):

[
  {
    "id": "TREAT-001",
    "treatmentCode": "NONE",
    "treatmentName": "무도장",
    "treatmentType": "NONE",
    "description": "표면처리 없음",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "TREAT-002",
    "treatmentCode": "POWDER",
    "treatmentName": "파우더도장",
    "treatmentType": "PAINTING",
    "description": "분체도장",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "TREAT-003",
    "treatmentCode": "ANODIZING",
    "treatmentName": "아노다이징",
    "treatmentType": "COATING",
    "description": "알루미늄 양극산화처리",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "TREAT-004",
    "treatmentCode": "ZINC",
    "treatmentName": "아연도금",
    "treatmentType": "PLATING",
    "description": "아연 도금처리",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

처리 타입:

  • NONE: 무도장
  • PAINTING: 도장 (파우더도장)
  • COATING: 코팅 (아노다이징)
  • PLATING: 도금 (아연도금, 크롬도금)

7. 부품 타입 옵션 (Part Type Options)

샘플 데이터 (3개):

[
  {
    "id": "PTYPE-001",
    "partType": "ASSEMBLY",
    "optionCode": "ASSY",
    "optionName": "조립품",
    "description": "여러 부품을 조립하는 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "PTYPE-002",
    "partType": "BENDING",
    "optionCode": "BEND",
    "optionName": "절곡품",
    "description": "절곡 가공 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "PTYPE-003",
    "partType": "PURCHASED",
    "optionCode": "PURCH",
    "optionName": "구매품",
    "description": "외부에서 구매하는 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

8. 부품 용도 옵션 (Part Usage Options)

샘플 데이터 (6개):

[
  {
    "id": "USAGE-001",
    "usageCode": "GUIDE_RAIL",
    "usageName": "가이드레일",
    "description": "가이드레일용 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "USAGE-002",
    "usageCode": "BOTTOM_FINISH",
    "usageName": "하단마감재",
    "description": "하단마감재용 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "USAGE-003",
    "usageCode": "CASE",
    "usageName": "케이스",
    "description": "케이스용 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "USAGE-004",
    "usageCode": "DOOR",
    "usageName": "도어",
    "description": "도어용 부품",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

9. 가이드레일 옵션 (Guide Rail Options)

샘플 데이터 (13개 중 일부):

[
  {
    "id": "GR-001",
    "optionType": "MODEL_TYPE",
    "optionCode": "SCREEN",
    "optionName": "스크린용",
    "description": "스크린 셔터용 가이드레일",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "GR-011",
    "optionType": "MODEL",
    "optionCode": "T40",
    "optionName": "T40",
    "parentOption": "SCREEN",
    "description": "T40 모델",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "GR-021",
    "optionType": "CERTIFICATION",
    "optionCode": "KFI",
    "optionName": "KFI인증",
    "description": "KFI 인증",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "GR-031",
    "optionType": "SHAPE",
    "optionCode": "ROUND",
    "optionName": "R형",
    "description": "라운드형",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "GR-041",
    "optionType": "FINISH",
    "optionCode": "POWDER",
    "optionName": "파우더도장",
    "description": "파우더 도장 마감",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "GR-051",
    "optionType": "LENGTH",
    "optionCode": "3000",
    "optionName": "3000mm",
    "description": "3미터",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

옵션 타입 분류:

  • MODEL_TYPE: 제품 유형 (스크린용, 철재용)
  • MODEL: 모델명 (T40, T60, 프리미엄) - parentOption 참조
  • CERTIFICATION: 인증 (KFI인증, 미인증)
  • SHAPE: 형상 (R형, ㄱ형)
  • FINISH: 마감 (파우더도장, 아노다이징)
  • LENGTH: 길이 (3000mm, 4000mm, 5000mm)

10. 품목 마스터 필드 (Item Master Fields)

샘플 데이터 (5개):

[
  {
    "id": "MASTER-001",
    "name": "품목코드",
    "fieldKey": "itemCode",
    "property": {
      "inputType": "textbox",
      "required": true,
      "row": 1,
      "col": 1
    },
    "category": "공통",
    "description": "품목의 고유 코드",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "MASTER-002",
    "name": "품목명",
    "fieldKey": "itemName",
    "property": {
      "inputType": "textbox",
      "required": true,
      "row": 1,
      "col": 1
    },
    "category": "공통",
    "description": "품목의 이름",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "MASTER-003",
    "name": "단위",
    "fieldKey": "unit",
    "property": {
      "inputType": "dropdown",
      "required": true,
      "row": 1,
      "col": 1,
      "options": ["EA", "SET", "KG", "M", "BOX"]
    },
    "category": "공통",
    "description": "품목의 단위",
    "isActive": true,
    "createdAt": "2025-01-01"
  },
  {
    "id": "MASTER-004",
    "name": "재질",
    "fieldKey": "material",
    "property": {
      "inputType": "dropdown",
      "required": false,
      "row": 1,
      "col": 1,
      "options": ["EGI 1.2T", "SUS 1.2T", "AL 1.5T"]
    },
    "category": "부품",
    "description": "부품의 재질",
    "isActive": true,
    "createdAt": "2025-01-01"
  }
]

inputType 종류:

  • textbox: 텍스트 입력
  • dropdown: 드롭다운 선택 (options 필수)

11. 품목 페이지 (Item Pages)

샘플 구조 (실제 Mock 데이터는 빈 배열):

[
  {
    "id": "PAGE-001",
    "pageName": "제품 등록",
    "itemType": "FG",
    "isActive": true,
    "createdAt": "2025-01-01",
    "sections": [
      {
        "id": "SECTION-001",
        "title": "기본정보",
        "order": 1,
        "isCollapsible": true,
        "isCollapsed": false,
        "fields": [
          {
            "name": "품목코드",
            "fieldKey": "itemCode",
            "property": {
              "inputType": "textbox",
              "required": true,
              "row": 1,
              "col": 1
            }
          },
          {
            "name": "품목명",
            "fieldKey": "itemName",
            "property": {
              "inputType": "textbox",
              "required": true,
              "row": 1,
              "col": 2
            }
          }
        ]
      }
    ]
  }
]

전체 설정 조회 API 응답 예시

GET /api/tenants/282/item-master-config 응답:

{
  "success": true,
  "data": {
    "tenantId": 282,
    "itemMasters": [],
    "specificationMasters": [
      /* 위의 27 규격 마스터 데이터 */
    ],
    "materialItemNames": [
      /* 위의 139 자재 품목명 데이터 */
    ],
    "itemCategories": [
      /* 위의 14 품목 카테고리 데이터 */
    ],
    "itemUnits": [
      /* 위의 7 품목 단위 데이터 */
    ],
    "itemMaterials": [
      /* 위의 7 품목 재질 데이터 */
    ],
    "surfaceTreatments": [
      /* 위의 5 표면처리 데이터 */
    ],
    "partTypeOptions": [
      /* 위의 3 부품 타입 옵션 데이터 */
    ],
    "partUsageOptions": [
      /* 위의 6 부품 용도 옵션 데이터 */
    ],
    "guideRailOptions": [
      /* 위의 13 가이드레일 옵션 데이터 */
    ],
    "itemMasterFields": [
      /* 위의 5 품목 마스터 필드 데이터 */
    ],
    "itemPages": []
  }
}

주의사항:

  • id 필드는 백엔드에서 자동 생성 (UUID 또는 Auto Increment)
  • createdAt, updatedAt 필드는 백엔드에서 자동 관리
  • Mock 데이터의 날짜는 예시용이며, 실제로는 백엔드에서 생성된 timestamp 사용

API 응답 구조

성공 응답

{
  "success": true,
  "data": {
    "id": "spec-001",
    "specificationCode": "1219*1200",
    "itemType": "RM",
    "itemName": "SPHC-SD",
    "createdAt": "2025-01-19T10:00:00Z",
    "updatedAt": "2025-01-19T10:00:00Z"
  }
}

에러 응답

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "필수 필드가 누락되었습니다.",
    "details": {
      "field": "itemName",
      "reason": "required"
    }
  }
}

일괄 저장 응답

{
  "success": true,
  "data": {
    "total": 10,
    "created": 8,
    "updated": 2,
    "failed": 0,
    "items": [...]
  }
}

에러 처리

HTTP 상태 코드

코드 의미 설명
200 OK 성공
201 Created 생성 성공
400 Bad Request 잘못된 요청
401 Unauthorized 인증 실패
403 Forbidden 권한 없음 (테넌트 불일치)
404 Not Found 리소스 없음
409 Conflict 중복 데이터
500 Internal Server Error 서버 오류

에러 코드

에러 코드 설명
VALIDATION_ERROR 유효성 검사 실패
UNAUTHORIZED 인증 필요
FORBIDDEN 권한 없음
NOT_FOUND 리소스 없음
DUPLICATE 중복 데이터
SERVER_ERROR 서버 오류

Next.js API Routes 구조

기존 구현 완료

  1. /api/tenants/[tenantId]/item-master-config/route.ts

    • GET: 전체 설정 조회
    • POST: 전체 설정 생성
    • PUT: 전체 설정 수정
  2. /api/tenants/[tenantId]/item-master-config/pages/[pageId]/route.ts

    • GET: 특정 페이지 조회
    • PUT: 특정 페이지 수정
    • DELETE: 특정 페이지 삭제

추가 필요 (선택사항)

개별 항목 CRUD가 필요한 경우 추가 라우트 생성:

/api/tenants/[tenantId]/item-master-config/
  ├── specification-masters/
  ├── material-item-names/
  ├── item-categories/
  ├── item-units/
  ├── item-materials/
  ├── surface-treatments/
  ├── part-type-options/
  ├── part-usage-options/
  ├── guide-rail-options/
  ├── item-master-fields/
  └── pages/
      └── [pageId]/

캐싱 전략

TenantAwareCache 사용

// ItemMasterContext.tsx에서 구현됨
cache.set('itemMasters', data, 3600000); // 1시간 TTL
cache.set('specificationMasters', data, 3600000);
// ... 기타 항목들

캐시 키 구조

mes-{tenantId}-itemMasters
mes-{tenantId}-specificationMasters
mes-{tenantId}-materialItemNames
mes-{tenantId}-itemCategories
mes-{tenantId}-itemUnits
mes-{tenantId}-itemMaterials
mes-{tenantId}-surfaceTreatments
mes-{tenantId}-partTypeOptions
mes-{tenantId}-partUsageOptions
mes-{tenantId}-guideRailOptions
mes-{tenantId}-itemMasterFields
mes-{tenantId}-itemPages

캐시 무효화

  • 테넌트 전환 시: 이전 테넌트 캐시 자동 삭제
  • 로그아웃 시: 현재 테넌트 캐시 삭제
  • 데이터 저장 시: 해당 항목 캐시 무효화

프론트엔드 구현 체크리스트

ItemMasterContext.tsx

  • Mock 데이터 주석 처리
  • API 호출 함수 구현
  • TenantAwareCache 연동
  • 에러 처리 추가
  • 로딩 상태 관리

ItemMasterDataManagement.tsx

  • 각 섹션별 저장 버튼 이벤트
  • API 호출 로직
  • 성공/실패 토스트 메시지
  • 낙관적 업데이트 (Optimistic UI)
  • 에러 핸들링

백엔드 요구사항

필수 구현

  • PHP /api/v1/tenants/{tenantId}/item-master-config 엔드포인트 구현
  • 테넌트 검증 로직 (인증된 사용자의 tenant.id와 URL의 tenantId 일치 확인)
  • 데이터베이스 테이블 생성
  • 트랜잭션 처리
  • 에러 응답 표준화

DB 초기 데이터 등록 (Seeding)

중요: 모든 데이터는 API로 제공되므로, DB에 초기 데이터 등록이 필수입니다.

시스템 기본값 (모든 테넌트 공통 또는 테넌트 생성 시 자동 복사):

  1. 품목 단위 (7개)

    • EA, SET, M, KG, L, M2, BOX
    • 우선순위: 🔴 높음 (필수)
  2. 품목 재질 (7개)

    • EGI-1.2T, EGI-1.55T, EGI-2.0T, SUS-1.2T, SUS-1.5T, AL-6063, AL-6061
    • 우선순위: 🔴 높음 (필수)
  3. 표면처리 (5개)

    • 무도장, 파우더도장, 아노다이징, 아연도금, 크롬도금
    • 우선순위: 🔴 높음 (필수)
  4. 품목 카테고리 (14개)

    • PRODUCT, PART, MATERIAL, SUB_MATERIAL 타입별 카테고리
    • 우선순위: 🟡 중간
  5. 부품 타입 옵션 (3개)

    • 조립품, 절곡품, 구매품
    • 우선순위: 🟡 중간
  6. 부품 용도 옵션 (6개)

    • 가이드레일, 하단마감재, 케이스, 도어, 브라켓, 일반
    • 우선순위: 🟡 중간
  7. 품목 마스터 필드 (5개)

    • 품목코드, 품목명, 단위, 재질, 표면처리
    • 우선순위: 🟡 중간

테넌트별 데이터 (선택적, 빈 배열로 시작 가능):

  1. 규격 마스터 (27개 샘플)

    • 우선순위: 🟢 낮음 (테스트/샘플 데이터)
  2. 자재 품목명 (139개 샘플)

    • 우선순위: 🟢 낮음 (테스트/샘플 데이터)
  3. 가이드레일 옵션 (13개 샘플)

    • 우선순위: 🟢 낮음 (테스트/샘플 데이트)

초기 데이터 등록 방법:

-- 예시: 품목 단위 초기 데이터
INSERT INTO item_units (tenant_id, unitCode, unitName, description, isActive) VALUES
  (NULL, 'EA', 'EA (개)', '낱개 단위', true),      -- tenant_id NULL = 전체 공통
  (NULL, 'SET', 'SET (세트)', '세트 단위', true),
  (NULL, 'M', 'M (미터)', '길이 단위', true),
  (NULL, 'KG', 'KG (킬로그램)', '무게 단위', true),
  (NULL, 'L', 'L (리터)', '부피 단위', true),
  (NULL, 'M2', '㎡ (제곱미터)', '면적 단위', true),
  (NULL, 'BOX', 'BOX (박스)', '박스 단위', true);

-- 또는 테넌트 생성 시 자동 복사
CREATE TRIGGER copy_default_data_on_tenant_create
AFTER INSERT ON tenants
FOR EACH ROW
BEGIN
  -- 기본값 자동 복사 로직
END;

API 응답 예시:

{
  "success": true,
  "data": {
    "tenantId": 282,
    "itemUnits": [
      {
        "id": "UNIT-001",
        "unitCode": "EA",
        "unitName": "EA (개)",
        "description": "낱개 단위",
        "isActive": true
      }
      // ... 6개 더
    ],
    "itemMaterials": [/* 7 기본 재질 */],
    "surfaceTreatments": [/* 5 기본 표면처리 */],
    "itemCategories": [/* 14 */],
    "partTypeOptions": [/* 3 */],
    "partUsageOptions": [/* 6 */],
    "itemMasterFields": [/* 5 */],
    "specificationMasters": [],  // 빈 배열 (테넌트별 데이터)
    "materialItemNames": [],
    "guideRailOptions": [],
    "itemPages": []
  }
}

참고: 위의 "API 응답 샘플 데이터" 섹션에 모든 초기 데이터의 상세 구조가 포함되어 있습니다.