삭제버튼 제어 동작하지 않던 오류 수정
This commit is contained in:
@@ -231,7 +231,7 @@ export const deleteFormData = async (
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { companyCode, userId } = req.user as any;
|
||||
const { tableName } = req.body;
|
||||
const { tableName, screenId } = req.body;
|
||||
|
||||
if (!tableName) {
|
||||
return res.status(400).json({
|
||||
@@ -240,7 +240,16 @@ export const deleteFormData = async (
|
||||
});
|
||||
}
|
||||
|
||||
await dynamicFormService.deleteFormData(id, tableName, companyCode, userId); // userId 추가
|
||||
// screenId를 숫자로 변환 (문자열로 전달될 수 있음)
|
||||
const parsedScreenId = screenId ? parseInt(screenId, 10) : undefined;
|
||||
|
||||
await dynamicFormService.deleteFormData(
|
||||
id,
|
||||
tableName,
|
||||
companyCode,
|
||||
userId,
|
||||
parsedScreenId // screenId 추가 (제어관리 실행용)
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
|
||||
@@ -1192,12 +1192,18 @@ export class DynamicFormService {
|
||||
|
||||
/**
|
||||
* 폼 데이터 삭제 (실제 테이블에서 직접 삭제)
|
||||
* @param id 삭제할 레코드 ID
|
||||
* @param tableName 테이블명
|
||||
* @param companyCode 회사 코드
|
||||
* @param userId 사용자 ID
|
||||
* @param screenId 화면 ID (제어관리 실행용, 선택사항)
|
||||
*/
|
||||
async deleteFormData(
|
||||
id: string | number,
|
||||
tableName: string,
|
||||
companyCode?: string,
|
||||
userId?: string
|
||||
userId?: string,
|
||||
screenId?: number
|
||||
): Promise<void> {
|
||||
try {
|
||||
console.log("🗑️ 서비스: 실제 테이블에서 폼 데이터 삭제 시작:", {
|
||||
@@ -1310,14 +1316,19 @@ export class DynamicFormService {
|
||||
const recordCompanyCode =
|
||||
deletedRecord?.company_code || companyCode || "*";
|
||||
|
||||
await this.executeDataflowControlIfConfigured(
|
||||
0, // DELETE는 screenId를 알 수 없으므로 0으로 설정 (추후 개선 필요)
|
||||
tableName,
|
||||
deletedRecord,
|
||||
"delete",
|
||||
userId || "system",
|
||||
recordCompanyCode
|
||||
);
|
||||
// screenId가 전달되지 않으면 제어관리를 실행하지 않음
|
||||
if (screenId && screenId > 0) {
|
||||
await this.executeDataflowControlIfConfigured(
|
||||
screenId,
|
||||
tableName,
|
||||
deletedRecord,
|
||||
"delete",
|
||||
userId || "system",
|
||||
recordCompanyCode
|
||||
);
|
||||
} else {
|
||||
console.log("ℹ️ screenId가 전달되지 않아 제어관리를 건너뜁니다. (screenId:", screenId, ")");
|
||||
}
|
||||
}
|
||||
} catch (controlError) {
|
||||
console.error("⚠️ 제어관리 실행 오류:", controlError);
|
||||
@@ -1662,10 +1673,16 @@ export class DynamicFormService {
|
||||
!!properties?.webTypeConfig?.dataflowConfig?.flowControls,
|
||||
});
|
||||
|
||||
// 버튼 컴포넌트이고 저장 액션이며 제어관리가 활성화된 경우
|
||||
// 버튼 컴포넌트이고 제어관리가 활성화된 경우
|
||||
// triggerType에 맞는 액션 타입 매칭: insert/update -> save, delete -> delete
|
||||
const buttonActionType = properties?.componentConfig?.action?.type;
|
||||
const isMatchingAction =
|
||||
(triggerType === "delete" && buttonActionType === "delete") ||
|
||||
((triggerType === "insert" || triggerType === "update") && buttonActionType === "save");
|
||||
|
||||
if (
|
||||
properties?.componentType === "button-primary" &&
|
||||
properties?.componentConfig?.action?.type === "save" &&
|
||||
isMatchingAction &&
|
||||
properties?.webTypeConfig?.enableDataflowControl === true
|
||||
) {
|
||||
const dataflowConfig = properties?.webTypeConfig?.dataflowConfig;
|
||||
|
||||
@@ -969,21 +969,56 @@ export class NodeFlowExecutionService {
|
||||
const insertedData = { ...data };
|
||||
|
||||
console.log("🗺️ 필드 매핑 처리 중...");
|
||||
fieldMappings.forEach((mapping: any) => {
|
||||
|
||||
// 🔥 채번 규칙 서비스 동적 import
|
||||
const { numberingRuleService } = await import("./numberingRuleService");
|
||||
|
||||
for (const mapping of fieldMappings) {
|
||||
fields.push(mapping.targetField);
|
||||
const value =
|
||||
mapping.staticValue !== undefined
|
||||
? mapping.staticValue
|
||||
: data[mapping.sourceField];
|
||||
|
||||
console.log(
|
||||
` ${mapping.sourceField} → ${mapping.targetField}: ${value === undefined ? "❌ undefined" : "✅ " + value}`
|
||||
);
|
||||
let value: any;
|
||||
|
||||
// 🔥 값 생성 유형에 따른 처리
|
||||
const valueType = mapping.valueType || (mapping.staticValue !== undefined ? "static" : "source");
|
||||
|
||||
if (valueType === "autoGenerate" && mapping.numberingRuleId) {
|
||||
// 자동 생성 (채번 규칙)
|
||||
const companyCode = context.buttonContext?.companyCode || "*";
|
||||
try {
|
||||
value = await numberingRuleService.allocateCode(
|
||||
mapping.numberingRuleId,
|
||||
companyCode
|
||||
);
|
||||
console.log(
|
||||
` 🔢 자동 생성(채번): ${mapping.targetField} = ${value} (규칙: ${mapping.numberingRuleId})`
|
||||
);
|
||||
} catch (error: any) {
|
||||
logger.error(`채번 규칙 적용 실패: ${error.message}`);
|
||||
console.error(
|
||||
` ❌ 채번 실패 → ${mapping.targetField}: ${error.message}`
|
||||
);
|
||||
throw new Error(
|
||||
`채번 규칙 '${mapping.numberingRuleName || mapping.numberingRuleId}' 적용 실패: ${error.message}`
|
||||
);
|
||||
}
|
||||
} else if (valueType === "static" || mapping.staticValue !== undefined) {
|
||||
// 고정값
|
||||
value = mapping.staticValue;
|
||||
console.log(
|
||||
` 📌 고정값: ${mapping.targetField} = ${value}`
|
||||
);
|
||||
} else {
|
||||
// 소스 필드
|
||||
value = data[mapping.sourceField];
|
||||
console.log(
|
||||
` ${mapping.sourceField} → ${mapping.targetField}: ${value === undefined ? "❌ undefined" : "✅ " + value}`
|
||||
);
|
||||
}
|
||||
|
||||
values.push(value);
|
||||
|
||||
// 🔥 삽입된 값을 데이터에 반영
|
||||
insertedData[mapping.targetField] = value;
|
||||
});
|
||||
}
|
||||
|
||||
// 🆕 writer와 company_code 자동 추가 (필드 매핑에 없는 경우)
|
||||
const hasWriterMapping = fieldMappings.some(
|
||||
@@ -1528,16 +1563,24 @@ export class NodeFlowExecutionService {
|
||||
}
|
||||
});
|
||||
|
||||
// 🔑 Primary Key 자동 추가 (context-data 모드)
|
||||
console.log("🔑 context-data 모드: Primary Key 자동 추가");
|
||||
const enhancedWhereConditions = await this.enhanceWhereConditionsWithPK(
|
||||
whereConditions,
|
||||
data,
|
||||
targetTable
|
||||
);
|
||||
// 🔑 Primary Key 자동 추가 여부 결정:
|
||||
// whereConditions가 명시적으로 설정되어 있으면 PK 자동 추가를 하지 않음
|
||||
// (사용자가 직접 조건을 설정한 경우 의도를 존중)
|
||||
let finalWhereConditions: any[];
|
||||
if (whereConditions && whereConditions.length > 0) {
|
||||
console.log("📋 사용자 정의 WHERE 조건 사용 (PK 자동 추가 안 함)");
|
||||
finalWhereConditions = whereConditions;
|
||||
} else {
|
||||
console.log("🔑 context-data 모드: Primary Key 자동 추가");
|
||||
finalWhereConditions = await this.enhanceWhereConditionsWithPK(
|
||||
whereConditions,
|
||||
data,
|
||||
targetTable
|
||||
);
|
||||
}
|
||||
|
||||
const whereResult = this.buildWhereClause(
|
||||
enhancedWhereConditions,
|
||||
finalWhereConditions,
|
||||
data,
|
||||
paramIndex
|
||||
);
|
||||
@@ -1907,22 +1950,30 @@ export class NodeFlowExecutionService {
|
||||
return deletedDataArray;
|
||||
}
|
||||
|
||||
// 🆕 context-data 모드: 개별 삭제 (PK 자동 추가)
|
||||
// 🆕 context-data 모드: 개별 삭제
|
||||
console.log("🎯 context-data 모드: 개별 삭제 시작");
|
||||
|
||||
for (const data of dataArray) {
|
||||
console.log("🔍 WHERE 조건 처리 중...");
|
||||
|
||||
// 🔑 Primary Key 자동 추가 (context-data 모드)
|
||||
console.log("🔑 context-data 모드: Primary Key 자동 추가");
|
||||
const enhancedWhereConditions = await this.enhanceWhereConditionsWithPK(
|
||||
whereConditions,
|
||||
data,
|
||||
targetTable
|
||||
);
|
||||
// 🔑 Primary Key 자동 추가 여부 결정:
|
||||
// whereConditions가 명시적으로 설정되어 있으면 PK 자동 추가를 하지 않음
|
||||
// (사용자가 직접 조건을 설정한 경우 의도를 존중)
|
||||
let finalWhereConditions: any[];
|
||||
if (whereConditions && whereConditions.length > 0) {
|
||||
console.log("📋 사용자 정의 WHERE 조건 사용 (PK 자동 추가 안 함)");
|
||||
finalWhereConditions = whereConditions;
|
||||
} else {
|
||||
console.log("🔑 context-data 모드: Primary Key 자동 추가");
|
||||
finalWhereConditions = await this.enhanceWhereConditionsWithPK(
|
||||
whereConditions,
|
||||
data,
|
||||
targetTable
|
||||
);
|
||||
}
|
||||
|
||||
const whereResult = this.buildWhereClause(
|
||||
enhancedWhereConditions,
|
||||
finalWhereConditions,
|
||||
data,
|
||||
1
|
||||
);
|
||||
@@ -2865,10 +2916,11 @@ export class NodeFlowExecutionService {
|
||||
|
||||
if (fieldValue === null || fieldValue === undefined || fieldValue === "") {
|
||||
logger.info(
|
||||
`⚠️ EXISTS 조건: 필드값이 비어있어 ${operator === "NOT_EXISTS_IN" ? "TRUE" : "FALSE"} 반환`
|
||||
`⚠️ EXISTS 조건: 필드값이 비어있어 FALSE 반환 (빈 값은 조건 검사하지 않음)`
|
||||
);
|
||||
// 값이 비어있으면: EXISTS_IN은 false, NOT_EXISTS_IN은 true
|
||||
return operator === "NOT_EXISTS_IN";
|
||||
// 값이 비어있으면 조건 검사 자체가 무의미하므로 항상 false 반환
|
||||
// 이렇게 하면 빈 값으로 인한 의도치 않은 INSERT/UPDATE/DELETE가 방지됨
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user