엑셀업로드 제어로직 개선

This commit is contained in:
kjs
2026-01-13 09:30:19 +09:00
parent b6fefe2ebd
commit 75e6c9eb1a
5 changed files with 190 additions and 20 deletions

View File

@@ -744,7 +744,9 @@ class MasterDetailExcelService {
result.masterInserted = 1;
logger.info(`마스터 레코드 생성: ${masterTable}, key=${generatedKey}`);
// 4. 디테일 레코드들 생성
// 4. 디테일 레코드들 생성 (삽입된 데이터 수집)
const insertedDetailRows: Record<string, any>[] = [];
for (const row of detailData) {
try {
const detailRowData: Record<string, any> = {
@@ -764,17 +766,26 @@ class MasterDetailExcelService {
const detailPlaceholders = detailCols.map((_, i) => `$${i + 1}`);
const detailValues = detailCols.map(k => detailRowData[k]);
await client.query(
// RETURNING *로 삽입된 데이터 반환받기
const insertResult = await client.query(
`INSERT INTO "${detailTable}" (${detailCols.map(c => `"${c}"`).join(", ")}, created_date)
VALUES (${detailPlaceholders.join(", ")}, NOW())`,
VALUES (${detailPlaceholders.join(", ")}, NOW())
RETURNING *`,
detailValues
);
if (insertResult.rows && insertResult.rows[0]) {
insertedDetailRows.push(insertResult.rows[0]);
}
result.detailInserted++;
} catch (error: any) {
result.errors.push(`디테일 행 처리 실패: ${error.message}`);
logger.error(`디테일 행 처리 실패:`, error);
}
}
logger.info(`디테일 레코드 ${insertedDetailRows.length}건 삽입 완료`);
await client.query("COMMIT");
result.success = result.errors.length === 0 || result.detailInserted > 0;
@@ -797,7 +808,7 @@ class MasterDetailExcelService {
try {
const { NodeFlowExecutionService } = await import("./nodeFlowExecutionService");
// 마스터 데이터를 제어에 전달
// 마스터 데이터 구성
const masterData = {
...masterFieldValues,
[relation!.masterKeyColumn]: result.generatedKey,
@@ -809,17 +820,28 @@ class MasterDetailExcelService {
// 순서대로 제어 실행
for (const flow of flowsToExecute.sort((a, b) => a.order - b.order)) {
logger.info(`업로드 후 제어 실행: flowId=${flow.flowId}, order=${flow.order}`);
logger.info(` 전달 데이터: 마스터 1건, 디테일 ${insertedDetailRows.length}`);
// 🆕 삽입된 디테일 데이터를 sourceData로 전달 (성능 최적화)
// - 전체 테이블 조회 대신 방금 INSERT한 데이터만 처리
// - tableSource 노드가 context-data 모드일 때 이 데이터를 사용
const controlResult = await NodeFlowExecutionService.executeFlow(
parseInt(flow.flowId),
{
sourceData: [masterData],
dataSourceType: "formData",
sourceData: insertedDetailRows.length > 0 ? insertedDetailRows : [masterData],
dataSourceType: "excelUpload", // 엑셀 업로드 데이터임을 명시
buttonId: "excel-upload-button",
screenId: screenId,
userId: userId,
companyCode: companyCode,
formData: masterData,
// 추가 컨텍스트: 마스터/디테일 정보
masterData: masterData,
detailData: insertedDetailRows,
masterTable: relation!.masterTable,
detailTable: relation!.detailTable,
masterKeyColumn: relation!.masterKeyColumn,
detailFkColumn: relation!.detailFkColumn,
}
);

View File

@@ -4446,6 +4446,8 @@ export class NodeFlowExecutionService {
/**
* 산술 연산 계산
* 다중 연산 지원: (leftOperand operator rightOperand) 이후 additionalOperations 순차 적용
* 예: (width * height) / 1000000 * qty
*/
private static evaluateArithmetic(
arithmetic: any,
@@ -4472,27 +4474,67 @@ export class NodeFlowExecutionService {
const leftNum = Number(left) || 0;
const rightNum = Number(right) || 0;
switch (arithmetic.operator) {
// 기본 연산 수행
let result = this.applyOperator(leftNum, arithmetic.operator, rightNum);
if (result === null) {
return null;
}
// 추가 연산 처리 (다중 연산 지원)
if (arithmetic.additionalOperations && Array.isArray(arithmetic.additionalOperations)) {
for (const addOp of arithmetic.additionalOperations) {
const operandValue = this.getOperandValue(
addOp.operand,
sourceRow,
targetRow,
resultValues
);
const operandNum = Number(operandValue) || 0;
result = this.applyOperator(result, addOp.operator, operandNum);
if (result === null) {
logger.warn(`⚠️ 추가 연산 실패: ${addOp.operator}`);
return null;
}
logger.info(` 추가 연산: ${addOp.operator} ${operandNum} = ${result}`);
}
}
return result;
}
/**
* 단일 연산자 적용
*/
private static applyOperator(
left: number,
operator: string,
right: number
): number | null {
switch (operator) {
case "+":
return leftNum + rightNum;
return left + right;
case "-":
return leftNum - rightNum;
return left - right;
case "*":
return leftNum * rightNum;
return left * right;
case "/":
if (rightNum === 0) {
if (right === 0) {
logger.warn(`⚠️ 0으로 나누기 시도`);
return null;
}
return leftNum / rightNum;
return left / right;
case "%":
if (rightNum === 0) {
if (right === 0) {
logger.warn(`⚠️ 0으로 나머지 연산 시도`);
return null;
}
return leftNum % rightNum;
return left % right;
default:
throw new Error(`지원하지 않는 연산자: ${arithmetic.operator}`);
throw new Error(`지원하지 않는 연산자: ${operator}`);
}
}