엔티티 카테고리 타입 컬럼 배지 표시기능

This commit is contained in:
kjs 2025-12-05 11:04:42 +09:00
parent 9e956999c5
commit 662956edd4
4 changed files with 101 additions and 32 deletions

View File

@ -365,6 +365,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
const [columnMeta, setColumnMeta] = useState<
Record<string, { webType?: string; codeCategory?: string; inputType?: string }>
>({});
// 🆕 엔티티 조인 테이블의 컬럼 메타데이터 (테이블명.컬럼명 → inputType)
const [joinedColumnMeta, setJoinedColumnMeta] = useState<
Record<string, { webType?: string; codeCategory?: string; inputType?: string }>
>({});
const [categoryMappings, setCategoryMappings] = useState<
Record<string, Record<string, { label: string; color?: string }>>
>({});
@ -1044,58 +1048,119 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
}
}
// 🆕 엔티티 조인 컬럼 중 카테고리 타입이 아니지만 조인된 테이블의 카테고리 필드인 경우도 로드
// 화면 설정의 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<string, { columnName: string; actualColumn: string }[]> = {};
// "테이블명.컬럼명" 형태 처리
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<string, { webType?: string; codeCategory?: string; inputType?: string }> = {};
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<string, { label: string; color?: string }> = {};
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<string, { label: string; color?: string }> = {};
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<TableListComponentProps> = ({
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<TableListComponentProps> = ({
return String(value);
}
},
[columnMeta, optimizedConvertCode, categoryMappings],
[columnMeta, joinedColumnMeta, optimizedConvertCode, categoryMappings],
);
// ========================================

View File

@ -1681,3 +1681,4 @@ const 출고등록_설정: ScreenSplitPanel = {

View File

@ -528,3 +528,4 @@ const { data: config } = await getScreenSplitPanel(screenId);

View File

@ -515,3 +515,4 @@ function ScreenViewPage() {