# 품목기준관리(ItemMaster) & 품목관리(Items) API 문서 > 프론트엔드 개발자를 위한 API 스펙 문서 > 작성일: 2025-12-10 ## 목차 1. [개요](#개요) 2. [품목관리 (Items) API](#품목관리-items-api) 3. [품목기준관리 (ItemMaster) API](#품목기준관리-itemmaster-api) 4. [공통 응답 형식](#공통-응답-형식) 5. [에러 처리](#에러-처리) --- ## 개요 ### 품목관리 (Items) vs 품목기준관리 (ItemMaster) | 구분 | 품목관리 (Items) | 품목기준관리 (ItemMaster) | |------|------------------|---------------------------| | **역할** | 실제 품목 데이터 CRUD | 품목 입력 화면/폼 구성 관리 | | **대상 데이터** | products, materials 테이블 | item_pages, item_sections, item_fields 테이블 | | **사용자** | 품목 등록/수정하는 일반 사용자 | 화면 구성을 설정하는 관리자 | | **비유** | 엑셀 데이터 | 엑셀 양식(템플릿) | ### 품목 유형 코드 (item_type / product_type) | 코드 | 설명 | 저장 테이블 | |------|------|-------------| | `FG` | 완제품 (Finished Goods) | products | | `PT` | 반제품/부품 (Part) | products | | `SM` | 반자재 (Semi-Material) | materials | | `RM` | 원자재 (Raw Material) | materials | | `CS` | 소모품 (Consumables) | materials | --- ## 품목관리 (Items) API 실제 품목 데이터를 조회/생성/수정/삭제하는 API입니다. ### 1. 통합 품목 목록 조회 **역할**: products와 materials를 통합하여 조회 (UNION 방식) ``` GET /api/v1/items ``` #### Request Parameters (Query) | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `type` | string | N | 품목 유형 필터 (쉼표 구분). 기본값: `FG,PT,SM,RM,CS` | | `search` 또는 `q` | string | N | 검색어 (코드, 이름, 태그) | | `category_id` | integer | N | 카테고리 ID 필터 | | `size` | integer | N | 페이지당 항목 수. 기본값: 20 | | `page` | integer | N | 페이지 번호. 기본값: 1 | | `include_deleted` | boolean | N | 삭제된 항목 포함 여부. 기본값: false | #### Request 예시 ```http GET /api/v1/items?type=FG,PT&search=모터&size=10&page=1 ``` #### Response ```json { "success": true, "message": "조회되었습니다.", "data": { "data": [ { "id": 1, "item_type": "FG", "code": "P-001", "name": "완제품A", "specification": null, "unit": "EA", "category_id": 5, "type_code": "FG", "created_at": "2025-01-01T00:00:00.000000Z", "deleted_at": null, "safety_stock": 100, "lead_time": 7 } ], "current_page": 1, "per_page": 20, "total": 150, "last_page": 8 } } ``` #### Response 필드 설명 | 필드 | 설명 | |------|------| | `id` | 품목 고유 ID (테이블별 독립) | | `item_type` | 품목 유형 코드 | | `code` | 품목 코드 | | `name` | 품목명 | | `specification` | 규격 (materials만 해당) | | `unit` | 단위 (EA, KG, M 등) | | `category_id` | 카테고리 ID | | `type_code` | 품목 유형 코드 (item_type과 동일) | | `created_at` | 생성일시 | | `deleted_at` | 삭제일시 (Soft Delete) | | `safety_stock` | 안전재고 (attributes에서 플랫 전개) | | `lead_time` | 리드타임 (attributes에서 플랫 전개) | > **Note**: `attributes` JSON 필드는 자동으로 최상위로 플랫 전개되어 반환됩니다. --- ### 2. 단일 품목 조회 (ID 기반) **역할**: 특정 ID의 품목 상세 정보 조회 (가격 정보 옵션) ``` GET /api/v1/items/{id} ``` #### Path Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `id` | integer | Y | 품목 ID | #### Query Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `item_type` | string | N | 품목 유형 코드. 기본값: `FG` | | `include_price` | boolean | N | 가격 정보 포함 여부. 기본값: false | | `client_id` | integer | N | 고객 ID (가격 조회 시) | | `price_date` | string | N | 가격 기준일 (YYYY-MM-DD) | #### Request 예시 ```http GET /api/v1/items/123?item_type=SM&include_price=true&client_id=5 ``` #### Response ```json { "success": true, "message": "조회되었습니다.", "data": { "id": 123, "item_type": "SM", "code": "M-001", "name": "반자재A", "specification": "10mm x 20mm", "unit": "EA", "category_id": 10, "category": { "id": 10, "name": "철강류" }, "type_code": "SM", "prices": { "sale": { "unit_price": 15000, "currency": "KRW", "effective_from": "2025-01-01" }, "purchase": { "unit_price": 10000, "currency": "KRW", "effective_from": "2025-01-01" } } } } ``` --- ### 3. 단일 품목 조회 (코드 기반) **역할**: 품목 코드로 상세 정보 조회 (Product → Material 순서로 검색) ``` GET /api/v1/items/code/{code} ``` #### Path Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `code` | string | Y | 품목 코드 | #### Query Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `include_bom` | boolean | N | BOM 정보 포함 여부. 기본값: false | #### Request 예시 ```http GET /api/v1/items/code/P-001?include_bom=true ``` --- ### 4. 품목 생성 **역할**: 새 품목 등록 (product_type에 따라 products 또는 materials에 저장) ``` POST /api/v1/items ``` #### Request Body | 필드 | 타입 | 필수 | 설명 | |------|------|------|------| | `code` | string | Y | 품목 코드 (최대 50자, 중복 시 자동 증가) | | `name` | string | Y | 품목명 (최대 255자) | | `product_type` | string | Y | 품목 유형: `FG`, `PT`, `SM`, `RM`, `CS` | | `unit` | string | Y | 단위 (최대 20자) | | `category_id` | integer | N | 카테고리 ID | | `description` | string | N | 설명 | | `is_sellable` | boolean | N | 판매 가능 여부. 기본값: true | | `is_purchasable` | boolean | N | 구매 가능 여부. 기본값: false | | `is_producible` | boolean | N | 생산 가능 여부. 기본값: false | | `safety_stock` | integer | N | 안전재고 (0 이상) | | `lead_time` | integer | N | 리드타임 (0 이상) | | `is_variable_size` | boolean | N | 가변 사이즈 여부 | | `product_category` | string | N | 제품 분류 (최대 20자) | | `part_type` | string | N | 부품 유형 (최대 20자) | | `attributes` | object | N | 동적 필드 (JSON) | | `material_code` | string | N | 자재 코드 (Material 전용) | | `item_name` | string | N | 품명 (Material 전용) | | `specification` | string | N | 규격 (Material 전용) | | `is_inspection` | string | N | 검수 여부: `Y`, `N` | | `search_tag` | string | N | 검색 태그 | | `remarks` | string | N | 비고 | | `options` | object | N | 옵션 (JSON) | #### Request 예시 ```json { "code": "P-NEW-001", "name": "신규 완제품", "product_type": "FG", "unit": "EA", "category_id": 5, "is_sellable": true, "safety_stock": 50, "attributes": { "color": "red", "size": "L" } } ``` #### Response ```json { "success": true, "message": "품목이 생성되었습니다.", "data": { "id": 999, "code": "P-NEW-001", "name": "신규 완제품", "product_type": "FG", "unit": "EA", "category_id": 5, "is_active": true, "is_sellable": true, "is_purchasable": false, "is_producible": false, "created_by": 1, "created_at": "2025-12-10T10:00:00.000000Z" } } ``` > **중복 코드 처리**: 코드가 이미 존재하면 자동으로 증가합니다. > - `P-001` 중복 → `P-002` > - `ABC` 중복 → `ABC-001` --- ### 5. 품목 수정 **역할**: 기존 품목 정보 수정 ``` PUT /api/v1/items/{id} ``` #### Path Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `id` | integer | Y | 품목 ID | #### Request Body | 필드 | 타입 | 필수 | 설명 | |------|------|------|------| | `item_type` | string | Y | 품목 유형 (테이블 분기용) | | `code` | string | N | 품목 코드 | | `name` | string | N | 품목명 | | ... | | | (생성과 동일한 필드, 모두 선택) | #### Request 예시 ```json { "item_type": "FG", "name": "수정된 완제품명", "safety_stock": 100 } ``` #### Response ```json { "success": true, "message": "품목이 수정되었습니다.", "data": { "id": 999, "code": "P-NEW-001", "name": "수정된 완제품명", "safety_stock": 100, "updated_by": 1, "updated_at": "2025-12-10T11:00:00.000000Z" } } ``` --- ### 6. 품목 삭제 (Soft Delete) **역할**: 품목 삭제 (BOM 구성품으로 사용 중이면 삭제 불가) ``` DELETE /api/v1/items/{id} ``` #### Path Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `id` | integer | Y | 품목 ID | #### Query Parameters | 파라미터 | 타입 | 필수 | 설명 | |----------|------|------|------| | `item_type` | string | N | 품목 유형. 기본값: `FG` | #### Response ```json { "success": true, "message": "품목이 삭제되었습니다.", "data": "success" } ``` #### 에러 Response (BOM 사용 중) ```json { "success": false, "message": "해당 품목은 3건의 BOM에서 구성품으로 사용 중입니다." } ``` --- ### 7. 품목 일괄 삭제 **역할**: 여러 품목 일괄 삭제 ``` DELETE /api/v1/items/batch ``` #### Request Body | 필드 | 타입 | 필수 | 설명 | |------|------|------|------| | `item_type` | string | Y | 품목 유형 | | `ids` | array | Y | 삭제할 품목 ID 배열 | #### Request 예시 ```json { "item_type": "FG", "ids": [1, 2, 3, 4, 5] } ``` --- ## 품목기준관리 (ItemMaster) API 품목 입력 화면의 구성(페이지, 섹션, 필드)을 관리하는 API입니다. ### 구조 개요 ``` ItemMaster 계층 구조: Page (페이지) ├── Section (섹션) - fields 타입 │ ├── Field (필드) │ ├── Field (필드) │ └── Field (필드) └── Section (섹션) - bom 타입 ├── BomItem (BOM 항목) └── BomItem (BOM 항목) ``` - **Page**: 품목 유형별 입력 화면 (예: 완제품 등록 페이지) - **Section**: 페이지 내 영역 구분 (예: 기본정보, BOM 구성) - **Field**: 입력 필드 정의 (예: 품목코드, 품목명) - **BomItem**: BOM 섹션의 구성품 정의 ### 1. 초기화 데이터 로드 **역할**: 프론트엔드 앱 초기화 시 필요한 전체 ItemMaster 데이터 로드 ``` GET /api/v1/item-master/init ``` #### Response ```json { "success": true, "message": "조회되었습니다.", "data": { "pages": [ { "id": 1, "tenant_id": 1, "group_id": null, "page_name": "완제품 등록", "item_type": "FG", "absolute_path": "/items/fg/create", "is_active": true, "sections": [ { "id": 10, "title": "기본정보", "type": "fields", "order_no": 1, "is_locked": false, "fields": [ { "id": 100, "field_name": "품목코드", "field_key": "code", "field_type": "textbox", "is_required": true, "order_no": 1, "is_locked": true } ] } ] } ], "sections": [...], "fields": [...], "customTabs": [...], "unitOptions": [...] } } ``` #### Response 필드 설명 | 필드 | 설명 | |------|------| | `pages` | 페이지 목록 (섹션, 필드 중첩 포함) | | `sections` | 모든 독립 섹션 목록 (재사용 가능) | | `fields` | 모든 독립 필드 목록 (재사용 가능) | | `customTabs` | 커스텀 탭 목록 (컬럼 설정 포함) | | `unitOptions` | 단위 옵션 목록 | --- ### 2. 페이지 API #### 페이지 목록 조회 ``` GET /api/v1/item-master/pages ``` | Query 파라미터 | 타입 | 필수 | 설명 | |----------------|------|------|------| | `item_type` | string | N | 품목 유형 필터 | #### 페이지 생성 ``` POST /api/v1/item-master/pages ``` | Request Body | 타입 | 필수 | 설명 | |--------------|------|------|------| | `page_name` | string | Y | 페이지명 (최대 255자) | | `item_type` | string | Y | 품목 유형: `FG`, `PT`, `SM`, `RM`, `CS` | | `absolute_path` | string | N | 절대 경로 (최대 500자) | #### 페이지 수정 ``` PUT /api/v1/item-master/pages/{id} ``` #### 페이지 삭제 ``` DELETE /api/v1/item-master/pages/{id} ``` --- ### 3. 섹션 API #### 독립 섹션 목록 조회 ``` GET /api/v1/item-master/sections ``` | Query 파라미터 | 타입 | 필수 | 설명 | |----------------|------|------|------| | `is_template` | boolean | N | 템플릿 섹션 필터 | #### 독립 섹션 생성 (페이지 연결 없음) ``` POST /api/v1/item-master/sections ``` | Request Body | 타입 | 필수 | 설명 | |--------------|------|------|------| | `group_id` | integer | N | 계층 번호 | | `title` | string | Y | 섹션 제목 (최대 255자) | | `type` | string | Y | 섹션 타입: `fields`, `bom` | #### 페이지에 섹션 생성 (연결) ``` POST /api/v1/item-master/pages/{pageId}/sections ``` #### 섹션 복제 ``` POST /api/v1/item-master/sections/{id}/clone ``` #### 섹션 사용처 조회 ``` GET /api/v1/item-master/sections/{id}/usage ``` **역할**: 해당 섹션이 어떤 페이지에서 사용되고 있는지 조회 #### 섹션 수정 ``` PUT /api/v1/item-master/sections/{id} ``` #### 섹션 삭제 ``` DELETE /api/v1/item-master/sections/{id} ``` #### 섹션 순서 변경 ``` PUT /api/v1/item-master/pages/{pageId}/sections/reorder ``` | Request Body | 타입 | 필수 | 설명 | |--------------|------|------|------| | `items` | array | Y | `[{id: 1, order_no: 1}, {id: 2, order_no: 2}]` | --- ### 4. 필드 API #### 독립 필드 목록 조회 ``` GET /api/v1/item-master/fields ``` #### 독립 필드 생성 (섹션 연결 없음) ``` POST /api/v1/item-master/fields ``` | Request Body | 타입 | 필수 | 설명 | |--------------|------|------|------| | `group_id` | integer | N | 계층 번호 | | `field_name` | string | Y | 필드 표시명 (최대 255자) | | `field_key` | string | N | 필드 키 (최대 80자, 영문 시작) | | `field_type` | string | Y | 필드 타입 (아래 참조) | | `is_required` | boolean | N | 필수 입력 여부 | | `default_value` | string | N | 기본값 | | `placeholder` | string | N | 플레이스홀더 (최대 255자) | | `display_condition` | object | N | 표시 조건 (JSON) | | `validation_rules` | object | N | 검증 규칙 (JSON) | | `options` | array | N | 드롭다운 옵션 등 (JSON) | | `properties` | object | N | 추가 속성 (JSON) | | `is_locked` | boolean | N | 잠금 여부 | #### 필드 타입 (field_type) | 타입 | 설명 | |------|------| | `textbox` | 한 줄 텍스트 입력 | | `number` | 숫자 입력 | | `dropdown` | 드롭다운 선택 | | `checkbox` | 체크박스 | | `date` | 날짜 선택 | | `textarea` | 여러 줄 텍스트 입력 | #### 섹션에 필드 생성 (연결) ``` POST /api/v1/item-master/sections/{sectionId}/fields ``` #### 필드 복제 ``` POST /api/v1/item-master/fields/{id}/clone ``` #### 필드 사용처 조회 ``` GET /api/v1/item-master/fields/{id}/usage ``` **역할**: 해당 필드가 어떤 섹션에서 사용되고 있는지 조회 #### 필드 수정 ``` PUT /api/v1/item-master/fields/{id} ``` #### 필드 삭제 ``` DELETE /api/v1/item-master/fields/{id} ``` --- ## 공통 응답 형식 모든 API는 동일한 응답 구조를 따릅니다. ### 성공 응답 ```json { "success": true, "message": "처리되었습니다.", "data": { ... } } ``` ### 페이지네이션 응답 ```json { "success": true, "message": "조회되었습니다.", "data": { "data": [...], "current_page": 1, "per_page": 20, "total": 100, "last_page": 5, "from": 1, "to": 20 } } ``` --- ## 에러 처리 ### 에러 응답 형식 ```json { "success": false, "message": "에러 메시지", "errors": { "field_name": ["검증 오류 메시지"] } } ``` ### 주요 HTTP 상태 코드 | 코드 | 설명 | |------|------| | `200` | 성공 | | `201` | 생성 성공 | | `400` | 잘못된 요청 (검증 실패, 중복 코드 등) | | `401` | 인증 필요 | | `403` | 권한 없음 | | `404` | 리소스 없음 | | `422` | 검증 실패 (Validation Error) | | `500` | 서버 오류 | ### 주요 에러 케이스 | 상황 | 메시지 예시 | |------|-------------| | 품목 없음 | "해당 품목을 찾을 수 없습니다." | | 코드 중복 | "이미 사용 중인 품목코드입니다." | | BOM 사용 중 | "해당 품목은 N건의 BOM에서 구성품으로 사용 중입니다." | | 필수 필드 누락 | "품목코드는 필수입니다." | | 잘못된 품목 유형 | "품목 유형은 FG, PT, SM, RM, CS 중 하나여야 합니다." | --- ## 인증 모든 API는 다음 인증이 필요합니다: 1. **API Key**: `X-API-KEY` 헤더 2. **Bearer Token**: `Authorization: Bearer {token}` 헤더 ```http GET /api/v1/items X-API-KEY: your-api-key Authorization: Bearer your-access-token ``` --- ## 변경 이력 | 날짜 | 버전 | 변경 내용 | |------|------|----------| | 2025-12-10 | 1.0 | 최초 작성 |