"use client" import { z } from "zod" import { createPqCriteria } from "../service" // PQ 생성 서버 액션 // PQ 데이터 검증을 위한 Zod 스키마 const pqItemSchema = z.object({ code: z.string().min(1, "Code is required"), checkPoint: z.string().min(1, "Check point is required"), groupName: z.string().min(1, "Group is required"), description: z.string().optional().nullable(), remarks: z.string().optional().nullable(), contractInfo: z.string().optional().nullable(), additionalRequirement: z.string().optional().nullable(), }); // 지원하는 그룹 이름 목록 const validGroupNames = [ "GENERAL", "Quality Management System", "Workshop & Environment", "Warranty", ]; type ImportPqItem = z.infer; interface ProcessResult { successCount: number; errorCount: number; errors?: Array<{ row: number; message: string }>; } /** * Excel 파일에서 가져온 PQ 데이터를 처리하는 함수 */ export async function processFileImport( jsonData: any[], pqListId: number, progressCallback?: (current: number, total: number) => void ): Promise { // 결과 카운터 초기화 let successCount = 0; let errorCount = 0; const errors: Array<{ row: number; message: string }> = []; // 헤더 행과 지침 행 건너뛰기 const dataRows = jsonData.filter(row => { // 행이 문자열로만 구성된 경우 지침 행으로 간주 if (Object.values(row).every(val => typeof val === 'string' && !val.includes(':'))) { return false; } // 빈 행 건너뛰기 if (Object.values(row).every(val => !val)) { return false; } return true; }); // 데이터 행이 없으면 빈 결과 반환 if (dataRows.length === 0) { return { successCount: 0, errorCount: 0 }; } // 각 행에 대해 처리 for (let i = 0; i < dataRows.length; i++) { const row = dataRows[i]; const rowIndex = i + 1; // 사용자에게 표시할 행 번호는 1부터 시작 // 진행 상황 콜백 호출 if (progressCallback) { progressCallback(i + 1, dataRows.length); } try { // 데이터 정제 const cleanedRow: ImportPqItem = { code: row.Code?.toString().trim() ?? "", checkPoint: row["Check Point"]?.toString().trim() ?? "", groupName: row["Group Name"]?.toString().trim() ?? "", description: row.Description?.toString() ?? "", remarks: row.Remarks?.toString() ?? "", contractInfo: row["Contract Info"]?.toString() ?? "", additionalRequirement: row["Additional Requirements"]?.toString() ?? "", }; // 데이터 유효성 검사 const validationResult = pqItemSchema.safeParse(cleanedRow); if (!validationResult.success) { const errorMessage = validationResult.error.errors.map( err => `${err.path.join('.')}: ${err.message}` ).join(', '); errors.push({ row: rowIndex, message: errorMessage }); errorCount++; continue; } // 그룹 이름 유효성 검사 if (!validGroupNames.includes(cleanedRow.groupName)) { errors.push({ row: rowIndex, message: `Invalid group name: ${cleanedRow.groupName}. Must be one of: ${validGroupNames.join(', ')}` }); errorCount++; continue; } // PQ 생성 서버 액션 호출 const createResult = await createPqCriteria(pqListId, cleanedRow); if (createResult.success) { successCount++; } else { errors.push({ row: rowIndex, message: createResult.message || "Unknown error" }); errorCount++; } } catch (error) { console.error(`Row ${rowIndex} processing error:`, error); errors.push({ row: rowIndex, message: error instanceof Error ? error.message : "Unknown error" }); errorCount++; } // 비동기 작업 쓰로틀링 if (i % 5 === 0) { await new Promise(resolve => setTimeout(resolve, 10)); } } // 처리 결과 반환 return { successCount, errorCount, errors: errors.length > 0 ? errors : undefined }; }