From dfdfae3018f8499240f48d28ce634f4a5c56e006 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Wed, 2 Apr 2025 09:54:08 +0000
Subject: 벤더 코멘트 처리
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/pq/table/pq-excel-template.tsx | 205 +++++++++++++++++++++++++++++++++++++
 1 file changed, 205 insertions(+)
 create mode 100644 lib/pq/table/pq-excel-template.tsx

(limited to 'lib/pq/table/pq-excel-template.tsx')

diff --git a/lib/pq/table/pq-excel-template.tsx b/lib/pq/table/pq-excel-template.tsx
new file mode 100644
index 00000000..aa8c1b3a
--- /dev/null
+++ b/lib/pq/table/pq-excel-template.tsx
@@ -0,0 +1,205 @@
+"use client"
+
+import * as ExcelJS from 'exceljs';
+import { saveAs } from 'file-saver';
+import { toast } from 'sonner';
+
+/**
+ * PQ 기준 Excel 템플릿을 다운로드하는 함수 (exceljs 사용)
+ * @param isProjectSpecific 프로젝트별 PQ 템플릿 여부
+ */
+export async function exportPqTemplate(isProjectSpecific: boolean = false) {
+  try {
+    // 워크북 생성
+    const workbook = new ExcelJS.Workbook();
+    
+    // 워크시트 생성
+    const sheetName = isProjectSpecific ? "Project PQ Template" : "General PQ Template";
+    const worksheet = workbook.addWorksheet(sheetName);
+    
+    // 그룹 옵션 정의 - 드롭다운 목록에 사용
+    const groupOptions = [
+      "GENERAL",
+      "Quality Management System",
+      "Workshop & Environment",
+      "Warranty",
+    ];
+    
+    // 일반 PQ 필드 (기본 필드)
+    const basicFields = [
+      { header: "Code", key: "code", width: 90 },
+      { header: "Check Point", key: "checkPoint", width: 180 },
+      { header: "Group Name", key: "groupName", width: 150 },
+      { header: "Description", key: "description", width: 240 },
+      { header: "Remarks", key: "remarks", width: 180 },
+    ];
+    
+    // 프로젝트별 PQ 추가 필드
+    const projectFields = isProjectSpecific 
+      ? [
+          { header: "Contract Info", key: "contractInfo", width: 180 },
+          { header: "Additional Requirements", key: "additionalRequirement", width: 240 },
+        ] 
+      : [];
+    
+    // 모든 필드 합치기
+    const fields = [...basicFields, ...projectFields];
+    
+    // 지침 행 추가
+    const instructionTitle = worksheet.addRow(["Instructions:"]);
+    instructionTitle.font = { bold: true, size: 12 };
+    worksheet.mergeCells(1, 1, 1, fields.length);
+    
+    const instructions = [
+      "1. 'Code' 필드는 고유해야 합니다 (예: 1-1, A.2.3).",
+      "2. 'Check Point'는 필수 항목입니다.",
+      "3. 'Group Name'은 드롭다운 목록에서 선택하세요: GENERAL, Quality Management System, Workshop & Environment, Warranty",
+      "4. 여러 줄 텍스트는 \\n으로 줄바꿈을 표시합니다.",
+      "5. 아래 회색 배경의 예시 행은 참고용입니다. 실제 데이터 입력 전에 이 행을 수정하거나 삭제해야 합니다.",
+    ];
+    
+    // 프로젝트별 PQ일 경우 추가 지침
+    if (isProjectSpecific) {
+      instructions.push(
+        "6. 'Contract Info'와 'Additional Requirements'는 프로젝트별 세부 정보를 위한 필드입니다."
+      );
+    }
+    
+    // 지침 행 추가
+    instructions.forEach((instruction, idx) => {
+      const row = worksheet.addRow([instruction]);
+      worksheet.mergeCells(idx + 2, 1, idx + 2, fields.length);
+      row.font = { color: { argb: '00808080' } };
+    });
+    
+    // 빈 행 추가
+    worksheet.addRow([]);
+    
+    // 헤더 행 추가
+    const headerRow = worksheet.addRow(fields.map(field => field.header));
+    headerRow.font = { bold: true, color: { argb: 'FFFFFFFF' } };
+    headerRow.fill = {
+      type: 'pattern',
+      pattern: 'solid',
+      fgColor: { argb: 'FF4472C4' }
+    };
+    headerRow.alignment = { vertical: 'middle', horizontal: 'center' };
+    
+    // 예시 행 표시를 위한 첫 번째 열 값 수정
+    const exampleData: Record<string, string> = {
+      code: "[예시 - 수정/삭제 필요] 1-1",
+      checkPoint: "Selling / 1 year Property",
+      groupName: "GENERAL",
+      description: "Address :\nTel. / Fax :\ne-mail :",
+      remarks: "Optional remarks",
+    };
+    
+    // 프로젝트별 PQ인 경우 예시 데이터에 추가 필드 추가
+    if (isProjectSpecific) {
+      exampleData.contractInfo = "Contract details for this project";
+      exampleData.additionalRequirement = "Additional technical requirements";
+    }
+    
+    const exampleRow = worksheet.addRow(fields.map(field => exampleData[field.key] || ""));
+    exampleRow.font = { italic: true };
+    exampleRow.fill = {
+      type: 'pattern',
+      pattern: 'solid',
+      fgColor: { argb: 'FFEDEDED' }
+    };
+    // 예시 행 첫 번째 셀에 코멘트 추가
+    const codeCell = worksheet.getCell(exampleRow.number, 1);
+    codeCell.note = '이 예시 행은 참고용입니다. 실제 데이터 입력 전에 수정하거나 삭제하세요.';
+    
+    // Group Name 열 인덱스 찾기 (0-based)
+    const groupNameIndex = fields.findIndex(field => field.key === "groupName");
+    
+    // 열 너비 설정
+    fields.forEach((field, index) => {
+      const column = worksheet.getColumn(index + 1);
+      column.width = field.width / 6.5; // ExcelJS에서는 픽셀과 다른 단위 사용
+    });
+    
+    // 각 셀에 테두리 추가
+    const headerRowNum = instructions.length + 3;
+    const exampleRowNum = headerRowNum + 1;
+    
+    for (let i = 1; i <= fields.length; i++) {
+      // 헤더 행에 테두리 추가
+      worksheet.getCell(headerRowNum, i).border = {
+        top: { style: 'thin' },
+        left: { style: 'thin' },
+        bottom: { style: 'thin' },
+        right: { style: 'thin' }
+      };
+      
+      // 예시 행에 테두리 추가
+      worksheet.getCell(exampleRowNum, i).border = {
+        top: { style: 'thin' },
+        left: { style: 'thin' },
+        bottom: { style: 'thin' },
+        right: { style: 'thin' }
+      };
+    }
+    
+    // 사용자 입력용 빈 행 추가 (10개)
+    for (let rowIdx = 0; rowIdx < 10; rowIdx++) {
+      // 빈 행 추가
+      const emptyRow = worksheet.addRow(Array(fields.length).fill(''));
+      const currentRowNum = exampleRowNum + 1 + rowIdx;
+      
+      // 각 셀에 테두리 추가
+      for (let colIdx = 1; colIdx <= fields.length; colIdx++) {
+        const cell = worksheet.getCell(currentRowNum, colIdx);
+        cell.border = {
+          top: { style: 'thin' },
+          left: { style: 'thin' },
+          bottom: { style: 'thin' },
+          right: { style: 'thin' }
+        };
+        
+        // Group Name 열에 데이터 유효성 검사 (드롭다운) 추가
+        if (colIdx === groupNameIndex + 1) {
+          cell.dataValidation = {
+            type: 'list',
+            allowBlank: true,
+            formulae: [`"${groupOptions.join(',')}"`],
+            showErrorMessage: true,
+            errorStyle: 'error',
+            error: '유효하지 않은 그룹입니다',
+            errorTitle: '입력 오류',
+            prompt: '목록에서 선택하세요',
+            promptTitle: '그룹 선택'
+          };
+        }
+      }
+    }
+    
+    // 예시 행이 있는 열에도 Group Name 드롭다운 적용
+    const exampleGroupCell = worksheet.getCell(exampleRowNum, groupNameIndex + 1);
+    exampleGroupCell.dataValidation = {
+      type: 'list',
+      allowBlank: true,
+      formulae: [`"${groupOptions.join(',')}"`],
+      showErrorMessage: true,
+      errorStyle: 'error',
+      error: '유효하지 않은 그룹입니다',
+      errorTitle: '입력 오류',
+      prompt: '목록에서 선택하세요',
+      promptTitle: '그룹 선택'
+    };
+    
+    // 워크북을 Excel 파일로 변환
+    const buffer = await workbook.xlsx.writeBuffer();
+    
+    // 파일명 설정 및 저장
+    const fileName = isProjectSpecific ? "project-pq-template.xlsx" : "general-pq-template.xlsx";
+    const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+    saveAs(blob, fileName);
+    
+    toast.success(`${isProjectSpecific ? '프로젝트별' : '일반'} PQ 템플릿이 다운로드되었습니다.`);
+  } catch (error) {
+    console.error("템플릿 다운로드 중 오류 발생:", error);
+    toast.error("템플릿 다운로드 중 오류가 발생했습니다.");
+  }
+}
\ No newline at end of file
-- 
cgit v1.2.3

