@@ -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 . include s( joinedColumnName ) ) continue ;
if ( ! joinedTableColumns [ joinedTable ] ) {
joinedTableColumn s [ 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 ) ;
i f ( response . data . success && response . data . data && Array . isArray ( response . data . data ) ) {
const mapping : Record < str ing , { label : string ; color ? : string } > = { } ;
for ( const col of columns ) {
const inputTypeInfo = inputTypes . f ind ( ( 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 ] ,
) ;
// ========================================