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", }); } } }