841 lines
22 KiB
TypeScript
841 lines
22 KiB
TypeScript
// @ts-nocheck
|
|
/**
|
|
* 플로우 관리 컨트롤러
|
|
*/
|
|
|
|
import { Request, Response } from "express";
|
|
import { FlowDefinitionService } from "../services/flowDefinitionService";
|
|
import { FlowStepService } from "../services/flowStepService";
|
|
import { FlowConnectionService } from "../services/flowConnectionService";
|
|
import { FlowExecutionService } from "../services/flowExecutionService";
|
|
import { FlowDataMoveService } from "../services/flowDataMoveService";
|
|
|
|
export class FlowController {
|
|
private flowDefinitionService: FlowDefinitionService;
|
|
private flowStepService: FlowStepService;
|
|
private flowConnectionService: FlowConnectionService;
|
|
private flowExecutionService: FlowExecutionService;
|
|
private flowDataMoveService: FlowDataMoveService;
|
|
|
|
constructor() {
|
|
this.flowDefinitionService = new FlowDefinitionService();
|
|
this.flowStepService = new FlowStepService();
|
|
this.flowConnectionService = new FlowConnectionService();
|
|
this.flowExecutionService = new FlowExecutionService();
|
|
this.flowDataMoveService = new FlowDataMoveService();
|
|
}
|
|
|
|
// ==================== 플로우 정의 ====================
|
|
|
|
/**
|
|
* 플로우 정의 생성
|
|
*/
|
|
createFlowDefinition = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const {
|
|
name,
|
|
description,
|
|
tableName,
|
|
dbSourceType,
|
|
dbConnectionId,
|
|
// REST API 관련 필드
|
|
restApiConnectionId,
|
|
restApiEndpoint,
|
|
restApiJsonPath,
|
|
} = req.body;
|
|
const userId = (req as any).user?.userId || "system";
|
|
const userCompanyCode = (req as any).user?.companyCode;
|
|
|
|
console.log("🔍 createFlowDefinition called with:", {
|
|
name,
|
|
description,
|
|
tableName,
|
|
dbSourceType,
|
|
dbConnectionId,
|
|
restApiConnectionId,
|
|
restApiEndpoint,
|
|
restApiJsonPath,
|
|
userCompanyCode,
|
|
});
|
|
|
|
if (!name) {
|
|
res.status(400).json({
|
|
success: false,
|
|
message: "Name is required",
|
|
});
|
|
return;
|
|
}
|
|
|
|
// REST API 또는 다중 연결인 경우 테이블 존재 확인 스킵
|
|
const isRestApi = dbSourceType === "restapi" || dbSourceType === "multi_restapi";
|
|
const isMultiConnection = dbSourceType === "multi_restapi" || dbSourceType === "multi_external_db";
|
|
|
|
// 테이블 이름이 제공된 경우에만 존재 확인 (REST API 및 다중 연결 제외)
|
|
if (tableName && !isRestApi && !isMultiConnection && !tableName.startsWith("_restapi_") && !tableName.startsWith("_multi_restapi_") && !tableName.startsWith("_multi_external_db_")) {
|
|
const tableExists =
|
|
await this.flowDefinitionService.checkTableExists(tableName);
|
|
if (!tableExists) {
|
|
res.status(400).json({
|
|
success: false,
|
|
message: `Table '${tableName}' does not exist`,
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
const flowDef = await this.flowDefinitionService.create(
|
|
{
|
|
name,
|
|
description,
|
|
tableName,
|
|
dbSourceType,
|
|
dbConnectionId,
|
|
restApiConnectionId,
|
|
restApiEndpoint,
|
|
restApiJsonPath,
|
|
restApiConnections: req.body.restApiConnections, // 다중 REST API 설정
|
|
},
|
|
userId,
|
|
userCompanyCode
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: flowDef,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error creating flow definition:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to create flow definition",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 정의 목록 조회
|
|
*/
|
|
getFlowDefinitions = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { tableName, isActive } = req.query;
|
|
const user = (req as any).user;
|
|
const userCompanyCode = user?.companyCode;
|
|
|
|
console.log("🎯 getFlowDefinitions called:", {
|
|
userId: user?.userId,
|
|
userCompanyCode: userCompanyCode,
|
|
userType: user?.userType,
|
|
tableName,
|
|
isActive,
|
|
});
|
|
|
|
const flows = await this.flowDefinitionService.findAll(
|
|
tableName as string | undefined,
|
|
isActive !== undefined ? isActive === "true" : undefined,
|
|
userCompanyCode
|
|
);
|
|
|
|
console.log(`✅ Returning ${flows.length} flows to user ${user?.userId}`);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: flows,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error fetching flow definitions:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to fetch flow definitions",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 정의 상세 조회 (단계 및 연결 포함)
|
|
*/
|
|
getFlowDefinitionDetail = async (
|
|
req: Request,
|
|
res: Response
|
|
): Promise<void> => {
|
|
try {
|
|
const { id } = req.params;
|
|
const flowId = parseInt(id);
|
|
|
|
const definition = await this.flowDefinitionService.findById(flowId);
|
|
if (!definition) {
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Flow definition not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
const steps = await this.flowStepService.findByFlowId(flowId);
|
|
const connections = await this.flowConnectionService.findByFlowId(flowId);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
definition,
|
|
steps,
|
|
connections,
|
|
},
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error fetching flow definition detail:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to fetch flow definition detail",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 정의 수정
|
|
*/
|
|
updateFlowDefinition = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { id } = req.params;
|
|
const flowId = parseInt(id);
|
|
const { name, description, isActive } = req.body;
|
|
|
|
const flowDef = await this.flowDefinitionService.update(flowId, {
|
|
name,
|
|
description,
|
|
isActive,
|
|
});
|
|
|
|
if (!flowDef) {
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Flow definition not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: flowDef,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error updating flow definition:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to update flow definition",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 정의 삭제
|
|
*/
|
|
deleteFlowDefinition = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { id } = req.params;
|
|
const flowId = parseInt(id);
|
|
|
|
const success = await this.flowDefinitionService.delete(flowId);
|
|
|
|
if (!success) {
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Flow definition not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: "Flow definition deleted successfully",
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error deleting flow definition:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to delete flow definition",
|
|
});
|
|
}
|
|
};
|
|
|
|
// ==================== 플로우 단계 ====================
|
|
|
|
/**
|
|
* 플로우 단계 목록 조회
|
|
*/
|
|
getFlowSteps = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId } = req.params;
|
|
const flowDefinitionId = parseInt(flowId);
|
|
|
|
const steps = await this.flowStepService.findByFlowId(flowDefinitionId);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: steps,
|
|
});
|
|
return;
|
|
} catch (error: any) {
|
|
console.error("Error fetching flow steps:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to fetch flow steps",
|
|
});
|
|
return;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 단계 생성
|
|
*/
|
|
createFlowStep = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId } = req.params;
|
|
const flowDefinitionId = parseInt(flowId);
|
|
const {
|
|
stepName,
|
|
stepOrder,
|
|
tableName,
|
|
conditionJson,
|
|
color,
|
|
positionX,
|
|
positionY,
|
|
} = req.body;
|
|
|
|
if (!stepName || stepOrder === undefined) {
|
|
res.status(400).json({
|
|
success: false,
|
|
message: "stepName and stepOrder are required",
|
|
});
|
|
return;
|
|
}
|
|
|
|
const step = await this.flowStepService.create({
|
|
flowDefinitionId,
|
|
stepName,
|
|
stepOrder,
|
|
tableName,
|
|
conditionJson,
|
|
color,
|
|
positionX,
|
|
positionY,
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: step,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error creating flow step:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to create flow step",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 단계 수정
|
|
*/
|
|
updateFlowStep = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { stepId } = req.params;
|
|
const id = parseInt(stepId);
|
|
const {
|
|
stepName,
|
|
stepOrder,
|
|
tableName,
|
|
conditionJson,
|
|
color,
|
|
positionX,
|
|
positionY,
|
|
moveType,
|
|
statusColumn,
|
|
statusValue,
|
|
targetTable,
|
|
fieldMappings,
|
|
integrationType,
|
|
integrationConfig,
|
|
displayConfig,
|
|
} = req.body;
|
|
|
|
const step = await this.flowStepService.update(id, {
|
|
stepName,
|
|
stepOrder,
|
|
tableName,
|
|
conditionJson,
|
|
color,
|
|
positionX,
|
|
positionY,
|
|
moveType,
|
|
statusColumn,
|
|
statusValue,
|
|
targetTable,
|
|
fieldMappings,
|
|
integrationType,
|
|
integrationConfig,
|
|
displayConfig,
|
|
});
|
|
|
|
if (!step) {
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Flow step not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: step,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error updating flow step:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to update flow step",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 단계 삭제
|
|
*/
|
|
deleteFlowStep = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { stepId } = req.params;
|
|
const id = parseInt(stepId);
|
|
|
|
const success = await this.flowStepService.delete(id);
|
|
|
|
if (!success) {
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Flow step not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: "Flow step deleted successfully",
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error deleting flow step:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to delete flow step",
|
|
});
|
|
}
|
|
};
|
|
|
|
// ==================== 플로우 연결 ====================
|
|
|
|
/**
|
|
* 플로우 연결 목록 조회
|
|
*/
|
|
getFlowConnections = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId } = req.params;
|
|
const flowDefinitionId = parseInt(flowId);
|
|
|
|
const connections =
|
|
await this.flowConnectionService.findByFlowId(flowDefinitionId);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: connections,
|
|
});
|
|
return;
|
|
} catch (error: any) {
|
|
console.error("Error fetching flow connections:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to fetch flow connections",
|
|
});
|
|
return;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 연결 생성
|
|
*/
|
|
createConnection = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowDefinitionId, fromStepId, toStepId, label } = req.body;
|
|
|
|
if (!flowDefinitionId || !fromStepId || !toStepId) {
|
|
res.status(400).json({
|
|
success: false,
|
|
message: "flowDefinitionId, fromStepId, and toStepId are required",
|
|
});
|
|
return;
|
|
}
|
|
|
|
const connection = await this.flowConnectionService.create({
|
|
flowDefinitionId,
|
|
fromStepId,
|
|
toStepId,
|
|
label,
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: connection,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error creating connection:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to create connection",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 연결 삭제
|
|
*/
|
|
deleteConnection = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { connectionId } = req.params;
|
|
const id = parseInt(connectionId);
|
|
|
|
const success = await this.flowConnectionService.delete(id);
|
|
|
|
if (!success) {
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Connection not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: "Connection deleted successfully",
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error deleting connection:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to delete connection",
|
|
});
|
|
}
|
|
};
|
|
|
|
// ==================== 플로우 실행 ====================
|
|
|
|
/**
|
|
* 단계별 데이터 카운트 조회
|
|
*/
|
|
getStepDataCount = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId, stepId } = req.params;
|
|
|
|
const count = await this.flowExecutionService.getStepDataCount(
|
|
parseInt(flowId),
|
|
parseInt(stepId)
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: { count },
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error getting step data count:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to get step data count",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 단계별 데이터 리스트 조회
|
|
*/
|
|
getStepDataList = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId, stepId } = req.params;
|
|
const { page = 1, pageSize = 20 } = req.query;
|
|
|
|
const data = await this.flowExecutionService.getStepDataList(
|
|
parseInt(flowId),
|
|
parseInt(stepId),
|
|
parseInt(page as string),
|
|
parseInt(pageSize as string)
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error getting step data list:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to get step data list",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우 스텝의 컬럼 라벨 조회
|
|
*/
|
|
getStepColumnLabels = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId, stepId } = req.params;
|
|
console.log("🏷️ [FlowController] 컬럼 라벨 조회 요청:", {
|
|
flowId,
|
|
stepId,
|
|
});
|
|
|
|
const step = await this.flowStepService.findById(parseInt(stepId));
|
|
if (!step) {
|
|
console.warn("⚠️ [FlowController] 스텝을 찾을 수 없음:", stepId);
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Step not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
const flowDef = await this.flowDefinitionService.findById(
|
|
parseInt(flowId)
|
|
);
|
|
if (!flowDef) {
|
|
console.warn("⚠️ [FlowController] 플로우를 찾을 수 없음:", flowId);
|
|
res.status(404).json({
|
|
success: false,
|
|
message: "Flow definition not found",
|
|
});
|
|
return;
|
|
}
|
|
|
|
// 테이블명 결정 (스텝 테이블 우선, 없으면 플로우 테이블)
|
|
const tableName = step.tableName || flowDef.tableName;
|
|
console.log("📋 [FlowController] 테이블명 결정:", {
|
|
stepTableName: step.tableName,
|
|
flowTableName: flowDef.tableName,
|
|
selectedTableName: tableName,
|
|
});
|
|
|
|
if (!tableName) {
|
|
console.warn("⚠️ [FlowController] 테이블명이 지정되지 않음");
|
|
res.json({
|
|
success: true,
|
|
data: {},
|
|
});
|
|
return;
|
|
}
|
|
|
|
// column_labels 테이블에서 라벨 정보 조회
|
|
const { query } = await import("../database/db");
|
|
const labelRows = await query<{
|
|
column_name: string;
|
|
column_label: string | null;
|
|
}>(
|
|
`SELECT column_name, column_label
|
|
FROM column_labels
|
|
WHERE table_name = $1 AND column_label IS NOT NULL`,
|
|
[tableName]
|
|
);
|
|
|
|
console.log(`✅ [FlowController] column_labels 조회 완료:`, {
|
|
tableName,
|
|
rowCount: labelRows.length,
|
|
labels: labelRows.map((r) => ({
|
|
col: r.column_name,
|
|
label: r.column_label,
|
|
})),
|
|
});
|
|
|
|
// { columnName: label } 형태의 객체로 변환
|
|
const labels: Record<string, string> = {};
|
|
labelRows.forEach((row) => {
|
|
if (row.column_label) {
|
|
labels[row.column_name] = row.column_label;
|
|
}
|
|
});
|
|
|
|
console.log("📦 [FlowController] 반환할 라벨 객체:", labels);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: labels,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("❌ [FlowController] 컬럼 라벨 조회 오류:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to get step column labels",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우의 모든 단계별 카운트 조회
|
|
*/
|
|
getAllStepCounts = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId } = req.params;
|
|
|
|
const counts = await this.flowExecutionService.getAllStepCounts(
|
|
parseInt(flowId)
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: counts,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error getting all step counts:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to get all step counts",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 데이터를 다음 단계로 이동
|
|
*/
|
|
moveData = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId, recordId, toStepId, note } = req.body;
|
|
const userId = (req as any).user?.userId || "system";
|
|
|
|
if (!flowId || !recordId || !toStepId) {
|
|
res.status(400).json({
|
|
success: false,
|
|
message: "flowId, recordId, and toStepId are required",
|
|
});
|
|
return;
|
|
}
|
|
|
|
await this.flowDataMoveService.moveDataToStep(
|
|
flowId,
|
|
recordId,
|
|
toStepId,
|
|
userId,
|
|
note
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: "Data moved successfully",
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error moving data:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to move data",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 여러 데이터를 동시에 이동
|
|
*/
|
|
moveBatchData = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId, fromStepId, toStepId, dataIds } = req.body;
|
|
const userId = (req as any).user?.userId || "system";
|
|
|
|
if (
|
|
!flowId ||
|
|
!fromStepId ||
|
|
!toStepId ||
|
|
!dataIds ||
|
|
!Array.isArray(dataIds)
|
|
) {
|
|
res.status(400).json({
|
|
success: false,
|
|
message:
|
|
"flowId, fromStepId, toStepId, and dataIds (array) are required",
|
|
});
|
|
return;
|
|
}
|
|
|
|
const result = await this.flowDataMoveService.moveBatchData(
|
|
flowId,
|
|
fromStepId,
|
|
toStepId,
|
|
dataIds,
|
|
userId
|
|
);
|
|
|
|
const successCount = result.results.filter((r) => r.success).length;
|
|
const failureCount = result.results.filter((r) => !r.success).length;
|
|
|
|
res.json({
|
|
success: result.success,
|
|
message: result.success
|
|
? `${successCount}건의 데이터를 성공적으로 이동했습니다`
|
|
: `${successCount}건 성공, ${failureCount}건 실패`,
|
|
data: {
|
|
successCount,
|
|
failureCount,
|
|
total: dataIds.length,
|
|
},
|
|
results: result.results,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error moving batch data:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to move batch data",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 데이터의 플로우 이력 조회
|
|
*/
|
|
getAuditLogs = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId, recordId } = req.params;
|
|
|
|
const logs = await this.flowDataMoveService.getAuditLogs(
|
|
parseInt(flowId),
|
|
recordId
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: logs,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error getting audit logs:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to get audit logs",
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 플로우의 모든 이력 조회
|
|
*/
|
|
getFlowAuditLogs = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { flowId } = req.params;
|
|
const { limit = 100 } = req.query;
|
|
|
|
const logs = await this.flowDataMoveService.getFlowAuditLogs(
|
|
parseInt(flowId),
|
|
parseInt(limit as string)
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: logs,
|
|
});
|
|
} catch (error: any) {
|
|
console.error("Error getting flow audit logs:", error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || "Failed to get flow audit logs",
|
|
});
|
|
}
|
|
};
|
|
}
|