ERP-node/backend-node/src/services/externalCallConfigService.ts

626 lines
18 KiB
TypeScript
Raw Normal View History

feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
import { query, queryOne } from "../database/db";
2025-09-17 17:14:59 +09:00
import { logger } from "../utils/logger";
// 외부 호출 설정 타입 정의
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);
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const conditions: string[] = [];
const params: any[] = [];
let paramIndex = 1;
2025-09-17 17:14:59 +09:00
// 회사 코드 필터
if (filter.company_code) {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
conditions.push(`company_code = $${paramIndex++}`);
params.push(filter.company_code);
2025-09-17 17:14:59 +09:00
}
// 호출 타입 필터
if (filter.call_type) {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
conditions.push(`call_type = $${paramIndex++}`);
params.push(filter.call_type);
2025-09-17 17:14:59 +09:00
}
// API 타입 필터
if (filter.api_type) {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
conditions.push(`api_type = $${paramIndex++}`);
params.push(filter.api_type);
2025-09-17 17:14:59 +09:00
}
// 활성화 상태 필터
if (filter.is_active) {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
conditions.push(`is_active = $${paramIndex++}`);
params.push(filter.is_active);
2025-09-17 17:14:59 +09:00
}
// 검색어 필터 (설정 이름 또는 설명)
if (filter.search) {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
conditions.push(
`(config_name ILIKE $${paramIndex} OR description ILIKE $${paramIndex})`
);
params.push(`%${filter.search}%`);
paramIndex++;
2025-09-17 17:14:59 +09:00
}
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const whereClause =
conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
const configs = await query<ExternalCallConfig>(
`SELECT * FROM external_call_configs
${whereClause}
ORDER BY is_active DESC, created_date DESC`,
params
);
2025-09-17 17:14:59 +09:00
logger.info(`외부 호출 설정 조회 결과: ${configs.length}`);
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
return configs;
2025-09-17 17:14:59 +09:00
} catch (error) {
logger.error("외부 호출 설정 목록 조회 실패:", error);
throw error;
}
}
/**
*
*/
async getConfigById(id: number): Promise<ExternalCallConfig | null> {
try {
logger.info(`=== 외부 호출 설정 조회: ID ${id} ===`);
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const config = await queryOne<ExternalCallConfig>(
`SELECT * FROM external_call_configs WHERE id = $1`,
[id]
);
2025-09-17 17:14:59 +09:00
if (config) {
logger.info(`외부 호출 설정 조회 성공: ${config.config_name}`);
} else {
logger.warn(`외부 호출 설정을 찾을 수 없음: ID ${id}`);
}
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
return config || null;
2025-09-17 17:14:59 +09:00
} 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 || "*",
});
// 중복 이름 검사
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const existingConfig = await queryOne<ExternalCallConfig>(
`SELECT * FROM external_call_configs
WHERE config_name = $1 AND company_code = $2 AND is_active = $3`,
[data.config_name, data.company_code || "*", "Y"]
);
2025-09-17 17:14:59 +09:00
if (existingConfig) {
throw new Error(
`동일한 이름의 외부 호출 설정이 이미 존재합니다: ${data.config_name}`
);
}
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const newConfig = await queryOne<ExternalCallConfig>(
`INSERT INTO external_call_configs
(config_name, call_type, api_type, config_data, description,
company_code, is_active, created_by, updated_by, created_date, updated_date)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW())
RETURNING *`,
[
data.config_name,
data.call_type,
data.api_type,
JSON.stringify(data.config_data),
data.description,
data.company_code || "*",
data.is_active || "Y",
data.created_by,
data.updated_by,
]
);
2025-09-17 17:14:59 +09:00
logger.info(
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
`외부 호출 설정 생성 완료: ${newConfig!.config_name} (ID: ${newConfig!.id})`
2025-09-17 17:14:59 +09:00
);
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
return newConfig!;
2025-09-17 17:14:59 +09:00
} 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) {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const duplicateConfig = await queryOne<ExternalCallConfig>(
`SELECT * FROM external_call_configs
WHERE config_name = $1 AND company_code = $2 AND is_active = $3 AND id != $4`,
[
data.config_name,
data.company_code || existingConfig.company_code,
"Y",
id,
]
);
2025-09-17 17:14:59 +09:00
if (duplicateConfig) {
throw new Error(
`동일한 이름의 외부 호출 설정이 이미 존재합니다: ${data.config_name}`
);
}
}
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
// 동적 UPDATE 쿼리 생성
const updateFields: string[] = ["updated_date = NOW()"];
const params: any[] = [];
let paramIndex = 1;
if (data.config_name) {
updateFields.push(`config_name = $${paramIndex++}`);
params.push(data.config_name);
}
if (data.call_type) {
updateFields.push(`call_type = $${paramIndex++}`);
params.push(data.call_type);
}
if (data.api_type !== undefined) {
updateFields.push(`api_type = $${paramIndex++}`);
params.push(data.api_type);
}
if (data.config_data) {
updateFields.push(`config_data = $${paramIndex++}`);
params.push(JSON.stringify(data.config_data));
}
if (data.description !== undefined) {
updateFields.push(`description = $${paramIndex++}`);
params.push(data.description);
}
if (data.company_code) {
updateFields.push(`company_code = $${paramIndex++}`);
params.push(data.company_code);
}
if (data.is_active) {
updateFields.push(`is_active = $${paramIndex++}`);
params.push(data.is_active);
}
if (data.updated_by) {
updateFields.push(`updated_by = $${paramIndex++}`);
params.push(data.updated_by);
}
params.push(id);
const updatedConfig = await queryOne<ExternalCallConfig>(
`UPDATE external_call_configs
SET ${updateFields.join(", ")}
WHERE id = $${paramIndex}
RETURNING *`,
params
);
2025-09-17 17:14:59 +09:00
logger.info(
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
`외부 호출 설정 수정 완료: ${updatedConfig!.config_name} (ID: ${id})`
2025-09-17 17:14:59 +09:00
);
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
return updatedConfig!;
2025-09-17 17:14:59 +09:00
} 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')
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
await query(
`UPDATE external_call_configs
SET is_active = $1, updated_by = $2, updated_date = NOW()
WHERE id = $3`,
["N", deletedBy, id]
);
2025-09-17 17:14:59 +09:00
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 : "테스트 실패",
};
}
}
2025-09-29 12:17:10 +09:00
/**
* 🔥
*/
async executeConfigWithDataMapping(
configId: number,
requestData: Record<string, any>,
contextData: Record<string, any>
): Promise<{
success: boolean;
message: string;
data?: any;
executionTime: number;
error?: string;
}> {
const startTime = performance.now();
try {
logger.info(`=== 외부호출 실행 시작 (ID: ${configId}) ===`);
// 1. 설정 조회
const config = await this.getConfigById(configId);
if (!config) {
throw new Error(`외부호출 설정을 찾을 수 없습니다: ${configId}`);
}
// 2. 데이터 매핑 처리 (있는 경우)
let processedData = requestData;
const configData = config.config_data as any;
if (configData?.dataMappingConfig?.outboundMapping) {
logger.info("Outbound 데이터 매핑 처리 중...");
processedData = await this.processOutboundMapping(
configData.dataMappingConfig.outboundMapping,
requestData
);
}
// 3. 외부 API 호출
const callResult = await this.executeExternalCall(
config,
processedData,
contextData
);
2025-09-29 12:17:10 +09:00
// 4. Inbound 데이터 매핑 처리 (있는 경우)
if (callResult.success && configData?.dataMappingConfig?.inboundMapping) {
2025-09-29 12:17:10 +09:00
logger.info("Inbound 데이터 매핑 처리 중...");
await this.processInboundMapping(
configData.dataMappingConfig.inboundMapping,
callResult.data
);
}
const executionTime = performance.now() - startTime;
logger.info(`외부호출 실행 완료: ${executionTime.toFixed(2)}ms`);
return {
success: callResult.success,
message: callResult.success
2025-09-29 12:17:10 +09:00
? `외부호출 '${config.config_name}' 실행 완료`
: `외부호출 '${config.config_name}' 실행 실패`,
data: callResult.data,
executionTime,
error: callResult.error,
};
} catch (error) {
const executionTime = performance.now() - startTime;
logger.error("외부호출 실행 실패:", error);
const errorMessage =
error instanceof Error ? error.message : "알 수 없는 오류";
2025-09-29 12:17:10 +09:00
return {
success: false,
message: `외부호출 실행 실패: ${errorMessage}`,
executionTime,
error: errorMessage,
};
}
}
/**
* 🔥 ( )
*/
async getConfigsForButtonControl(companyCode: string): Promise<
Array<{
id: string;
name: string;
description?: string;
apiUrl: string;
method: string;
hasDataMapping: boolean;
}>
> {
2025-09-29 12:17:10 +09:00
try {
feat: Phase 3.12 ExternalCallConfigService Raw Query 전환 완료 외부 호출 설정 관리 서비스의 모든 Prisma 호출을 Raw Query로 전환: ## 전환 완료 (8개 Prisma 호출) 1. **getConfigs()** - 목록 조회 - prisma.findMany → query<ExternalCallConfig>() - 동적 WHERE 조건 (5개 필터) - ILIKE 검색 (config_name, description) 2. **getConfigById()** - 단건 조회 - prisma.findUnique → queryOne<ExternalCallConfig>() 3-4. **createConfig()** - 생성 - 중복 검사: prisma.findFirst → queryOne() - 생성: prisma.create → queryOne() with INSERT RETURNING - JSON 필드 처리: config_data 5-6. **updateConfig()** - 수정 - 중복 검사: prisma.findFirst → queryOne() with id != $4 - 수정: prisma.update → queryOne() with 동적 UPDATE - 9개 필드에 대한 조건부 SET 절 생성 7. **deleteConfig()** - 논리 삭제 - prisma.update → query() with is_active = 'N' 8. **getExternalCallConfigsForButtonControl()** - 버튼 제어용 - prisma.findMany with select → query() with SELECT ## 기술적 개선사항 - **동적 WHERE 조건**: 5개 필터 조건 조합 및 파라미터 인덱싱 - **동적 UPDATE 쿼리**: 변경된 필드만 포함하는 SET 절 생성 - **JSON 필드**: config_data를 JSON.stringify()로 처리 - **ILIKE 검색**: 대소문자 구분 없는 검색 구현 - **중복 검사**: id 제외 조건으로 자신 제외 로직 유지 ## 코드 정리 - prisma import 완전 제거 - query, queryOne 함수 사용 - 컴파일 및 린터 오류 없음 문서: PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md 진행률: Phase 3 136/162 (84.0%)
2025-10-01 12:07:14 +09:00
const configs = await query<{
id: number;
config_name: string;
description: string | null;
config_data: any;
}>(
`SELECT id, config_name, description, config_data
FROM external_call_configs
WHERE company_code = $1 AND is_active = $2
ORDER BY config_name ASC`,
[companyCode, "Y"]
);
2025-09-29 12:17:10 +09:00
return configs.map((config) => {
const configData = config.config_data as any;
return {
id: config.id.toString(),
name: config.config_name,
description: config.description || undefined,
apiUrl: configData?.restApiSettings?.apiUrl || "",
method: configData?.restApiSettings?.httpMethod || "GET",
hasDataMapping: !!configData?.dataMappingConfig,
2025-09-29 12:17:10 +09:00
};
});
} catch (error) {
logger.error("버튼 제어용 외부호출 설정 조회 실패:", error);
throw error;
}
}
/**
* 🔥 API
*/
private async executeExternalCall(
config: ExternalCallConfig,
requestData: Record<string, any>,
contextData: Record<string, any>
): Promise<{ success: boolean; data?: any; error?: string }> {
try {
const configData = config.config_data as any;
const restApiSettings = configData?.restApiSettings;
if (!restApiSettings) {
throw new Error("REST API 설정이 없습니다.");
}
const {
apiUrl,
httpMethod,
headers = {},
timeout = 30000,
} = restApiSettings;
2025-09-29 12:17:10 +09:00
// 요청 헤더 준비
const requestHeaders = {
"Content-Type": "application/json",
...headers,
};
// 인증 처리
if (restApiSettings.authentication?.type === "basic") {
const { username, password } = restApiSettings.authentication;
const credentials = Buffer.from(`${username}:${password}`).toString(
"base64"
);
2025-09-29 12:17:10 +09:00
requestHeaders["Authorization"] = `Basic ${credentials}`;
} else if (restApiSettings.authentication?.type === "bearer") {
const { token } = restApiSettings.authentication;
requestHeaders["Authorization"] = `Bearer ${token}`;
}
// 요청 본문 준비
let requestBody = undefined;
if (["POST", "PUT", "PATCH"].includes(httpMethod.toUpperCase())) {
requestBody = JSON.stringify({
...requestData,
_context: contextData, // 컨텍스트 정보 추가
});
}
logger.info(`외부 API 호출: ${httpMethod} ${apiUrl}`);
// 실제 HTTP 요청 (여기서는 간단한 예시)
// 실제 구현에서는 axios나 fetch를 사용
const response = await fetch(apiUrl, {
method: httpMethod,
headers: requestHeaders,
body: requestBody,
signal: AbortSignal.timeout(timeout),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const responseData = await response.json();
2025-09-29 12:17:10 +09:00
return {
success: true,
data: responseData,
};
} catch (error) {
logger.error("외부 API 호출 실패:", error);
const errorMessage =
error instanceof Error ? error.message : "알 수 없는 오류";
2025-09-29 12:17:10 +09:00
return {
success: false,
error: errorMessage,
};
}
}
/**
* 🔥 Outbound
*/
private async processOutboundMapping(
mapping: any,
sourceData: Record<string, any>
): Promise<Record<string, any>> {
try {
// 간단한 매핑 로직 (실제로는 더 복잡한 변환 로직 필요)
const mappedData: Record<string, any> = {};
if (mapping.fieldMappings) {
for (const fieldMapping of mapping.fieldMappings) {
const { sourceField, targetField, transformation } = fieldMapping;
2025-09-29 12:17:10 +09:00
let value = sourceData[sourceField];
2025-09-29 12:17:10 +09:00
// 변환 로직 적용
if (transformation) {
switch (transformation.type) {
case "format":
// 포맷 변환 로직
break;
case "calculate":
// 계산 로직
break;
default:
// 기본값 그대로 사용
break;
}
}
2025-09-29 12:17:10 +09:00
mappedData[targetField] = value;
}
}
return mappedData;
} catch (error) {
logger.error("Outbound 데이터 매핑 처리 실패:", error);
return sourceData; // 실패 시 원본 데이터 반환
}
}
/**
* 🔥 Inbound
*/
private async processInboundMapping(
mapping: any,
responseData: any
): Promise<void> {
try {
// Inbound 매핑 로직 (응답 데이터를 내부 시스템에 저장)
logger.info("Inbound 데이터 매핑 처리:", mapping);
2025-09-29 12:17:10 +09:00
// 실제 구현에서는 응답 데이터를 파싱하여 내부 테이블에 저장하는 로직 필요
// 예: 외부 API에서 받은 사용자 정보를 내부 사용자 테이블에 업데이트
} catch (error) {
logger.error("Inbound 데이터 매핑 처리 실패:", error);
// Inbound 매핑 실패는 전체 플로우를 중단하지 않음
}
}
2025-09-17 17:14:59 +09:00
}
export default new ExternalCallConfigService();