import { buildInvoicePartyDetailsSection } from '../../../shared/party-details-section/pdf-party-details.section'; import { buildInvoiceTableData, getAvailablePageWidth } from '../../../shared/table-section/pdf-table.section'; import { buildInvoiceTotalsAndNotesSection, buildSignatureSection } from '../../../shared/totals-section/pdf-totals.section'; import { toStr } from '../../../shared/header-footer-section/pdf-shared.utils'; import { TrUtils } from '../../../utils/tr-utils'; import JsBarcode from 'jsbarcode'; import { buildFooter, buildDocumentHeaderSection, buildPageNumberHeader, buildDocumentHeadingSection, buildLogoWatermarkBackground, buildWatermark, deriveHeaderDataFromInvoice, normalizeHeaderStyle, resolvePageMargins, resolvePageOrientation, resolvePageSize } from '../../../shared/header-footer-section/pdf-header-footer.section'; const PAGE_MARGINS: [number, number, number, number] = [20, 20, 20, 20]; const CELL_PADDING_LEFT = 4; const CELL_PADDING_RIGHT = 4; const BORDER_WIDTH = 0.5; const TABLE_BORDER_COLOR = '#d3d3d3'; export function CreateInvoicePDFService(PDFInvoiceData: any = {}, PrintConfigData: any = {}, printCopies: string[] = []) { const dd = buildPdfDocDefinition(PDFInvoiceData, PrintConfigData, printCopies); // pdfMake.createPdf(dd).open(); return dd; } export function DownloadInvoicePDFService(filename: string = 'invoice.pdf', PDFInvoiceData: any = {}, PrintConfigData: any = {}, printCopies: string[] = []) { const dd = buildPdfDocDefinition(PDFInvoiceData, PrintConfigData, printCopies); // pdfMake.createPdf(dd).download(filename); return dd; } export function GetInvoicePdfDataUrl(PDFInvoiceData: any = {}, PrintConfigData: any = {}, printCopies: string[] = []) { const dd = buildPdfDocDefinition(PDFInvoiceData, PrintConfigData, printCopies); return dd; // return new Promise((resolve, reject) => { // let settled = false; // const done = (value: string) => { // if (!settled) { // settled = true; // resolve(value); // } // }; // const fail = (error: any) => { // if (!settled) { // settled = true; // reject(error); // } // }; // try { // if (typeof pdfDoc.getDataUrl === 'function') { // const result = pdfDoc.getDataUrl((dataUrl: string) => done(dataUrl)); // if (result && typeof result.then === 'function') { // result.then((dataUrl: string) => done(dataUrl)).catch(fail); // } // return; // } // if (typeof pdfDoc.getBlob === 'function') { // const result = pdfDoc.getBlob((blob: Blob) => done(URL.createObjectURL(blob))); // if (result && typeof result.then === 'function') { // result.then((blob: Blob) => done(URL.createObjectURL(blob))).catch(fail); // } // return; // } // fail(new Error('No supported preview API found on pdf document instance.')); // } catch (error) { // fail(error); // } // }); } function CustomerInfo(InvoicePDFData: any) { let CustomerTable: any = [ [{ text: 'Name', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData.Customer.Name, style: ['headerstyle'], fontSize: 9 }], [{ text: 'Address', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData.Customer.Adrs?.[0], style: ['headerstyle'], fontSize: 9 }], ]; if (!TrUtils.IsEmpty(InvoicePDFData.Customer.Code)) { CustomerTable.unshift([{ text: 'UHID', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData.Customer.Code, style: ['headerstyle'], fontSize: 9 }]); } if (!TrUtils.IsEmpty(InvoicePDFData.Customer.DLNo)) { CustomerTable.push([{ text: 'DLNo', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData.Customer.DLNo, style: ['headerstyle'], fontSize: 9 }]); } return CustomerTable; } function GetBarCode(code: string, PrCustBar: boolean) { if (!TrUtils.IsNull(code) && PrCustBar) { return { svg: textToSvgBarcode(code).svg }; } return {}; } function textToSvgBarcode(text: string): any { const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); JsBarcode(svgElement, text, { format: 'CODE128', width: 1.25, height: 25, margin: 0, marginTop: 8, displayValue: true, fontSize: 7, textMargin: 0, fontOptions: 'bold' }); return { svg: svgElement.outerHTML }; } function GetPartyDetails(PrintConfig: any, InvoicePDFData: any) { return { style: 'tableExample', marginBottom: 4, table: { widths: ['*', 'auto', '*'], body: [ [{ marginLeft: 5, table: { lineHeight: 0.5, body: CustomerInfo(InvoicePDFData) }, layout: 'noBorders' }, GetBarCode(InvoicePDFData.Customer?.Code, PrintConfig?.Customer?.ShowBarCode), { marginRight: 5, marginLeft: 70, table: { lineHeight: 0.5, body: [ [{ text: 'Receipt No', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData._id, style: ['headerstyle'], fontSize: 9 }], [{ text: 'Date', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData.CrDate, style: ['headerstyle'], fontSize: 9 }], [{ text: 'Doctor', style: ['headerstyle'], fontSize: 9 }, { text: ':', style: ['headerstyle'], fontSize: 9 }, { text: InvoicePDFData.Name, style: ['headerstyle'], fontSize: 9 }] ] }, layout: 'noBorders' }] ] }, layout: HeaderLayOut() }; } function HeaderLayOut() { return { hLineWidth: function (i: any, node: any) { return (i === 0 || i === 1 || i === node.table.body.length) ? BORDER_WIDTH : 0; }, vLineWidth: function (i: any, node: any) { return (i === 0 || i === node.table.widths.length) ? BORDER_WIDTH : 0; }, hLineColor: function () { return TABLE_BORDER_COLOR; }, vLineColor: function () { return TABLE_BORDER_COLOR; }, }; } function GetMainHeaderInfo(Entity: any, Image: any, AColor: any, HColor: any, InvoicePDFData: any) { if (!TrUtils.IsNull(Image)) { return { columns: [{ image: Image, width: 60, height: 60, marginBottom: 5 }, { stack: [ { text: Entity.CName, style: ['headerstyle'], color: HColor, alignment: 'left', fontSize: 15 }, { text: GetAddress(Entity), alignment: 'left', style: ['headerstyle'], color: AColor, fontSize: 9 }, { columns: GetHeaderInfo(InvoicePDFData.Entity, 0) }, { text: InvoicePDFData.HeaderName, alignment: 'center', style: ['Receiptheader1'], marginTop: 5 } ] } ], columnGap: 10 }; } return { stack: [ { text: InvoicePDFData.Entity.CName, style: ['headerstyle'], alignment: 'center', fontSize: 15 }, { text: GetAddress(InvoicePDFData.Entity), alignment: 'center', style: ['headerstyle'], fontSize: 9 }, { columns: GetHeaderInfo(InvoicePDFData.Entity, 5) }, { text: InvoicePDFData.HeaderName, alignment: 'center', style: ['Receiptheader1'] } ] }; } function GetAddress(Entity: any) { return Entity.Adrs1 + ', ' + Entity.Adrs2 + ', ' + Entity.City + '-' + Entity.PIN + ', Cell : ' + Entity.Phone; } function GetHeaderInfo(Entity: any, marginleft: number) { let TaxInfo: any = []; if (!TrUtils.IsEmpty(Entity.GSTIN)) { TaxInfo.push({ text: 'GSTIN : ' + Entity.GSTIN, marginTop: 2, marginLeft: marginleft, alignment: 'left', fontSize: 9, width: 'auto' }); } if (!TrUtils.IsEmpty(Entity.DLNo)) { TaxInfo.push({ text: 'D.L.NO : ' + Entity.DLNo, marginTop: 2, marginLeft: 5, alignment: 'left', fontSize: 9, width: '*' }); } return TaxInfo; } function buildPdfDocDefinition(PDFInvoiceData: any = {}, PrintConfigData: any = {}, printCopies: string[] = []) { const PrintConfig = normalizePrintConfig(PDFInvoiceData, PrintConfigData); const requestedPageOrientation = resolvePageOrientation(PrintConfig?.Orientation || PrintConfig?.PageOrientation); const pageSize = resolvePageSize(PrintConfig?.PSize, requestedPageOrientation); const basePageMargins = resolvePageMargins(PrintConfig?.pageMargins); const copyLabels = normalizeCopyLabels(printCopies); const watermark = buildWatermark(PrintConfig, PDFInvoiceData); const background = buildLogoWatermarkBackground(PrintConfig, PDFInvoiceData); const pageHeader = buildPageNumberHeader(PrintConfig); const pageFooter = buildFooter(PrintConfig); let pageMargins: [number, number, number, number] = pageHeader !== null ? [basePageMargins[0], Math.max(basePageMargins[1], 18), basePageMargins[2], basePageMargins[3]] : basePageMargins; const raw = String(PrintConfig?.PSize ?? '').trim().toLowerCase(); const normalized = raw.replace(/[\s_-]/g, ''); if (normalized === 'halfa4') { pageMargins = [15, 15, 15, 435.945]; } const availableWidth = getAvailablePageWidth(pageSize, requestedPageOrientation, pageMargins); const content: any[] = []; copyLabels.forEach((copyLabel: string, index: number) => { let invoiceHeaderContent: any; let invoicePartyDetailsContent: any; let invoiceContentSections: any[]; if (PrintConfigData.IsPoSPrint) { invoiceHeaderContent = [GetMainHeaderInfo(PDFInvoiceData?.Entity, PDFInvoiceData?.Image, PrintConfig?.headerStyles?.OrgNameClr, PrintConfig?.headerStyles?.AdrsClr, PDFInvoiceData)]; invoicePartyDetailsContent = [GetPartyDetails(PrintConfig, PDFInvoiceData)]; } else { invoiceHeaderContent = buildDocumentHeaderSection(PrintConfig, PDFInvoiceData); invoicePartyDetailsContent = buildInvoicePartyDetailsSection(PDFInvoiceData, PrintConfig?.Customer, PrintConfig); } const invoiceTotalsAndNotesContent = buildInvoiceTotalsAndNotesSection(PDFInvoiceData, availableWidth, PrintConfigData); const signatureContent = buildSignatureSection(PrintConfig, PDFInvoiceData, availableWidth); const tableData = buildInvoiceTableData(PDFInvoiceData, PrintConfig, availableWidth); if (PrintConfigData.IsPoSPrint) { invoiceContentSections = [ ...invoiceHeaderContent, ...invoicePartyDetailsContent, ]; } else { const invoiceHeadingContent = buildDocumentHeadingSection(PDFInvoiceData, PrintConfig, availableWidth); invoiceContentSections = [ ...invoiceHeaderContent, ...invoiceHeadingContent, ...invoicePartyDetailsContent, ]; } if (index > 0) { content.push({ text: '', pageBreak: 'before' }); } if (copyLabel) { content.push({ text: copyLabel, alignment: 'right', bold: true, fontSize: 8, margin: [0, 0, 0, 2] }); } content.push( ...invoiceContentSections, { table: { lineHeight: 2, headerRows: tableData.headerRows.length, widths: tableData.widths, body: tableData.body }, layout: { paddingLeft: () => CELL_PADDING_LEFT, paddingRight: () => CELL_PADDING_RIGHT, vLineWidth: () => BORDER_WIDTH, hLineWidth: () => BORDER_WIDTH, vLineColor: () => TABLE_BORDER_COLOR, hLineColor: () => TABLE_BORDER_COLOR } }, ...invoiceTotalsAndNotesContent, ...signatureContent ); }); const dd = { pageSize: pageSize, ...(typeof pageSize === 'string' ? { pageOrientation: requestedPageOrientation } : {}), pageMargins: pageMargins, content: content, info: { title: GetFileName(PDFInvoiceData), subject: Array.isArray(printCopies) ? printCopies.join(', ') : '' }, ...(background ? { background } : {}), ...(watermark ? { watermark } : {}), ...(pageHeader !== null ? { header: pageHeader } : {}), ...(pageFooter !== null ? { footer: pageFooter } : {}) }; return dd; } function GetFileName(ROPrintData: any) { let fileName: string = ROPrintData.HeaderName; if (!TrUtils.IsNull(ROPrintData.Product) && !TrUtils.IsEmpty(ROPrintData.Product.RegNo)) { fileName = fileName + '-' + ROPrintData.Product.RegNo; } return fileName; } function normalizeCopyLabels(printCopies: string[] = []) { const labels = Array.isArray(printCopies) ? printCopies .map((entry: any) => toStr(entry).trim()) .filter((entry: string) => !!entry) : []; return labels.length > 0 ? labels : ['']; } function normalizePrintConfig(PDFInvoiceData: any, PrintConfigData: any) { const config = PrintConfigData || {}; const itemsHeader = Array.isArray(config?.TableConfig) ? config.TableConfig : []; const headerData = config?.headerData ? config.headerData : deriveHeaderDataFromInvoice(PDFInvoiceData); const pageMargins = resolvePageMargins(config?.Margin ?? PAGE_MARGINS); const watermarkText = toStr(config?.WatermarkText); const watermark = !!config?.Watermark; const watermarkEnabled = !!config?.WatermarkEnabled; const footerText = toStr(config?.Footer?.Text); const headerStyles = normalizeHeaderStyle(config?.headerStyles ?? { OrgNameFsize: config?.OrgNameFsize, OrgNameClr: config?.OrgNameClr, AdrsFsize: config?.AdrsFsize, AdrsClr: config?.AdrsClr }); const fixedTo = normalizeFixedTo(config?.fixedTo); return { ...config, itemsHeader, headerData, pageMargins, watermarkText, watermark, watermarkEnabled, footerText, headerStyles, fixedTo }; } function normalizeFixedTo(value: any) { const parsed = Number(value); if (!Number.isFinite(parsed) || parsed < 0) { return 2; } return Math.floor(parsed); }