diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-21 07:54:26 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-21 07:54:26 +0000 |
| commit | 14f61e24947fb92dd71ec0a7196a6e815f8e66da (patch) | |
| tree | 317c501d64662d05914330628f867467fba78132 /lib/tech-vendors/table/vendor-all-export.ts | |
| parent | 194bd4bd7e6144d5c09c5e3f5476d254234dce72 (diff) | |
(최겸)기술영업 RFQ 담당자 초대, 요구사항 반영
Diffstat (limited to 'lib/tech-vendors/table/vendor-all-export.ts')
| -rw-r--r-- | lib/tech-vendors/table/vendor-all-export.ts | 512 |
1 files changed, 256 insertions, 256 deletions
diff --git a/lib/tech-vendors/table/vendor-all-export.ts b/lib/tech-vendors/table/vendor-all-export.ts index f2650102..f1492324 100644 --- a/lib/tech-vendors/table/vendor-all-export.ts +++ b/lib/tech-vendors/table/vendor-all-export.ts @@ -1,257 +1,257 @@ -// /lib/vendor-export.ts -import ExcelJS from "exceljs" -import { TechVendor, TechVendorContact, TechVendorItem } from "@/db/schema/techVendors" -import { exportTechVendorDetails } from "../service"; - -/** - * 선택된 벤더의 모든 관련 정보를 통합 시트 형식으로 엑셀로 내보내는 함수 - * - 기본정보 시트 - * - 연락처 시트 - * - 아이템 시트 - * 각 시트에는 식별을 위한 벤더 코드, 벤더명, 세금ID가 포함됨 - */ -export async function exportVendorsWithRelatedData( - vendors: TechVendor[], - filename = "tech-vendors-detailed" -): Promise<void> { - if (!vendors.length) return; - - // 선택된 벤더 ID 목록 - const vendorIds = vendors.map(vendor => vendor.id); - - try { - // 서버로부터 모든 관련 데이터 가져오기 - const vendorsWithDetails = await exportTechVendorDetails(vendorIds); - - if (!vendorsWithDetails.length) { - throw new Error("내보내기 데이터를 가져오는 중 오류가 발생했습니다."); - } - - // 워크북 생성 - const workbook = new ExcelJS.Workbook(); - - // 데이터 타입 확인 (서비스에서 반환하는 실제 데이터 형태) - const vendorData = vendorsWithDetails as unknown as any[]; - - // ===== 1. 기본 정보 시트 ===== - createBasicInfoSheet(workbook, vendorData); - - // ===== 2. 연락처 시트 ===== - createContactsSheet(workbook, vendorData); - - // ===== 3. 아이템 시트 ===== - createItemsSheet(workbook, vendorData); - - - // 파일 다운로드 - const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - }); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `${filename}-${new Date().toISOString().split("T")[0]}.xlsx`; - link.click(); - URL.revokeObjectURL(url); - - return; - } catch (error) { - console.error("Export error:", error); - throw error; - } -} - -// 기본 정보 시트 생성 함수 -function createBasicInfoSheet( - workbook: ExcelJS.Workbook, - vendors: TechVendor[] -): void { - const basicInfoSheet = workbook.addWorksheet("기본정보"); - - // 기본 정보 시트 헤더 설정 - basicInfoSheet.columns = [ - { header: "업체코드", key: "vendorCode", width: 15 }, - { header: "업체명", key: "vendorName", width: 20 }, - { header: "세금ID", key: "taxId", width: 15 }, - { header: "국가", key: "country", width: 10 }, - { header: "상태", key: "status", width: 15 }, - { header: "이메일", key: "email", width: 20 }, - { header: "전화번호", key: "phone", width: 15 }, - { header: "웹사이트", key: "website", width: 20 }, - { header: "주소", key: "address", width: 30 }, - { header: "대표자명", key: "representativeName", width: 15 }, - { header: "생성일", key: "createdAt", width: 15 }, - { header: "벤더타입", key: "techVendorType", width: 15 }, - { header: "대리점명", key: "agentName", width: 15 }, - { header: "대리점연락처", key: "agentPhone", width: 15 }, - { header: "대리점이메일", key: "agentEmail", width: 25 }, - { header: "대리점주소", key: "agentAddress", width: 30 }, - { header: "대리점국가", key: "agentCountry", width: 15 }, - { header: "대리점영문국가명", key: "agentCountryEng", width: 20 }, - ]; - - // 헤더 스타일 설정 - applyHeaderStyle(basicInfoSheet); - - // 벤더 데이터 추가 - vendors.forEach((vendor: TechVendor) => { - basicInfoSheet.addRow({ - vendorCode: vendor.vendorCode || "", - vendorName: vendor.vendorName, - taxId: vendor.taxId, - country: vendor.country, - status: getStatusText(vendor.status), // 상태 코드를 읽기 쉬운 텍스트로 변환 - email: vendor.email, - phone: vendor.phone, - website: vendor.website, - address: vendor.address, - representativeName: vendor.representativeName, - createdAt: vendor.createdAt ? formatDate(vendor.createdAt) : "", - techVendorType: vendor.techVendorType?.split(',').join(', ') || vendor.techVendorType, - }); - }); -} - -// 연락처 시트 생성 함수 -function createContactsSheet( - workbook: ExcelJS.Workbook, - vendors: TechVendor[] -): void { - const contactsSheet = workbook.addWorksheet("연락처"); - - contactsSheet.columns = [ - // 벤더 식별 정보 - { header: "업체코드", key: "vendorCode", width: 15 }, - { header: "업체명", key: "vendorName", width: 20 }, - { header: "세금ID", key: "taxId", width: 15 }, - // 연락처 정보 - { header: "이름", key: "contactName", width: 15 }, - { header: "직책", key: "contactPosition", width: 15 }, - { header: "이메일", key: "contactEmail", width: 25 }, - { header: "전화번호", key: "contactPhone", width: 15 }, - { header: "주요 연락처", key: "isPrimary", width: 10 }, - ]; - - // 헤더 스타일 설정 - applyHeaderStyle(contactsSheet); - - // 벤더별 연락처 데이터 추가 - vendors.forEach((vendor: TechVendor) => { - if (vendor.contacts && vendor.contacts.length > 0) { - vendor.contacts.forEach((contact: TechVendorContact) => { - contactsSheet.addRow({ - // 벤더 식별 정보 - vendorCode: vendor.vendorCode || "", - vendorName: vendor.vendorName, - taxId: vendor.taxId, - // 연락처 정보 - contactName: contact.contactName, - contactPosition: contact.contactPosition || "", - contactEmail: contact.contactEmail, - contactPhone: contact.contactPhone || "", - isPrimary: contact.isPrimary ? "예" : "아니오", - }); - }); - } else { - // 연락처가 없는 경우에도 벤더 정보만 추가 - contactsSheet.addRow({ - vendorCode: vendor.vendorCode || "", - vendorName: vendor.vendorName, - taxId: vendor.taxId, - contactName: "", - contactPosition: "", - contactEmail: "", - contactPhone: "", - isPrimary: "", - }); - } - }); -} - -// 아이템 시트 생성 함수 -function createItemsSheet( - workbook: ExcelJS.Workbook, - vendors: TechVendor[] -): void { - const itemsSheet = workbook.addWorksheet("아이템"); - - itemsSheet.columns = [ - // 벤더 식별 정보 - { header: "업체코드", key: "vendorCode", width: 15 }, - { header: "업체명", key: "vendorName", width: 20 }, - { header: "세금ID", key: "taxId", width: 15 }, - // 아이템 정보 - { header: "아이템 코드", key: "itemCode", width: 15 }, - { header: "아이템명", key: "itemName", width: 25 }, - { header: "설명", key: "description", width: 30 }, - { header: "등록일", key: "createdAt", width: 15 }, - ]; - - // 헤더 스타일 설정 - applyHeaderStyle(itemsSheet); - - // 벤더별 아이템 데이터 추가 - vendors.forEach((vendor: TechVendor) => { - if (vendor.items && vendor.items.length > 0) { - vendor.items.forEach((item: TechVendorItem) => { - itemsSheet.addRow({ - // 벤더 식별 정보 - vendorCode: vendor.vendorCode || "", - vendorName: vendor.vendorName, - taxId: vendor.taxId, - // 아이템 정보 - itemCode: item.itemCode, - itemName: item.itemName, - createdAt: item.createdAt ? formatDate(item.createdAt) : "", - }); - }); - } else { - // 아이템이 없는 경우에도 벤더 정보만 추가 - itemsSheet.addRow({ - vendorCode: vendor.vendorCode || "", - vendorName: vendor.vendorName, - taxId: vendor.taxId, - itemCode: "", - itemName: "", - createdAt: "", - }); - } - }); -} - - -// 헤더 스타일 적용 함수 -function applyHeaderStyle(sheet: ExcelJS.Worksheet): void { - const headerRow = sheet.getRow(1); - headerRow.font = { bold: true }; - headerRow.alignment = { horizontal: "center" }; - headerRow.eachCell((cell: ExcelJS.Cell) => { - cell.fill = { - type: "pattern", - pattern: "solid", - fgColor: { argb: "FFCCCCCC" }, - }; - }); -} - -// 날짜 포맷 함수 -function formatDate(date: Date | string): string { - if (!date) return ""; - if (typeof date === 'string') { - date = new Date(date); - } - return date.toISOString().split('T')[0]; -} - - -// 상태 코드를 읽기 쉬운 텍스트로 변환하는 함수 -function getStatusText(status: string): string { - const statusMap: Record<string, string> = { - "ACTIVE": "활성", - "INACTIVE": "비활성", - "BLACKLISTED": "거래 금지" - }; - - return statusMap[status] || status; +// /lib/vendor-export.ts
+import ExcelJS from "exceljs"
+import { TechVendor, TechVendorContact, TechVendorItem } from "@/db/schema/techVendors"
+import { exportTechVendorDetails } from "../service";
+
+/**
+ * 선택된 벤더의 모든 관련 정보를 통합 시트 형식으로 엑셀로 내보내는 함수
+ * - 기본정보 시트
+ * - 연락처 시트
+ * - 아이템 시트
+ * 각 시트에는 식별을 위한 벤더 코드, 벤더명, 세금ID가 포함됨
+ */
+export async function exportVendorsWithRelatedData(
+ vendors: TechVendor[],
+ filename = "tech-vendors-detailed"
+): Promise<void> {
+ if (!vendors.length) return;
+
+ // 선택된 벤더 ID 목록
+ const vendorIds = vendors.map(vendor => vendor.id);
+
+ try {
+ // 서버로부터 모든 관련 데이터 가져오기
+ const vendorsWithDetails = await exportTechVendorDetails(vendorIds);
+
+ if (!vendorsWithDetails.length) {
+ throw new Error("내보내기 데이터를 가져오는 중 오류가 발생했습니다.");
+ }
+
+ // 워크북 생성
+ const workbook = new ExcelJS.Workbook();
+
+ // 데이터 타입 확인 (서비스에서 반환하는 실제 데이터 형태)
+ const vendorData = vendorsWithDetails as unknown as any[];
+
+ // ===== 1. 기본 정보 시트 =====
+ createBasicInfoSheet(workbook, vendorData);
+
+ // ===== 2. 연락처 시트 =====
+ createContactsSheet(workbook, vendorData);
+
+ // ===== 3. 아이템 시트 =====
+ createItemsSheet(workbook, vendorData);
+
+
+ // 파일 다운로드
+ const buffer = await workbook.xlsx.writeBuffer();
+ const blob = new Blob([buffer], {
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ });
+ const url = URL.createObjectURL(blob);
+ const link = document.createElement("a");
+ link.href = url;
+ link.download = `${filename}-${new Date().toISOString().split("T")[0]}.xlsx`;
+ link.click();
+ URL.revokeObjectURL(url);
+
+ return;
+ } catch (error) {
+ console.error("Export error:", error);
+ throw error;
+ }
+}
+
+// 기본 정보 시트 생성 함수
+function createBasicInfoSheet(
+ workbook: ExcelJS.Workbook,
+ vendors: TechVendor[]
+): void {
+ const basicInfoSheet = workbook.addWorksheet("기본정보");
+
+ // 기본 정보 시트 헤더 설정
+ basicInfoSheet.columns = [
+ { header: "업체코드", key: "vendorCode", width: 15 },
+ { header: "업체명", key: "vendorName", width: 20 },
+ { header: "세금ID", key: "taxId", width: 15 },
+ { header: "국가", key: "country", width: 10 },
+ { header: "상태", key: "status", width: 15 },
+ { header: "이메일", key: "email", width: 20 },
+ { header: "전화번호", key: "phone", width: 15 },
+ { header: "웹사이트", key: "website", width: 20 },
+ { header: "주소", key: "address", width: 30 },
+ { header: "대표자명", key: "representativeName", width: 15 },
+ { header: "생성일", key: "createdAt", width: 15 },
+ { header: "벤더타입", key: "techVendorType", width: 15 },
+ { header: "에이전트명", key: "agentName", width: 15 },
+ { header: "에이전트연락처", key: "agentPhone", width: 15 },
+ { header: "에이전트이메일", key: "agentEmail", width: 25 },
+ { header: "에이전트주소", key: "agentAddress", width: 30 },
+ { header: "에이전트국가", key: "agentCountry", width: 15 },
+ { header: "에이전트영문국가명", key: "agentCountryEng", width: 20 },
+ ];
+
+ // 헤더 스타일 설정
+ applyHeaderStyle(basicInfoSheet);
+
+ // 벤더 데이터 추가
+ vendors.forEach((vendor: TechVendor) => {
+ basicInfoSheet.addRow({
+ vendorCode: vendor.vendorCode || "",
+ vendorName: vendor.vendorName,
+ taxId: vendor.taxId,
+ country: vendor.country,
+ status: getStatusText(vendor.status), // 상태 코드를 읽기 쉬운 텍스트로 변환
+ email: vendor.email,
+ phone: vendor.phone,
+ website: vendor.website,
+ address: vendor.address,
+ representativeName: vendor.representativeName,
+ createdAt: vendor.createdAt ? formatDate(vendor.createdAt) : "",
+ techVendorType: vendor.techVendorType?.split(',').join(', ') || vendor.techVendorType,
+ });
+ });
+}
+
+// 연락처 시트 생성 함수
+function createContactsSheet(
+ workbook: ExcelJS.Workbook,
+ vendors: TechVendor[]
+): void {
+ const contactsSheet = workbook.addWorksheet("연락처");
+
+ contactsSheet.columns = [
+ // 벤더 식별 정보
+ { header: "업체코드", key: "vendorCode", width: 15 },
+ { header: "업체명", key: "vendorName", width: 20 },
+ { header: "세금ID", key: "taxId", width: 15 },
+ // 연락처 정보
+ { header: "이름", key: "contactName", width: 15 },
+ { header: "직책", key: "contactPosition", width: 15 },
+ { header: "이메일", key: "contactEmail", width: 25 },
+ { header: "전화번호", key: "contactPhone", width: 15 },
+ { header: "주요 연락처", key: "isPrimary", width: 10 },
+ ];
+
+ // 헤더 스타일 설정
+ applyHeaderStyle(contactsSheet);
+
+ // 벤더별 연락처 데이터 추가
+ vendors.forEach((vendor: TechVendor) => {
+ if (vendor.contacts && vendor.contacts.length > 0) {
+ vendor.contacts.forEach((contact: TechVendorContact) => {
+ contactsSheet.addRow({
+ // 벤더 식별 정보
+ vendorCode: vendor.vendorCode || "",
+ vendorName: vendor.vendorName,
+ taxId: vendor.taxId,
+ // 연락처 정보
+ contactName: contact.contactName,
+ contactPosition: contact.contactPosition || "",
+ contactEmail: contact.contactEmail,
+ contactPhone: contact.contactPhone || "",
+ isPrimary: contact.isPrimary ? "예" : "아니오",
+ });
+ });
+ } else {
+ // 연락처가 없는 경우에도 벤더 정보만 추가
+ contactsSheet.addRow({
+ vendorCode: vendor.vendorCode || "",
+ vendorName: vendor.vendorName,
+ taxId: vendor.taxId,
+ contactName: "",
+ contactPosition: "",
+ contactEmail: "",
+ contactPhone: "",
+ isPrimary: "",
+ });
+ }
+ });
+}
+
+// 아이템 시트 생성 함수
+function createItemsSheet(
+ workbook: ExcelJS.Workbook,
+ vendors: TechVendor[]
+): void {
+ const itemsSheet = workbook.addWorksheet("아이템");
+
+ itemsSheet.columns = [
+ // 벤더 식별 정보
+ { header: "업체코드", key: "vendorCode", width: 15 },
+ { header: "업체명", key: "vendorName", width: 20 },
+ { header: "세금ID", key: "taxId", width: 15 },
+ // 아이템 정보
+ { header: "아이템 코드", key: "itemCode", width: 15 },
+ { header: "아이템명", key: "itemName", width: 25 },
+ { header: "설명", key: "description", width: 30 },
+ { header: "등록일", key: "createdAt", width: 15 },
+ ];
+
+ // 헤더 스타일 설정
+ applyHeaderStyle(itemsSheet);
+
+ // 벤더별 아이템 데이터 추가
+ vendors.forEach((vendor: TechVendor) => {
+ if (vendor.items && vendor.items.length > 0) {
+ vendor.items.forEach((item: TechVendorItem) => {
+ itemsSheet.addRow({
+ // 벤더 식별 정보
+ vendorCode: vendor.vendorCode || "",
+ vendorName: vendor.vendorName,
+ taxId: vendor.taxId,
+ // 아이템 정보
+ itemCode: item.itemCode,
+ itemName: item.itemName,
+ createdAt: item.createdAt ? formatDate(item.createdAt) : "",
+ });
+ });
+ } else {
+ // 아이템이 없는 경우에도 벤더 정보만 추가
+ itemsSheet.addRow({
+ vendorCode: vendor.vendorCode || "",
+ vendorName: vendor.vendorName,
+ taxId: vendor.taxId,
+ itemCode: "",
+ itemName: "",
+ createdAt: "",
+ });
+ }
+ });
+}
+
+
+// 헤더 스타일 적용 함수
+function applyHeaderStyle(sheet: ExcelJS.Worksheet): void {
+ const headerRow = sheet.getRow(1);
+ headerRow.font = { bold: true };
+ headerRow.alignment = { horizontal: "center" };
+ headerRow.eachCell((cell: ExcelJS.Cell) => {
+ cell.fill = {
+ type: "pattern",
+ pattern: "solid",
+ fgColor: { argb: "FFCCCCCC" },
+ };
+ });
+}
+
+// 날짜 포맷 함수
+function formatDate(date: Date | string): string {
+ if (!date) return "";
+ if (typeof date === 'string') {
+ date = new Date(date);
+ }
+ return date.toISOString().split('T')[0];
+}
+
+
+// 상태 코드를 읽기 쉬운 텍스트로 변환하는 함수
+function getStatusText(status: string): string {
+ const statusMap: Record<string, string> = {
+ "ACTIVE": "활성",
+ "INACTIVE": "비활성",
+ "BLACKLISTED": "거래 금지"
+ };
+
+ return statusMap[status] || status;
}
\ No newline at end of file |
