From 37f55540833c2d5894513eca9fc8f7c6233fc2d2 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Thu, 29 May 2025 05:17:13 +0000
Subject: (대표님) 0529 14시 16분 변경사항 저장 (Vendor Data, Docu)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/form-data/import-excel-form.tsx | 117 ++++++++++++++++++++++++-----
 1 file changed, 99 insertions(+), 18 deletions(-)

(limited to 'components/form-data/import-excel-form.tsx')

diff --git a/components/form-data/import-excel-form.tsx b/components/form-data/import-excel-form.tsx
index d425a909..f32e44d8 100644
--- a/components/form-data/import-excel-form.tsx
+++ b/components/form-data/import-excel-form.tsx
@@ -1,17 +1,18 @@
-// lib/excelUtils.ts (continued)
 import ExcelJS from "exceljs";
 import { saveAs } from "file-saver";
 import { toast } from "sonner";
 import { DataTableColumnJSON } from "./form-data-table-columns";
 import { updateFormDataInDB } from "@/lib/forms/services";
 import { decryptWithServerAction } from "../drm/drmUtils";
-// Assuming the previous types are defined above
+
+// Enhanced options interface with editableFieldsMap
 export interface ImportExcelOptions {
   file: File;
   tableData: GenericData[];
   columnsJSON: DataTableColumnJSON[];
-  formCode?: string;        // Optional - provide to enable direct DB save
-  contractItemId?: number;  // Optional - provide to enable direct DB save
+  formCode?: string;
+  contractItemId?: number;
+  editableFieldsMap?: Map<string, string[]>; // 새로 추가
   onPendingChange?: (isPending: boolean) => void;
   onDataUpdate?: (updater: ((prev: GenericData[]) => GenericData[]) | GenericData[]) => void;
 }
