192 lines
5.4 KiB
TypeScript
192 lines
5.4 KiB
TypeScript
|
|
import { Request, Response } from "express";
|
||
|
|
import { PrismaClient } from "@prisma/client";
|
||
|
|
import { logger } from "../utils/logger";
|
||
|
|
|
||
|
|
const prisma = new PrismaClient();
|
||
|
|
|
||
|
|
export interface EntityReferenceOption {
|
||
|
|
value: string;
|
||
|
|
label: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface EntityReferenceData {
|
||
|
|
options: EntityReferenceOption[];
|
||
|
|
referenceInfo: {
|
||
|
|
referenceTable: string;
|
||
|
|
referenceColumn: string;
|
||
|
|
displayColumn: string | null;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface CodeReferenceData {
|
||
|
|
options: EntityReferenceOption[];
|
||
|
|
codeCategory: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export class EntityReferenceController {
|
||
|
|
/**
|
||
|
|
* 엔티티 참조 데이터 조회
|
||
|
|
* GET /api/entity-reference/:tableName/:columnName
|
||
|
|
*/
|
||
|
|
static async getEntityReferenceData(req: Request, res: Response) {
|
||
|
|
try {
|
||
|
|
const { tableName, columnName } = req.params;
|
||
|
|
const { limit = 100, search } = req.query;
|
||
|
|
|
||
|
|
logger.info(`엔티티 참조 데이터 조회 요청: ${tableName}.${columnName}`, {
|
||
|
|
limit,
|
||
|
|
search,
|
||
|
|
});
|
||
|
|
|
||
|
|
// 컬럼 정보 조회
|
||
|
|
const columnInfo = await prisma.column_labels.findFirst({
|
||
|
|
where: {
|
||
|
|
table_name: tableName,
|
||
|
|
column_name: columnName,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!columnInfo) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: `컬럼 '${tableName}.${columnName}'을 찾을 수 없습니다.`,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// detailSettings에서 참조 테이블 정보 추출
|
||
|
|
let referenceTable = "";
|
||
|
|
let displayColumn = "name";
|
||
|
|
|
||
|
|
try {
|
||
|
|
if (columnInfo.detail_settings) {
|
||
|
|
const detailSettings = JSON.parse(columnInfo.detail_settings);
|
||
|
|
referenceTable = detailSettings.referenceTable || "";
|
||
|
|
displayColumn = detailSettings.displayColumn || "name";
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
logger.warn("detailSettings 파싱 실패:", error);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!referenceTable) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: `컬럼 '${columnName}'에 참조 테이블이 설정되지 않았습니다.`,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 동적 쿼리로 참조 데이터 조회
|
||
|
|
let query = `SELECT id, ${displayColumn} as display_name FROM ${referenceTable}`;
|
||
|
|
const queryParams: any[] = [];
|
||
|
|
|
||
|
|
// 검색 조건 추가
|
||
|
|
if (search) {
|
||
|
|
query += ` WHERE ${displayColumn} ILIKE $1`;
|
||
|
|
queryParams.push(`%${search}%`);
|
||
|
|
}
|
||
|
|
|
||
|
|
query += ` ORDER BY ${displayColumn} LIMIT $${queryParams.length + 1}`;
|
||
|
|
queryParams.push(Number(limit));
|
||
|
|
|
||
|
|
const referenceData = await prisma.$queryRawUnsafe(query, ...queryParams);
|
||
|
|
|
||
|
|
// 옵션 형태로 변환
|
||
|
|
const options: EntityReferenceOption[] = (referenceData as any[]).map(
|
||
|
|
(row) => ({
|
||
|
|
value: String(row.id),
|
||
|
|
label: String(row.display_name || row.id),
|
||
|
|
})
|
||
|
|
);
|
||
|
|
|
||
|
|
const result: EntityReferenceData = {
|
||
|
|
options,
|
||
|
|
referenceInfo: {
|
||
|
|
referenceTable,
|
||
|
|
referenceColumn: "id",
|
||
|
|
displayColumn,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
logger.info(`엔티티 참조 데이터 조회 완료: ${options.length}개 항목`);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
message: "엔티티 참조 데이터 조회 성공",
|
||
|
|
data: result,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("엔티티 참조 데이터 조회 실패:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "엔티티 참조 데이터 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 공통 코드 데이터 조회
|
||
|
|
* GET /api/entity-reference/code/:codeCategory
|
||
|
|
*/
|
||
|
|
static async getCodeData(req: Request, res: Response) {
|
||
|
|
try {
|
||
|
|
const { codeCategory } = req.params;
|
||
|
|
const { limit = 100, search } = req.query;
|
||
|
|
|
||
|
|
logger.info(`공통 코드 데이터 조회 요청: ${codeCategory}`, {
|
||
|
|
limit,
|
||
|
|
search,
|
||
|
|
});
|
||
|
|
|
||
|
|
// code_info 테이블에서 공통 코드 조회
|
||
|
|
let whereClause: 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" } },
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
const codes = await prisma.code_info.findMany({
|
||
|
|
where: whereClause,
|
||
|
|
orderBy: { sort_order: "asc" },
|
||
|
|
take: Number(limit),
|
||
|
|
select: {
|
||
|
|
code_value: true,
|
||
|
|
code_name: true,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
// 옵션 형태로 변환
|
||
|
|
const options: EntityReferenceOption[] = codes.map((code: any) => ({
|
||
|
|
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,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("공통 코드 데이터 조회 실패:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "공통 코드 데이터 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|