From 662956edd44e566cee7355ea6324cb60b203b69c Mon Sep 17 00:00:00 2001 From: kjs Date: Fri, 5 Dec 2025 11:04:42 +0900 Subject: [PATCH] =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=ED=83=80=EC=9E=85=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=20=EB=B0=B0=EC=A7=80=20=ED=91=9C=EC=8B=9C=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table-list/TableListComponent.tsx | 130 +++++++++++++----- ..._임베딩_및_데이터_전달_시스템_구현_계획서.md | 1 + 화면_임베딩_시스템_Phase1-4_구현_완료.md | 1 + 화면_임베딩_시스템_충돌_분석_보고서.md | 1 + 4 files changed, 101 insertions(+), 32 deletions(-) diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index 22c26e45..5b397d57 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -365,6 +365,10 @@ export const TableListComponent: React.FC = ({ const [columnMeta, setColumnMeta] = useState< Record >({}); + // 🆕 엔티티 조인 테이블의 컬럼 메타데이터 (테이블명.컬럼명 → inputType) + const [joinedColumnMeta, setJoinedColumnMeta] = useState< + Record + >({}); const [categoryMappings, setCategoryMappings] = useState< Record> >({}); @@ -1044,58 +1048,119 @@ export const TableListComponent: React.FC = ({ } } - // 🆕 엔티티 조인 컬럼 중 카테고리 타입이 아니지만 조인된 테이블의 카테고리 필드인 경우도 로드 - // 화면 설정의 columns에서 "테이블명.컬럼명" 형태의 조인 컬럼 추출 + // 🆕 엔티티 조인 컬럼의 inputType 정보 가져오기 및 카테고리 매핑 로드 + // 1. "테이블명.컬럼명" 형태의 조인 컬럼 추출 const joinedColumns = tableConfig.columns ?.filter((col) => col.columnName?.includes(".")) .map((col) => col.columnName) || []; - // 알려진 카테고리 필드 목록 (조인된 테이블에서 자주 사용되는 카테고리 컬럼) - const knownCategoryFields = ["material", "division", "status", "currency_code", "inbound_type", "outbound_type"]; + // 2. additionalJoinInfo가 있는 컬럼도 추출 (예: item_code_material → item_info.material) + const additionalJoinColumns = tableConfig.columns + ?.filter((col: any) => col.additionalJoinInfo?.referenceTable) + .map((col: any) => ({ + columnName: col.columnName, // 예: item_code_material + referenceTable: col.additionalJoinInfo.referenceTable, // 예: item_info + // joinAlias에서 실제 컬럼명 추출 (item_code_material → material) + actualColumn: col.additionalJoinInfo.joinAlias?.replace(`${col.additionalJoinInfo.sourceColumn}_`, '') || col.columnName, + })) || []; + console.log("🔍 [TableList] additionalJoinInfo 컬럼:", additionalJoinColumns); + + // 조인 테이블별로 그룹화 + const joinedTableColumns: Record = {}; + + // "테이블명.컬럼명" 형태 처리 for (const joinedColumn of joinedColumns) { - // 이미 로드된 컬럼은 스킵 - if (mappings[joinedColumn]) continue; - const parts = joinedColumn.split("."); if (parts.length !== 2) continue; const joinedTable = parts[0]; const joinedColumnName = parts[1]; - // 알려진 카테고리 필드인 경우만 로드 시도 - if (!knownCategoryFields.includes(joinedColumnName)) continue; - + if (!joinedTableColumns[joinedTable]) { + joinedTableColumns[joinedTable] = []; + } + joinedTableColumns[joinedTable].push({ + columnName: joinedColumn, + actualColumn: joinedColumnName, + }); + } + + // additionalJoinInfo 형태 처리 + for (const col of additionalJoinColumns) { + if (!joinedTableColumns[col.referenceTable]) { + joinedTableColumns[col.referenceTable] = []; + } + joinedTableColumns[col.referenceTable].push({ + columnName: col.columnName, // 예: item_code_material + actualColumn: col.actualColumn, // 예: material + }); + } + + console.log("🔍 [TableList] 조인 테이블별 컬럼:", joinedTableColumns); + + // 조인된 테이블별로 inputType 정보 가져오기 + const newJoinedColumnMeta: Record = {}; + + for (const [joinedTable, columns] of Object.entries(joinedTableColumns)) { try { - console.log(`📡 [TableList] 조인 테이블 카테고리 로드 시도 [${joinedColumn}]:`, { - url: `/table-categories/${joinedTable}/${joinedColumnName}/values`, - }); + // 조인 테이블의 컬럼 inputType 정보 가져오기 (이미 import된 tableTypeApi 사용) + const inputTypes = await tableTypeApi.getColumnInputTypes(joinedTable); - const response = await apiClient.get(`/table-categories/${joinedTable}/${joinedColumnName}/values`); + console.log(`📡 [TableList] 조인 테이블 inputType 로드 [${joinedTable}]:`, inputTypes); - if (response.data.success && response.data.data && Array.isArray(response.data.data)) { - const mapping: Record = {}; + for (const col of columns) { + const inputTypeInfo = inputTypes.find((it: any) => it.columnName === col.actualColumn); - response.data.data.forEach((item: any) => { - const key = String(item.valueCode); - mapping[key] = { - label: item.valueLabel, - color: item.color, - }; - }); + // 컬럼명 그대로 저장 (item_code_material 또는 item_info.material) + newJoinedColumnMeta[col.columnName] = { + inputType: inputTypeInfo?.inputType, + }; - if (Object.keys(mapping).length > 0) { - mappings[joinedColumn] = mapping; - console.log(`✅ [TableList] 조인 테이블 카테고리 매핑 로드 완료 [${joinedColumn}]:`, { - mappingCount: Object.keys(mapping).length, - }); + console.log(` 🔗 [${col.columnName}] (실제: ${col.actualColumn}) inputType: ${inputTypeInfo?.inputType || "unknown"}`); + + // inputType이 category인 경우 카테고리 매핑 로드 + if (inputTypeInfo?.inputType === "category" && !mappings[col.columnName]) { + try { + console.log(`📡 [TableList] 조인 테이블 카테고리 로드 시도 [${col.columnName}]:`, { + url: `/table-categories/${joinedTable}/${col.actualColumn}/values`, + }); + + const response = await apiClient.get(`/table-categories/${joinedTable}/${col.actualColumn}/values`); + + if (response.data.success && response.data.data && Array.isArray(response.data.data)) { + const mapping: Record = {}; + + response.data.data.forEach((item: any) => { + const key = String(item.valueCode); + mapping[key] = { + label: item.valueLabel, + color: item.color, + }; + }); + + if (Object.keys(mapping).length > 0) { + mappings[col.columnName] = mapping; + console.log(`✅ [TableList] 조인 테이블 카테고리 매핑 로드 완료 [${col.columnName}]:`, { + mappingCount: Object.keys(mapping).length, + }); + } + } + } catch (error) { + console.log(`ℹ️ [TableList] 조인 테이블 카테고리 없음 (${col.columnName})`); + } } } } catch (error) { - // 조인 테이블 카테고리 로드 실패는 무시 (카테고리가 아닌 필드일 수 있음) - console.log(`ℹ️ [TableList] 조인 테이블 카테고리 없음 (${joinedColumn})`); + console.error(`❌ [TableList] 조인 테이블 inputType 로드 실패 [${joinedTable}]:`, error); } } + + // 조인 컬럼 메타데이터 상태 업데이트 + if (Object.keys(newJoinedColumnMeta).length > 0) { + setJoinedColumnMeta(newJoinedColumnMeta); + console.log("✅ [TableList] 조인 컬럼 메타데이터 설정:", newJoinedColumnMeta); + } console.log("📊 [TableList] 전체 카테고리 매핑 설정:", { mappingsCount: Object.keys(mappings).length, @@ -1929,7 +1994,8 @@ export const TableListComponent: React.FC = ({ return rowData.writer_name; } - const meta = columnMeta[column.columnName]; + // 🆕 메인 테이블 메타 또는 조인 테이블 메타에서 정보 가져오기 + const meta = columnMeta[column.columnName] || joinedColumnMeta[column.columnName]; // inputType 기반 포맷팅 (columnMeta에서 가져온 inputType 우선) const inputType = meta?.inputType || column.inputType; @@ -2119,7 +2185,7 @@ export const TableListComponent: React.FC = ({ return String(value); } }, - [columnMeta, optimizedConvertCode, categoryMappings], + [columnMeta, joinedColumnMeta, optimizedConvertCode, categoryMappings], ); // ======================================== diff --git a/화면_임베딩_및_데이터_전달_시스템_구현_계획서.md b/화면_임베딩_및_데이터_전달_시스템_구현_계획서.md index 687896c1..313a7567 100644 --- a/화면_임베딩_및_데이터_전달_시스템_구현_계획서.md +++ b/화면_임베딩_및_데이터_전달_시스템_구현_계획서.md @@ -1681,3 +1681,4 @@ const 출고등록_설정: ScreenSplitPanel = { + diff --git a/화면_임베딩_시스템_Phase1-4_구현_완료.md b/화면_임베딩_시스템_Phase1-4_구현_완료.md index bc025b41..373b6ec7 100644 --- a/화면_임베딩_시스템_Phase1-4_구현_완료.md +++ b/화면_임베딩_시스템_Phase1-4_구현_완료.md @@ -528,3 +528,4 @@ const { data: config } = await getScreenSplitPanel(screenId); + diff --git a/화면_임베딩_시스템_충돌_분석_보고서.md b/화면_임베딩_시스템_충돌_분석_보고서.md index cdd94d36..5d315706 100644 --- a/화면_임베딩_시스템_충돌_분석_보고서.md +++ b/화면_임베딩_시스템_충돌_분석_보고서.md @@ -515,3 +515,4 @@ function ScreenViewPage() { +