248 lines
6.5 KiB
TypeScript
248 lines
6.5 KiB
TypeScript
// @ts-nocheck
|
|
/**
|
|
* 플로우 정의 서비스
|
|
*/
|
|
|
|
import db from "../database/db";
|
|
import {
|
|
FlowDefinition,
|
|
CreateFlowDefinitionRequest,
|
|
UpdateFlowDefinitionRequest,
|
|
} from "../types/flow";
|
|
|
|
export class FlowDefinitionService {
|
|
/**
|
|
* 플로우 정의 생성
|
|
*/
|
|
async create(
|
|
request: CreateFlowDefinitionRequest,
|
|
userId: string,
|
|
userCompanyCode?: string
|
|
): Promise<FlowDefinition> {
|
|
const companyCode = request.companyCode || userCompanyCode || "*";
|
|
|
|
console.log("🔥 flowDefinitionService.create called with:", {
|
|
name: request.name,
|
|
description: request.description,
|
|
tableName: request.tableName,
|
|
dbSourceType: request.dbSourceType,
|
|
dbConnectionId: request.dbConnectionId,
|
|
restApiConnectionId: request.restApiConnectionId,
|
|
restApiEndpoint: request.restApiEndpoint,
|
|
restApiJsonPath: request.restApiJsonPath,
|
|
restApiConnections: request.restApiConnections,
|
|
companyCode,
|
|
userId,
|
|
});
|
|
|
|
const query = `
|
|
INSERT INTO flow_definition (
|
|
name, description, table_name, db_source_type, db_connection_id,
|
|
rest_api_connection_id, rest_api_endpoint, rest_api_json_path,
|
|
rest_api_connections, company_code, created_by
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
RETURNING *
|
|
`;
|
|
|
|
const values = [
|
|
request.name,
|
|
request.description || null,
|
|
request.tableName || null,
|
|
request.dbSourceType || "internal",
|
|
request.dbConnectionId || null,
|
|
request.restApiConnectionId || null,
|
|
request.restApiEndpoint || null,
|
|
request.restApiJsonPath || "response",
|
|
request.restApiConnections ? JSON.stringify(request.restApiConnections) : null,
|
|
companyCode,
|
|
userId,
|
|
];
|
|
|
|
console.log("💾 Executing INSERT with values:", values);
|
|
|
|
const result = await db.query(query, values);
|
|
|
|
return this.mapToFlowDefinition(result[0]);
|
|
}
|
|
|
|
/**
|
|
* 플로우 정의 목록 조회
|
|
*/
|
|
async findAll(
|
|
tableName?: string,
|
|
isActive?: boolean,
|
|
companyCode?: string
|
|
): Promise<FlowDefinition[]> {
|
|
console.log("🔍 flowDefinitionService.findAll called with:", {
|
|
tableName,
|
|
isActive,
|
|
companyCode,
|
|
});
|
|
|
|
let query = "SELECT * FROM flow_definition WHERE 1=1";
|
|
const params: any[] = [];
|
|
let paramIndex = 1;
|
|
|
|
// 회사 코드 필터링
|
|
if (companyCode && companyCode !== "*") {
|
|
query += ` AND company_code = $${paramIndex}`;
|
|
params.push(companyCode);
|
|
paramIndex++;
|
|
console.log(`✅ Company filter applied: company_code = ${companyCode}`);
|
|
} else {
|
|
console.log(`⚠️ No company filter (companyCode: ${companyCode})`);
|
|
}
|
|
|
|
if (tableName) {
|
|
query += ` AND table_name = $${paramIndex}`;
|
|
params.push(tableName);
|
|
paramIndex++;
|
|
}
|
|
|
|
if (isActive !== undefined) {
|
|
query += ` AND is_active = $${paramIndex}`;
|
|
params.push(isActive);
|
|
paramIndex++;
|
|
}
|
|
|
|
query += " ORDER BY created_at DESC";
|
|
|
|
console.log("📋 Final query:", query);
|
|
console.log("📋 Query params:", params);
|
|
|
|
const result = await db.query(query, params);
|
|
console.log(`📊 Found ${result.length} flow definitions`);
|
|
return result.map(this.mapToFlowDefinition);
|
|
}
|
|
|
|
/**
|
|
* 플로우 정의 단일 조회
|
|
*/
|
|
async findById(id: number): Promise<FlowDefinition | null> {
|
|
const query = "SELECT * FROM flow_definition WHERE id = $1";
|
|
const result = await db.query(query, [id]);
|
|
|
|
if (result.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return this.mapToFlowDefinition(result[0]);
|
|
}
|
|
|
|
/**
|
|
* 플로우 정의 수정
|
|
*/
|
|
async update(
|
|
id: number,
|
|
request: UpdateFlowDefinitionRequest
|
|
): Promise<FlowDefinition | null> {
|
|
const fields: string[] = [];
|
|
const params: any[] = [];
|
|
let paramIndex = 1;
|
|
|
|
if (request.name !== undefined) {
|
|
fields.push(`name = $${paramIndex}`);
|
|
params.push(request.name);
|
|
paramIndex++;
|
|
}
|
|
|
|
if (request.description !== undefined) {
|
|
fields.push(`description = $${paramIndex}`);
|
|
params.push(request.description);
|
|
paramIndex++;
|
|
}
|
|
|
|
if (request.isActive !== undefined) {
|
|
fields.push(`is_active = $${paramIndex}`);
|
|
params.push(request.isActive);
|
|
paramIndex++;
|
|
}
|
|
|
|
if (fields.length === 0) {
|
|
return this.findById(id);
|
|
}
|
|
|
|
fields.push(`updated_at = NOW()`);
|
|
|
|
const query = `
|
|
UPDATE flow_definition
|
|
SET ${fields.join(", ")}
|
|
WHERE id = $${paramIndex}
|
|
RETURNING *
|
|
`;
|
|
params.push(id);
|
|
|
|
const result = await db.query(query, params);
|
|
|
|
if (result.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return this.mapToFlowDefinition(result[0]);
|
|
}
|
|
|
|
/**
|
|
* 플로우 정의 삭제
|
|
*/
|
|
async delete(id: number): Promise<boolean> {
|
|
const query = "DELETE FROM flow_definition WHERE id = $1 RETURNING id";
|
|
const result = await db.query(query, [id]);
|
|
return result.length > 0;
|
|
}
|
|
|
|
/**
|
|
* 테이블 존재 여부 확인
|
|
*/
|
|
async checkTableExists(tableName: string): Promise<boolean> {
|
|
const query = `
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
AND table_name = $1
|
|
) as exists
|
|
`;
|
|
|
|
const result = await db.query(query, [tableName]);
|
|
return result[0].exists;
|
|
}
|
|
|
|
/**
|
|
* DB 행을 FlowDefinition 객체로 변환
|
|
*/
|
|
private mapToFlowDefinition(row: any): FlowDefinition {
|
|
// rest_api_connections 파싱 (JSONB → 배열)
|
|
let restApiConnections = undefined;
|
|
if (row.rest_api_connections) {
|
|
try {
|
|
restApiConnections = typeof row.rest_api_connections === 'string'
|
|
? JSON.parse(row.rest_api_connections)
|
|
: row.rest_api_connections;
|
|
} catch (e) {
|
|
console.warn("Failed to parse rest_api_connections:", e);
|
|
restApiConnections = [];
|
|
}
|
|
}
|
|
|
|
return {
|
|
id: row.id,
|
|
name: row.name,
|
|
description: row.description,
|
|
tableName: row.table_name,
|
|
dbSourceType: row.db_source_type || "internal",
|
|
dbConnectionId: row.db_connection_id,
|
|
// REST API 관련 필드 (단일)
|
|
restApiConnectionId: row.rest_api_connection_id,
|
|
restApiEndpoint: row.rest_api_endpoint,
|
|
restApiJsonPath: row.rest_api_json_path,
|
|
// 다중 REST API 관련 필드
|
|
restApiConnections: restApiConnections,
|
|
companyCode: row.company_code || "*",
|
|
isActive: row.is_active,
|
|
createdBy: row.created_by,
|
|
createdAt: row.created_at,
|
|
updatedAt: row.updated_at,
|
|
};
|
|
}
|
|
}
|