diff --git a/backend-node/src/controllers/entityReferenceController.ts b/backend-node/src/controllers/entityReferenceController.ts index 633cde62..af360b6c 100644 --- a/backend-node/src/controllers/entityReferenceController.ts +++ b/backend-node/src/controllers/entityReferenceController.ts @@ -49,65 +49,46 @@ export class EntityReferenceController { if (!columnInfo) { return res.status(404).json({ success: false, - message: `컬럼 '${tableName}.${columnName}'을 찾을 수 없습니다.`, + message: `컬럼 정보를 찾을 수 없습니다: ${tableName}.${columnName}`, }); } - // column_labels에서 참조 테이블 정보 가져오기 - let referenceTable = columnInfo.reference_table || ""; - let referenceColumn = columnInfo.reference_column || ""; - let displayColumn = "name"; // 기본 표시 컬럼 - - // detailSettings에서 displayColumn 정보 추출 - try { - if (columnInfo.detail_settings) { - const detailSettings = JSON.parse(columnInfo.detail_settings); - displayColumn = detailSettings.displayColumn || displayColumn; - } - } catch (error) { - logger.warn("detailSettings 파싱 실패:", error); - } - - // reference_table이 없는 경우 컬럼명 기반으로 추론 - if (!referenceTable) { - if (columnName.endsWith("_code")) { - // dept_code -> dept_info - const baseTableName = columnName.replace("_code", "_info"); - referenceTable = baseTableName; - referenceColumn = columnName; // dept_code - logger.info(`참조 테이블 추론: ${columnName} -> ${referenceTable}`); - } else if (columnName.endsWith("_id")) { - // user_id -> user_info - const baseTableName = columnName.replace("_id", "_info"); - referenceTable = baseTableName; - referenceColumn = columnName; // user_id - logger.info(`참조 테이블 추론: ${columnName} -> ${referenceTable}`); - } - } - - if (!referenceTable) { + // webType 확인 + if (columnInfo.web_type !== "entity") { return res.status(400).json({ success: false, - message: `컬럼 '${tableName}.${columnName}'에 참조 테이블이 설정되지 않았습니다.`, + message: `컬럼 '${tableName}.${columnName}'은 entity 타입이 아닙니다. webType: ${columnInfo.web_type}`, }); } - // 테이블별 적절한 표시 컬럼 설정 - if (referenceTable === "dept_info") { - displayColumn = "dept_name"; - } else if (referenceTable === "user_info") { - displayColumn = "user_name"; + // column_labels에서 직접 참조 정보 가져오기 + const referenceTable = columnInfo.reference_table; + const referenceColumn = columnInfo.reference_column; + const displayColumn = columnInfo.display_column || "name"; + + // entity 타입인데 참조 테이블 정보가 없으면 오류 + if (!referenceTable || !referenceColumn) { + return res.status(400).json({ + success: false, + message: `Entity 타입 컬럼 '${tableName}.${columnName}'에 참조 테이블 정보가 설정되지 않았습니다. column_labels에서 reference_table과 reference_column을 확인해주세요.`, + }); } - // referenceColumn이 없으면 테이블별 Primary Key로 설정 - if (!referenceColumn) { - if (referenceTable === "dept_info") { - referenceColumn = "dept_code"; - } else if (referenceTable === "user_info") { - referenceColumn = "user_id"; - } else { - referenceColumn = "id"; // 기본값 - } + // 참조 테이블이 실제로 존재하는지 확인 + try { + await prisma.$queryRawUnsafe(`SELECT 1 FROM ${referenceTable} LIMIT 1`); + logger.info( + `Entity 참조 설정: ${tableName}.${columnName} -> ${referenceTable}.${referenceColumn} (display: ${displayColumn})` + ); + } catch (error) { + logger.error( + `참조 테이블 '${referenceTable}'이 존재하지 않습니다:`, + error + ); + return res.status(400).json({ + success: false, + message: `참조 테이블 '${referenceTable}'이 존재하지 않습니다. column_labels의 reference_table 설정을 확인해주세요.`, + }); } // 동적 쿼리로 참조 데이터 조회 @@ -140,28 +121,24 @@ export class EntityReferenceController { }) ); - const result: EntityReferenceData = { - options, - referenceInfo: { - referenceTable, - referenceColumn: "id", - displayColumn, - }, - }; - logger.info(`엔티티 참조 데이터 조회 완료: ${options.length}개 항목`); return res.json({ success: true, - message: "엔티티 참조 데이터 조회 성공", - data: result, + data: { + options, + referenceInfo: { + referenceTable, + referenceColumn, + displayColumn, + }, + }, }); } catch (error) { logger.error("엔티티 참조 데이터 조회 실패:", error); return res.status(500).json({ success: false, message: "엔티티 참조 데이터 조회 중 오류가 발생했습니다.", - error: error instanceof Error ? error.message : "Unknown error", }); } } @@ -180,54 +157,51 @@ export class EntityReferenceController { search, }); - // code_info 테이블에서 공통 코드 조회 - let whereClause: any = { + // code_info 테이블에서 코드 데이터 조회 + let whereCondition: any = { code_category: codeCategory, is_active: "Y", }; - // 검색 조건 추가 if (search) { - whereClause.OR = [ - { code_value: { contains: String(search), mode: "insensitive" } }, - { code_name: { contains: String(search), mode: "insensitive" } }, - ]; + whereCondition.code_name = { + contains: String(search), + mode: "insensitive", + }; } - const codes = await prisma.code_info.findMany({ - where: whereClause, - orderBy: { sort_order: "asc" }, - take: Number(limit), + const codeData = await prisma.code_info.findMany({ + where: whereCondition, select: { code_value: true, code_name: true, }, + orderBy: { + code_name: "asc", + }, + take: Number(limit), }); // 옵션 형태로 변환 - const options: EntityReferenceOption[] = codes.map((code: any) => ({ - value: code.code_value || "", - label: code.code_name || "", + const options: EntityReferenceOption[] = codeData.map((code) => ({ + value: code.code_value, + label: code.code_name, })); - const result: CodeReferenceData = { - options, - codeCategory, - }; - logger.info(`공통 코드 데이터 조회 완료: ${options.length}개 항목`); return res.json({ success: true, - message: "공통 코드 데이터 조회 성공", - data: result, + data: { + options, + codeCategory, + }, }); } catch (error) { logger.error("공통 코드 데이터 조회 실패:", error); return res.status(500).json({ success: false, message: "공통 코드 데이터 조회 중 오류가 발생했습니다.", - error: error instanceof Error ? error.message : "Unknown error", }); } } diff --git a/frontend/components/dataflow/condition/WebTypeInput.tsx b/frontend/components/dataflow/condition/WebTypeInput.tsx index 7b96b6af..55c4310f 100644 --- a/frontend/components/dataflow/condition/WebTypeInput.tsx +++ b/frontend/components/dataflow/condition/WebTypeInput.tsx @@ -33,6 +33,8 @@ export const WebTypeInput: React.FC = ({ placeholder, tableName, }) => { + // tableName은 props 또는 column.tableName에서 가져옴 + const effectiveTableName = tableName || (column as ColumnInfo & { tableName?: string }).tableName; const webType = column.webType || "text"; const [entityOptions, setEntityOptions] = useState([]); const [codeOptions, setCodeOptions] = useState([]); @@ -79,20 +81,12 @@ export const WebTypeInput: React.FC = ({ const loadEntityData = useCallback(async () => { try { setLoading(true); - // tableName이 없으면 referenceTable에서 추론 (dept_code -> dept_info) - const effectiveTableName = - tableName || - (() => { - if (column.columnName?.endsWith("_code")) { - return column.columnName.replace("_code", "_info"); - } - if (column.columnName?.endsWith("_id")) { - return column.columnName.replace("_id", "_info"); - } - return "unknown_table"; - })(); - console.log(`🔍 Entity API 호출: ${effectiveTableName}.${column.columnName}`); + // entity 타입은 반드시 effectiveTableName과 columnName이 있어야 함 + if (!effectiveTableName || !column.columnName) { + throw new Error("Entity 타입에는 tableName과 columnName이 필요합니다."); + } + const data = await EntityReferenceAPI.getEntityReferenceData(effectiveTableName, column.columnName, { limit: 100, }); @@ -102,7 +96,7 @@ export const WebTypeInput: React.FC = ({ } finally { setLoading(false); } - }, [tableName, column.columnName]); + }, [effectiveTableName, column.columnName]); const loadCodeData = useCallback(async () => { try { @@ -119,36 +113,41 @@ export const WebTypeInput: React.FC = ({ } }, [column.codeCategory, detailSettings.codeCategory, fallbackCodeCategory]); - // Entity 타입일 때 참조 데이터 로드 + // webType에 따른 데이터 로드 useEffect(() => { - // 디버깅: dept_code 필드의 정보 확인 - if (column.columnName === "dept_code") { - console.log("🔍 dept_code 필드 디버깅:", { + // 디버깅: entity 타입 필드 정보 확인 + if (column.columnName === "manager_name" || webType === "entity") { + console.log("🔍 Entity 필드 디버깅:", { columnName: column.columnName, webType: webType, - referenceTable: column.referenceTable, tableName: tableName, - shouldLoadEntity: (webType === "entity" || column.referenceTable) && tableName && column.columnName, - fullColumn: column, + effectiveTableName: effectiveTableName, + referenceTable: column.referenceTable, + referenceColumn: column.referenceColumn, + displayColumn: (column as any).displayColumn, + shouldLoadEntity: webType === "entity" && effectiveTableName && column.columnName, }); } - // webType이 entity이거나, referenceTable이 있으면 entity로 처리 - if ((webType === "entity" || column.referenceTable) && column.columnName) { - // tableName이 없으면 referenceTable에서 추론 - const effectiveTableName = tableName || (column.referenceTable ? "unknown" : null); - if (effectiveTableName) { - loadEntityData(); - } + if (webType === "entity" && effectiveTableName && column.columnName) { + // entity 타입: 다른 테이블 참조 + console.log("🚀 Entity 데이터 로드 시작:", effectiveTableName, column.columnName); + loadEntityData(); } else if (webType === "code" && (column.codeCategory || detailSettings.codeCategory || fallbackCodeCategory)) { + // code 타입: code_info 테이블에서 공통 코드 조회 loadCodeData(); } + // text 타입: 일반 텍스트 입력 + // file 타입: 파일 업로드 }, [ webType, - tableName, + effectiveTableName, column.columnName, column.codeCategory, column.referenceTable, + column.referenceColumn, + (column as any).displayColumn, + tableName, fallbackCodeCategory, detailSettings.codeCategory, loadEntityData, @@ -201,8 +200,8 @@ export const WebTypeInput: React.FC = ({ className, }; - // WebType별 렌더링 (referenceTable이 있으면 entity로 처리) - const actualWebType = webType === "entity" || column.referenceTable ? "entity" : webType; + // WebType별 렌더링 (column_labels의 webType을 정확히 따름) + const actualWebType = webType; switch (actualWebType) { case "text":