restapi 버튼 동작
This commit is contained in:
235
backend-node/src/controllers/dataflowExecutionController.ts
Normal file
235
backend-node/src/controllers/dataflowExecutionController.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* 🔥 데이터플로우 실행 컨트롤러
|
||||
*
|
||||
* 버튼 제어에서 관계 실행 시 사용되는 컨트롤러
|
||||
*/
|
||||
|
||||
import { Request, Response } from "express";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import logger from "../utils/logger";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
/**
|
||||
* 데이터 액션 실행
|
||||
*/
|
||||
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 {
|
||||
// TODO: 외부 데이터베이스 연결 및 실행 로직 구현
|
||||
// 현재는 로그만 출력하고 성공으로 처리
|
||||
logger.info(`외부 DB 액션 실행: ${connection.name} (${connection.host}:${connection.port})`);
|
||||
logger.info(`테이블: ${tableName}, 액션: ${actionType}`, data);
|
||||
|
||||
// 임시 성공 응답
|
||||
return {
|
||||
success: true,
|
||||
message: `외부 DB 액션 실행 완료: ${actionType} on ${tableName}`,
|
||||
connection: connection.name,
|
||||
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 query = `INSERT INTO ${tableName} (${columns}) VALUES (${placeholders}) RETURNING *`;
|
||||
|
||||
logger.info(`INSERT 쿼리 실행:`, { query, values });
|
||||
|
||||
const result = await prisma.$queryRawUnsafe(query, ...values);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
action: 'insert',
|
||||
tableName,
|
||||
data: result,
|
||||
affectedRows: Array.isArray(result) ? result.length : 1,
|
||||
};
|
||||
} 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;
|
||||
|
||||
if (!id) {
|
||||
throw new Error('UPDATE를 위한 ID가 필요합니다');
|
||||
}
|
||||
|
||||
const setClause = Object.keys(updateData)
|
||||
.map((key, index) => `${key} = $${index + 1}`)
|
||||
.join(', ');
|
||||
|
||||
const values = Object.values(updateData);
|
||||
const query = `UPDATE ${tableName} SET ${setClause} WHERE id = $${values.length + 1} RETURNING *`;
|
||||
|
||||
logger.info(`UPDATE 쿼리 실행:`, { query, values: [...values, id] });
|
||||
|
||||
const result = await prisma.$queryRawUnsafe(query, ...values, id);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
action: 'update',
|
||||
tableName,
|
||||
data: result,
|
||||
affectedRows: Array.isArray(result) ? result.length : 1,
|
||||
};
|
||||
} 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;
|
||||
|
||||
if (!id) {
|
||||
throw new Error('DELETE를 위한 ID가 필요합니다');
|
||||
}
|
||||
|
||||
const query = `DELETE FROM ${tableName} WHERE id = $1 RETURNING *`;
|
||||
|
||||
logger.info(`DELETE 쿼리 실행:`, { query, values: [id] });
|
||||
|
||||
const result = await prisma.$queryRawUnsafe(query, id);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
action: 'delete',
|
||||
tableName,
|
||||
data: result,
|
||||
affectedRows: Array.isArray(result) ? result.length : 1,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`DELETE 실행 오류:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user