diff --git a/packages/server/src/modules/CreditNotes/queries/GetCreditNotePdf.serivce.ts b/packages/server/src/modules/CreditNotes/queries/GetCreditNotePdf.serivce.ts index f71ba89a0..1c49af845 100644 --- a/packages/server/src/modules/CreditNotes/queries/GetCreditNotePdf.serivce.ts +++ b/packages/server/src/modules/CreditNotes/queries/GetCreditNotePdf.serivce.ts @@ -1,10 +1,10 @@ import { Inject, Injectable } from '@nestjs/common'; +import { renderCreditNotePaperTemplateHtml } from '@bigcapital/pdf-templates'; import { GetCreditNoteService } from './GetCreditNote.service'; import { CreditNoteBrandingTemplate } from './CreditNoteBrandingTemplate.service'; import { transformCreditNoteToPdfTemplate } from '../utils'; import { CreditNote } from '../models/CreditNote'; import { ChromiumlyTenancy } from '@/modules/ChromiumlyTenancy/ChromiumlyTenancy.service'; -import { TemplateInjectable } from '@/modules/TemplateInjectable/TemplateInjectable.service'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { PdfTemplateModel } from '@/modules/PdfTemplate/models/PdfTemplate'; import { CreditNotePdfTemplateAttributes } from '../types/CreditNotes.types'; @@ -15,7 +15,6 @@ import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; export class GetCreditNotePdf { /** * @param {ChromiumlyTenancy} chromiumlyTenancy - Chromiumly tenancy service. - * @param {TemplateInjectable} templateInjectable - Template injectable service. * @param {GetCreditNote} getCreditNoteService - Get credit note service. * @param {CreditNoteBrandingTemplate} creditNoteBrandingTemplate - Credit note branding template service. * @param {EventEmitter2} eventPublisher - Event publisher service. @@ -24,7 +23,6 @@ export class GetCreditNotePdf { */ constructor( private readonly chromiumlyTenancy: ChromiumlyTenancy, - private readonly templateInjectable: TemplateInjectable, private readonly getCreditNoteService: GetCreditNoteService, private readonly creditNoteBrandingTemplate: CreditNoteBrandingTemplate, private readonly eventPublisher: EventEmitter2, @@ -36,23 +34,40 @@ export class GetCreditNotePdf { private readonly pdfTemplateModel: TenantModelProxy< typeof PdfTemplateModel >, - ) {} + ) { } /** - * Retrieves sale invoice pdf content. + * Retrieves credit note html content. + * @param {number} creditNoteId - Credit note id. + * @returns {Promise} + */ + public async getCreditNoteHtml(creditNoteId: number): Promise { + const brandingAttributes = + await this.getCreditNoteBrandingAttributes(creditNoteId); + + // Map attributes to match the React component props + // The branding template returns companyLogoUri, but type may have companyLogo + const props = { + ...brandingAttributes, + companyLogoUri: + (brandingAttributes as any).companyLogoUri || + (brandingAttributes as any).companyLogo || + '', + }; + + return renderCreditNotePaperTemplateHtml(props); + } + + /** + * Retrieves credit note pdf content. * @param {number} creditNoteId - Credit note id. * @returns {Promise<[Buffer, string]>} */ public async getCreditNotePdf( creditNoteId: number, ): Promise<[Buffer, string]> { - const brandingAttributes = - await this.getCreditNoteBrandingAttributes(creditNoteId); - const htmlContent = await this.templateInjectable.render( - 'modules/credit-note-standard', - brandingAttributes, - ); const filename = await this.getCreditNoteFilename(creditNoteId); + const htmlContent = await this.getCreditNoteHtml(creditNoteId); const document = await this.chromiumlyTenancy.convertHtmlContent(htmlContent); diff --git a/shared/pdf-templates/src/components/CreditNotePaperTemplate.tsx b/shared/pdf-templates/src/components/CreditNotePaperTemplate.tsx new file mode 100644 index 000000000..b83370dcf --- /dev/null +++ b/shared/pdf-templates/src/components/CreditNotePaperTemplate.tsx @@ -0,0 +1,257 @@ +import { + PaperTemplate, + PaperTemplateProps, + PaperTemplateTotalBorder, +} from './PaperTemplate'; +import { Box } from '../lib/layout/Box'; +import { Text } from '../lib/text/Text'; +import { Stack } from '../lib/layout/Stack'; +import { Group } from '../lib/layout/Group'; +import { + DefaultPdfTemplateTerms, + DefaultPdfTemplateItemDescription, + DefaultPdfTemplateItemName, + DefaultPdfTemplateAddressBilledTo, + DefaultPdfTemplateAddressBilledFrom, +} from './_constants'; + +interface CreditNoteLine { + item?: string; + description?: string; + quantity?: string; + rate?: string; + total?: string; +} + +export interface CreditNotePaperTemplateProps extends PaperTemplateProps { + primaryColor?: string; + secondaryColor?: string; + + // Company + showCompanyLogo?: boolean; + companyLogoUri?: string; + + companyName?: string; + + // Credit Note number + showCreditNoteNumber?: boolean; + creditNoteNumebr?: string; + creditNoteNumberLabel?: string; + + // Credit Note date + showCreditNoteDate?: boolean; + creditNoteDate?: string; + creditNoteDateLabel?: string; + + // Address + showCustomerAddress?: boolean; + customerAddress?: string; + + showCompanyAddress?: boolean; + companyAddress?: string; + + billedToLabel?: string; + + // Entries + lineItemLabel?: string; + lineQuantityLabel?: string; + lineRateLabel?: string; + lineTotalLabel?: string; + + // Subtotal + showSubtotal?: boolean; + subtotalLabel?: string; + subtotal?: string; + + // Total + showTotal?: boolean; + totalLabel?: string; + total?: string; + + // Customer Note + showCustomerNote?: boolean; + customerNote?: string; + customerNoteLabel?: string; + + // Terms & Conditions + showTermsConditions?: boolean; + termsConditions?: string; + termsConditionsLabel?: string; + + lines?: Array; +} + +export function CreditNotePaperTemplate({ + // # Colors + primaryColor, + secondaryColor, + + // # Company + companyName = 'Bigcapital Technology, Inc.', + + showCompanyLogo = true, + companyLogoUri = '', + + // # Credit Note number + creditNoteNumberLabel = 'Credit Note Number', + creditNoteNumebr = '346D3D40-0001', + showCreditNoteNumber = true, + + // # Credit Note date + creditNoteDate = 'September 3, 2024', + creditNoteDateLabel = 'Credit Note Date', + showCreditNoteDate = true, + + // Address + showCustomerAddress = true, + customerAddress = DefaultPdfTemplateAddressBilledTo, + + showCompanyAddress = true, + companyAddress = DefaultPdfTemplateAddressBilledFrom, + + billedToLabel = 'Billed To', + + // Entries + lineItemLabel = 'Item', + lineQuantityLabel = 'Qty', + lineRateLabel = 'Rate', + lineTotalLabel = 'Total', + + // Subtotal + subtotalLabel = 'Subtotal', + showSubtotal = true, + subtotal = '1000.00', + + // Total + totalLabel = 'Total', + showTotal = true, + total = '$1000.00', + + // Customer Note + showCustomerNote = true, + customerNote = '', + customerNoteLabel = 'Customer Note', + + // Terms & Conditions + termsConditionsLabel = 'Terms & Conditions', + showTermsConditions = true, + termsConditions = DefaultPdfTemplateTerms, + + lines = [ + { + item: DefaultPdfTemplateItemName, + description: DefaultPdfTemplateItemDescription, + rate: '1', + quantity: '1000', + total: '$1000.00', + }, + ], + ...props +}: CreditNotePaperTemplateProps) { + return ( + + + + + + + + {showCreditNoteNumber && ( + + {creditNoteNumebr} + + )} + {showCreditNoteDate && ( + + {creditNoteDate} + + )} + + + + {companyLogoUri && showCompanyLogo && ( + + )} + + + + {showCompanyAddress && ( + + + + )} + {showCustomerAddress && ( + + {billedToLabel} + + + )} + + + + ( + + {data.item} + {data.description && ( + + {data.description} + + )} + + ), + thStyle: { width: '60%' }, + }, + { + label: lineQuantityLabel, + accessor: 'quantity', + align: 'right', + }, + { label: lineRateLabel, accessor: 'rate', align: 'right' }, + { label: lineTotalLabel, accessor: 'total', align: 'right' }, + ]} + data={lines} + /> + + {showSubtotal && ( + + )} + {showTotal && ( + + )} + + + + + {showCustomerNote && customerNote && ( + + {customerNote} + + )} + + {showTermsConditions && termsConditions && ( + + {termsConditions} + + )} + + + + ); +} diff --git a/shared/pdf-templates/src/index.ts b/shared/pdf-templates/src/index.ts index 5f9a7aee8..35b66e232 100644 --- a/shared/pdf-templates/src/index.ts +++ b/shared/pdf-templates/src/index.ts @@ -1,5 +1,6 @@ export * from './components/PaperTemplate'; export * from './components/InvoicePaperTemplate'; +export * from './components/CreditNotePaperTemplate'; export * from './components/EstimatePaperTemplate'; export * from './components/ReceiptPaperTemplate'; export * from './components/PaymentReceivedPaperTemplate'; @@ -7,6 +8,7 @@ export * from './components/FinancialSheetTemplate'; export * from './components/ExportResourceTableTemplate'; export * from './renders/render-invoice-paper-template'; +export * from './renders/render-credit-note-paper-template'; export * from './renders/render-estimate-paper-template'; export * from './renders/render-receipt-paper-template'; export * from './renders/render-payment-received-paper-template'; diff --git a/shared/pdf-templates/src/renders/render-credit-note-paper-template.tsx b/shared/pdf-templates/src/renders/render-credit-note-paper-template.tsx new file mode 100644 index 000000000..a34b7ca25 --- /dev/null +++ b/shared/pdf-templates/src/renders/render-credit-note-paper-template.tsx @@ -0,0 +1,17 @@ +import { + CreditNotePaperTemplate, + CreditNotePaperTemplateProps, +} from '../components/CreditNotePaperTemplate'; +import { renderSSR } from './render-ssr'; + +/** + * Renders credit note paper template html. + * @param {CreditNotePaperTemplateProps} props + * @returns {string} + */ +export const renderCreditNotePaperTemplateHtml = ( + props: CreditNotePaperTemplateProps +) => { + return renderSSR(); +}; +