저장버튼 제어기능 (insert)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import prisma from "../config/database";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { EventTriggerService } from "./eventTriggerService";
|
||||
import { DataflowControlService } from "./dataflowControlService";
|
||||
|
||||
export interface FormDataResult {
|
||||
id: number;
|
||||
@@ -42,6 +43,71 @@ export interface TableColumn {
|
||||
}
|
||||
|
||||
export class DynamicFormService {
|
||||
private dataflowControlService = new DataflowControlService();
|
||||
/**
|
||||
* 값을 PostgreSQL 타입에 맞게 변환
|
||||
*/
|
||||
private convertValueForPostgreSQL(value: any, dataType: string): any {
|
||||
if (value === null || value === undefined || value === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const lowerDataType = dataType.toLowerCase();
|
||||
|
||||
// 숫자 타입 처리
|
||||
if (
|
||||
lowerDataType.includes("integer") ||
|
||||
lowerDataType.includes("bigint") ||
|
||||
lowerDataType.includes("serial")
|
||||
) {
|
||||
return parseInt(value) || null;
|
||||
}
|
||||
|
||||
if (
|
||||
lowerDataType.includes("numeric") ||
|
||||
lowerDataType.includes("decimal") ||
|
||||
lowerDataType.includes("real") ||
|
||||
lowerDataType.includes("double")
|
||||
) {
|
||||
return parseFloat(value) || null;
|
||||
}
|
||||
|
||||
// 불린 타입 처리
|
||||
if (lowerDataType.includes("boolean")) {
|
||||
if (typeof value === "boolean") return value;
|
||||
if (typeof value === "string") {
|
||||
return value.toLowerCase() === "true" || value === "1";
|
||||
}
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
// 기본적으로 문자열로 반환
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블의 컬럼 정보 조회 (타입 포함)
|
||||
*/
|
||||
private async getTableColumnInfo(
|
||||
tableName: string
|
||||
): Promise<Array<{ column_name: string; data_type: string }>> {
|
||||
try {
|
||||
const result = await prisma.$queryRaw<
|
||||
Array<{ column_name: string; data_type: string }>
|
||||
>`
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = ${tableName}
|
||||
AND table_schema = 'public'
|
||||
`;
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`테이블 ${tableName}의 컬럼 정보 조회 실패:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블의 컬럼명 목록 조회 (간단 버전)
|
||||
*/
|
||||
@@ -196,6 +262,32 @@ export class DynamicFormService {
|
||||
dataToInsert,
|
||||
});
|
||||
|
||||
// 테이블 컬럼 정보 조회하여 타입 변환 적용
|
||||
console.log("🔍 테이블 컬럼 정보 조회 중...");
|
||||
const columnInfo = await this.getTableColumnInfo(tableName);
|
||||
console.log("📊 테이블 컬럼 정보:", columnInfo);
|
||||
|
||||
// 각 컬럼의 타입에 맞게 데이터 변환
|
||||
Object.keys(dataToInsert).forEach((columnName) => {
|
||||
const column = columnInfo.find((col) => col.column_name === columnName);
|
||||
if (column) {
|
||||
const originalValue = dataToInsert[columnName];
|
||||
const convertedValue = this.convertValueForPostgreSQL(
|
||||
originalValue,
|
||||
column.data_type
|
||||
);
|
||||
|
||||
if (originalValue !== convertedValue) {
|
||||
console.log(
|
||||
`🔄 타입 변환: ${columnName} (${column.data_type}) = "${originalValue}" -> ${convertedValue}`
|
||||
);
|
||||
dataToInsert[columnName] = convertedValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log("✅ 타입 변환 완료된 데이터:", dataToInsert);
|
||||
|
||||
// 동적 SQL을 사용하여 실제 테이블에 UPSERT
|
||||
const columns = Object.keys(dataToInsert);
|
||||
const values: any[] = Object.values(dataToInsert);
|
||||
@@ -264,6 +356,19 @@ export class DynamicFormService {
|
||||
// 트리거 오류는 로그만 남기고 메인 저장 프로세스는 계속 진행
|
||||
}
|
||||
|
||||
// 🎯 제어관리 실행 (새로 추가)
|
||||
try {
|
||||
await this.executeDataflowControlIfConfigured(
|
||||
screenId,
|
||||
tableName,
|
||||
insertedRecord as Record<string, any>,
|
||||
"insert"
|
||||
);
|
||||
} catch (controlError) {
|
||||
console.error("⚠️ 제어관리 실행 오류:", controlError);
|
||||
// 제어관리 오류는 로그만 남기고 메인 저장 프로세스는 계속 진행
|
||||
}
|
||||
|
||||
return {
|
||||
id: insertedRecord.id || insertedRecord.objid || 0,
|
||||
screenId: screenId,
|
||||
@@ -674,6 +779,85 @@ export class DynamicFormService {
|
||||
throw new Error(`테이블 컬럼 정보 조회 실패: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 제어관리 실행 (화면에 설정된 경우)
|
||||
*/
|
||||
private async executeDataflowControlIfConfigured(
|
||||
screenId: number,
|
||||
tableName: string,
|
||||
savedData: Record<string, any>,
|
||||
triggerType: "insert" | "update" | "delete"
|
||||
): Promise<void> {
|
||||
try {
|
||||
console.log(`🎯 제어관리 설정 확인 중... (screenId: ${screenId})`);
|
||||
|
||||
// 화면의 저장 버튼에서 제어관리 설정 조회
|
||||
const screenLayouts = await prisma.screen_layouts.findMany({
|
||||
where: {
|
||||
screen_id: screenId,
|
||||
component_type: "component",
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`📋 화면 컴포넌트 조회 결과:`, screenLayouts.length);
|
||||
|
||||
// 저장 버튼 중에서 제어관리가 활성화된 것 찾기
|
||||
for (const layout of screenLayouts) {
|
||||
const properties = layout.properties as any;
|
||||
|
||||
// 버튼 컴포넌트이고 저장 액션이며 제어관리가 활성화된 경우
|
||||
if (
|
||||
properties?.componentType === "button-primary" &&
|
||||
properties?.componentConfig?.action?.type === "save" &&
|
||||
properties?.webTypeConfig?.enableDataflowControl === true &&
|
||||
properties?.webTypeConfig?.dataflowConfig?.selectedDiagramId
|
||||
) {
|
||||
const diagramId =
|
||||
properties.webTypeConfig.dataflowConfig.selectedDiagramId;
|
||||
const relationshipId =
|
||||
properties.webTypeConfig.dataflowConfig.selectedRelationshipId;
|
||||
|
||||
console.log(`🎯 제어관리 설정 발견:`, {
|
||||
componentId: layout.component_id,
|
||||
diagramId,
|
||||
relationshipId,
|
||||
triggerType,
|
||||
});
|
||||
|
||||
// 제어관리 실행
|
||||
const controlResult =
|
||||
await this.dataflowControlService.executeDataflowControl(
|
||||
diagramId,
|
||||
relationshipId,
|
||||
triggerType,
|
||||
savedData,
|
||||
tableName
|
||||
);
|
||||
|
||||
console.log(`🎯 제어관리 실행 결과:`, controlResult);
|
||||
|
||||
if (controlResult.success) {
|
||||
console.log(`✅ 제어관리 실행 성공: ${controlResult.message}`);
|
||||
if (
|
||||
controlResult.executedActions &&
|
||||
controlResult.executedActions.length > 0
|
||||
) {
|
||||
console.log(`📊 실행된 액션들:`, controlResult.executedActions);
|
||||
}
|
||||
} else {
|
||||
console.warn(`⚠️ 제어관리 실행 실패: ${controlResult.message}`);
|
||||
}
|
||||
|
||||
// 첫 번째 설정된 제어관리만 실행 (여러 개가 있을 경우)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ 제어관리 설정 확인 및 실행 오류:", error);
|
||||
// 에러를 다시 던지지 않음 - 메인 저장 프로세스에 영향 주지 않기 위해
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 싱글톤 인스턴스 생성 및 export
|
||||
|
||||
Reference in New Issue
Block a user