import { PrismaClient } from "@prisma/client"; import { logger } from "../utils/logger"; const prisma = new PrismaClient(); // 외부 호출 설정 타입 정의 export interface ExternalCallConfig { id?: number; config_name: string; call_type: string; api_type?: string; config_data: any; description?: string; company_code?: string; is_active?: string; created_by?: string; updated_by?: string; } export interface ExternalCallConfigFilter { company_code?: string; call_type?: string; api_type?: string; is_active?: string; search?: string; } export class ExternalCallConfigService { /** * 외부 호출 설정 목록 조회 */ async getConfigs( filter: ExternalCallConfigFilter = {} ): Promise { try { logger.info("=== 외부 호출 설정 목록 조회 시작 ==="); logger.info(`필터 조건:`, filter); const where: any = {}; // 회사 코드 필터 if (filter.company_code) { where.company_code = filter.company_code; } // 호출 타입 필터 if (filter.call_type) { where.call_type = filter.call_type; } // API 타입 필터 if (filter.api_type) { where.api_type = filter.api_type; } // 활성화 상태 필터 if (filter.is_active) { where.is_active = filter.is_active; } // 검색어 필터 (설정 이름 또는 설명) if (filter.search) { where.OR = [ { config_name: { contains: filter.search, mode: "insensitive" } }, { description: { contains: filter.search, mode: "insensitive" } }, ]; } const configs = await prisma.external_call_configs.findMany({ where, orderBy: [{ is_active: "desc" }, { created_date: "desc" }], }); logger.info(`외부 호출 설정 조회 결과: ${configs.length}개`); return configs as ExternalCallConfig[]; } catch (error) { logger.error("외부 호출 설정 목록 조회 실패:", error); throw error; } } /** * 외부 호출 설정 단일 조회 */ async getConfigById(id: number): Promise { try { logger.info(`=== 외부 호출 설정 조회: ID ${id} ===`); const config = await prisma.external_call_configs.findUnique({ where: { id }, }); if (config) { logger.info(`외부 호출 설정 조회 성공: ${config.config_name}`); } else { logger.warn(`외부 호출 설정을 찾을 수 없음: ID ${id}`); } return config as ExternalCallConfig | null; } catch (error) { logger.error(`외부 호출 설정 조회 실패 (ID: ${id}):`, error); throw error; } } /** * 외부 호출 설정 생성 */ async createConfig(data: ExternalCallConfig): Promise { try { logger.info("=== 외부 호출 설정 생성 시작 ==="); logger.info(`생성할 설정:`, { config_name: data.config_name, call_type: data.call_type, api_type: data.api_type, company_code: data.company_code || "*", }); // 중복 이름 검사 const existingConfig = await prisma.external_call_configs.findFirst({ where: { config_name: data.config_name, company_code: data.company_code || "*", is_active: "Y", }, }); if (existingConfig) { throw new Error( `동일한 이름의 외부 호출 설정이 이미 존재합니다: ${data.config_name}` ); } const newConfig = await prisma.external_call_configs.create({ data: { config_name: data.config_name, call_type: data.call_type, api_type: data.api_type, config_data: data.config_data, description: data.description, company_code: data.company_code || "*", is_active: data.is_active || "Y", created_by: data.created_by, updated_by: data.updated_by, }, }); logger.info( `외부 호출 설정 생성 완료: ${newConfig.config_name} (ID: ${newConfig.id})` ); return newConfig as ExternalCallConfig; } catch (error) { logger.error("외부 호출 설정 생성 실패:", error); throw error; } } /** * 외부 호출 설정 수정 */ async updateConfig( id: number, data: Partial ): Promise { try { logger.info(`=== 외부 호출 설정 수정 시작: ID ${id} ===`); // 기존 설정 존재 확인 const existingConfig = await this.getConfigById(id); if (!existingConfig) { throw new Error(`외부 호출 설정을 찾을 수 없습니다: ID ${id}`); } // 이름 중복 검사 (다른 설정과 중복되는지) if (data.config_name && data.config_name !== existingConfig.config_name) { const duplicateConfig = await prisma.external_call_configs.findFirst({ where: { config_name: data.config_name, company_code: data.company_code || existingConfig.company_code, is_active: "Y", id: { not: id }, }, }); if (duplicateConfig) { throw new Error( `동일한 이름의 외부 호출 설정이 이미 존재합니다: ${data.config_name}` ); } } const updatedConfig = await prisma.external_call_configs.update({ where: { id }, data: { ...(data.config_name && { config_name: data.config_name }), ...(data.call_type && { call_type: data.call_type }), ...(data.api_type !== undefined && { api_type: data.api_type }), ...(data.config_data && { config_data: data.config_data }), ...(data.description !== undefined && { description: data.description, }), ...(data.company_code && { company_code: data.company_code }), ...(data.is_active && { is_active: data.is_active }), ...(data.updated_by && { updated_by: data.updated_by }), updated_date: new Date(), }, }); logger.info( `외부 호출 설정 수정 완료: ${updatedConfig.config_name} (ID: ${id})` ); return updatedConfig as ExternalCallConfig; } catch (error) { logger.error(`외부 호출 설정 수정 실패 (ID: ${id}):`, error); throw error; } } /** * 외부 호출 설정 삭제 (논리 삭제) */ async deleteConfig(id: number, deletedBy?: string): Promise { try { logger.info(`=== 외부 호출 설정 삭제 시작: ID ${id} ===`); // 기존 설정 존재 확인 const existingConfig = await this.getConfigById(id); if (!existingConfig) { throw new Error(`외부 호출 설정을 찾을 수 없습니다: ID ${id}`); } // 논리 삭제 (is_active = 'N') await prisma.external_call_configs.update({ where: { id }, data: { is_active: "N", updated_by: deletedBy, updated_date: new Date(), }, }); logger.info( `외부 호출 설정 삭제 완료: ${existingConfig.config_name} (ID: ${id})` ); } catch (error) { logger.error(`외부 호출 설정 삭제 실패 (ID: ${id}):`, error); throw error; } } /** * 외부 호출 설정 테스트 */ async testConfig(id: number): Promise<{ success: boolean; message: string }> { try { logger.info(`=== 외부 호출 설정 테스트 시작: ID ${id} ===`); const config = await this.getConfigById(id); if (!config) { throw new Error(`외부 호출 설정을 찾을 수 없습니다: ID ${id}`); } // TODO: ExternalCallService를 사용하여 실제 테스트 호출 // 현재는 기본적인 검증만 수행 const configData = config.config_data as any; let isValid = true; let validationMessage = ""; switch (config.api_type) { case "discord": if (!configData.webhookUrl) { isValid = false; validationMessage = "Discord 웹훅 URL이 필요합니다."; } break; case "slack": if (!configData.webhookUrl) { isValid = false; validationMessage = "Slack 웹훅 URL이 필요합니다."; } break; case "kakao-talk": if (!configData.accessToken) { isValid = false; validationMessage = "카카오톡 액세스 토큰이 필요합니다."; } break; default: if (config.call_type === "rest-api" && !configData.url) { isValid = false; validationMessage = "API URL이 필요합니다."; } } if (!isValid) { logger.warn(`외부 호출 설정 테스트 실패: ${validationMessage}`); return { success: false, message: validationMessage }; } logger.info(`외부 호출 설정 테스트 성공: ${config.config_name}`); return { success: true, message: "설정이 유효합니다." }; } catch (error) { logger.error(`외부 호출 설정 테스트 실패 (ID: ${id}):`, error); return { success: false, message: error instanceof Error ? error.message : "테스트 실패", }; } } } export default new ExternalCallConfigService();