import { Request, Response } from "express"; import { logger } from "../utils/logger"; import { AuthenticatedRequest } from "../types/auth"; import { ApiResponse } from "../types/common"; import { DataflowService } from "../services/dataflowService"; /** * 테이블 관계 생성 */ export async function createTableRelationship( req: AuthenticatedRequest, res: Response ): Promise { try { logger.info("=== 테이블 관계 생성 시작 ==="); const { relationshipName, fromTableName, fromColumnName, toTableName, toColumnName, relationshipType, connectionType, settings, } = req.body; // 필수 필드 검증 if ( !relationshipName || !fromTableName || !fromColumnName || !toTableName || !toColumnName ) { const response: ApiResponse = { success: false, message: "필수 필드가 누락되었습니다.", error: { code: "MISSING_REQUIRED_FIELDS", details: "relationshipName, fromTableName, fromColumnName, toTableName, toColumnName는 필수입니다.", }, }; res.status(400).json(response); return; } // 사용자 정보에서 회사 코드 가져오기 const companyCode = (req.user as any)?.company_code || "*"; const userId = (req.user as any)?.userId || "system"; const dataflowService = new DataflowService(); const relationship = await dataflowService.createTableRelationship({ relationshipName, fromTableName, fromColumnName, toTableName, toColumnName, relationshipType: relationshipType || "one-to-one", connectionType: connectionType || "simple-key", companyCode, settings: settings || {}, createdBy: userId, }); logger.info(`테이블 관계 생성 완료: ${relationship.relationship_id}`); const response: ApiResponse = { success: true, message: "테이블 관계가 성공적으로 생성되었습니다.", data: relationship, }; res.status(201).json(response); } catch (error) { logger.error("테이블 관계 생성 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "테이블 관계 생성 중 오류가 발생했습니다.", error: { code: "TABLE_RELATIONSHIP_CREATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } /** * 테이블 관계 목록 조회 (회사별) */ export async function getTableRelationships( req: AuthenticatedRequest, res: Response ): Promise { try { logger.info("=== 테이블 관계 목록 조회 시작 ==="); // 사용자 정보에서 회사 코드 가져오기 const companyCode = (req.user as any)?.company_code || "*"; const dataflowService = new DataflowService(); const relationships = await dataflowService.getTableRelationships(companyCode); logger.info(`테이블 관계 목록 조회 완료: ${relationships.length}개`); const response: ApiResponse = { success: true, message: "테이블 관계 목록을 성공적으로 조회했습니다.", data: relationships, }; res.status(200).json(response); } catch (error) { logger.error("테이블 관계 목록 조회 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "테이블 관계 목록 조회 중 오류가 발생했습니다.", error: { code: "TABLE_RELATIONSHIPS_LIST_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } /** * 테이블 관계 수정 */ export async function updateTableRelationship( req: AuthenticatedRequest, res: Response ): Promise { try { logger.info("=== 테이블 관계 수정 시작 ==="); const { relationshipId } = req.params; const updateData = req.body; if (!relationshipId) { const response: ApiResponse = { success: false, message: "관계 ID가 필요합니다.", error: { code: "MISSING_RELATIONSHIP_ID", details: "relationshipId 파라미터가 누락되었습니다.", }, }; res.status(400).json(response); return; } // 사용자 정보에서 회사 코드와 사용자 ID 가져오기 const companyCode = (req.user as any)?.company_code || "*"; const userId = (req.user as any)?.userId || "system"; const dataflowService = new DataflowService(); const relationship = await dataflowService.updateTableRelationship( parseInt(relationshipId), { ...updateData, updatedBy: userId, }, companyCode ); if (!relationship) { const response: ApiResponse = { success: false, message: "테이블 관계를 찾을 수 없습니다.", error: { code: "TABLE_RELATIONSHIP_NOT_FOUND", details: `관계 ID ${relationshipId}를 찾을 수 없습니다.`, }, }; res.status(404).json(response); return; } logger.info(`테이블 관계 수정 완료: ${relationshipId}`); const response: ApiResponse = { success: true, message: "테이블 관계가 성공적으로 수정되었습니다.", data: relationship, }; res.status(200).json(response); } catch (error) { logger.error("테이블 관계 수정 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "테이블 관계 수정 중 오류가 발생했습니다.", error: { code: "TABLE_RELATIONSHIP_UPDATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } /** * 테이블 관계 삭제 */ export async function deleteTableRelationship( req: AuthenticatedRequest, res: Response ): Promise { try { logger.info("=== 테이블 관계 삭제 시작 ==="); const { relationshipId } = req.params; if (!relationshipId) { const response: ApiResponse = { success: false, message: "관계 ID가 필요합니다.", error: { code: "MISSING_RELATIONSHIP_ID", details: "relationshipId 파라미터가 누락되었습니다.", }, }; res.status(400).json(response); return; } // 사용자 정보에서 회사 코드 가져오기 const companyCode = (req.user as any)?.company_code || "*"; const dataflowService = new DataflowService(); const success = await dataflowService.deleteTableRelationship( parseInt(relationshipId), companyCode ); if (!success) { const response: ApiResponse = { success: false, message: "테이블 관계를 찾을 수 없습니다.", error: { code: "TABLE_RELATIONSHIP_NOT_FOUND", details: `관계 ID ${relationshipId}를 찾을 수 없습니다.`, }, }; res.status(404).json(response); return; } logger.info(`테이블 관계 삭제 완료: ${relationshipId}`); const response: ApiResponse = { success: true, message: "테이블 관계가 성공적으로 삭제되었습니다.", }; res.status(200).json(response); } catch (error) { logger.error("테이블 관계 삭제 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "테이블 관계 삭제 중 오류가 발생했습니다.", error: { code: "TABLE_RELATIONSHIP_DELETE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } /** * 특정 테이블 관계 조회 */ export async function getTableRelationship( req: AuthenticatedRequest, res: Response ): Promise { try { logger.info("=== 테이블 관계 조회 시작 ==="); const { relationshipId } = req.params; if (!relationshipId) { const response: ApiResponse = { success: false, message: "관계 ID가 필요합니다.", error: { code: "MISSING_RELATIONSHIP_ID", details: "relationshipId 파라미터가 누락되었습니다.", }, }; res.status(400).json(response); return; } // 사용자 정보에서 회사 코드 가져오기 const companyCode = (req.user as any)?.company_code || "*"; const dataflowService = new DataflowService(); const relationship = await dataflowService.getTableRelationship( parseInt(relationshipId), companyCode ); if (!relationship) { const response: ApiResponse = { success: false, message: "테이블 관계를 찾을 수 없습니다.", error: { code: "TABLE_RELATIONSHIP_NOT_FOUND", details: `관계 ID ${relationshipId}를 찾을 수 없습니다.`, }, }; res.status(404).json(response); return; } logger.info(`테이블 관계 조회 완료: ${relationshipId}`); const response: ApiResponse = { success: true, message: "테이블 관계를 성공적으로 조회했습니다.", data: relationship, }; res.status(200).json(response); } catch (error) { logger.error("테이블 관계 조회 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "테이블 관계 조회 중 오류가 발생했습니다.", error: { code: "TABLE_RELATIONSHIP_GET_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } // ==================== 데이터 연결 관리 API ==================== /** * 데이터 관계 연결 생성 */ export async function createDataLink( req: Request, res: Response ): Promise { try { const { relationshipId, fromTableName, fromColumnName, toTableName, toColumnName, connectionType, bridgeData, } = req.body; // 필수 필드 검증 if ( !relationshipId || !fromTableName || !fromColumnName || !toTableName || !toColumnName || !connectionType ) { const response: ApiResponse = { success: false, message: "필수 필드가 누락되었습니다.", error: { code: "MISSING_REQUIRED_FIELDS", details: "필수 필드: relationshipId, fromTableName, fromColumnName, toTableName, toColumnName, connectionType", }, }; res.status(400).json(response); return; } const userInfo = (req as any).user; const companyCode = userInfo?.company_code || "*"; const createdBy = userInfo?.userId || "system"; const dataflowService = new DataflowService(); const bridge = await dataflowService.createDataLink({ relationshipId, fromTableName, fromColumnName, toTableName, toColumnName, connectionType, companyCode, bridgeData, createdBy, }); const response: ApiResponse = { success: true, message: "데이터 연결이 성공적으로 생성되었습니다.", data: bridge, }; res.status(201).json(response); } catch (error) { logger.error("데이터 연결 생성 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "데이터 연결 생성 중 오류가 발생했습니다.", error: { code: "DATA_LINK_CREATE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } /** * 관계별 연결된 데이터 조회 */ export async function getLinkedDataByRelationship( req: Request, res: Response ): Promise { try { const relationshipId = parseInt(req.params.relationshipId); if (!relationshipId || isNaN(relationshipId)) { const response: ApiResponse = { success: false, message: "유효하지 않은 관계 ID입니다.", error: { code: "INVALID_RELATIONSHIP_ID", details: "관계 ID는 숫자여야 합니다.", }, }; res.status(400).json(response); return; } const userInfo = (req as any).user; const companyCode = userInfo?.company_code || "*"; const dataflowService = new DataflowService(); const linkedData = await dataflowService.getLinkedDataByRelationship( relationshipId, companyCode ); const response: ApiResponse = { success: true, message: "연결된 데이터를 성공적으로 조회했습니다.", data: linkedData, }; res.status(200).json(response); } catch (error) { logger.error("연결된 데이터 조회 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "연결된 데이터 조회 중 오류가 발생했습니다.", error: { code: "LINKED_DATA_GET_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } /** * 데이터 연결 삭제 */ export async function deleteDataLink( req: Request, res: Response ): Promise { try { const bridgeId = parseInt(req.params.bridgeId); if (!bridgeId || isNaN(bridgeId)) { const response: ApiResponse = { success: false, message: "유효하지 않은 Bridge ID입니다.", error: { code: "INVALID_BRIDGE_ID", details: "Bridge ID는 숫자여야 합니다.", }, }; res.status(400).json(response); return; } const userInfo = (req as any).user; const companyCode = userInfo?.company_code || "*"; const deletedBy = userInfo?.userId || "system"; const dataflowService = new DataflowService(); await dataflowService.deleteDataLink(bridgeId, companyCode, deletedBy); const response: ApiResponse = { success: true, message: "데이터 연결이 성공적으로 삭제되었습니다.", data: null, }; res.status(200).json(response); } catch (error) { logger.error("데이터 연결 삭제 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "데이터 연결 삭제 중 오류가 발생했습니다.", error: { code: "DATA_LINK_DELETE_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } } // ==================== 테이블 데이터 조회 ==================== /** * 테이블 실제 데이터 조회 (페이징) * GET /api/dataflow/table-data/:tableName */ export async function getTableData(req: Request, res: Response): Promise { try { const { tableName } = req.params; const { page = "1", limit = "10", search = "", searchColumn = "", } = req.query; if (!tableName) { const response: ApiResponse = { success: false, message: "테이블명이 필요합니다.", error: { code: "MISSING_TABLE_NAME", details: "테이블명을 제공해주세요.", }, }; res.status(400).json(response); return; } const pageNum = parseInt(page as string) || 1; const limitNum = parseInt(limit as string) || 10; const userInfo = (req as any).user; const companyCode = userInfo?.company_code || "*"; const dataflowService = new DataflowService(); const result = await dataflowService.getTableData( tableName, pageNum, limitNum, search as string, searchColumn as string, companyCode ); const response: ApiResponse = { success: true, message: "테이블 데이터를 성공적으로 조회했습니다.", data: result, }; res.status(200).json(response); } catch (error) { logger.error("테이블 데이터 조회 중 오류 발생:", error); const response: ApiResponse = { success: false, message: "테이블 데이터 조회 중 오류가 발생했습니다.", error: { code: "TABLE_DATA_GET_ERROR", details: error instanceof Error ? error.message : "Unknown error", }, }; res.status(500).json(response); } }