diff options
Diffstat (limited to 'lib/tech-vendor-possible-items/table/excel-import.tsx')
| -rw-r--r-- | lib/tech-vendor-possible-items/table/excel-import.tsx | 130 |
1 files changed, 92 insertions, 38 deletions
diff --git a/lib/tech-vendor-possible-items/table/excel-import.tsx b/lib/tech-vendor-possible-items/table/excel-import.tsx index fbf984dd..743879b3 100644 --- a/lib/tech-vendor-possible-items/table/excel-import.tsx +++ b/lib/tech-vendor-possible-items/table/excel-import.tsx @@ -3,21 +3,35 @@ import * as ExcelJS from 'exceljs';
import { ImportTechVendorPossibleItemData, ImportResult, importTechVendorPossibleItems } from '../service';
import { saveAs } from "file-saver";
+import { decryptWithServerAction } from "@/components/drm/drmUtils"
+import { toast } from 'sonner';
export interface ExcelImportResult extends ImportResult {
errorFileUrl?: string;
}
/**
- * Excel 파일에서 tech vendor possible items 데이터를 읽고 import
+ * Excel 파일에서 tech vendor possible items 데이터를 읽고 import (새로운 스키마 버전)
*/
export async function importTechVendorPossibleItemsFromExcel(
file: File
): Promise<ExcelImportResult> {
+
try {
- const buffer = await file.arrayBuffer();
- const workbook = new ExcelJS.Workbook();
- await workbook.xlsx.load(buffer);
+ // DRM 복호화 처리 - 서버 액션 직접 호출
+ let arrayBuffer: ArrayBuffer;
+ try {
+ toast.info("파일 복호화 중...");
+ arrayBuffer = await decryptWithServerAction(file);
+ } catch (decryptError) {
+ console.error("파일 복호화 실패, 원본 파일 사용:", decryptError);
+ toast.warning("파일 복호화에 실패하여 원본 파일을 사용합니다.");
+ // 복호화 실패 시 원본 파일 사용
+ arrayBuffer = await file.arrayBuffer();
+ }
+ // ExcelJS 워크북 로드
+ const workbook = new ExcelJS.Workbook();
+ await workbook.xlsx.load(arrayBuffer);
// 첫 번째 워크시트에서 데이터 읽기
const worksheet = workbook.getWorksheet(1);
@@ -33,31 +47,48 @@ export async function importTechVendorPossibleItemsFromExcel( const data: ImportTechVendorPossibleItemData[] = [];
// 데이터 행 읽기 (헤더 제외)
+ // 새로운 스키마: 벤더이메일, 아이템코드, 공종, 선종, 아이템리스트, 서브아이템리스트
worksheet.eachRow((row, rowNumber) => {
if (rowNumber === 1) return; // 헤더 건너뛰기
- const itemCode = row.getCell(1).value?.toString()?.trim();
- const vendorCode = row.getCell(2).value?.toString()?.trim();
- const vendorEmail = row.getCell(3).value?.toString()?.trim();
+ const vendorEmail = row.getCell(1).value?.toString()?.trim(); // 필수
+ const itemCode = row.getCell(2).value?.toString()?.trim(); // 필수
+ const workType = row.getCell(3).value?.toString()?.trim(); // 선택
+ const shipTypes = row.getCell(4).value?.toString()?.trim(); // 선택
+ const itemList = row.getCell(5).value?.toString()?.trim(); // 선택
+ const subItemList = row.getCell(6).value?.toString()?.trim(); // 선택
+ const vendorCode = row.getCell(7).value?.toString()?.trim(); // 선택 (호환성)
// 빈 행 건너뛰기
- if (!itemCode && !vendorCode && !vendorEmail) return;
+ if (!vendorEmail && !itemCode && !workType && !shipTypes && !itemList && !subItemList && !vendorCode) {
+ return;
+ }
- // 벤더 코드 또는 이메일 중 하나는 있어야 함
- if (itemCode && (vendorCode || vendorEmail)) {
+ // 필수 필드 체크: 벤더이메일, 아이템코드
+ if (!vendorEmail || !itemCode) {
+ // 불완전한 데이터도 포함하여 에러 처리
data.push({
- vendorCode: vendorCode || '',
- vendorEmail: vendorEmail || '',
- itemCode,
- });
- } else {
- // 불완전한 데이터 처리
- data.push({
- vendorCode: vendorCode || '',
vendorEmail: vendorEmail || '',
itemCode: itemCode || '',
+ workType: workType || undefined,
+ shipTypes: shipTypes || undefined,
+ itemList: itemList || undefined,
+ subItemList: subItemList || undefined,
+ vendorCode: vendorCode || undefined,
});
+ return;
}
+
+ // 완전한 데이터 추가
+ data.push({
+ vendorEmail,
+ itemCode,
+ workType: workType || undefined,
+ shipTypes: shipTypes || undefined,
+ itemList: itemList || undefined,
+ subItemList: subItemList || undefined,
+ vendorCode: vendorCode || undefined,
+ });
});
if (data.length === 0) {
@@ -99,7 +130,7 @@ export async function importTechVendorPossibleItemsFromExcel( }
/**
- * 실패한 항목들을 포함한 오류 Excel 파일 생성
+ * 실패한 항목들을 포함한 오류 Excel 파일 생성 (새로운 스키마 버전)
*/
async function createErrorExcelFile(
failedRows: ImportResult['failedRows']
@@ -108,12 +139,16 @@ async function createErrorExcelFile( const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Import 오류 목록');
- // 헤더 설정
+ // 헤더 설정 (새로운 스키마에 맞춰)
worksheet.columns = [
{ header: '행 번호', key: 'row', width: 10 },
+ { header: '벤더이메일', key: 'vendorEmail', width: 30 },
{ header: '아이템코드', key: 'itemCode', width: 20 },
+ { header: '공종', key: 'workType', width: 15 },
+ { header: '선종', key: 'shipTypes', width: 20 },
+ { header: '아이템리스트', key: 'itemList', width: 30 },
+ { header: '서브아이템리스트', key: 'subItemList', width: 30 },
{ header: '벤더코드', key: 'vendorCode', width: 15 },
- { header: '벤더이메일', key: 'vendorEmail', width: 30 },
{ header: '오류 내용', key: 'error', width: 60 },
{ header: '해결 방법', key: 'solution', width: 40 },
];
@@ -142,19 +177,25 @@ async function createErrorExcelFile( failedRows.forEach((item) => {
let solution = '시스템 관리자에게 문의하세요';
- if (item.error.includes('벤더 코드') || item.error.includes('벤더 이메일')) {
- solution = '등록된 벤더 코드 또는 이메일인지 확인하세요';
+ if (item.error.includes('벤더 이메일')) {
+ solution = '올바른 이메일 형식으로 등록된 벤더 이메일인지 확인하세요';
} else if (item.error.includes('아이템 코드')) {
- solution = '벤더 타입에 맞는 아이템 코드인지 확인하세요';
+ solution = '아이템 코드가 누락되었거나 잘못된 형식입니다';
} else if (item.error.includes('이미 존재')) {
- solution = '중복된 조합입니다. 제거하거나 건너뛰세요';
+ solution = '중복된 조합입니다. 기존 데이터를 확인하세요';
+ } else if (item.error.includes('찾을 수 없습니다')) {
+ solution = '벤더 이메일이 시스템에 등록되어 있는지 확인하세요';
}
const row = worksheet.addRow({
row: item.row,
- itemCode: item.itemCode || '누락',
- vendorCode: item.vendorCode || '누락',
vendorEmail: item.vendorEmail || '누락',
+ itemCode: item.itemCode || '누락',
+ workType: item.workType || '',
+ shipTypes: item.shipTypes || '',
+ itemList: item.itemList || '',
+ subItemList: item.subItemList || '',
+ vendorCode: item.vendorCode || '',
error: item.error,
solution: solution,
});
@@ -169,24 +210,35 @@ async function createErrorExcelFile( });
});
- // 안내사항 추가
+ // 안내사항 추가 (새로운 스키마에 맞춰)
const instructionSheet = workbook.addWorksheet('오류 해결 가이드');
const instructions = [
- ['📋 오류 유형별 해결 방법', ''],
+ ['📋 새로운 스키마 Import 가이드', ''],
['', ''],
- ['1. 벤더 코드/이메일 오류:', ''],
- [' • 시스템에 등록된 벤더 코드 또는 이메일인지 확인', ''],
+ ['📌 필수 필드:', ''],
+ [' • 벤더이메일: 시스템에 등록된 벤더의 이메일 주소', ''],
+ [' • 아이템코드: 처리할 아이템의 코드', ''],
+ ['', ''],
+ ['📌 선택 필드:', ''],
+ [' • 공종: 작업 유형 (예: 용접, 도장, 기계 등)', ''],
+ [' • 선종: 선박 유형 (예: 컨테이너선, 벌크선, 탱커 등)', ''],
+ [' • 아이템리스트: 아이템에 대한 상세 설명', ''],
+ [' • 서브아이템리스트: 세부 아이템들에 대한 설명', ''],
+ [' • 벤더코드: 호환성을 위한 선택 필드', ''],
+ ['', ''],
+ ['🔍 오류 유형별 해결 방법:', ''],
+ ['', ''],
+ ['1. 벤더 이메일 오류:', ''],
+ [' • 올바른 이메일 형식 확인 (예: vendor@example.com)', ''],
+ [' • 시스템에 등록된 벤더 이메일인지 확인', ''],
[' • 벤더 관리 메뉴에서 등록 상태 확인', ''],
- [' • 벤더 코드가 없으면 벤더 이메일로 대체 가능', ''],
['', ''],
['2. 아이템 코드 오류:', ''],
- [' • 벤더 타입과 일치하는 아이템인지 확인', ''],
- [' • 조선 벤더 → item_shipbuilding 테이블', ''],
- [' • 해양TOP 벤더 → item_offshore_top 테이블', ''],
- [' • 해양HULL 벤더 → item_offshore_hull 테이블', ''],
+ [' • 아이템 코드가 누락되지 않았는지 확인', ''],
+ [' • 특수문자나 공백이 포함되지 않았는지 확인', ''],
['', ''],
['3. 중복 오류:', ''],
- [' • 이미 등록된 벤더-아이템 조합', ''],
+ [' • 동일한 벤더 + 아이템코드 + 공종 + 선종 조합', ''],
[' • 기존 데이터 확인 후 중복 제거', ''],
['', ''],
['📞 추가 문의: 시스템 관리자', ''],
@@ -196,12 +248,14 @@ async function createErrorExcelFile( const row = instructionSheet.addRow(rowData);
if (index === 0) {
row.getCell(1).font = { bold: true, size: 14, color: { argb: 'FF1F4E79' } };
+ } else if (rowData[0]?.includes('📌') || rowData[0]?.includes('🔍')) {
+ row.getCell(1).font = { bold: true, color: { argb: 'FF1F4E79' } };
} else if (rowData[0]?.includes(':')) {
row.getCell(1).font = { bold: true, color: { argb: 'FF1F4E79' } };
}
});
- instructionSheet.getColumn(1).width = 50;
+ instructionSheet.getColumn(1).width = 60;
// 파일 생성 및 다운로드
const buffer = await workbook.xlsx.writeBuffer();
|
