diff options
Diffstat (limited to 'components/form-data/import-excel-form.tsx')
| -rw-r--r-- | components/form-data/import-excel-form.tsx | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/components/form-data/import-excel-form.tsx b/components/form-data/import-excel-form.tsx index e3ac9e0e..637b0ccf 100644 --- a/components/form-data/import-excel-form.tsx +++ b/components/form-data/import-excel-form.tsx @@ -17,13 +17,14 @@ export interface ImportError { expectedFormat?: string; } -// Simplified options interface without editableFieldsMap +// Updated options interface with editableFieldsMap export interface ImportExcelOptions { file: File; tableData: GenericData[]; columnsJSON: DataTableColumnJSON[]; formCode?: string; contractItemId?: number; + editableFieldsMap?: Map<string, string[]>; // 새로 추가 onPendingChange?: (isPending: boolean) => void; onDataUpdate?: (updater: ((prev: GenericData[]) => GenericData[]) | GenericData[]) => void; } @@ -42,6 +43,7 @@ export interface ExportExcelOptions { tableData: GenericData[]; columnsJSON: DataTableColumnJSON[]; formCode: string; + editableFieldsMap?: Map<string, string[]>; // 새로 추가 onPendingChange?: (isPending: boolean) => void; } @@ -50,6 +52,31 @@ interface GenericData { } /** + * Check if a field is editable for a specific TAG_NO + */ +function isFieldEditable( + column: DataTableColumnJSON, + tagNo: string, + editableFieldsMap: Map<string, string[]> +): boolean { + // SHI-only fields (shi === "OUT" or shi === null) are never editable + if (column.shi === "OUT" || column.shi === null) return false; + + // System fields are never editable + if (column.key === "TAG_NO" || column.key === "TAG_DESC" || column.key === "status") return false; + + // If no editableFieldsMap provided, assume all non-SHI fields are editable + if (!editableFieldsMap || editableFieldsMap.size === 0) return true; + + // If TAG_NO not in map, no fields are editable + if (!editableFieldsMap.has(tagNo)) return false; + + // Check if this field is in the editable fields list for this TAG_NO + const editableFields = editableFieldsMap.get(tagNo) || []; + return editableFields.includes(column.key); +} + +/** * Create error sheet with import validation results */ function createImportErrorSheet(workbook: ExcelJS.Workbook, errors: ImportError[], headerErrors?: string[]) { @@ -156,6 +183,9 @@ function createImportErrorSheet(workbook: ExcelJS.Workbook, errors: ImportError[ case "HEADER_MISMATCH": bgColor = "FFFFE0E0"; // Very light red break; + case "READ_ONLY_FIELD": + bgColor = "FFF0F0F0"; // Light gray + break; } cell.fill = { @@ -188,6 +218,7 @@ export async function importExcelData({ columnsJSON, formCode, contractItemId, + editableFieldsMap = new Map(), // 새로 추가 onPendingChange, onDataUpdate }: ImportExcelOptions): Promise<ImportExcelResult> { @@ -321,8 +352,11 @@ export async function importExcelData({ const colIndex = keyToIndexMap.get(col.key); if (colIndex === undefined) return; - // Check if this is a SHI-only field (skip processing but preserve existing value) - if (col.shi === true) { + // Check if this field is editable for this TAG_NO + const fieldEditable = isFieldEditable(col, tagNo, editableFieldsMap); + + if (!fieldEditable) { + // If field is not editable, preserve existing value if (existingRowData && existingRowData[col.key] !== undefined) { rowObj[col.key] = existingRowData[col.key]; } else { @@ -339,8 +373,36 @@ export async function importExcelData({ } } + // Determine skip reason + let skipReason = ""; + if (col.shi === "OUT" || col.shi === null) { + skipReason = "SHI-only field"; + } else if (col.key === "TAG_NO" || col.key === "TAG_DESC" || col.key === "status") { + skipReason = "System field"; + } else { + skipReason = "Not editable for this TAG"; + } + // Log skipped field - skippedFields.push(`${col.label} (SHI-only field)`); + skippedFields.push(`${col.label} (${skipReason})`); + + // Check if Excel contains a value for a read-only field and warn + const cellValue = rowValues[colIndex] ?? ""; + const stringVal = String(cellValue).trim(); + if (stringVal && existingRowData && String(existingRowData[col.key] || "").trim() !== stringVal) { + validationErrors.push({ + tagNo: tagNo || `Row-${rowNum}`, + rowIndex: rowNum, + columnKey: col.key, + columnLabel: col.label, + errorType: "READ_ONLY_FIELD", + errorMessage: `Attempting to modify read-only field. ${skipReason}.`, + currentValue: stringVal, + expectedFormat: `Field is read-only. Current value: ${existingRowData[col.key] || "empty"}`, + }); + hasErrors = true; + } + return; // Skip processing Excel value for this column } @@ -419,7 +481,7 @@ export async function importExcelData({ const totalSkippedFields = skippedFieldsLog.reduce((sum, log) => sum + log.fields.length, 0); console.log("Skipped fields summary:", skippedFieldsLog); toast.info( - `${totalSkippedFields} SHI-only fields were skipped across ${skippedFieldsLog.length} rows. Check console for details.` + `${totalSkippedFields} read-only fields were skipped across ${skippedFieldsLog.length} rows. Check console for details.` ); } @@ -537,7 +599,7 @@ export async function importExcelData({ } const successMessage = skippedFieldsLog.length > 0 - ? `Successfully updated ${successCount} rows (SHI-only fields were preserved)` + ? `Successfully updated ${successCount} rows (read-only fields were preserved)` : `Successfully updated ${successCount} rows`; toast.success(successMessage); @@ -567,7 +629,7 @@ export async function importExcelData({ } const successMessage = skippedFieldsLog.length > 0 - ? `Imported ${importedData.length} rows successfully (SHI-only fields preserved)` + ? `Imported ${importedData.length} rows successfully (read-only fields preserved)` : `Imported ${importedData.length} rows successfully`; toast.success(`${successMessage} (local only)`); |
