ERP-node/backend-node/src/controllers/dataflowExecutionController.ts

252 lines
7.1 KiB
TypeScript
Raw Normal View History

2025-09-29 12:17:10 +09:00
/**
* 🔥
*
2025-09-29 12:17:10 +09:00
*
*/
import { Request, Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { query } from "../database/db";
2025-09-29 12:17:10 +09:00
import logger from "../utils/logger";
/**
*
*/
export async function executeDataAction(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const { tableName, data, actionType, connection } = req.body;
const companyCode = req.user?.companyCode || "*";
logger.info(`데이터 액션 실행 시작: ${actionType} on ${tableName}`, {
tableName,
actionType,
dataKeys: Object.keys(data),
connection: connection?.name,
});
// 연결 정보에 따라 다른 데이터베이스에 저장
let result;
if (connection && connection.id !== 0) {
// 외부 데이터베이스 연결
result = await executeExternalDatabaseAction(tableName, data, actionType, connection);
} else {
// 메인 데이터베이스 (현재 시스템)
result = await executeMainDatabaseAction(tableName, data, actionType, companyCode);
}
logger.info(`데이터 액션 실행 완료: ${actionType} on ${tableName}`, result);
res.json({
success: true,
message: `데이터 액션 실행 완료: ${actionType}`,
data: result,
});
} catch (error: any) {
logger.error("데이터 액션 실행 실패:", error);
res.status(500).json({
success: false,
message: `데이터 액션 실행 실패: ${error.message}`,
errorCode: "DATA_ACTION_EXECUTION_ERROR",
});
}
}
/**
*
*/
async function executeMainDatabaseAction(
tableName: string,
data: Record<string, any>,
actionType: string,
companyCode: string
): Promise<any> {
try {
// 회사 코드 추가
const dataWithCompany = {
...data,
company_code: companyCode,
};
switch (actionType.toLowerCase()) {
case 'insert':
return await executeInsert(tableName, dataWithCompany);
case 'update':
return await executeUpdate(tableName, dataWithCompany);
case 'upsert':
return await executeUpsert(tableName, dataWithCompany);
case 'delete':
return await executeDelete(tableName, dataWithCompany);
default:
throw new Error(`지원하지 않는 액션 타입: ${actionType}`);
}
} catch (error) {
logger.error(`메인 DB 액션 실행 오류 (${actionType}):`, error);
throw error;
}
}
/**
*
*/
async function executeExternalDatabaseAction(
tableName: string,
data: Record<string, any>,
actionType: string,
connection: any
): Promise<any> {
try {
logger.info(`외부 DB 액션 실행: ${connection.name} (${connection.host}:${connection.port})`);
logger.info(`테이블: ${tableName}, 액션: ${actionType}`, data);
2025-09-29 15:21:14 +09:00
// 🔥 실제 외부 DB 연결 및 실행 로직 구현
const { MultiConnectionQueryService } = await import('../services/multiConnectionQueryService');
const queryService = new MultiConnectionQueryService();
let result;
switch (actionType.toLowerCase()) {
case 'insert':
result = await queryService.insertDataToConnection(connection.id, tableName, data);
logger.info(`외부 DB INSERT 성공:`, result);
break;
case 'update':
// TODO: UPDATE 로직 구현 (조건 필요)
throw new Error('UPDATE 액션은 아직 지원되지 않습니다. 조건 설정이 필요합니다.');
case 'delete':
// TODO: DELETE 로직 구현 (조건 필요)
throw new Error('DELETE 액션은 아직 지원되지 않습니다. 조건 설정이 필요합니다.');
default:
throw new Error(`지원하지 않는 액션 타입: ${actionType}`);
}
2025-09-29 12:17:10 +09:00
return {
success: true,
message: `외부 DB 액션 실행 완료: ${actionType} on ${tableName}`,
connection: connection.name,
2025-09-29 15:21:14 +09:00
data: result,
2025-09-29 12:17:10 +09:00
affectedRows: 1,
};
} catch (error) {
logger.error(`외부 DB 액션 실행 오류 (${actionType}):`, error);
throw error;
}
}
/**
* INSERT
*/
async function executeInsert(tableName: string, data: Record<string, any>): Promise<any> {
try {
// 동적 테이블 접근을 위한 raw query 사용
const columns = Object.keys(data).join(', ');
const values = Object.values(data);
const placeholders = values.map((_, index) => `$${index + 1}`).join(', ');
const insertQuery = `INSERT INTO ${tableName} (${columns}) VALUES (${placeholders}) RETURNING *`;
logger.info(`INSERT 쿼리 실행:`, { query: insertQuery, values });
const result = await query<any>(insertQuery, values);
2025-09-29 12:17:10 +09:00
return {
success: true,
action: 'insert',
tableName,
data: result,
affectedRows: result.length,
2025-09-29 12:17:10 +09:00
};
} catch (error) {
logger.error(`INSERT 실행 오류:`, error);
throw error;
}
}
/**
* UPDATE
*/
async function executeUpdate(tableName: string, data: Record<string, any>): Promise<any> {
try {
// ID 또는 기본키를 기준으로 업데이트
const { id, ...updateData } = data;
2025-09-29 12:17:10 +09:00
if (!id) {
throw new Error('UPDATE를 위한 ID가 필요합니다');
}
const setClause = Object.keys(updateData)
.map((key, index) => `${key} = $${index + 1}`)
.join(', ');
2025-09-29 12:17:10 +09:00
const values = Object.values(updateData);
const updateQuery = `UPDATE ${tableName} SET ${setClause} WHERE id = $${values.length + 1} RETURNING *`;
logger.info(`UPDATE 쿼리 실행:`, { query: updateQuery, values: [...values, id] });
const result = await query<any>(updateQuery, [...values, id]);
2025-09-29 12:17:10 +09:00
return {
success: true,
action: 'update',
tableName,
data: result,
affectedRows: result.length,
2025-09-29 12:17:10 +09:00
};
} catch (error) {
logger.error(`UPDATE 실행 오류:`, error);
throw error;
}
}
/**
* UPSERT
*/
async function executeUpsert(tableName: string, data: Record<string, any>): Promise<any> {
try {
// 먼저 INSERT를 시도하고, 실패하면 UPDATE
try {
return await executeInsert(tableName, data);
} catch (insertError) {
// INSERT 실패 시 UPDATE 시도
logger.info(`INSERT 실패, UPDATE 시도:`, insertError);
return await executeUpdate(tableName, data);
}
} catch (error) {
logger.error(`UPSERT 실행 오류:`, error);
throw error;
}
}
/**
* DELETE
*/
async function executeDelete(tableName: string, data: Record<string, any>): Promise<any> {
try {
const { id } = data;
2025-09-29 12:17:10 +09:00
if (!id) {
throw new Error('DELETE를 위한 ID가 필요합니다');
}
const deleteQuery = `DELETE FROM ${tableName} WHERE id = $1 RETURNING *`;
logger.info(`DELETE 쿼리 실행:`, { query: deleteQuery, values: [id] });
const result = await query<any>(deleteQuery, [id]);
2025-09-29 12:17:10 +09:00
return {
success: true,
action: 'delete',
tableName,
data: result,
affectedRows: result.length,
2025-09-29 12:17:10 +09:00
};
} catch (error) {
logger.error(`DELETE 실행 오류:`, error);
throw error;
}
}