From 97b5cd7a5b6d79ae5753abeadb6757024fa1aa71 Mon Sep 17 00:00:00 2001 From: kjs Date: Wed, 19 Nov 2025 13:48:44 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=8B=A4=EB=8B=A8=EA=B3=84=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=20=ED=99=98=EA=B2=BD=EC=97=90=EC=84=9C=20=EB=B6=80?= =?UTF-8?q?=EB=AA=A8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A7=A4=ED=95=91=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 문제: - 메인 화면(거래처 선택) → 첫 번째 모달(품목 선택) → 두 번째 모달(상세 입력) - selectedRowsData는 바로 이전 화면 데이터만 제공하여 2단계 이전 데이터 접근 불가 - customer_id가 NULL로 저장됨 해결: - modalDataStore의 전역 레지스트리에서 모든 누적 데이터 접근 - sourceTable에 따라 적절한 데이터 소스 자동 선택 - 거래처 데이터(customer_mng)를 modalDataStore에서 직접 가져옴 기술적 변경: - ButtonPrimaryComponent: allComponents에서 componentConfigs 수집 및 전달 - ButtonActionContext: componentConfigs 속성 추가 - handleBatchSave: modalDataStore에서 테이블별 데이터 조회 - parentDataMapping 로직: sourceTable 기반 데이터 소스 자동 감지 - 디버깅 로그 강화 (modalDataStore 키, 데이터 소스 추적) --- .../button-primary/ButtonPrimaryComponent.tsx | 14 +++++- frontend/lib/utils/buttonActions.ts | 49 +++++++++++++++---- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/frontend/lib/registry/components/button-primary/ButtonPrimaryComponent.tsx b/frontend/lib/registry/components/button-primary/ButtonPrimaryComponent.tsx index 1ae66e0b..112a285c 100644 --- a/frontend/lib/registry/components/button-primary/ButtonPrimaryComponent.tsx +++ b/frontend/lib/registry/components/button-primary/ButtonPrimaryComponent.tsx @@ -393,6 +393,16 @@ export const ButtonPrimaryComponent: React.FC = ({ return; } + // 🆕 모든 컴포넌트의 설정 수집 (parentDataMapping 등) + const componentConfigs: Record = {}; + if (allComponents && Array.isArray(allComponents)) { + for (const comp of allComponents) { + if (comp.id && comp.componentConfig) { + componentConfigs[comp.id] = comp.componentConfig; + } + } + } + const context: ButtonActionContext = { formData: formData || {}, originalData: originalData || {}, // 부분 업데이트용 원본 데이터 추가 @@ -418,7 +428,9 @@ export const ButtonPrimaryComponent: React.FC = ({ // 플로우 선택된 데이터 정보 추가 flowSelectedData, flowSelectedStepId, - }; + // 🆕 컴포넌트별 설정 (parentDataMapping 등) + componentConfigs, + } as ButtonActionContext; // 확인이 필요한 액션인지 확인 if (confirmationRequiredActions.includes(processedConfig.action.type)) { diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index ca390a8f..58a3b288 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -135,6 +135,9 @@ export interface ButtonActionContext { currentPage?: number; // 현재 페이지 pageSize?: number; // 페이지 크기 totalItems?: number; // 전체 항목 수 + + // 🆕 컴포넌트별 설정 (parentDataMapping 등) + componentConfigs?: Record; // 컴포넌트 ID → 컴포넌트 설정 } /** @@ -538,9 +541,19 @@ export class ButtonActionExecutor { // selectedRowsData 또는 originalData를 parentData로 사용 const parentData = selectedRowsData?.[0] || originalData || {}; + // 🆕 modalDataStore에서 누적된 모든 테이블 데이터 가져오기 + // (여러 단계 모달에서 전달된 데이터 접근용) + const modalDataStore = typeof window !== 'undefined' + ? (window as any).__modalDataRegistry || {} + : {}; + console.log(`🔍 [handleBatchSave] 부모 데이터:`, { hasParentData: Object.keys(parentData).length > 0, parentDataKeys: Object.keys(parentData), + parentDataFull: parentData, + selectedRowsData, + originalData, + modalDataStoreKeys: Object.keys(modalDataStore), }); // 각 SelectedItemsDetailInput 컴포넌트의 데이터 처리 @@ -555,14 +568,15 @@ export class ButtonActionExecutor { console.log(`📦 [handleBatchSave] ${key} 처리 중 (${items.length}개 품목)`); // 🆕 이 컴포넌트의 parentDataMapping 설정 가져오기 - // TODO: 실제로는 componentConfig에서 가져와야 함 - // 현재는 selectedItemsKeys[0]을 사용하여 임시로 가져옴 - const componentConfig = (context as any).componentConfigs?.[key]; + const componentConfig = context.componentConfigs?.[key]; const parentDataMapping = componentConfig?.parentDataMapping || []; console.log(`🔍 [handleBatchSave] parentDataMapping 설정:`, { + componentId: key, + hasComponentConfig: !!componentConfig, hasMapping: parentDataMapping.length > 0, - mappings: parentDataMapping + mappings: parentDataMapping, + sourceTable: componentConfig?.sourceTable, }); // 🆕 각 품목의 그룹 간 조합(카티션 곱) 생성 @@ -615,8 +629,8 @@ export class ButtonActionExecutor { let sourceData: any; // 🔍 sourceTable과 실제 데이터 테이블 비교 - // - parentData는 이전 화면 데이터 (예: 거래처 테이블) - // - item.originalData는 선택된 항목 데이터 (예: 품목 테이블) + // - modalDataStore는 모든 이전 화면의 누적 데이터 (예: 거래처, 품목) + // - item.originalData는 현재 선택된 항목 데이터 (예: 품목 테이블) // 원본 데이터 테이블명 확인 (sourceTable이 config에 명시되어 있음) const sourceTableName = mapping.sourceTable; @@ -629,13 +643,30 @@ export class ButtonActionExecutor { sourceData = item.originalData; console.log(` 📦 소스: 선택된 항목 데이터 (${sourceTableName})`); } else { - // 이전 화면 데이터 사용 - sourceData = parentData; - console.log(` 👤 소스: 이전 화면 데이터 (${sourceTableName})`); + // 🆕 modalDataStore에서 해당 테이블 데이터 가져오기 + const tableData = modalDataStore[sourceTableName]; + if (tableData && Array.isArray(tableData) && tableData.length > 0) { + sourceData = tableData[0]; // 첫 번째 항목 사용 + console.log(` 🌐 소스: modalDataStore (${sourceTableName})`); + } else { + // 폴백: 이전 화면 데이터 사용 + sourceData = parentData; + console.log(` 👤 소스: 이전 화면 데이터 (${sourceTableName}) [폴백]`); + } } const sourceValue = sourceData[mapping.sourceField]; + console.log(` 🔍 데이터 소스 상세:`, { + sourceTable: sourceTableName, + selectedItemTable, + isFromSelectedItem: sourceTableName === selectedItemTable, + sourceDataKeys: Object.keys(sourceData), + sourceField: mapping.sourceField, + sourceValue, + targetField: mapping.targetField + }); + if (sourceValue !== undefined && sourceValue !== null) { mappedData[mapping.targetField] = sourceValue; console.log(` ✅ [${sourceTableName}] ${mapping.sourceField} → ${mapping.targetField}: ${sourceValue}`);