summaryrefslogtreecommitdiff
path: root/components/form-data/import-excel-form.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/form-data/import-excel-form.tsx')
-rw-r--r--components/form-data/import-excel-form.tsx117
1 files changed, 99 insertions, 18 deletions
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
+}