fix: 품목기준관리 실시간 동기화 수정
- BOM 항목 추가/수정/삭제 시 섹션탭 즉시 반영 - 섹션 복제 시 UI 즉시 업데이트 (null vs undefined 이슈 해결) - 항목 수정 기능 추가 (useTemplateManagement) - 실시간 동기화 문서 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -31,10 +31,17 @@ export interface PaginationMeta {
|
||||
/**
|
||||
* 초기화 API 응답 - 화면 진입 시 전체 데이터 로드
|
||||
* GET /v1/item-master/init
|
||||
*
|
||||
* 2025-11-27 변경사항:
|
||||
* - masterFields → 독립 필드(item_fields WHERE section_id IS NULL)로 대체 예정
|
||||
* - fields 필드 추가: 모든 필드 목록 (독립 필드 + 섹션 내 필드)
|
||||
*/
|
||||
export interface InitResponse {
|
||||
pages: ItemPageResponse[];
|
||||
sections?: ItemSectionResponse[]; // 2025-11-26 추가: 모든 섹션 (독립 섹션 포함)
|
||||
fields?: ItemFieldResponse[]; // 2025-11-27 추가: 모든 필드 (독립 필드 = section_id IS NULL)
|
||||
sectionTemplates: SectionTemplateResponse[];
|
||||
/** @deprecated 2025-11-27: item_fields로 통합됨. fields 필드 사용 권장 */
|
||||
masterFields: MasterFieldResponse[];
|
||||
customTabs: CustomTabResponse[];
|
||||
tabColumns: Record<number, TabColumnResponse[]>; // tab_id를 key로 사용
|
||||
@@ -65,8 +72,10 @@ export interface ItemPageResponse {
|
||||
tenant_id: number;
|
||||
page_name: string;
|
||||
item_type: string;
|
||||
description: string | null; // 2025-11-26 추가: 페이지 설명
|
||||
absolute_path: string | null;
|
||||
is_active: boolean;
|
||||
order_no: number; // 2025-11-26 추가: 순서 번호
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string;
|
||||
@@ -101,33 +110,84 @@ export interface ItemSectionRequest {
|
||||
|
||||
/**
|
||||
* 섹션 응답
|
||||
* 2025-11-26: section_templates 테이블 통합으로 is_template, is_default, description, group_id 추가
|
||||
*/
|
||||
export interface ItemSectionResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
page_id: number;
|
||||
group_id: number | null; // 그룹 ID (독립 섹션 그룹화용)
|
||||
page_id: number | null; // 페이지 ID (null이면 독립 섹션)
|
||||
title: string;
|
||||
type: 'fields' | 'bom';
|
||||
order_no: number;
|
||||
is_template: boolean; // 템플릿 여부 (section_templates 통합)
|
||||
is_default: boolean; // 기본 템플릿 여부
|
||||
description: string | null; // 섹션 설명
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
fields?: ItemFieldResponse[]; // Nested 조회 시 포함
|
||||
bomItems?: BomItemResponse[]; // Nested 조회 시 포함
|
||||
bomItems?: BomItemResponse[]; // Nested 조회 시 포함 (camelCase)
|
||||
bom_items?: BomItemResponse[]; // 2025-11-27: 백엔드가 snake_case로 반환
|
||||
}
|
||||
|
||||
/**
|
||||
* 섹션 순서 변경 요청
|
||||
* PUT /v1/item-master/pages/{pageId}/sections/reorder
|
||||
* 백엔드 API는 'items' 필드를 기대함
|
||||
*/
|
||||
export interface SectionReorderRequest {
|
||||
section_orders: Array<{
|
||||
items: Array<{
|
||||
id: number;
|
||||
order_no: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 독립 섹션 생성 요청
|
||||
* POST /v1/item-master/sections
|
||||
* 2025-11-26 신규 API
|
||||
*/
|
||||
export interface IndependentSectionRequest {
|
||||
group_id?: number;
|
||||
title: string;
|
||||
type: 'fields' | 'bom';
|
||||
is_template?: boolean;
|
||||
is_default?: boolean;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 섹션 사용처 응답
|
||||
* GET /v1/item-master/sections/{id}/usage
|
||||
* 2025-11-26 신규 API
|
||||
*/
|
||||
export interface SectionUsageResponse {
|
||||
section_id: number;
|
||||
direct_page: {
|
||||
id: number;
|
||||
page_name: string;
|
||||
item_type: string;
|
||||
} | null;
|
||||
linked_pages: Array<{
|
||||
id: number;
|
||||
page_name: string;
|
||||
item_type: string;
|
||||
}>;
|
||||
total_usage_count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 페이지에 섹션 연결 요청
|
||||
* POST /v1/item-master/pages/{id}/link-section
|
||||
* 2025-11-26 신규 API
|
||||
*/
|
||||
export interface LinkSectionRequest {
|
||||
child_id: number; // 연결할 섹션 ID (백엔드: child_id)
|
||||
order_no?: number;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 필드 관리
|
||||
// ============================================
|
||||
@@ -151,11 +211,14 @@ export interface ItemFieldRequest {
|
||||
|
||||
/**
|
||||
* 필드 응답
|
||||
* 2025-11-26: section_id를 nullable로 변경 (독립 필드 지원)
|
||||
* 2025-11-27: item_master_fields 테이블 통합으로 category, description, is_common 추가
|
||||
*/
|
||||
export interface ItemFieldResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
section_id: number;
|
||||
group_id: number | null; // 그룹 ID (독립 필드 그룹화용)
|
||||
section_id: number | null; // 섹션 ID (null이면 독립 필드/마스터 항목)
|
||||
master_field_id?: number | null; // 마스터 항목 ID (마스터에서 가져온 경우)
|
||||
field_name: string;
|
||||
field_type: 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea';
|
||||
@@ -167,6 +230,10 @@ export interface ItemFieldResponse {
|
||||
validation_rules: Record<string, any> | null;
|
||||
options: Array<{ label: string; value: string }> | null;
|
||||
properties: Record<string, any> | null;
|
||||
// 2025-11-27 추가: item_master_fields 통합으로 추가된 필드
|
||||
category: string | null; // 카테고리 (예: "공통", "완제품", "부품")
|
||||
description: string | null; // 필드 설명
|
||||
is_common: boolean; // 공통 필드 여부
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string;
|
||||
@@ -184,6 +251,59 @@ export interface FieldReorderRequest {
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 독립 필드 생성 요청
|
||||
* POST /v1/item-master/fields
|
||||
* 2025-11-26 신규 API
|
||||
* 2025-11-27: item_master_fields 통합으로 category, description, is_common 추가
|
||||
*/
|
||||
export interface IndependentFieldRequest {
|
||||
group_id?: number;
|
||||
field_name: string;
|
||||
field_type: 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea';
|
||||
is_required?: boolean;
|
||||
default_value?: string;
|
||||
placeholder?: string;
|
||||
options?: Array<{ label: string; value: string }>;
|
||||
properties?: Record<string, any>;
|
||||
validation_rules?: Record<string, any>;
|
||||
display_condition?: Record<string, any>;
|
||||
// 2025-11-27 추가: item_master_fields 통합으로 추가된 필드
|
||||
category?: string;
|
||||
description?: string;
|
||||
is_common?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 필드 사용처 응답
|
||||
* GET /v1/item-master/fields/{id}/usage
|
||||
* 2025-11-26 신규 API
|
||||
*/
|
||||
export interface FieldUsageResponse {
|
||||
field_id: number;
|
||||
direct_section: {
|
||||
id: number;
|
||||
title: string;
|
||||
type: 'fields' | 'bom';
|
||||
} | null;
|
||||
linked_sections: Array<{
|
||||
id: number;
|
||||
title: string;
|
||||
type: 'fields' | 'bom';
|
||||
}>;
|
||||
total_usage_count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 섹션에 필드 연결 요청
|
||||
* POST /v1/item-master/sections/{id}/link-field
|
||||
* 2025-11-26 신규 API
|
||||
*/
|
||||
export interface LinkFieldRequest {
|
||||
child_id: number; // 연결할 필드 ID (백엔드: child_id)
|
||||
order_no?: number;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// BOM 관리
|
||||
// ============================================
|
||||
@@ -206,11 +326,13 @@ export interface BomItemRequest {
|
||||
|
||||
/**
|
||||
* BOM 항목 응답
|
||||
* 2025-11-26: section_id를 nullable로 변경 (독립 BOM 지원)
|
||||
*/
|
||||
export interface BomItemResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
section_id: number;
|
||||
group_id: number | null; // 그룹 ID (독립 BOM 그룹화용)
|
||||
section_id: number | null; // 섹션 ID (null이면 독립 BOM)
|
||||
item_code: string | null;
|
||||
item_name: string;
|
||||
quantity: number;
|
||||
@@ -225,6 +347,115 @@ export interface BomItemResponse {
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 독립 BOM 항목 생성 요청
|
||||
* POST /v1/item-master/bom-items
|
||||
* 2025-11-26 신규 API
|
||||
*/
|
||||
export interface IndependentBomItemRequest {
|
||||
group_id?: number;
|
||||
item_code?: string;
|
||||
item_name: string;
|
||||
quantity?: number;
|
||||
unit?: string;
|
||||
unit_price?: number;
|
||||
spec?: string;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 엔티티 관계 (Entity Relationships)
|
||||
// 2025-11-27 신규: 독립 엔티티 + 링크 테이블 구조
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* 엔티티 타입 상수
|
||||
*/
|
||||
export type EntityType = 'page' | 'section' | 'field' | 'bom';
|
||||
export type ParentEntityType = 'page' | 'section';
|
||||
export type ChildEntityType = 'section' | 'field' | 'bom';
|
||||
|
||||
/**
|
||||
* 엔티티 관계 응답
|
||||
* entity_relationships 테이블의 레코드
|
||||
*/
|
||||
export interface EntityRelationshipResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
group_id: number; // 그룹 ID (1: 품목관리)
|
||||
parent_type: ParentEntityType;
|
||||
parent_id: number;
|
||||
child_type: ChildEntityType;
|
||||
child_id: number;
|
||||
order_no: number;
|
||||
metadata: Record<string, any> | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 엔티티 연결 요청 (공통)
|
||||
* POST /pages/{pageId}/link-section
|
||||
* POST /pages/{pageId}/link-field
|
||||
* POST /sections/{sectionId}/link-field
|
||||
* POST /sections/{sectionId}/link-bom
|
||||
*/
|
||||
export interface LinkEntityRequest {
|
||||
child_id: number;
|
||||
order_no?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 관계 순서 변경 요청
|
||||
* POST /v1/item-master/relationships/reorder
|
||||
*/
|
||||
export interface ReorderRelationshipsRequest {
|
||||
parent_type: ParentEntityType;
|
||||
parent_id: number;
|
||||
ordered_items: Array<{
|
||||
child_type: ChildEntityType;
|
||||
child_id: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 섹션에 BOM 연결 요청
|
||||
* POST /v1/item-master/sections/{id}/link-bom
|
||||
*/
|
||||
export interface LinkBomRequest {
|
||||
child_id: number;
|
||||
order_no?: number;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 페이지 구조 조회
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* 페이지 전체 구조 응답
|
||||
* GET /v1/item-master/pages/{id}/structure
|
||||
* 2025-11-27 업데이트: 링크 테이블 기반 구조
|
||||
*/
|
||||
export interface PageStructureResponse {
|
||||
page: ItemPageResponse;
|
||||
sections: Array<{
|
||||
section: ItemSectionResponse;
|
||||
order_no: number;
|
||||
fields: Array<{
|
||||
field: ItemFieldResponse;
|
||||
order_no: number;
|
||||
}>;
|
||||
bom_items: Array<{
|
||||
bom_item: BomItemResponse;
|
||||
order_no: number;
|
||||
}>;
|
||||
}>;
|
||||
direct_fields: Array<{
|
||||
field: ItemFieldResponse;
|
||||
order_no: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 섹션 템플릿
|
||||
// ============================================
|
||||
@@ -258,13 +489,17 @@ export interface SectionTemplateResponse {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 마스터 필드
|
||||
// 마스터 필드 (DEPRECATED)
|
||||
// 2025-11-27: item_master_fields 테이블이 item_fields로 통합됨
|
||||
// 독립 필드 = item_fields WHERE section_id IS NULL
|
||||
// IndependentFieldRequest 및 ItemFieldResponse 사용 권장
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* 마스터 필드 생성/수정 요청
|
||||
* POST /v1/item-master/master-fields
|
||||
* PUT /v1/item-master/master-fields/{id}
|
||||
* @deprecated 2025-11-27: item_fields로 통합됨. IndependentFieldRequest 사용 권장
|
||||
* POST /v1/item-master/master-fields → POST /v1/item-master/fields 사용
|
||||
* PUT /v1/item-master/master-fields/{id} → PUT /v1/item-master/fields/{id} 사용
|
||||
*/
|
||||
export interface MasterFieldRequest {
|
||||
field_name: string;
|
||||
@@ -280,6 +515,8 @@ export interface MasterFieldRequest {
|
||||
|
||||
/**
|
||||
* 마스터 필드 응답
|
||||
* @deprecated 2025-11-27: item_fields로 통합됨. ItemFieldResponse 사용 권장
|
||||
* 독립 필드 조회: GET /v1/item-master/fields?section_id=null
|
||||
*/
|
||||
export interface MasterFieldResponse {
|
||||
id: number;
|
||||
|
||||
Reference in New Issue
Block a user