@@ -21,6 +22,7 @@ export interface ImportExcelResult {
   importedCount?: number;
   error?: any;
   message?: string;
+  skippedFields?: { tagNo: string, fields: string[] }[]; // 건너뛴 필드 정보
 }
 
 export interface ExportExcelOptions {
@@ -30,7 +32,6 @@ export interface ExportExcelOptions {
   onPendingChange?: (isPending: boolean) => void;
 }
 
-// For typing consistency
 interface GenericData {
   [key: string]: any;
 }
@@ -41,6 +42,7 @@ export async function importExcelData({
   columnsJSON,
   formCode,
   contractItemId,
+  editableFieldsMap = new Map(), // 기본값으로 빈 Map
   onPendingChange,
   onDataUpdate
 }: ImportExcelOptions): Promise<ImportExcelResult> {
@@ -59,7 +61,6 @@ export async function importExcelData({
     });
 
     const workbook = new ExcelJS.Workbook();
-    // const arrayBuffer = await file.arrayBuffer();
     const arrayBuffer = await decryptWithServerAction(file);
     await workbook.xlsx.load(arrayBuffer);
 
@@ -127,6 +128,7 @@ export async function importExcelData({
     const importedData: GenericData[] = [];
     const lastRowNumber = worksheet.lastRow?.number || 1;
     let errorCount = 0;
+    const skippedFieldsLog: { tagNo: string, fields: string[] }[] = []; // 건너뛴 필드 로그
 
     // Process each data row
     for (let rowNum = 2; rowNum <= lastRowNumber; rowNum++) {
@@ -135,21 +137,51 @@ export async function importExcelData({
       if (!rowValues || rowValues.length <= 1) continue; // Skip empty rows
 
       let errorMessage = "";
+      let warningMessage = "";
       const rowObj: Record<string, any> = {};
+      const skippedFields: string[] = []; // 현재 행에서 건너뛴 필드들
       
-      // Get the TAG_NO first to identify existing data
+      // Get the TAG_NO first to identify existing data and editable fields
       const tagNoColIndex = keyToIndexMap.get("TAG_NO");
       const tagNo = tagNoColIndex ? String(rowValues[tagNoColIndex] ?? "").trim() : "";
       const existingRowData = existingDataMap.get(tagNo);
+      
+      // Get editable fields for this specific TAG
+      const editableFields = editableFieldsMap.has(tagNo) ? editableFieldsMap.get(tagNo)! : [];
 
       // Process each column
       columnsJSON.forEach((col) => {
         const colIndex = keyToIndexMap.get(col.key);
         if (colIndex === undefined) return;
 
-        // Check if this column should be ignored (col.shi === true)
+        // Determine if this field is editable
+        let isFieldEditable = true;
+        let skipReason = "";
+
+        // 1. Check if this is a SHI-only field
         if (col.shi === true) {
-          // Use existing value instead of Excel value
+          isFieldEditable = false;
+          skipReason = "SHI-only field";
+        }
+        // 2. Check if this field is editable based on TAG class attributes
+        else if (col.key !== "TAG_NO" && col.key !== "TAG_DESC") {
+          // For non-basic fields, check if they're in the editable list
+          if (tagNo && editableFieldsMap.has(tagNo)) {
+            if (!editableFields.includes(col.key)) {
+              isFieldEditable = false;
+              skipReason = "Not editable for this TAG class";
+            }
+          } else if (tagNo) {
+            // If TAG exists but no editable fields info, treat as not editable
+            isFieldEditable = false;
+            skipReason = "No editable fields info for this TAG";
+          }
+        }
+        // 3. TAG_NO and TAG_DESC are always considered basic fields
+        // (They should be editable, but you might want to add specific logic here)
+
+        // If field is not editable, use existing value or default
+        if (!isFieldEditable) {
           if (existingRowData && existingRowData[col.key] !== undefined) {
             rowObj[col.key] = existingRowData[col.key];
           } else {
@@ -165,9 +197,13 @@ export async function importExcelData({
                 break;
             }
           }
+          
+          // Log skipped field
+          skippedFields.push(`${col.label} (${skipReason})`);
           return; // Skip processing Excel value for this column
         }
 
+        // Process Excel value for editable fields
         const cellValue = rowValues[colIndex] ?? "";
         let stringVal = String(cellValue).trim();
 
@@ -212,6 +248,15 @@ export async function importExcelData({
         }
       });
 
+      // Log skipped fields for this TAG
+      if (skippedFields.length > 0) {
+        skippedFieldsLog.push({
+          tagNo: tagNo,
+          fields: skippedFields
+        });
+        warningMessage += `Skipped ${skippedFields.length} non-editable fields. `;
+      }
+
       // Validate TAG_NO
       const tagNum = rowObj["TAG_NO"];
       if (!tagNum) {
@@ -225,10 +270,23 @@ export async function importExcelData({
         row.getCell(lastColIndex).value = errorMessage.trim();
         errorCount++;
       } else {
+        // Add warning message to Excel if there are skipped fields
+        if (warningMessage) {
+          row.getCell(lastColIndex).value = `WARNING: ${warningMessage.trim()}`;
+        }
         importedData.push(rowObj);
       }
     }
 
+    // Show summary of skipped fields
+    if (skippedFieldsLog.length > 0) {
+      const totalSkippedFields = skippedFieldsLog.reduce((sum, log) => sum + log.fields.length, 0);
+      console.log("Skipped fields summary:", skippedFieldsLog);
+      toast.info(
+        `${totalSkippedFields} non-editable fields were skipped across ${skippedFieldsLog.length} rows. Check console for details.`
+      );
+    }
+
     // If there are validation errors, download error report and exit
     if (errorCount > 0) {
       const outBuffer = await workbook.xlsx.writeBuffer();
@@ -236,7 +294,11 @@ export async function importExcelData({
       toast.error(
         `There are ${errorCount} error row(s). Please check downloaded file.`
       );
-      return { success: false, error: "Data validation errors" };
+      return { 
+        success: false, 
+        error: "Data validation errors",
+        skippedFields: skippedFieldsLog
+      };
     }
 
     // If we reached here, all data is valid
@@ -310,13 +372,15 @@ export async function importExcelData({
             return { 
               success: true, 
               importedCount: successCount,
-              message: `Partially successful: ${successCount} rows updated, ${errorCount} errors` 
+              message: `Partially successful: ${successCount} rows updated, ${errorCount} errors`,
+              skippedFields: skippedFieldsLog
             };
           } else {
             return { 
               success: false, 
               error: "All updates failed", 
-              message: errors.join("\n")
+              message: errors.join("\n"),
+              skippedFields: skippedFieldsLog
             };
           }
         }
@@ -326,16 +390,25 @@ export async function importExcelData({
           onDataUpdate(() => mergedData);
         }
         
-        toast.success(`Successfully updated ${successCount} rows`);
+        const successMessage = skippedFieldsLog.length > 0 
+          ? `Successfully updated ${successCount} rows (some non-editable fields were preserved)`
+          : `Successfully updated ${successCount} rows`;
+        
+        toast.success(successMessage);
         return { 
           success: true, 
           importedCount: successCount, 
-          message: "All data imported and saved to database" 
+          message: "All data imported and saved to database",
+          skippedFields: skippedFieldsLog
         };
       } catch (saveError) {
         console.error("Failed to save imported data:", saveError);
         toast.error("Failed to save imported data to database");
-        return { success: false, error: saveError };
+        return { 
+          success: false, 
+          error: saveError,
+          skippedFields: skippedFieldsLog
+        };
       }
     } else {
       // Fall back to just updating local state if DB parameters aren't provided
@@ -343,8 +416,16 @@ export async function importExcelData({
         onDataUpdate(() => mergedData);
       }
       
-      toast.success(`Imported ${importedData.length} rows successfully (local only)`);
-      return { success: true, importedCount: importedData.length };
+      const successMessage = skippedFieldsLog.length > 0 
+        ? `Imported ${importedData.length} rows successfully (some fields preserved)`
+        : `Imported ${importedData.length} rows successfully`;
+      
+      toast.success(`${successMessage} (local only)`);
+      return { 
+        success: true, 
+        importedCount: importedData.length,
+        skippedFields: skippedFieldsLog
+      };
     }
     
   } catch (err) {
@@ -354,4 +435,4 @@ export async function importExcelData({
   } finally {
     if (onPendingChange) onPendingChange(false);
   }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3

