314 lines
9.3 KiB
TypeScript
314 lines
9.3 KiB
TypeScript
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<ExternalCallConfig[]> {
|
|
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<ExternalCallConfig | null> {
|
|
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<ExternalCallConfig> {
|
|
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<ExternalCallConfig>
|
|
): Promise<ExternalCallConfig> {
|
|
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<void> {
|
|
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();
|