diff --git a/frontend/lib/api/dynamicForm.ts b/frontend/lib/api/dynamicForm.ts index a5a3b2eb..d2433c48 100644 --- a/frontend/lib/api/dynamicForm.ts +++ b/frontend/lib/api/dynamicForm.ts @@ -93,10 +93,15 @@ export class DynamicFormApi { ): Promise> { try { console.log("๐Ÿ”„ ํผ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ์š”์ฒญ:", { id, formData }); + console.log("๐ŸŒ API URL:", `/dynamic-form/${id}`); + console.log("๐Ÿ“ฆ ์š”์ฒญ ๋ณธ๋ฌธ:", JSON.stringify(formData, null, 2)); const response = await apiClient.put(`/dynamic-form/${id}`, formData); console.log("โœ… ํผ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต:", response.data); + console.log("๐Ÿ“Š ์‘๋‹ต ์ƒํƒœ:", response.status); + console.log("๐Ÿ“‹ ์‘๋‹ต ํ—ค๋”:", response.headers); + return { success: true, data: response.data, @@ -104,6 +109,8 @@ export class DynamicFormApi { }; } catch (error: any) { console.error("โŒ ํผ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ์‹คํŒจ:", error); + console.error("๐Ÿ“Š ์—๋Ÿฌ ์‘๋‹ต:", error.response?.data); + console.error("๐Ÿ“Š ์—๋Ÿฌ ์ƒํƒœ:", error.response?.status); const errorMessage = error.response?.data?.message || error.message || "๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."; diff --git a/frontend/lib/registry/components/universal-form-modal/UniversalFormModalComponent.tsx b/frontend/lib/registry/components/universal-form-modal/UniversalFormModalComponent.tsx index 4ee024a4..3e043331 100644 --- a/frontend/lib/registry/components/universal-form-modal/UniversalFormModalComponent.tsx +++ b/frontend/lib/registry/components/universal-form-modal/UniversalFormModalComponent.tsx @@ -333,6 +333,14 @@ export function UniversalFormModalComponent({ } } + // ๐Ÿ†• ํ…Œ์ด๋ธ” ์„น์…˜ ๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉ (ํ’ˆ๋ชฉ ๋ฆฌ์ŠคํŠธ ๋“ฑ) + for (const [key, value] of Object.entries(formData)) { + if (key.startsWith("_tableSection_") && Array.isArray(value)) { + event.detail.formData[key] = value; + console.log(`[UniversalFormModal] ํ…Œ์ด๋ธ” ์„น์…˜ ๋ณ‘ํ•ฉ: ${key}, ${value.length}๊ฐœ ํ•ญ๋ชฉ`); + } + } + // ๐Ÿ†• ์ˆ˜์ • ๋ชจ๋“œ: ์›๋ณธ ๊ทธ๋ฃน ๋ฐ์ดํ„ฐ ์ „๋‹ฌ (UPDATE/DELETE ์ถ”์ ์šฉ) if (originalGroupedData.length > 0) { event.detail.formData._originalGroupedData = originalGroupedData; @@ -355,15 +363,9 @@ export function UniversalFormModalComponent({ // ํ…Œ์ด๋ธ” ํƒ€์ž… ์„น์…˜ ์ฐพ๊ธฐ const tableSection = config.sections.find((s) => s.type === "table"); if (!tableSection) { - // console.log("[UniversalFormModal] ํ…Œ์ด๋ธ” ์„น์…˜ ์—†์Œ - _groupedData ๋ฌด์‹œ"); return; } - // console.log("[UniversalFormModal] ์ˆ˜์ • ๋ชจ๋“œ - ํ…Œ์ด๋ธ” ์„น์…˜ ์ดˆ๊ธฐํ™”:", { - // sectionId: tableSection.id, - // itemCount: _groupedData.length, - // }); - // ์›๋ณธ ๋ฐ์ดํ„ฐ ์ €์žฅ (์ˆ˜์ •/์‚ญ์ œ ์ถ”์ ์šฉ) setOriginalGroupedData(JSON.parse(JSON.stringify(_groupedData))); diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index 4c9d638b..7512d6c0 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -724,11 +724,16 @@ export class ButtonActionExecutor { // originalData๋Š” ์ˆ˜์ • ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ editData๋กœ ์ „๋‹ฌ๋˜์–ด context.originalData๋กœ ์„ค์ •๋จ // ๋นˆ ๊ฐ์ฒด {}๋„ truthy์ด๋ฏ€๋กœ Object.keys๋กœ ์‹ค์ œ ๋ฐ์ดํ„ฐ ์œ ๋ฌด ํ™•์ธ const hasRealOriginalData = originalData && Object.keys(originalData).length > 0; - const isUpdate = hasRealOriginalData && !!primaryKeyValue; + + // ๐Ÿ†• ํด๋ฐฑ ๋กœ์ง: originalData๊ฐ€ ์—†์–ด๋„ formData์— id๊ฐ€ ์žˆ์œผ๋ฉด UPDATE๋กœ ํŒ๋‹จ + // ์กฐ๊ฑด๋ถ€ ์ปจํ…Œ์ด๋„ˆ ๋“ฑ์—์„œ originalData ์ „๋‹ฌ์ด ๋ˆ„๋ฝ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌ + const hasIdInFormData = formData.id !== undefined && formData.id !== null && formData.id !== ""; + const isUpdate = (hasRealOriginalData || hasIdInFormData) && !!primaryKeyValue; console.log("๐Ÿ” [handleSave] INSERT/UPDATE ํŒ๋‹จ:", { hasOriginalData: !!originalData, hasRealOriginalData, + hasIdInFormData, originalDataKeys: originalData ? Object.keys(originalData) : [], primaryKeyValue, isUpdate, @@ -741,18 +746,18 @@ export class ButtonActionExecutor { // UPDATE ์ฒ˜๋ฆฌ - ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ ์‚ฌ์šฉ (์›๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ) console.log("๐Ÿ”„ UPDATE ๋ชจ๋“œ๋กœ ์ €์žฅ:", { primaryKeyValue, - formData, - originalData, hasOriginalData: !!originalData, + hasIdInFormData, + updateReason: hasRealOriginalData ? "originalData ์กด์žฌ" : "formData.id ์กด์žฌ (ํด๋ฐฑ)", }); - if (originalData) { + if (hasRealOriginalData) { // ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ: ๋ณ€๊ฒฝ๋œ ํ•„๋“œ๋งŒ ์—…๋ฐ์ดํŠธ console.log("๐Ÿ“ ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ ์‹คํ–‰ (๋ณ€๊ฒฝ๋œ ํ•„๋“œ๋งŒ)"); saveResult = await DynamicFormApi.updateFormDataPartial(primaryKeyValue, originalData, formData, tableName); } else { - // ์ „์ฒด ์—…๋ฐ์ดํŠธ (๊ธฐ์กด ๋ฐฉ์‹) - console.log("๐Ÿ“ ์ „์ฒด ์—…๋ฐ์ดํŠธ ์‹คํ–‰ (๋ชจ๋“  ํ•„๋“œ)"); + // ์ „์ฒด ์—…๋ฐ์ดํŠธ (originalData ์—†์ด id๋กœ UPDATE ํŒ๋‹จ๋œ ๊ฒฝ์šฐ) + console.log("๐Ÿ“ ์ „์ฒด ์—…๋ฐ์ดํŠธ ์‹คํ–‰ (originalData ์—†์Œ - ํด๋ฐฑ ๋ชจ๋“œ)"); saveResult = await DynamicFormApi.updateFormData(primaryKeyValue, { tableName, data: formData, @@ -1862,37 +1867,45 @@ export class ButtonActionExecutor { const originalItem = originalGroupedData.find((orig) => orig.id === item.id); if (!originalItem) { - console.warn(`โš ๏ธ [UPDATE] ์›๋ณธ ๋ฐ์ดํ„ฐ ์—†์Œ - INSERT๋กœ ์ฒ˜๋ฆฌ: id=${item.id}`); - // ์›๋ณธ์ด ์—†์œผ๋ฉด ์‹ ๊ทœ๋กœ ์ฒ˜๋ฆฌ - const rowToSave = { ...commonFieldsData, ...item, ...userInfo }; - Object.keys(rowToSave).forEach((key) => { + // ๐Ÿ†• ํด๋ฐฑ ๋กœ์ง: ์›๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์–ด๋„ id๊ฐ€ ์žˆ์œผ๋ฉด UPDATE ์‹œ๋„ + // originalGroupedData ์ „๋‹ฌ์ด ๋ˆ„๋ฝ๋œ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌ + console.warn(`โš ๏ธ [UPDATE] ์›๋ณธ ๋ฐ์ดํ„ฐ ์—†์Œ - id๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ UPDATE ์‹œ๋„ (ํด๋ฐฑ): id=${item.id}`); + + // โš ๏ธ ์ค‘์š”: commonFieldsData๊ฐ€ item๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์•ผ ํ•จ + // item์— ์žˆ๋Š” ๊ธฐ์กด ๊ฐ’(์˜ˆ: manager_id=123)์ด commonFieldsData์˜ ์ƒˆ ๊ฐ’(manager_id=234)์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๋„๋ก + // ์ˆœ์„œ: item(๊ธฐ์กด) โ†’ commonFieldsData(์ƒˆ๋กœ ์ž…๋ ฅ) โ†’ userInfo(๋ฉ”ํƒ€๋ฐ์ดํ„ฐ) + const rowToUpdate = { ...item, ...commonFieldsData, ...userInfo }; + Object.keys(rowToUpdate).forEach((key) => { if (key.startsWith("_")) { - delete rowToSave[key]; + delete rowToUpdate[key]; } }); - delete rowToSave.id; // id ์ œ๊ฑฐํ•˜์—ฌ INSERT - // ๐Ÿ†• ๋ฉ”์ธ ๋ ˆ์ฝ”๋“œ ID ์—ฐ๊ฒฐ (๋ณ„๋„ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ) - if (targetTableName && mainRecordId && saveConfig.primaryKeyColumn) { - rowToSave[saveConfig.primaryKeyColumn] = mainRecordId; - } - - const saveResult = await DynamicFormApi.saveFormData({ - screenId: screenId!, + console.log("๐Ÿ“ [UPDATE ํด๋ฐฑ] ์ €์žฅํ•  ๋ฐ์ดํ„ฐ:", { + id: item.id, tableName: saveTableName, - data: rowToSave, + commonFieldsData, + itemFields: Object.keys(item).filter(k => !k.startsWith("_")), + rowToUpdate, }); - if (!saveResult.success) { - throw new Error(saveResult.message || "ํ’ˆ๋ชฉ ์ €์žฅ ์‹คํŒจ"); + // id๋ฅผ ์œ ์ง€ํ•˜๊ณ  UPDATE ์‹คํ–‰ + const updateResult = await DynamicFormApi.updateFormData(item.id, { + tableName: saveTableName, + data: rowToUpdate, + }); + + if (!updateResult.success) { + throw new Error(updateResult.message || "ํ’ˆ๋ชฉ ์ˆ˜์ • ์‹คํŒจ"); } - insertedCount++; + updatedCount++; continue; } // ๋ณ€๊ฒฝ ์‚ฌํ•ญ ํ™•์ธ (๊ณตํ†ต ํ•„๋“œ ํฌํ•จ) - const currentDataWithCommon = { ...commonFieldsData, ...item }; + // โš ๏ธ ์ค‘์š”: commonFieldsData๊ฐ€ item๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์•ผ ํ•จ (์ƒˆ๋กœ ์ž…๋ ฅํ•œ ๊ฐ’์ด ๊ธฐ์กด ๊ฐ’์„ ๋ฎ์–ด์”€) + const currentDataWithCommon = { ...item, ...commonFieldsData }; const hasChanges = this.checkForChanges(originalItem, currentDataWithCommon); if (hasChanges) { @@ -1917,13 +1930,14 @@ export class ButtonActionExecutor { } // 3๏ธโƒฃ ์‚ญ์ œ๋œ ํ’ˆ๋ชฉ DELETE (์›๋ณธ์—๋Š” ์žˆ์ง€๋งŒ ํ˜„์žฌ์—๋Š” ์—†๋Š” ํ•ญ๋ชฉ) - const currentIds = new Set(currentItems.map((item) => item.id).filter(Boolean)); - const deletedItems = originalGroupedData.filter((orig) => orig.id && !currentIds.has(orig.id)); + // โš ๏ธ id ํƒ€์ž… ํ†ต์ผ: ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋น„๊ต (์ˆซ์ž vs ๋ฌธ์ž์—ด ๋ถˆ์ผ์น˜ ๋ฐฉ์ง€) + const currentIds = new Set(currentItems.map((item) => String(item.id)).filter(Boolean)); + const deletedItems = originalGroupedData.filter((orig) => orig.id && !currentIds.has(String(orig.id))); for (const deletedItem of deletedItems) { console.log(`๐Ÿ—‘๏ธ [DELETE] ํ’ˆ๋ชฉ ์‚ญ์ œ: id=${deletedItem.id}, tableName=${saveTableName}`); - const deleteResult = await DynamicFormApi.deleteFormDataFromTable(saveTableName, deletedItem.id); + const deleteResult = await DynamicFormApi.deleteFormDataFromTable(deletedItem.id, saveTableName); if (!deleteResult.success) { throw new Error(deleteResult.message || "ํ’ˆ๋ชฉ ์‚ญ์ œ ์‹คํŒจ");