web_type에 따른 input 변화 구현
This commit is contained in:
parent
c3cb1a0033
commit
0bad11686e
|
|
@ -49,65 +49,46 @@ export class EntityReferenceController {
|
||||||
if (!columnInfo) {
|
if (!columnInfo) {
|
||||||
return res.status(404).json({
|
return res.status(404).json({
|
||||||
success: false,
|
success: false,
|
||||||
message: `컬럼 '${tableName}.${columnName}'을 찾을 수 없습니다.`,
|
message: `컬럼 정보를 찾을 수 없습니다: ${tableName}.${columnName}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// column_labels에서 참조 테이블 정보 가져오기
|
// webType 확인
|
||||||
let referenceTable = columnInfo.reference_table || "";
|
if (columnInfo.web_type !== "entity") {
|
||||||
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) {
|
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
success: false,
|
success: false,
|
||||||
message: `컬럼 '${tableName}.${columnName}'에 참조 테이블이 설정되지 않았습니다.`,
|
message: `컬럼 '${tableName}.${columnName}'은 entity 타입이 아닙니다. webType: ${columnInfo.web_type}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 테이블별 적절한 표시 컬럼 설정
|
// column_labels에서 직접 참조 정보 가져오기
|
||||||
if (referenceTable === "dept_info") {
|
const referenceTable = columnInfo.reference_table;
|
||||||
displayColumn = "dept_name";
|
const referenceColumn = columnInfo.reference_column;
|
||||||
} else if (referenceTable === "user_info") {
|
const displayColumn = columnInfo.display_column || "name";
|
||||||
displayColumn = "user_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) {
|
try {
|
||||||
if (referenceTable === "dept_info") {
|
await prisma.$queryRawUnsafe(`SELECT 1 FROM ${referenceTable} LIMIT 1`);
|
||||||
referenceColumn = "dept_code";
|
logger.info(
|
||||||
} else if (referenceTable === "user_info") {
|
`Entity 참조 설정: ${tableName}.${columnName} -> ${referenceTable}.${referenceColumn} (display: ${displayColumn})`
|
||||||
referenceColumn = "user_id";
|
);
|
||||||
} else {
|
} catch (error) {
|
||||||
referenceColumn = "id"; // 기본값
|
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}개 항목`);
|
logger.info(`엔티티 참조 데이터 조회 완료: ${options.length}개 항목`);
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: "엔티티 참조 데이터 조회 성공",
|
data: {
|
||||||
data: result,
|
options,
|
||||||
|
referenceInfo: {
|
||||||
|
referenceTable,
|
||||||
|
referenceColumn,
|
||||||
|
displayColumn,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("엔티티 참조 데이터 조회 실패:", error);
|
logger.error("엔티티 참조 데이터 조회 실패:", error);
|
||||||
return res.status(500).json({
|
return res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
message: "엔티티 참조 데이터 조회 중 오류가 발생했습니다.",
|
message: "엔티티 참조 데이터 조회 중 오류가 발생했습니다.",
|
||||||
error: error instanceof Error ? error.message : "Unknown error",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -180,54 +157,51 @@ export class EntityReferenceController {
|
||||||
search,
|
search,
|
||||||
});
|
});
|
||||||
|
|
||||||
// code_info 테이블에서 공통 코드 조회
|
// code_info 테이블에서 코드 데이터 조회
|
||||||
let whereClause: any = {
|
let whereCondition: any = {
|
||||||
code_category: codeCategory,
|
code_category: codeCategory,
|
||||||
is_active: "Y",
|
is_active: "Y",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 검색 조건 추가
|
|
||||||
if (search) {
|
if (search) {
|
||||||
whereClause.OR = [
|
whereCondition.code_name = {
|
||||||
{ code_value: { contains: String(search), mode: "insensitive" } },
|
contains: String(search),
|
||||||
{ code_name: { contains: String(search), mode: "insensitive" } },
|
mode: "insensitive",
|
||||||
];
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const codes = await prisma.code_info.findMany({
|
const codeData = await prisma.code_info.findMany({
|
||||||
where: whereClause,
|
where: whereCondition,
|
||||||
orderBy: { sort_order: "asc" },
|
|
||||||
take: Number(limit),
|
|
||||||
select: {
|
select: {
|
||||||
code_value: true,
|
code_value: true,
|
||||||
code_name: true,
|
code_name: true,
|
||||||
},
|
},
|
||||||
|
orderBy: {
|
||||||
|
code_name: "asc",
|
||||||
|
},
|
||||||
|
take: Number(limit),
|
||||||
});
|
});
|
||||||
|
|
||||||
// 옵션 형태로 변환
|
// 옵션 형태로 변환
|
||||||
const options: EntityReferenceOption[] = codes.map((code: any) => ({
|
const options: EntityReferenceOption[] = codeData.map((code) => ({
|
||||||
value: code.code_value || "",
|
value: code.code_value,
|
||||||
label: code.code_name || "",
|
label: code.code_name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result: CodeReferenceData = {
|
|
||||||
options,
|
|
||||||
codeCategory,
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.info(`공통 코드 데이터 조회 완료: ${options.length}개 항목`);
|
logger.info(`공통 코드 데이터 조회 완료: ${options.length}개 항목`);
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: "공통 코드 데이터 조회 성공",
|
data: {
|
||||||
data: result,
|
options,
|
||||||
|
codeCategory,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("공통 코드 데이터 조회 실패:", error);
|
logger.error("공통 코드 데이터 조회 실패:", error);
|
||||||
return res.status(500).json({
|
return res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
message: "공통 코드 데이터 조회 중 오류가 발생했습니다.",
|
message: "공통 코드 데이터 조회 중 오류가 발생했습니다.",
|
||||||
error: error instanceof Error ? error.message : "Unknown error",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ export const WebTypeInput: React.FC<WebTypeInputProps> = ({
|
||||||
placeholder,
|
placeholder,
|
||||||
tableName,
|
tableName,
|
||||||
}) => {
|
}) => {
|
||||||
|
// tableName은 props 또는 column.tableName에서 가져옴
|
||||||
|
const effectiveTableName = tableName || (column as ColumnInfo & { tableName?: string }).tableName;
|
||||||
const webType = column.webType || "text";
|
const webType = column.webType || "text";
|
||||||
const [entityOptions, setEntityOptions] = useState<EntityReferenceOption[]>([]);
|
const [entityOptions, setEntityOptions] = useState<EntityReferenceOption[]>([]);
|
||||||
const [codeOptions, setCodeOptions] = useState<EntityReferenceOption[]>([]);
|
const [codeOptions, setCodeOptions] = useState<EntityReferenceOption[]>([]);
|
||||||
|
|
@ -79,20 +81,12 @@ export const WebTypeInput: React.FC<WebTypeInputProps> = ({
|
||||||
const loadEntityData = useCallback(async () => {
|
const loadEntityData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
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, {
|
const data = await EntityReferenceAPI.getEntityReferenceData(effectiveTableName, column.columnName, {
|
||||||
limit: 100,
|
limit: 100,
|
||||||
});
|
});
|
||||||
|
|
@ -102,7 +96,7 @@ export const WebTypeInput: React.FC<WebTypeInputProps> = ({
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [tableName, column.columnName]);
|
}, [effectiveTableName, column.columnName]);
|
||||||
|
|
||||||
const loadCodeData = useCallback(async () => {
|
const loadCodeData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -119,36 +113,41 @@ export const WebTypeInput: React.FC<WebTypeInputProps> = ({
|
||||||
}
|
}
|
||||||
}, [column.codeCategory, detailSettings.codeCategory, fallbackCodeCategory]);
|
}, [column.codeCategory, detailSettings.codeCategory, fallbackCodeCategory]);
|
||||||
|
|
||||||
// Entity 타입일 때 참조 데이터 로드
|
// webType에 따른 데이터 로드
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 디버깅: dept_code 필드의 정보 확인
|
// 디버깅: entity 타입 필드 정보 확인
|
||||||
if (column.columnName === "dept_code") {
|
if (column.columnName === "manager_name" || webType === "entity") {
|
||||||
console.log("🔍 dept_code 필드 디버깅:", {
|
console.log("🔍 Entity 필드 디버깅:", {
|
||||||
columnName: column.columnName,
|
columnName: column.columnName,
|
||||||
webType: webType,
|
webType: webType,
|
||||||
referenceTable: column.referenceTable,
|
|
||||||
tableName: tableName,
|
tableName: tableName,
|
||||||
shouldLoadEntity: (webType === "entity" || column.referenceTable) && tableName && column.columnName,
|
effectiveTableName: effectiveTableName,
|
||||||
fullColumn: column,
|
referenceTable: column.referenceTable,
|
||||||
|
referenceColumn: column.referenceColumn,
|
||||||
|
displayColumn: (column as any).displayColumn,
|
||||||
|
shouldLoadEntity: webType === "entity" && effectiveTableName && column.columnName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// webType이 entity이거나, referenceTable이 있으면 entity로 처리
|
if (webType === "entity" && effectiveTableName && column.columnName) {
|
||||||
if ((webType === "entity" || column.referenceTable) && column.columnName) {
|
// entity 타입: 다른 테이블 참조
|
||||||
// tableName이 없으면 referenceTable에서 추론
|
console.log("🚀 Entity 데이터 로드 시작:", effectiveTableName, column.columnName);
|
||||||
const effectiveTableName = tableName || (column.referenceTable ? "unknown" : null);
|
loadEntityData();
|
||||||
if (effectiveTableName) {
|
|
||||||
loadEntityData();
|
|
||||||
}
|
|
||||||
} else if (webType === "code" && (column.codeCategory || detailSettings.codeCategory || fallbackCodeCategory)) {
|
} else if (webType === "code" && (column.codeCategory || detailSettings.codeCategory || fallbackCodeCategory)) {
|
||||||
|
// code 타입: code_info 테이블에서 공통 코드 조회
|
||||||
loadCodeData();
|
loadCodeData();
|
||||||
}
|
}
|
||||||
|
// text 타입: 일반 텍스트 입력
|
||||||
|
// file 타입: 파일 업로드
|
||||||
}, [
|
}, [
|
||||||
webType,
|
webType,
|
||||||
tableName,
|
effectiveTableName,
|
||||||
column.columnName,
|
column.columnName,
|
||||||
column.codeCategory,
|
column.codeCategory,
|
||||||
column.referenceTable,
|
column.referenceTable,
|
||||||
|
column.referenceColumn,
|
||||||
|
(column as any).displayColumn,
|
||||||
|
tableName,
|
||||||
fallbackCodeCategory,
|
fallbackCodeCategory,
|
||||||
detailSettings.codeCategory,
|
detailSettings.codeCategory,
|
||||||
loadEntityData,
|
loadEntityData,
|
||||||
|
|
@ -201,8 +200,8 @@ export const WebTypeInput: React.FC<WebTypeInputProps> = ({
|
||||||
className,
|
className,
|
||||||
};
|
};
|
||||||
|
|
||||||
// WebType별 렌더링 (referenceTable이 있으면 entity로 처리)
|
// WebType별 렌더링 (column_labels의 webType을 정확히 따름)
|
||||||
const actualWebType = webType === "entity" || column.referenceTable ? "entity" : webType;
|
const actualWebType = webType;
|
||||||
|
|
||||||
switch (actualWebType) {
|
switch (actualWebType) {
|
||||||
case "text":
|
case "text":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue