diff --git a/backend-node/src/controllers/dynamicFormController.ts b/backend-node/src/controllers/dynamicFormController.ts index 47ee4e94..9b8ef6fc 100644 --- a/backend-node/src/controllers/dynamicFormController.ts +++ b/backend-node/src/controllers/dynamicFormController.ts @@ -12,6 +12,14 @@ export const saveFormData = async ( const { companyCode, userId } = req.user as any; const { screenId, tableName, data } = req.body; + // πŸ” 디버깅: μ‚¬μš©μž 정보 확인 + console.log("πŸ” [saveFormData] μ‚¬μš©μž 정보:", { + userId, + companyCode, + reqUser: req.user, + dataWriter: data.writer, + }); + // ν•„μˆ˜ ν•„λ“œ 검증 (screenIdλŠ” 0일 수 μžˆμœΌλ―€λ‘œ undefined 체크) if (screenId === undefined || screenId === null || !tableName || !data) { return res.status(400).json({ @@ -25,9 +33,12 @@ export const saveFormData = async ( ...data, created_by: userId, updated_by: userId, + writer: data.writer || userId, // βœ… writerκ°€ μ—†μœΌλ©΄ userId둜 μ„€μ • screen_id: screenId, }; + console.log("βœ… [saveFormData] μ΅œμ’… writer κ°’:", formDataWithMeta.writer); + // company_codeλŠ” μ‚¬μš©μžκ°€ λͺ…μ‹œμ μœΌλ‘œ μž…λ ₯ν•œ κ²½μš°μ—λ§Œ μΆ”κ°€ if (data.company_code !== undefined) { formDataWithMeta.company_code = data.company_code; @@ -86,6 +97,7 @@ export const saveFormDataEnhanced = async ( ...data, created_by: userId, updated_by: userId, + writer: data.writer || userId, // βœ… writerκ°€ μ—†μœΌλ©΄ userId둜 μ„€μ • screen_id: screenId, }; @@ -134,6 +146,7 @@ export const updateFormData = async ( const formDataWithMeta = { ...data, updated_by: userId, + writer: data.writer || userId, // βœ… writerκ°€ μ—†μœΌλ©΄ userId둜 μ„€μ • updated_at: new Date(), }; @@ -186,6 +199,7 @@ export const updateFormDataPartial = async ( const newDataWithMeta = { ...newData, updated_by: userId, + writer: newData.writer || userId, // βœ… writerκ°€ μ—†μœΌλ©΄ userId둜 μ„€μ • }; const result = await dynamicFormService.updateFormDataPartial( diff --git a/backend-node/src/services/ddlExecutionService.ts b/backend-node/src/services/ddlExecutionService.ts index 37659bcf..2ed01231 100644 --- a/backend-node/src/services/ddlExecutionService.ts +++ b/backend-node/src/services/ddlExecutionService.ts @@ -363,7 +363,7 @@ export class DDLExecutionService { "id" varchar(500) PRIMARY KEY DEFAULT gen_random_uuid()::text, "created_date" timestamp DEFAULT now(), "updated_date" timestamp DEFAULT now(), - "writer" varchar(500), + "writer" varchar(500) DEFAULT NULL, "company_code" varchar(500)`; // μ΅œμ’… CREATE TABLE 쿼리 diff --git a/frontend/components/screen/InteractiveScreenViewer.tsx b/frontend/components/screen/InteractiveScreenViewer.tsx index 8a114aa4..572aab37 100644 --- a/frontend/components/screen/InteractiveScreenViewer.tsx +++ b/frontend/components/screen/InteractiveScreenViewer.tsx @@ -1221,6 +1221,12 @@ export const InteractiveScreenViewer: React.FC = ( const handleSaveAction = async () => { // console.log("πŸ’Ύ μ €μž₯ μ‹œμž‘"); + // βœ… μ‚¬μš©μž 정보가 λ‘œλ“œλ˜μ§€ μ•Šμ•˜μœΌλ©΄ μ €μž₯ λΆˆκ°€ + if (!user?.userId) { + alert("μ‚¬μš©μž 정보λ₯Ό λΆˆλŸ¬μ˜€λŠ” μ€‘μž…λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."); + return; + } + // κ°œμ„ λœ 검증 μ‹œμŠ€ν…œμ΄ ν™œμ„±ν™”λœ 경우 if (enhancedValidation) { // console.log("πŸ” κ°œμ„ λœ 검증 μ‹œμŠ€ν…œ μ‚¬μš©"); @@ -1357,19 +1363,26 @@ export const InteractiveScreenViewer: React.FC = ( allComponents.find(c => c.columnName)?.tableName || "dynamic_form_data"; // κΈ°λ³Έκ°’ - // πŸ†• μžλ™μœΌλ‘œ μž‘μ„±μž 정보 μΆ”κ°€ - const writerValue = user?.userId || userName || "unknown"; + // πŸ†• μžλ™μœΌλ‘œ μž‘μ„±μž 정보 μΆ”κ°€ (user.userIdκ°€ ν™•μ‹€νžˆ 있음) + const writerValue = user.userId; + const companyCodeValue = user.companyCode || ""; + console.log("πŸ‘€ ν˜„μž¬ μ‚¬μš©μž 정보:", { - userId: user?.userId, + userId: user.userId, userName: userName, - writerValue: writerValue, + companyCode: user.companyCode, // βœ… νšŒμ‚¬ μ½”λ“œ + formDataWriter: mappedData.writer, // βœ… νΌμ—μ„œ μž…λ ₯ν•œ writer κ°’ + formDataCompanyCode: mappedData.company_code, // βœ… νΌμ—μ„œ μž…λ ₯ν•œ company_code κ°’ + defaultWriterValue: writerValue, + companyCodeValue, // βœ… μ΅œμ’… νšŒμ‚¬ μ½”λ“œ κ°’ }); const dataWithUserInfo = { ...mappedData, - writer: writerValue, // ν…Œμ΄λΈ” 생성 μ‹œ μžλ™ μƒμ„±λ˜λŠ” 컬럼 - created_by: writerValue, - updated_by: writerValue, + writer: mappedData.writer || writerValue, // βœ… μž…λ ₯κ°’ μš°μ„ , μ—†μœΌλ©΄ userId + created_by: writerValue, // created_byλŠ” 항상 λ‘œκ·ΈμΈν•œ μ‚¬λžŒ + updated_by: writerValue, // updated_byλŠ” 항상 λ‘œκ·ΈμΈν•œ μ‚¬λžŒ + company_code: mappedData.company_code || companyCodeValue, // βœ… μž…λ ₯κ°’ μš°μ„ , μ—†μœΌλ©΄ user.companyCode }; const saveData: DynamicFormData = { diff --git a/frontend/components/screen/InteractiveScreenViewerDynamic.tsx b/frontend/components/screen/InteractiveScreenViewerDynamic.tsx index e85aab58..8df068eb 100644 --- a/frontend/components/screen/InteractiveScreenViewerDynamic.tsx +++ b/frontend/components/screen/InteractiveScreenViewerDynamic.tsx @@ -190,6 +190,9 @@ export const InteractiveScreenViewerDynamic: React.FC { console.log("πŸ” ν…Œμ΄λΈ”μ—μ„œ μ„ νƒλœ ν–‰ 데이터:", selectedData); diff --git a/frontend/components/screen/SaveModal.tsx b/frontend/components/screen/SaveModal.tsx index 271a83d9..dd402933 100644 --- a/frontend/components/screen/SaveModal.tsx +++ b/frontend/components/screen/SaveModal.tsx @@ -105,6 +105,12 @@ export const SaveModal: React.FC = ({ const handleSave = async () => { if (!screenData || !screenId) return; + // βœ… μ‚¬μš©μž 정보가 λ‘œλ“œλ˜μ§€ μ•Šμ•˜μœΌλ©΄ μ €μž₯ λΆˆκ°€ + if (!user?.userId) { + toast.error("μ‚¬μš©μž 정보λ₯Ό λΆˆλŸ¬μ˜€λŠ” μ€‘μž…λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."); + return; + } + try { setIsSaving(true); @@ -129,19 +135,26 @@ export const SaveModal: React.FC = ({ // μ €μž₯ν•  데이터 μ€€λΉ„ const dataToSave = initialData ? changedData : formData; - // πŸ†• μžλ™μœΌλ‘œ μž‘μ„±μž 정보 μΆ”κ°€ - const writerValue = user?.userId || userName || "unknown"; + // πŸ†• μžλ™μœΌλ‘œ μž‘μ„±μž 정보 μΆ”κ°€ (user.userIdκ°€ ν™•μ‹€νžˆ 있음) + const writerValue = user.userId; + const companyCodeValue = user.companyCode || ""; + console.log("πŸ‘€ ν˜„μž¬ μ‚¬μš©μž 정보:", { - userId: user?.userId, + userId: user.userId, userName: userName, - writerValue: writerValue, + companyCode: user.companyCode, // βœ… νšŒμ‚¬ μ½”λ“œ + formDataWriter: dataToSave.writer, // βœ… νΌμ—μ„œ μž…λ ₯ν•œ writer κ°’ + formDataCompanyCode: dataToSave.company_code, // βœ… νΌμ—μ„œ μž…λ ₯ν•œ company_code κ°’ + defaultWriterValue: writerValue, + companyCodeValue, // βœ… μ΅œμ’… νšŒμ‚¬ μ½”λ“œ κ°’ }); const dataWithUserInfo = { ...dataToSave, - writer: writerValue, // ν…Œμ΄λΈ” 생성 μ‹œ μžλ™ μƒμ„±λ˜λŠ” 컬럼 - created_by: writerValue, - updated_by: writerValue, + writer: dataToSave.writer || writerValue, // βœ… μž…λ ₯κ°’ μš°μ„ , μ—†μœΌλ©΄ userId + created_by: writerValue, // created_byλŠ” 항상 λ‘œκ·ΈμΈν•œ μ‚¬λžŒ + updated_by: writerValue, // updated_byλŠ” 항상 λ‘œκ·ΈμΈν•œ μ‚¬λžŒ + company_code: dataToSave.company_code || companyCodeValue, // βœ… μž…λ ₯κ°’ μš°μ„ , μ—†μœΌλ©΄ user.companyCode }; // ν…Œμ΄λΈ”λͺ… κ²°μ • @@ -277,6 +290,9 @@ export const SaveModal: React.FC = ({ }} screenId={screenId} tableName={screenData.tableName} + userId={user?.userId} // βœ… μ‚¬μš©μž ID 전달 + userName={user?.userName} // βœ… μ‚¬μš©μž 이름 전달 + companyCode={user?.companyCode} // βœ… νšŒμ‚¬ μ½”λ“œ 전달 formData={formData} originalData={originalData} onFormDataChange={(fieldName, value) => { diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index 74a53561..465bb5ce 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -284,7 +284,7 @@ export const TableListComponent: React.FC = ({ // 컬럼 라벨 κ°€μ Έμ˜€κΈ° // ======================================== - const fetchColumnLabels = async () => { + const fetchColumnLabels = useCallback(async () => { if (!tableConfig.selectedTable) return; try { @@ -339,13 +339,13 @@ export const TableListComponent: React.FC = ({ } catch (error) { console.error("컬럼 라벨 κ°€μ Έμ˜€κΈ° μ‹€νŒ¨:", error); } - }; + }, [tableConfig.selectedTable]); // ======================================== // ν…Œμ΄λΈ” 라벨 κ°€μ Έμ˜€κΈ° // ======================================== - const fetchTableLabel = async () => { + const fetchTableLabel = useCallback(async () => { if (!tableConfig.selectedTable) return; try { @@ -374,7 +374,7 @@ export const TableListComponent: React.FC = ({ } catch (error) { console.error("ν…Œμ΄λΈ” 라벨 κ°€μ Έμ˜€κΈ° μ‹€νŒ¨:", error); } - }; + }, [tableConfig.selectedTable]); // ======================================== // 데이터 κ°€μ Έμ˜€κΈ° @@ -930,7 +930,7 @@ export const TableListComponent: React.FC = ({ useEffect(() => { fetchColumnLabels(); fetchTableLabel(); - }, [tableConfig.selectedTable]); + }, [tableConfig.selectedTable, fetchColumnLabels, fetchTableLabel]); useEffect(() => { if (!isDesignMode && tableConfig.selectedTable) { @@ -945,6 +945,7 @@ export const TableListComponent: React.FC = ({ searchTerm, refreshKey, isDesignMode, + fetchTableDataDebounced, ]); useEffect(() => { diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index 8b805d93..eb5046e3 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -203,15 +203,29 @@ export class ButtonActionExecutor { // INSERT 처리 // πŸ†• μžλ™μœΌλ‘œ μž‘μ„±μž 정보 μΆ”κ°€ - const writerValue = context.userId || context.userName || "unknown"; + if (!context.userId) { + throw new Error("μ‚¬μš©μž 정보λ₯Ό 뢈러올 수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ λ‘œκ·ΈμΈν•΄μ£Όμ„Έμš”."); + } + + const writerValue = context.userId; const companyCodeValue = context.companyCode || ""; + console.log("πŸ‘€ [buttonActions] μ‚¬μš©μž 정보:", { + userId: context.userId, + userName: context.userName, + companyCode: context.companyCode, // βœ… νšŒμ‚¬ μ½”λ“œ + formDataWriter: formData.writer, // βœ… νΌμ—μ„œ μž…λ ₯ν•œ writer κ°’ + formDataCompanyCode: formData.company_code, // βœ… νΌμ—μ„œ μž…λ ₯ν•œ company_code κ°’ + defaultWriterValue: writerValue, + companyCodeValue, // βœ… μ΅œμ’… νšŒμ‚¬ μ½”λ“œ κ°’ + }); + const dataWithUserInfo = { ...formData, - writer: writerValue, - created_by: writerValue, - updated_by: writerValue, - company_code: companyCodeValue, + writer: formData.writer || writerValue, // βœ… μž…λ ₯κ°’ μš°μ„ , μ—†μœΌλ©΄ userId + created_by: writerValue, // created_byλŠ” 항상 λ‘œκ·ΈμΈν•œ μ‚¬λžŒ + updated_by: writerValue, // updated_byλŠ” 항상 λ‘œκ·ΈμΈν•œ μ‚¬λžŒ + company_code: formData.company_code || companyCodeValue, // βœ… μž…λ ₯κ°’ μš°μ„ , μ—†μœΌλ©΄ user.companyCode }; saveResult = await DynamicFormApi.saveFormData({