feat(UniversalFormModal): 섹션별 저장 방식 설정 기능 추가
SectionSaveMode 타입 추가 (공통 저장/개별 저장) SaveSettingsModal에 섹션별/필드별 저장 방식 설정 UI 추가 saveSingleRow()에 공통 필드 + 품목 병합 저장 로직 구현 buttonActions.ts에 외부 저장 버튼용 병합 저장 처리 추가
This commit is contained in:
@@ -675,6 +675,14 @@ export class ButtonActionExecutor {
|
||||
console.log("⚠️ [handleSave] formData 전체 내용:", context.formData);
|
||||
}
|
||||
|
||||
// 🆕 Universal Form Modal 테이블 섹션 병합 저장 처리
|
||||
// 범용_폼_모달 내부에 _tableSection_ 데이터가 있는 경우 공통 필드 + 개별 품목 병합 저장
|
||||
const universalFormModalResult = await this.handleUniversalFormModalTableSectionSave(config, context, formData);
|
||||
if (universalFormModalResult.handled) {
|
||||
console.log("✅ [handleSave] Universal Form Modal 테이블 섹션 저장 완료");
|
||||
return universalFormModalResult.success;
|
||||
}
|
||||
|
||||
// 폼 유효성 검사
|
||||
if (config.validateForm) {
|
||||
const validation = this.validateFormData(formData);
|
||||
@@ -1479,6 +1487,122 @@ export class ButtonActionExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🆕 Universal Form Modal 테이블 섹션 병합 저장 처리
|
||||
* 범용_폼_모달 내부의 공통 필드 + _tableSection_ 데이터를 병합하여 품목별로 저장
|
||||
*/
|
||||
private static async handleUniversalFormModalTableSectionSave(
|
||||
config: ButtonActionConfig,
|
||||
context: ButtonActionContext,
|
||||
formData: Record<string, any>,
|
||||
): Promise<{ handled: boolean; success: boolean }> {
|
||||
const { tableName, screenId } = context;
|
||||
|
||||
// 범용_폼_모달 키 찾기 (컬럼명에 따라 다를 수 있음)
|
||||
const universalFormModalKey = Object.keys(formData).find((key) => {
|
||||
const value = formData[key];
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
||||
// _tableSection_ 키가 있는지 확인
|
||||
return Object.keys(value).some((k) => k.startsWith("_tableSection_"));
|
||||
});
|
||||
|
||||
if (!universalFormModalKey) {
|
||||
return { handled: false, success: false };
|
||||
}
|
||||
|
||||
console.log("🎯 [handleUniversalFormModalTableSectionSave] Universal Form Modal 감지:", universalFormModalKey);
|
||||
|
||||
const modalData = formData[universalFormModalKey];
|
||||
|
||||
// _tableSection_ 데이터 추출
|
||||
const tableSectionData: Record<string, any[]> = {};
|
||||
const commonFieldsData: Record<string, any> = {};
|
||||
|
||||
for (const [key, value] of Object.entries(modalData)) {
|
||||
if (key.startsWith("_tableSection_")) {
|
||||
const sectionId = key.replace("_tableSection_", "");
|
||||
tableSectionData[sectionId] = value as any[];
|
||||
} else if (!key.startsWith("_")) {
|
||||
// _로 시작하지 않는 필드는 공통 필드로 처리
|
||||
commonFieldsData[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("🎯 [handleUniversalFormModalTableSectionSave] 데이터 분리:", {
|
||||
commonFields: Object.keys(commonFieldsData),
|
||||
tableSections: Object.keys(tableSectionData),
|
||||
tableSectionCounts: Object.entries(tableSectionData).map(([k, v]) => ({ [k]: v.length })),
|
||||
});
|
||||
|
||||
// 테이블 섹션 데이터가 없으면 처리하지 않음
|
||||
const hasTableSectionData = Object.values(tableSectionData).some((arr) => arr.length > 0);
|
||||
if (!hasTableSectionData) {
|
||||
console.log("⚠️ [handleUniversalFormModalTableSectionSave] 테이블 섹션 데이터 없음 - 일반 저장으로 전환");
|
||||
return { handled: false, success: false };
|
||||
}
|
||||
|
||||
try {
|
||||
// 사용자 정보 추가
|
||||
if (!context.userId) {
|
||||
throw new Error("사용자 정보를 불러올 수 없습니다. 다시 로그인해주세요.");
|
||||
}
|
||||
|
||||
const userInfo = {
|
||||
writer: context.userId,
|
||||
created_by: context.userId,
|
||||
updated_by: context.userId,
|
||||
company_code: context.companyCode || "",
|
||||
};
|
||||
|
||||
let totalSaved = 0;
|
||||
|
||||
// 각 테이블 섹션의 품목별로 저장
|
||||
for (const [sectionId, items] of Object.entries(tableSectionData)) {
|
||||
console.log(`🔄 [handleUniversalFormModalTableSectionSave] 섹션 ${sectionId} 저장 시작: ${items.length}개 품목`);
|
||||
|
||||
for (const item of items) {
|
||||
// 공통 필드 + 품목 데이터 병합
|
||||
const rowToSave = { ...commonFieldsData, ...item, ...userInfo };
|
||||
|
||||
// 내부 메타데이터 제거
|
||||
Object.keys(rowToSave).forEach((key) => {
|
||||
if (key.startsWith("_")) {
|
||||
delete rowToSave[key];
|
||||
}
|
||||
});
|
||||
|
||||
console.log("📝 [handleUniversalFormModalTableSectionSave] 저장할 행:", rowToSave);
|
||||
|
||||
// INSERT 실행
|
||||
const saveResult = await DynamicFormApi.saveFormData({
|
||||
screenId: screenId!,
|
||||
tableName: tableName!,
|
||||
data: rowToSave,
|
||||
});
|
||||
|
||||
if (!saveResult.success) {
|
||||
throw new Error(saveResult.message || "품목 저장 실패");
|
||||
}
|
||||
|
||||
totalSaved++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ [handleUniversalFormModalTableSectionSave] 총 ${totalSaved}개 행 저장 완료`);
|
||||
toast.success(`${totalSaved}개 항목이 저장되었습니다.`);
|
||||
|
||||
// 저장 성공 이벤트 발생
|
||||
window.dispatchEvent(new CustomEvent("saveSuccess"));
|
||||
window.dispatchEvent(new CustomEvent("refreshTable"));
|
||||
|
||||
return { handled: true, success: true };
|
||||
} catch (error: any) {
|
||||
console.error("❌ [handleUniversalFormModalTableSectionSave] 저장 오류:", error);
|
||||
toast.error(error.message || "저장 중 오류가 발생했습니다.");
|
||||
return { handled: true, success: false };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🆕 배치 저장 액션 처리 (SelectedItemsDetailInput용 - 새로운 데이터 구조)
|
||||
* ItemData[] → 각 품목의 details 배열을 개별 레코드로 저장
|
||||
|
||||
Reference in New Issue
Block a user