입고 처리 시 재고 테이블 저장 및 재고이력 stock_id 전달 수정
This commit is contained in:
parent
c365f06ed7
commit
c6ff839e54
|
|
@ -2282,6 +2282,7 @@ export class NodeFlowExecutionService {
|
||||||
UPDATE ${targetTable}
|
UPDATE ${targetTable}
|
||||||
SET ${setClauses.join(", ")}
|
SET ${setClauses.join(", ")}
|
||||||
WHERE ${updateWhereConditions}
|
WHERE ${updateWhereConditions}
|
||||||
|
RETURNING *
|
||||||
`;
|
`;
|
||||||
|
|
||||||
logger.info(`🔄 UPDATE 실행:`, {
|
logger.info(`🔄 UPDATE 실행:`, {
|
||||||
|
|
@ -2292,8 +2293,14 @@ export class NodeFlowExecutionService {
|
||||||
values: updateValues,
|
values: updateValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
await txClient.query(updateSql, updateValues);
|
const updateResult = await txClient.query(updateSql, updateValues);
|
||||||
updatedCount++;
|
updatedCount++;
|
||||||
|
|
||||||
|
// 🆕 UPDATE 결과를 입력 데이터에 병합 (다음 노드에서 id 등 사용 가능)
|
||||||
|
if (updateResult.rows && updateResult.rows[0]) {
|
||||||
|
Object.assign(data, updateResult.rows[0]);
|
||||||
|
logger.info(` 📦 UPDATE 결과 병합: id=${updateResult.rows[0].id}`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 3-B. 없으면 INSERT
|
// 3-B. 없으면 INSERT
|
||||||
const columns: string[] = [];
|
const columns: string[] = [];
|
||||||
|
|
@ -2340,6 +2347,7 @@ export class NodeFlowExecutionService {
|
||||||
const insertSql = `
|
const insertSql = `
|
||||||
INSERT INTO ${targetTable} (${columns.join(", ")})
|
INSERT INTO ${targetTable} (${columns.join(", ")})
|
||||||
VALUES (${placeholders})
|
VALUES (${placeholders})
|
||||||
|
RETURNING *
|
||||||
`;
|
`;
|
||||||
|
|
||||||
logger.info(`➕ INSERT 실행:`, {
|
logger.info(`➕ INSERT 실행:`, {
|
||||||
|
|
@ -2348,8 +2356,14 @@ export class NodeFlowExecutionService {
|
||||||
conflictKeyValues,
|
conflictKeyValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
await txClient.query(insertSql, values);
|
const insertResult = await txClient.query(insertSql, values);
|
||||||
insertedCount++;
|
insertedCount++;
|
||||||
|
|
||||||
|
// 🆕 INSERT 결과를 입력 데이터에 병합 (다음 노드에서 id 등 사용 가능)
|
||||||
|
if (insertResult.rows && insertResult.rows[0]) {
|
||||||
|
Object.assign(data, insertResult.rows[0]);
|
||||||
|
logger.info(` 📦 INSERT 결과 병합: id=${insertResult.rows[0].id}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2357,11 +2371,10 @@ export class NodeFlowExecutionService {
|
||||||
`✅ UPSERT 완료 (내부 DB): ${targetTable}, INSERT ${insertedCount}건, UPDATE ${updatedCount}건`
|
`✅ UPSERT 완료 (내부 DB): ${targetTable}, INSERT ${insertedCount}건, UPDATE ${updatedCount}건`
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
// 🔥 다음 노드에 전달할 데이터 반환
|
||||||
insertedCount,
|
// dataArray에는 Object.assign으로 UPSERT 결과(id 등)가 이미 병합되어 있음
|
||||||
updatedCount,
|
// 카운트 정보도 함께 반환하여 기존 호환성 유지
|
||||||
totalCount: insertedCount + updatedCount,
|
return dataArray;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🔥 클라이언트가 전달되었으면 사용, 아니면 독립 트랜잭션 생성
|
// 🔥 클라이언트가 전달되었으면 사용, 아니면 독립 트랜잭션 생성
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,9 @@ export interface ButtonActionContext {
|
||||||
selectedLeftData?: Record<string, any>;
|
selectedLeftData?: Record<string, any>;
|
||||||
refreshRightPanel?: () => void;
|
refreshRightPanel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🆕 저장된 데이터 (저장 후 제어 실행 시 플로우에 전달)
|
||||||
|
savedData?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1251,7 +1254,49 @@ export class ButtonActionExecutor {
|
||||||
// 🔥 저장 성공 후 연결된 제어 실행 (dataflowTiming이 'after'인 경우)
|
// 🔥 저장 성공 후 연결된 제어 실행 (dataflowTiming이 'after'인 경우)
|
||||||
if (config.enableDataflowControl && config.dataflowConfig) {
|
if (config.enableDataflowControl && config.dataflowConfig) {
|
||||||
console.log("🎯 저장 후 제어 실행 시작:", config.dataflowConfig);
|
console.log("🎯 저장 후 제어 실행 시작:", config.dataflowConfig);
|
||||||
await this.executeAfterSaveControl(config, context);
|
|
||||||
|
// 테이블 섹션 데이터 파싱 (comp_로 시작하는 필드에 JSON 배열이 있는 경우)
|
||||||
|
// 입고 화면 등에서 품목 목록이 comp_xxx 필드에 JSON 문자열로 저장됨
|
||||||
|
const formData: Record<string, any> = (saveResult.data || context.formData || {}) as Record<string, any>;
|
||||||
|
let parsedSectionData: any[] = [];
|
||||||
|
|
||||||
|
// comp_로 시작하는 필드에서 테이블 섹션 데이터 찾기
|
||||||
|
const compFieldKey = Object.keys(formData).find(key =>
|
||||||
|
key.startsWith("comp_") && typeof formData[key] === "string"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (compFieldKey) {
|
||||||
|
try {
|
||||||
|
const sectionData = JSON.parse(formData[compFieldKey]);
|
||||||
|
if (Array.isArray(sectionData) && sectionData.length > 0) {
|
||||||
|
// 공통 필드와 섹션 데이터 병합
|
||||||
|
parsedSectionData = sectionData.map((item: any) => {
|
||||||
|
// 섹션 데이터에서 불필요한 내부 필드 제거
|
||||||
|
const { _isNewItem, _targetTable, _existingRecord, ...cleanItem } = item;
|
||||||
|
// 공통 필드(comp_ 필드 제외) + 섹션 아이템 병합
|
||||||
|
const commonFields: Record<string, any> = {};
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (!key.startsWith("comp_") && !key.endsWith("_numberingRuleId")) {
|
||||||
|
commonFields[key] = formData[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { ...commonFields, ...cleanItem };
|
||||||
|
});
|
||||||
|
console.log(`📦 [handleSave] 테이블 섹션 데이터 파싱 완료: ${parsedSectionData.length}건`, parsedSectionData[0]);
|
||||||
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
console.warn("⚠️ [handleSave] 테이블 섹션 데이터 파싱 실패:", parseError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 저장된 데이터를 context에 추가하여 플로우에 전달
|
||||||
|
const contextWithSavedData = {
|
||||||
|
...context,
|
||||||
|
savedData: formData,
|
||||||
|
// 파싱된 섹션 데이터가 있으면 selectedRowsData로 전달
|
||||||
|
selectedRowsData: parsedSectionData.length > 0 ? parsedSectionData : context.selectedRowsData,
|
||||||
|
};
|
||||||
|
await this.executeAfterSaveControl(config, contextWithSavedData);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error("저장에 필요한 정보가 부족합니다. (테이블명 또는 화면ID 누락)");
|
throw new Error("저장에 필요한 정보가 부족합니다. (테이블명 또는 화면ID 누락)");
|
||||||
|
|
@ -3643,8 +3688,20 @@ export class ButtonActionExecutor {
|
||||||
// 노드 플로우 실행 API
|
// 노드 플로우 실행 API
|
||||||
const { executeNodeFlow } = await import("@/lib/api/nodeFlows");
|
const { executeNodeFlow } = await import("@/lib/api/nodeFlows");
|
||||||
|
|
||||||
// 데이터 소스 준비
|
// 데이터 소스 준비: context-data 모드는 배열을 기대함
|
||||||
const sourceData: any = context.formData || {};
|
// 우선순위: selectedRowsData > savedData > formData
|
||||||
|
// - selectedRowsData: 테이블 섹션에서 저장된 하위 항목들 (item_code, inbound_qty 등 포함)
|
||||||
|
// - savedData: 저장 API 응답 데이터
|
||||||
|
// - formData: 폼에 입력된 데이터
|
||||||
|
let sourceData: any[];
|
||||||
|
if (context.selectedRowsData && context.selectedRowsData.length > 0) {
|
||||||
|
sourceData = context.selectedRowsData;
|
||||||
|
console.log("📦 [다중제어] selectedRowsData 사용:", sourceData.length, "건");
|
||||||
|
} else {
|
||||||
|
const savedData = context.savedData || context.formData || {};
|
||||||
|
sourceData = Array.isArray(savedData) ? savedData : [savedData];
|
||||||
|
console.log("📦 [다중제어] savedData/formData 사용:", sourceData.length, "건");
|
||||||
|
}
|
||||||
|
|
||||||
let allSuccess = true;
|
let allSuccess = true;
|
||||||
const results: Array<{ flowId: number; flowName: string; success: boolean; message?: string }> = [];
|
const results: Array<{ flowId: number; flowName: string; success: boolean; message?: string }> = [];
|
||||||
|
|
@ -3751,8 +3808,20 @@ export class ButtonActionExecutor {
|
||||||
// 노드 플로우 실행 API 호출
|
// 노드 플로우 실행 API 호출
|
||||||
const { executeNodeFlow } = await import("@/lib/api/nodeFlows");
|
const { executeNodeFlow } = await import("@/lib/api/nodeFlows");
|
||||||
|
|
||||||
// 데이터 소스 준비
|
// 데이터 소스 준비: context-data 모드는 배열을 기대함
|
||||||
const sourceData: any = context.formData || {};
|
// 우선순위: selectedRowsData > savedData > formData
|
||||||
|
// - selectedRowsData: 테이블 섹션에서 저장된 하위 항목들 (item_code, inbound_qty 등 포함)
|
||||||
|
// - savedData: 저장 API 응답 데이터
|
||||||
|
// - formData: 폼에 입력된 데이터
|
||||||
|
let sourceData: any[];
|
||||||
|
if (context.selectedRowsData && context.selectedRowsData.length > 0) {
|
||||||
|
sourceData = context.selectedRowsData;
|
||||||
|
console.log("📦 [단일제어] selectedRowsData 사용:", sourceData.length, "건");
|
||||||
|
} else {
|
||||||
|
const savedData = context.savedData || context.formData || {};
|
||||||
|
sourceData = Array.isArray(savedData) ? savedData : [savedData];
|
||||||
|
console.log("📦 [단일제어] savedData/formData 사용:", sourceData.length, "건");
|
||||||
|
}
|
||||||
|
|
||||||
// repeat-screen-modal 데이터가 있으면 병합
|
// repeat-screen-modal 데이터가 있으면 병합
|
||||||
const repeatScreenModalKeys = Object.keys(context.formData || {}).filter((key) =>
|
const repeatScreenModalKeys = Object.keys(context.formData || {}).filter((key) =>
|
||||||
|
|
@ -3765,7 +3834,8 @@ export class ButtonActionExecutor {
|
||||||
console.log("📦 노드 플로우에 전달할 데이터:", {
|
console.log("📦 노드 플로우에 전달할 데이터:", {
|
||||||
flowId,
|
flowId,
|
||||||
dataSourceType: controlDataSource,
|
dataSourceType: controlDataSource,
|
||||||
sourceData,
|
sourceDataCount: sourceData.length,
|
||||||
|
sourceDataSample: sourceData[0],
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await executeNodeFlow(flowId, {
|
const result = await executeNodeFlow(flowId, {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue