From d84602bdf369636e29d298a96218bd672de4afd7 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 2 Sep 2025 10:31:53 +0000 Subject: (최겸) 기술영업 수정사항 반영 및 구매 PQ/실사 첨부오류 변경 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tech-vendors/table/import-button.tsx | 76 ++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'lib/tech-vendors/table/import-button.tsx') diff --git a/lib/tech-vendors/table/import-button.tsx b/lib/tech-vendors/table/import-button.tsx index 1d3bf242..b268d29d 100644 --- a/lib/tech-vendors/table/import-button.tsx +++ b/lib/tech-vendors/table/import-button.tsx @@ -101,8 +101,14 @@ export function ImportTechVendorButton({ onSuccess }: ImportTechVendorButtonProp // 헤더를 기반으로 인덱스 매핑 생성 const headerMapping: Record = {}; headerValues.forEach((value, index) => { - if (typeof value === 'string') { - headerMapping[value] = index; + // 리치텍스트를 일반 텍스트로 변환 + const cleanValue = typeof value === 'string' ? value : + value && typeof value === 'object' && 'richText' in value ? + value.richText?.map((rt: any) => rt.text || '').join('') || '' : + String(value || ''); + + if (cleanValue && cleanValue.trim()) { + headerMapping[cleanValue] = index; } }); @@ -156,7 +162,19 @@ export function ImportTechVendorButton({ onSuccess }: ImportTechVendorButtonProp // 헤더 매핑에 따라 데이터 추출 Object.entries(headerMapping).forEach(([header, index]) => { - rowData[header] = values[index] || ""; + const rawValue = values[index]; + + // 리치텍스트를 일반 텍스트로 변환 + let cleanValue = ""; + if (typeof rawValue === 'string') { + cleanValue = rawValue; + } else if (rawValue && typeof rawValue === 'object' && 'richText' in rawValue) { + cleanValue = rawValue.richText?.map((rt: any) => rt.text || '').join('') || ''; + } else if (rawValue !== null && rawValue !== undefined) { + cleanValue = String(rawValue); + } + + rowData[header] = cleanValue; }); // 빈 행이 아닌 경우만 추가 @@ -271,6 +289,58 @@ export function ImportTechVendorButton({ onSuccess }: ImportTechVendorButtonProp toast.error(result.error || "벤더 가져오기에 실패했습니다."); } + // 에러가 있으면 에러 엑셀 다운로드 (성공/실패 상관없이) + if (result.details?.errors && result.details.errors.length > 0) { + try { + // 에러 데이터를 Excel로 변환 + const errorWorkbook = new ExcelJS.Workbook(); + const errorWorksheet = errorWorkbook.addWorksheet("오류내역"); + + // 헤더 추가 + errorWorksheet.columns = [ + { header: "업체명", key: "vendorName", width: 25 }, + { header: "이메일", key: "email", width: 30 }, + { header: "오류내용", key: "error", width: 80, style: { alignment: { wrapText: true }, font: { color: { argb: "FFFF0000" } } } }, + ]; + + // 헤더 스타일 설정 + const headerRow = errorWorksheet.getRow(1); + headerRow.font = { bold: true }; + headerRow.fill = { + type: "pattern", + pattern: "solid", + fgColor: { argb: "FFFFCCCC" }, + }; + + // 오류 데이터 추가 + result.details.errors.forEach(errorItem => { + errorWorksheet.addRow({ + vendorName: errorItem.vendorName || "N/A", + email: errorItem.email || "N/A", + error: errorItem.error || "알 수 없는 오류", + }); + }); + + const buffer = await errorWorkbook.xlsx.writeBuffer(); + const blob = new Blob([buffer], { + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + }); + const url = window.URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = "벤더_import_에러.xlsx"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + + toast.info("에러 내역 파일이 다운로드되었습니다."); + } catch (excelError) { + console.error("에러 엑셀 생성 실패:", excelError); + toast.error("에러 엑셀 생성에 실패했습니다."); + } + } + // 상태 초기화 및 다이얼로그 닫기 setFile(null); setOpen(false); -- cgit v1.2.3