Files
wace_rps/frontend/lib/utils/purchaseOrderPdf.ts
T
hjjeong 17b08c7a09 구매관리 발주서 메일 발송 + PDF 다운로드 + 행추가/삭제 제거
- backend purchaseOrderMailService 신설 — getOrderMailInfo / getPartnerManagerList /
  sendOrderMail (SMTP PURCHASE, 발송 성공 시 mail_send_yn='Y'/mail_send_date 갱신)
- backend routes — GET /order-form/mail-info/:objid, POST /order-form/mail,
  GET /options/partner-managers/:partnerObjid
- frontend lib/utils/purchaseOrderPdf — html2canvas-pro + jsPDF (A4, scale=2,
  input/textarea → 텍스트 변환). download:true 면 파일 저장, 아니면 base64 반환
- PurchaseOrderMailDialog 신설 — EstimateMailDialog 패턴 단순화 (한글/영문 본문 분기,
  공급업체 단일 email 자동 채움)
- 3개 양식 다이얼로그 — 읽기전용 + 저장된 발주서일 때 "메일 발송" + "PDF 다운로드"
  버튼 노출. window.print 간이판 제거
- 3개 양식 다이얼로그 — "행 추가"/"선택 행 삭제" 버튼 + 그리드 체크박스 컬럼 제거
  (wace 운영판은 모두 주석 처리/부재. 발주서는 품의서에서 자동 채움된 품목 그대로 사용)
2026-05-19 14:57:47 +09:00

60 lines
2.3 KiB
TypeScript

// 발주서 다이얼로그 컨테이너 DOM → PDF base64 변환 헬퍼.
// 영업관리 estimate template2 (lib + sales/estimate/template2/pop/page.tsx 372-438) 패턴 단순화 버전.
// - 다이얼로그 안의 양식 컨테이너를 html2canvas-pro 로 캡처 (scale=2, 흰배경, input/textarea → 텍스트)
// - A4 비율로 jsPDF 에 그려 datauristring 반환 (메일 첨부) 또는 save (파일 다운로드)
export async function generatePurchaseOrderPdf(
container: HTMLElement,
opts?: { filename?: string; download?: boolean },
): Promise<string> {
const html2canvas = (await import("html2canvas-pro")).default;
const jspdfModule: any = await import("jspdf");
const jsPDF = jspdfModule.jsPDF ?? jspdfModule.default;
const canvas = await html2canvas(container, {
scale: 2,
useCORS: true,
backgroundColor: "#ffffff",
onclone: (doc) => {
// input/textarea/select → 텍스트로 교체 (편집 윤곽 제거)
doc.querySelectorAll("input, textarea").forEach((el) => {
const v = (el as HTMLInputElement | HTMLTextAreaElement).value ?? "";
const span = doc.createElement("span");
span.textContent = v;
(span.style as any).whiteSpace = "pre-wrap";
el.parentNode?.replaceChild(span, el);
});
// ShadCN Select 트리거 안의 표시 텍스트만 추출 — 화살표/아이콘은 제거
doc.querySelectorAll('[role="combobox"]').forEach((el) => {
const text = el.textContent ?? "";
const span = doc.createElement("span");
span.textContent = text.trim();
el.parentNode?.replaceChild(span, el);
});
},
});
const pdf = new jsPDF("p", "mm", "a4");
const imgData = canvas.toDataURL("image/jpeg", 0.85);
const imgWidth = 210;
const pageHeight = 297;
const imgHeight = (canvas.height * imgWidth) / canvas.width;
let heightLeft = imgHeight;
let position = 0;
pdf.addImage(imgData, "JPEG", 0, position, imgWidth, imgHeight, undefined, "FAST");
heightLeft -= pageHeight;
while (heightLeft > 0) {
position = heightLeft - imgHeight;
pdf.addPage();
pdf.addImage(imgData, "JPEG", 0, position, imgWidth, imgHeight, undefined, "FAST");
heightLeft -= pageHeight;
}
if (opts?.download) {
pdf.save(opts.filename ?? "purchase_order.pdf");
}
return pdf.output("datauristring") as string;
}