summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-05 11:44:32 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-05 11:44:32 +0000
commit50adedf48ee4674ebe00f1ee72d93485183cdc51 (patch)
tree18053ab04d94c750028eee5d5d2f16ba4f38f50e /components
parent66d64b482f2b6b52b0dd396ef998f27d491c70dd (diff)
(대표님, 최겸, 임수민) EDP 입력 진행률, 견적목록관리, EDP excel import 오류수정, GTC-Contract
Diffstat (limited to 'components')
-rw-r--r--components/form-data-stat/form-data-stat-table.tsx7
-rw-r--r--components/form-data/import-excel-form.tsx216
2 files changed, 122 insertions, 101 deletions
diff --git a/components/form-data-stat/form-data-stat-table.tsx b/components/form-data-stat/form-data-stat-table.tsx
index 624e85fb..fe59785d 100644
--- a/components/form-data-stat/form-data-stat-table.tsx
+++ b/components/form-data-stat/form-data-stat-table.tsx
@@ -83,6 +83,7 @@ export function VendorFormStatusTable({
),
size: 200,
enablePinning: true,
+ meta: { excelHeader: "벤더명" },
},
{
accessorKey: "formCount",
@@ -93,6 +94,7 @@ export function VendorFormStatusTable({
</div>
),
size: 100,
+ meta: { excelHeader: "Form 개수" },
},
{
accessorKey: "tagCount",
@@ -103,6 +105,7 @@ export function VendorFormStatusTable({
</div>
),
size: 100,
+ meta: { excelHeader: "Tag 개수" },
},
{
accessorKey: "totalFields",
@@ -113,6 +116,7 @@ export function VendorFormStatusTable({
</div>
),
size: 100,
+ meta: { excelHeader: "전체 필드" },
},
{
accessorKey: "completedFields",
@@ -123,6 +127,7 @@ export function VendorFormStatusTable({
</div>
),
size: 100,
+ meta: { excelHeader: "완료 필드" },
},
{
accessorKey: "completionRate",
@@ -145,6 +150,7 @@ export function VendorFormStatusTable({
);
},
size: 180,
+ meta: { excelHeader: "완료율" },
},
{
id: "progress",
@@ -158,6 +164,7 @@ export function VendorFormStatusTable({
);
},
size: 120,
+ meta: { excelHeader: "진행 상태" },
},
], []);
diff --git a/components/form-data/import-excel-form.tsx b/components/form-data/import-excel-form.tsx
index 637b0ccf..df6ab6c1 100644
--- a/components/form-data/import-excel-form.tsx
+++ b/components/form-data/import-excel-form.tsx
@@ -2,7 +2,7 @@ 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 { updateFormDataBatchInDB } from "@/lib/forms/services";
import { decryptWithServerAction } from "../drm/drmUtils";
// Define error structure for import
@@ -37,6 +37,7 @@ export interface ImportExcelResult {
skippedFields?: { tagNo: string, fields: string[] }[]; // 건너뛴 필드 정보
errorCount?: number;
hasErrors?: boolean;
+ notFoundTags?: string[];
}
export interface ExportExcelOptions {
@@ -529,119 +530,132 @@ export async function importExcelData({
});
// If formCode and contractItemId are provided, save directly to DB
- if (formCode && contractItemId) {
- try {
- // Process each imported row individually
- let successCount = 0;
- let errorCount = 0;
- const errors = [];
-
- // Since updateFormDataInDB expects a single row at a time,
- // we need to process each imported row individually
- for (const importedRow of importedData) {
- try {
- const result = await updateFormDataInDB(
- formCode,
- contractItemId,
- importedRow
- );
-
- if (result.success) {
- successCount++;
- } else {
- errorCount++;
- errors.push(`Error updating tag ${importedRow.TAG_NO}: ${result.message}`);
- }
- } catch (rowError) {
- errorCount++;
- errors.push(`Exception updating tag ${importedRow.TAG_NO}: ${rowError instanceof Error ? rowError.message : 'Unknown error'}`);
- }
- }
-
- // If any errors occurred
- if (errorCount > 0) {
- console.error("Errors during import:", errors);
-
- if (successCount > 0) {
- toast.warning(`Partially successful: ${successCount} rows updated, ${errorCount} errors`);
- } else {
- toast.error(`Failed to update all ${errorCount} rows`);
- }
-
- // If some rows were updated successfully, update the local state
- if (successCount > 0) {
- if (onDataUpdate) {
- onDataUpdate(() => mergedData);
- }
- return {
- success: true,
- importedCount: successCount,
- message: `Partially successful: ${successCount} rows updated, ${errorCount} errors`,
- errorCount: errorCount,
- hasErrors: errorCount > 0,
- skippedFields: skippedFieldsLog
- };
- } else {
- return {
- success: false,
- error: "All updates failed",
- message: errors.join("\n"),
- errorCount: errorCount,
- hasErrors: true,
- skippedFields: skippedFieldsLog
- };
- }
- }
-
- // All rows were updated successfully
+ // importExcelData 함수에서 DB 저장 부분
+if (formCode && contractItemId) {
+ try {
+ // 배치 업데이트 함수 호출
+ const result = await updateFormDataBatchInDB(
+ formCode,
+ contractItemId,
+ importedData // 모든 imported rows를 한번에 전달
+ );
+
+ if (result.success) {
+ // 로컬 상태 업데이트
+ if (onDataUpdate) {
+ onDataUpdate(() => mergedData);
+ }
+
+ // 성공 메시지 구성
+ const { updatedCount, notFoundTags } = result.data || {};
+
+ let message = `Successfully updated ${updatedCount || importedData.length} rows`;
+
+ // 건너뛴 필드가 있는 경우
+ if (skippedFieldsLog.length > 0) {
+ const totalSkippedFields = skippedFieldsLog.reduce((sum, log) => sum + log.fields.length, 0);
+ message += ` (${totalSkippedFields} read-only fields preserved)`;
+ }
+
+ // 찾을 수 없는 TAG가 있는 경우
+ if (notFoundTags && notFoundTags.length > 0) {
+ console.warn("Tags not found in database:", notFoundTags);
+ message += `. Warning: ${notFoundTags.length} tags not found in database`;
+ }
+
+ toast.success(message);
+
+ return {
+ success: true,
+ importedCount: updatedCount || importedData.length,
+ message: message,
+ errorCount: 0,
+ hasErrors: false,
+ skippedFields: skippedFieldsLog,
+ notFoundTags: notFoundTags
+ };
+
+ } else {
+ // 배치 업데이트 실패
+ console.error("Batch update failed:", result.message);
+
+ // 부분 성공인 경우
+ if (result.data?.updatedCount > 0) {
+ // 부분적으로라도 업데이트된 경우 로컬 상태 업데이트
if (onDataUpdate) {
onDataUpdate(() => mergedData);
}
- const successMessage = skippedFieldsLog.length > 0
- ? `Successfully updated ${successCount} rows (read-only fields were preserved)`
- : `Successfully updated ${successCount} rows`;
+ toast.warning(
+ `Partially updated: ${result.data.updatedCount} of ${importedData.length} rows updated. ` +
+ `${result.data.failedCount || 0} failed.`
+ );
- toast.success(successMessage);
- return {
- success: true,
- importedCount: successCount,
- message: "All data imported and saved to database",
- errorCount: 0,
- hasErrors: false,
+ return {
+ success: true, // 부분 성공도 success로 처리
+ importedCount: result.data.updatedCount,
+ message: result.message,
+ errorCount: result.data.failedCount || 0,
+ hasErrors: true,
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,
- errorCount: 1,
+
+ } else {
+ // 완전 실패
+ toast.error(result.message || "Failed to update data to database");
+
+ return {
+ success: false,
+ error: result.message,
+ errorCount: importedData.length,
hasErrors: true,
skippedFields: skippedFieldsLog
};
}
- } else {
- // Fall back to just updating local state if DB parameters aren't provided
- if (onDataUpdate) {
- onDataUpdate(() => mergedData);
- }
-
- const successMessage = skippedFieldsLog.length > 0
- ? `Imported ${importedData.length} rows successfully (read-only fields preserved)`
- : `Imported ${importedData.length} rows successfully`;
-
- toast.success(`${successMessage} (local only)`);
- return {
- success: true,
- importedCount: importedData.length,
- errorCount: 0,
- hasErrors: false,
- skippedFields: skippedFieldsLog
- };
}
+ } catch (saveError) {
+ // 예외 발생 처리
+ console.error("Failed to save imported data:", saveError);
+
+ const errorMessage = saveError instanceof Error
+ ? saveError.message
+ : "Unknown error occurred";
+
+ toast.error(`Database update failed: ${errorMessage}`);
+
+ return {
+ success: false,
+ error: saveError,
+ message: errorMessage,
+ errorCount: importedData.length,
+ hasErrors: true,
+ skippedFields: skippedFieldsLog
+ };
+ }
+
+} else {
+ // formCode나 contractItemId가 없는 경우 - 로컬 업데이트만
+ if (onDataUpdate) {
+ onDataUpdate(() => mergedData);
+ }
+
+ const successMessage = skippedFieldsLog.length > 0
+ ? `Imported ${importedData.length} rows successfully (read-only fields preserved)`
+ : `Imported ${importedData.length} rows successfully`;
+
+ toast.success(`${successMessage} (local only - no database connection)`);
+
+ return {
+ success: true,
+ importedCount: importedData.length,
+ message: "Data imported locally only",
+ errorCount: 0,
+ hasErrors: false,
+ skippedFields: skippedFieldsLog
+ };
+}
+
} catch (err) {
console.error("Excel import error:", err);
toast.error("Excel import failed.");