diff options
Diffstat (limited to 'lib/items-tech/table/ship')
| -rw-r--r-- | lib/items-tech/table/ship/import-item-handler.tsx | 112 |
1 files changed, 85 insertions, 27 deletions
diff --git a/lib/items-tech/table/ship/import-item-handler.tsx b/lib/items-tech/table/ship/import-item-handler.tsx index b0f475ff..e95d1987 100644 --- a/lib/items-tech/table/ship/import-item-handler.tsx +++ b/lib/items-tech/table/ship/import-item-handler.tsx @@ -1,7 +1,8 @@ "use client"
import { z } from "zod"
-import { createShipbuildingImportItem } from "../../service" // 아이템 생성 서버 액션
+import { createShipbuildingImportItem, getMaxShipbuildingIMCode } from "../../service" // 아이템 생성 서버 액션
+import { splitItemCodes, createErrorExcelFile, ExtendedProcessResult, processEmptyItemCodes } from "../../utils/import-utils"
// 아이템 데이터 검증을 위한 Zod 스키마
const itemSchema = z.object({
@@ -13,23 +14,25 @@ const itemSchema = z.object({ itemList: z.string().nullable().optional(),
});
-interface ProcessResult {
- successCount: number;
- errorCount: number;
- errors: Array<{ row: number; message: string }>;
-}
-
/**
* Excel 파일에서 가져온 조선 아이템 데이터 처리하는 함수
*/
export async function processFileImport(
jsonData: Record<string, unknown>[],
progressCallback?: (current: number, total: number) => void
-): Promise<ProcessResult> {
+): Promise<ExtendedProcessResult> {
// 결과 카운터 초기화
let successCount = 0;
let errorCount = 0;
- const errors: Array<{ row: number; message: string }> = [];
+ const errors: Array<{
+ row: number;
+ message: string;
+ itemCode?: string;
+ workType?: string;
+ originalData?: Record<string, any>;
+ }> = [];
+ const processedItemCodes: string[] = [];
+ const duplicateItemCodes: string[] = [];
// 빈 행 등 필터링
const dataRows = jsonData.filter(row => {
@@ -42,9 +45,19 @@ export async function processFileImport( // 데이터 행이 없으면 빈 결과 반환
if (dataRows.length === 0) {
- return { successCount: 0, errorCount: 0, errors: [] };
+ return {
+ successCount: 0,
+ errorCount: 0,
+ errors: [],
+ processedItemCodes: [],
+ duplicateItemCodes: []
+ };
}
+ // 기존 IM 코드의 최대 번호 조회
+ const maxIMCode = await getMaxShipbuildingIMCode();
+ let nextIMNumber = maxIMCode + 1;
+
// 각 행에 대해 처리
for (let i = 0; i < dataRows.length; i++) {
const row = dataRows[i];
@@ -81,35 +94,73 @@ export async function processFileImport( errors.push({
row: rowIndex,
message: errorMessage,
+ originalData: cleanedRow
});
errorCount++;
continue;
}
+
+ // itemCode 분할 처리
+ const rawItemCodes = splitItemCodes(cleanedRow.itemCode);
- // 아이템 생성
- const result = await createShipbuildingImportItem({
- itemCode: cleanedRow.itemCode,
- workType: cleanedRow.workType as "기장" | "전장" | "선실" | "배관" | "철의" | "선체",
- shipTypes: cleanedRow.shipTypes,
- itemList: cleanedRow.itemList,
- });
+ // 빈 itemCode 처리 (임시 코드 생성)
+ const { codes: itemCodes, nextNumber } = processEmptyItemCodes(rawItemCodes, nextIMNumber);
+ nextIMNumber = nextNumber;
+
+ // 각 itemCode에 대해 개별 처리
+ let rowSuccessCount = 0;
+ let rowErrorCount = 0;
- if (result.success || !result.error) {
- successCount++;
- } else {
- errors.push({
- row: rowIndex,
- message: result.message || result.error || "알 수 없는 오류",
- });
- errorCount++;
+ for (const singleItemCode of itemCodes) {
+ try {
+ // 아이템 생성
+ const result = await createShipbuildingImportItem({
+ itemCode: singleItemCode,
+ workType: cleanedRow.workType as "기장" | "전장" | "선실" | "배관" | "철의" | "선체",
+ shipTypes: cleanedRow.shipTypes,
+ itemList: cleanedRow.itemList,
+ });
+
+ if (result.success || !result.error) {
+ rowSuccessCount++;
+ processedItemCodes.push(singleItemCode);
+ } else {
+ rowErrorCount++;
+ if (result.message?.includes('중복') || result.error?.includes('중복')) {
+ duplicateItemCodes.push(singleItemCode);
+ }
+
+ errors.push({
+ row: rowIndex,
+ message: `${singleItemCode}: ${result.message || result.error || "알 수 없는 오류"}`,
+ itemCode: singleItemCode,
+ workType: cleanedRow.workType,
+ originalData: cleanedRow
+ });
+ }
+ } catch (error) {
+ rowErrorCount++;
+ console.error(`${rowIndex}행 ${singleItemCode} 처리 오류:`, error);
+ errors.push({
+ row: rowIndex,
+ message: `${singleItemCode}: ${error instanceof Error ? error.message : "알 수 없는 오류"}`,
+ itemCode: singleItemCode,
+ workType: cleanedRow.workType,
+ originalData: cleanedRow
+ });
+ }
}
+ // 행별 성공/실패 카운트 업데이트
+ successCount += rowSuccessCount;
+ errorCount += rowErrorCount;
+
} catch (error) {
console.error(`${rowIndex}행 처리 오류:`, error);
-
errors.push({
row: rowIndex,
message: error instanceof Error ? error.message : "알 수 없는 오류",
+ originalData: row as Record<string, any>
});
errorCount++;
}
@@ -120,10 +171,17 @@ export async function processFileImport( }
}
+ // 에러가 있으면 Excel 파일 생성
+ if (errors.length > 0) {
+ await createErrorExcelFile(errors, 'ship');
+ }
+
// 처리 결과 반환
return {
successCount,
errorCount,
- errors
+ errors,
+ processedItemCodes,
+ duplicateItemCodes
};
}
\ No newline at end of file |
