diff --git a/packages/server/resources/views/modules/credit-note-standard.pug b/packages/server/resources/views/modules/credit-note-standard.pug index ae201b305..cc3d95b5a 100644 --- a/packages/server/resources/views/modules/credit-note-standard.pug +++ b/packages/server/resources/views/modules/credit-note-standard.pug @@ -48,8 +48,8 @@ block head box-sizing: border-box; display: flex; flex-flow: wrap; - -webkit-box-align: center; - align-items: center; + -webkit-box-align: flex-start; + align-items: flex-start; -webkit-box-pack: start; justify-content: flex-start; gap: 10px; @@ -150,17 +150,14 @@ block content div(class=`${prefix}-terms-item__value`) #{creditNoteDate} div(class=`${prefix}-address-section`) - if showBilledFromAddress - div(class=`${prefix}-address`) - strong #{companyName} - each address in billedFromAddress - div #{address} + if showCompanyAddress + div(class=`${prefix}-address-from`) + div !{companyAddress} - if showBilledToAddress - div(class=`${prefix}-address`) + if showCustomerAddress + div(class=`${prefix}-address-to`) strong #{billedToLabel} - each address in billedToAddress - div #{address} + div !{customerAddress} table(class=`${prefix}-table`) thead diff --git a/packages/server/resources/views/modules/estimate-regular.pug b/packages/server/resources/views/modules/estimate-regular.pug index d245990ee..455a0372c 100644 --- a/packages/server/resources/views/modules/estimate-regular.pug +++ b/packages/server/resources/views/modules/estimate-regular.pug @@ -47,9 +47,7 @@ block head box-sizing: border-box; display: flex; flex-flow: wrap; - -webkit-box-align: center; - align-items: center; - -webkit-box-pack: start; + align-items: flex-start; justify-content: flex-start; gap: 10px; margin-bottom: 24px; @@ -156,17 +154,14 @@ block content //- Addresses (Group section) div(class=`${prefix}-addresses`) - if showBilledFromAddress - div(class=`${prefix}-address`) - strong #{companyName} - each item in billedFromAddress - div(class=`${prefix}-address__item`) #{item} + if showCompanyAddress + div(class=`${prefix}-address-from`) + div !{companyAddress} - if showBilledToAddress - div(class=`${prefix}-address`) + if showCustomerAddress + div(class=`${prefix}-address-to`) strong #{billedToLabel} - each item in billedToAddress - div(class=`${prefix}-address__item`) #{item} + div !{customerAddress} //- Table section (Line items) table(class=`${prefix}-table`) diff --git a/packages/server/resources/views/modules/invoice-standard.pug b/packages/server/resources/views/modules/invoice-standard.pug index 6c8ca5f70..121ae7492 100644 --- a/packages/server/resources/views/modules/invoice-standard.pug +++ b/packages/server/resources/views/modules/invoice-standard.pug @@ -48,9 +48,7 @@ block head box-sizing: border-box; display: flex; flex-flow: wrap; - -webkit-box-align: center; - align-items: center; - -webkit-box-pack: start; + align-items: flex-start; justify-content: flex-start; gap: 10px; margin-bottom: 24px; @@ -167,17 +165,14 @@ block content //- Address section div(class=`${prefix}-address-root`) - if showBilledFromAddress + if showCompanyAddress div(class=`${prefix}-address-from`) - strong #{companyName} - each item in billedFromAddres - div(class=`${prefix}-address-from__item`) #{item} + div !{companyAddress} - if showBillingToAddress + if showCustomerAddress div(class=`${prefix}-address-to`) strong #{billedToLabel} - each item in billedToAddress - div(class=`${prefix}-address-to__item`) #{item} + div !{customerAddress} //- Invoice table table(class=`${prefix}-table`) diff --git a/packages/server/resources/views/modules/payment-receive-standard.pug b/packages/server/resources/views/modules/payment-receive-standard.pug index ec6dae598..bfdf9cea0 100644 --- a/packages/server/resources/views/modules/payment-receive-standard.pug +++ b/packages/server/resources/views/modules/payment-receive-standard.pug @@ -46,9 +46,7 @@ block head box-sizing: border-box; display: flex; flex-flow: wrap; - -webkit-box-align: center; - align-items: center; - -webkit-box-pack: start; + align-items: flex-start; justify-content: flex-start; gap: 10px; margin-bottom: 24px; @@ -140,17 +138,14 @@ block content div(class=`${prefix}-terms-item__value`) #{paymentReceivedDate} div(class=`${prefix}-addresses`) - if showBilledFromAddress - div(class=`${prefix}-address`) - strong(class=`${prefix}-address__item`) #{companyName} - each addressLine in billedFromAddress - div(class=`${prefix}-address__item`) #{addressLine} + if showCompanyAddress + div(class=`${prefix}-address-from`) + div !{companyAddress} - if showBillingToAddress - div(class=`${prefix}-address`) - strong(class=`${prefix}-address__item`) #{billedToLabel} - each addressLine in billedToAddress - div(class=`${prefix}-address__item`) #{addressLine} + if showCustomerAddress + div(class=`${prefix}-address-to`) + strong #{billedToLabel} + div !{customerAddress} table(class=`${prefix}-table`) thead diff --git a/packages/server/resources/views/modules/receipt-regular.pug b/packages/server/resources/views/modules/receipt-regular.pug index 39185c1d7..1c986c805 100644 --- a/packages/server/resources/views/modules/receipt-regular.pug +++ b/packages/server/resources/views/modules/receipt-regular.pug @@ -46,8 +46,8 @@ block head box-sizing: border-box; display: flex; flex-flow: wrap; - -webkit-box-align: center; - align-items: center; + -webkit-box-align: flex-start; + align-items: flex-start; -webkit-box-pack: start; justify-content: flex-start; gap: 10px; @@ -146,17 +146,14 @@ block content //- Address Section div(class=`${prefix}-address-section`) - if showBilledFromAddress - div(class=`${prefix}-address`) - strong= companyName - each addressLine in billedFromAddress - div= addressLine + if showCompanyAddress + div(class=`${prefix}-address-from`) + div !{companyAddress} - if showBilledToAddress - div(class=`${prefix}-address`) - strong= billedToLabel - each addressLine in billedToAddress - div= addressLine + if showCustomerAddress + div(class=`${prefix}-address-to`) + strong #{billedToLabel} + div !{customerAddress} //- Table Section table(class=`${prefix}-table`) diff --git a/packages/server/src/api/controllers/PdfTemplates/PdfTemplatesController.ts b/packages/server/src/api/controllers/PdfTemplates/PdfTemplatesController.ts index c3758250d..f78be6650 100644 --- a/packages/server/src/api/controllers/PdfTemplates/PdfTemplatesController.ts +++ b/packages/server/src/api/controllers/PdfTemplates/PdfTemplatesController.ts @@ -31,6 +31,7 @@ export class PdfTemplatesController extends BaseController { this.validationResult, this.editPdfTemplate.bind(this) ); + router.get('/state', this.getOrganizationBrandingState.bind(this)); router.get( '/', [query('resource').optional()], @@ -175,4 +176,20 @@ export class PdfTemplatesController extends BaseController { next(error); } } + async getOrganizationBrandingState( + req: Request, + res: Response, + next: NextFunction + ) { + const { tenantId } = req; + + try { + const data = + await this.pdfTemplateApplication.getPdfTemplateBrandingState(tenantId); + + return res.status(200).send({ data }); + } catch (error) { + next(error); + } + } } diff --git a/packages/server/src/interfaces/CreditNote.ts b/packages/server/src/interfaces/CreditNote.ts index ffb4c26ba..aff44b125 100644 --- a/packages/server/src/interfaces/CreditNote.ts +++ b/packages/server/src/interfaces/CreditNote.ts @@ -262,16 +262,24 @@ export type ICreditNoteGLCommonEntry = Pick< >; export interface CreditNotePdfTemplateAttributes { + // # Primary color primaryColor: string; secondaryColor: string; + + // # Company logo showCompanyLogo: boolean; companyLogo: string; + + // # Company name companyName: string; - billedToAddress: string[]; - billedFromAddress: string[]; - showBilledToAddress: boolean; - showBilledFromAddress: boolean; + // # Customer Address + showCustomerAddress: boolean; + customerAddress: string; + + // # Company address + showCompanyAddress: boolean; + companyAddress: string; billedToLabel: string; total: string; diff --git a/packages/server/src/interfaces/PaymentReceive.ts b/packages/server/src/interfaces/PaymentReceive.ts index 8dd880872..f09323a55 100644 --- a/packages/server/src/interfaces/PaymentReceive.ts +++ b/packages/server/src/interfaces/PaymentReceive.ts @@ -207,10 +207,13 @@ export interface PaymentReceivedPdfTemplateAttributes { companyLogo: string; companyName: string; - billedToAddress: string[]; - billedFromAddress: string[]; - showBilledFromAddress: boolean; - showBillingToAddress: boolean; + // Customer Address + showCustomerAddress: boolean; + customerAddress: string; + + // Company address + showCompanyAddress: boolean; + companyAddress: string; billedToLabel: string; total: string; diff --git a/packages/server/src/interfaces/SaleInvoice.ts b/packages/server/src/interfaces/SaleInvoice.ts index 5eef382f3..6e3f94088 100644 --- a/packages/server/src/interfaces/SaleInvoice.ts +++ b/packages/server/src/interfaces/SaleInvoice.ts @@ -294,8 +294,13 @@ export interface InvoicePdfTemplateAttributes { invoiceNumber: string; showInvoiceNumber: boolean; - showBillingToAddress: boolean; - showBilledFromAddress: boolean; + // Customer Address + showCustomerAddress: boolean; + customerAddress: string; + + // Company address + showCompanyAddress: boolean; + companyAddress: string; billedToLabel: string; lineItemLabel: string; @@ -333,7 +338,4 @@ export interface InvoicePdfTemplateAttributes { statementLabel: string; showStatement: boolean; statement: string; - - billedToAddress: string[]; - billedFromAddres: string[]; } diff --git a/packages/server/src/interfaces/SaleReceipt.ts b/packages/server/src/interfaces/SaleReceipt.ts index d3e458313..6966722ff 100644 --- a/packages/server/src/interfaces/SaleReceipt.ts +++ b/packages/server/src/interfaces/SaleReceipt.ts @@ -163,11 +163,13 @@ export interface ISaleReceiptBrandingTemplateAttributes { companyLogo: string; companyName: string; - // Address - billedToAddress: string[]; - billedFromAddress: string[]; - showBilledFromAddress: boolean; - showBilledToAddress: boolean; + // Customer Address + showCustomerAddress: boolean; + customerAddress: string; + + // Company address + showCompanyAddress: boolean; + companyAddress: string; billedToLabel: string; // Total diff --git a/packages/server/src/services/Attachments/utils.ts b/packages/server/src/services/Attachments/utils.ts new file mode 100644 index 000000000..50af9da9d --- /dev/null +++ b/packages/server/src/services/Attachments/utils.ts @@ -0,0 +1,7 @@ +import path from 'path'; +import config from '@/config'; + + +export const getUploadedObjectUri = (objectKey: string) => { + return path.join(config.s3.endpoint, config.s3.bucket, objectKey); +} \ No newline at end of file diff --git a/packages/server/src/services/CreditNotes/CreditNoteBrandingTemplate.ts b/packages/server/src/services/CreditNotes/CreditNoteBrandingTemplate.ts index 1b35dc29b..872f16ef4 100644 --- a/packages/server/src/services/CreditNotes/CreditNoteBrandingTemplate.ts +++ b/packages/server/src/services/CreditNotes/CreditNoteBrandingTemplate.ts @@ -1,26 +1,44 @@ -import { Inject } from "typedi"; -import { GetPdfTemplate } from "../PdfTemplate/GetPdfTemplate"; -import { defaultCreditNoteBrandingAttributes } from "./constants"; -import { mergePdfTemplateWithDefaultAttributes } from "../Sales/Invoices/utils"; +import { Inject } from 'typedi'; +import { GetPdfTemplate } from '../PdfTemplate/GetPdfTemplate'; +import { defaultCreditNoteBrandingAttributes } from './constants'; +import { mergePdfTemplateWithDefaultAttributes } from '../Sales/Invoices/utils'; +import { GetOrganizationBrandingAttributes } from '../PdfTemplate/GetOrganizationBrandingAttributes'; export class CreditNoteBrandingTemplate { @Inject() private getPdfTemplateService: GetPdfTemplate; + @Inject() + private getOrgBrandingAttributes: GetOrganizationBrandingAttributes; + /** * Retrieves the credit note branding template. - * @param {number} tenantId - * @param {number} templateId + * @param {number} tenantId + * @param {number} templateId * @returns {} */ - public async getCreditNoteBrandingTemplate(tenantId: number, templateId: number) { + public async getCreditNoteBrandingTemplate( + tenantId: number, + templateId: number + ) { const template = await this.getPdfTemplateService.getPdfTemplate( tenantId, templateId ); + // Retrieves the organization branding attributes. + const commonOrgBrandingAttrs = + await this.getOrgBrandingAttributes.getOrganizationBrandingAttributes( + tenantId + ); + // Merges the default branding attributes with common organization branding attrs. + const organizationBrandingAttrs = { + ...defaultCreditNoteBrandingAttributes, + ...commonOrgBrandingAttrs, + }; + const attributes = mergePdfTemplateWithDefaultAttributes( template.attributes, - defaultCreditNoteBrandingAttributes + organizationBrandingAttrs ); return { ...template, diff --git a/packages/server/src/services/CreditNotes/GetCreditNotePdf.ts b/packages/server/src/services/CreditNotes/GetCreditNotePdf.ts index 5a1ea0faf..4205fbfaa 100644 --- a/packages/server/src/services/CreditNotes/GetCreditNotePdf.ts +++ b/packages/server/src/services/CreditNotes/GetCreditNotePdf.ts @@ -34,8 +34,6 @@ export default class GetCreditNotePdf { tenantId, creditNoteId ); - console.log(brandingAttributes, 'brandingAttributes'); - const htmlContent = await this.templateInjectable.render( tenantId, 'modules/credit-note-standard', diff --git a/packages/server/src/services/CreditNotes/constants.ts b/packages/server/src/services/CreditNotes/constants.ts index db44e5968..4f1d51d30 100644 --- a/packages/server/src/services/CreditNotes/constants.ts +++ b/packages/server/src/services/CreditNotes/constants.ts @@ -80,24 +80,13 @@ export const defaultCreditNoteBrandingAttributes = { // # Company name companyName: 'Bigcapital Technology, Inc.', - // Address - billedToAddress: [ - 'Bigcapital Technology, Inc.', - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - billedFromAddress: [ - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - showBilledToAddress: true, - showBilledFromAddress: true, + // # Customer address + showCustomerAddress: true, + customerAddress: '', + + // # Company address + showCompanyAddress: true, + companyAddress: '', billedToLabel: 'Billed To', // Total diff --git a/packages/server/src/services/CreditNotes/utils.ts b/packages/server/src/services/CreditNotes/utils.ts index 6b94d955e..8936f922c 100644 --- a/packages/server/src/services/CreditNotes/utils.ts +++ b/packages/server/src/services/CreditNotes/utils.ts @@ -1,4 +1,5 @@ import { CreditNotePdfTemplateAttributes, ICreditNote } from '@/interfaces'; +import { contactAddressTextFormat } from '@/utils/address-text-format'; export const transformCreditNoteToPdfTemplate = ( creditNote: ICreditNote @@ -19,5 +20,6 @@ export const transformCreditNoteToPdfTemplate = ( })), customerNote: creditNote.note, termsConditions: creditNote.termsConditions, + customerAddress: contactAddressTextFormat(creditNote.customer), }; }; diff --git a/packages/server/src/services/PdfTemplate/GetOrganizationBrandingAttributes.ts b/packages/server/src/services/PdfTemplate/GetOrganizationBrandingAttributes.ts new file mode 100644 index 000000000..989bc0714 --- /dev/null +++ b/packages/server/src/services/PdfTemplate/GetOrganizationBrandingAttributes.ts @@ -0,0 +1,31 @@ +import { Service } from 'typedi'; +import { TenantMetadata } from '@/system/models'; +import { CommonOrganizationBrandingAttributes } from './types'; + +@Service() +export class GetOrganizationBrandingAttributes { + /** + * Retrieves the given organization branding attributes initial state. + * @param {number} tenantId + * @returns {Promise} + */ + async getOrganizationBrandingAttributes( + tenantId: number + ): Promise { + const tenantMetadata = await TenantMetadata.query().findOne({ tenantId }); + + const companyName = tenantMetadata?.name; + const primaryColor = tenantMetadata?.primaryColor; + const companyLogoKey = tenantMetadata?.logoKey; + const companyLogoUri = tenantMetadata?.logoUri; + const companyAddress = tenantMetadata?.addressTextFormatted; + + return { + companyName, + companyAddress, + companyLogoUri, + companyLogoKey, + primaryColor, + }; + } +} diff --git a/packages/server/src/services/PdfTemplate/GetPdfTemplateBrandingState.ts b/packages/server/src/services/PdfTemplate/GetPdfTemplateBrandingState.ts new file mode 100644 index 000000000..358bb747e --- /dev/null +++ b/packages/server/src/services/PdfTemplate/GetPdfTemplateBrandingState.ts @@ -0,0 +1,15 @@ +import { Inject, Service } from 'typedi'; +import { GetOrganizationBrandingAttributes } from './GetOrganizationBrandingAttributes'; + +@Service() +export class GetPdfTemplateBrandingState { + @Inject() + private getOrgBrandingAttributes: GetOrganizationBrandingAttributes; + + getBrandingState(tenantId: number) { + const brandingAttributes = + this.getOrgBrandingAttributes.getOrganizationBrandingAttributes(tenantId); + + return brandingAttributes; + } +} diff --git a/packages/server/src/services/PdfTemplate/GetPdfTemplateTransformer.ts b/packages/server/src/services/PdfTemplate/GetPdfTemplateTransformer.ts index d7977dced..fddc28c59 100644 --- a/packages/server/src/services/PdfTemplate/GetPdfTemplateTransformer.ts +++ b/packages/server/src/services/PdfTemplate/GetPdfTemplateTransformer.ts @@ -1,5 +1,6 @@ import { Transformer } from '@/lib/Transformer/Transformer'; import { getTransactionTypeLabel } from '@/utils/transactions-types'; +import { getUploadedObjectUri } from '../Attachments/utils'; export class GetPdfTemplateTransformer extends Transformer { /** @@ -56,7 +57,7 @@ class GetPdfTemplateAttributesTransformer extends Transformer { */ protected companyLogoUri(template) { return template.companyLogoKey - ? `https://bigcapital.sfo3.digitaloceanspaces.com/${template.companyLogoKey}` + ? getUploadedObjectUri(template.companyLogoKey) : ''; } } diff --git a/packages/server/src/services/PdfTemplate/PdfTemplateApplication.ts b/packages/server/src/services/PdfTemplate/PdfTemplateApplication.ts index 5f77475ff..e9ff586af 100644 --- a/packages/server/src/services/PdfTemplate/PdfTemplateApplication.ts +++ b/packages/server/src/services/PdfTemplate/PdfTemplateApplication.ts @@ -6,6 +6,7 @@ import { GetPdfTemplate } from './GetPdfTemplate'; import { GetPdfTemplates } from './GetPdfTemplates'; import { EditPdfTemplate } from './EditPdfTemplate'; import { AssignPdfTemplateDefault } from './AssignPdfTemplateDefault'; +import { GetPdfTemplateBrandingState } from './GetPdfTemplateBrandingState'; @Service() export class PdfTemplateApplication { @@ -27,6 +28,9 @@ export class PdfTemplateApplication { @Inject() private assignPdfTemplateDefaultService: AssignPdfTemplateDefault; + @Inject() + private getPdfTemplateBrandingStateService: GetPdfTemplateBrandingState; + /** * Creates a new PDF template. * @param {number} tenantId - @@ -120,4 +124,12 @@ export class PdfTemplateApplication { templateId ); } + + /** + * + * @param {number} tenantId + */ + public async getPdfTemplateBrandingState(tenantId: number) { + return this.getPdfTemplateBrandingStateService.getBrandingState(tenantId); + } } diff --git a/packages/server/src/services/PdfTemplate/types.ts b/packages/server/src/services/PdfTemplate/types.ts index abe9345a0..6fad632ab 100644 --- a/packages/server/src/services/PdfTemplate/types.ts +++ b/packages/server/src/services/PdfTemplate/types.ts @@ -65,3 +65,12 @@ export interface ICreateInvoicePdfTemplateDTO { statementLabel?: string; showStatement?: boolean; } + + +export interface CommonOrganizationBrandingAttributes { + companyName?: string; + primaryColor?: string; + companyLogoKey?: string; + companyLogoUri?: string; + companyAddress?: string; +} diff --git a/packages/server/src/services/Sales/Estimates/constants.ts b/packages/server/src/services/Sales/Estimates/constants.ts index e4783e0f9..b42d66763 100644 --- a/packages/server/src/services/Sales/Estimates/constants.ts +++ b/packages/server/src/services/Sales/Estimates/constants.ts @@ -185,23 +185,10 @@ export const defaultEstimatePdfBrandingAttributes = { companyName: '', - billedToAddress: [ - 'Bigcapital Technology, Inc.', - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - billedFromAddress: [ - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - showBilledFromAddress: true, - showBilledToAddress: true, + customerAddress: '', + companyAddress: '', + showCustomerAddress: true, + showCompanyAddress: true, billedToLabel: 'Billed To', total: '$1000.00', @@ -244,7 +231,6 @@ export const defaultEstimatePdfBrandingAttributes = { expirationDate: 'September 3, 2024', }; - interface EstimatePdfBrandingLineItem { item: string; description: string; @@ -260,10 +246,13 @@ export interface EstimatePdfBrandingAttributes { companyLogo: string; companyName: string; - billedToAddress: string[]; - billedFromAddress: string[]; - showBilledFromAddress: boolean; - showBilledToAddress: boolean; + // Customer Address + showCustomerAddress: boolean; + customerAddress: string; + + // Company Address + showCompanyAddress: boolean; + companyAddress: string; billedToLabel: string; total: string; @@ -295,4 +284,4 @@ export interface EstimatePdfBrandingAttributes { expirationDateLabel: string; showExpirationDate: boolean; expirationDate: string; -} \ No newline at end of file +} diff --git a/packages/server/src/services/Sales/Estimates/utils.ts b/packages/server/src/services/Sales/Estimates/utils.ts index 879667893..f15a25546 100644 --- a/packages/server/src/services/Sales/Estimates/utils.ts +++ b/packages/server/src/services/Sales/Estimates/utils.ts @@ -1,3 +1,4 @@ +import { contactAddressTextFormat } from '@/utils/address-text-format'; import { EstimatePdfBrandingAttributes } from './constants'; export const transformEstimateToPdfTemplate = ( @@ -18,5 +19,6 @@ export const transformEstimateToPdfTemplate = ( subtotal: estimate.formattedSubtotal, customerNote: estimate.customerNote, termsConditions: estimate.termsConditions, + customerAddress: contactAddressTextFormat(estimate.customer), }; }; diff --git a/packages/server/src/services/Sales/Invoices/SaleEstimatePdfTemplate.ts b/packages/server/src/services/Sales/Invoices/SaleEstimatePdfTemplate.ts index de324ea90..54048619a 100644 --- a/packages/server/src/services/Sales/Invoices/SaleEstimatePdfTemplate.ts +++ b/packages/server/src/services/Sales/Invoices/SaleEstimatePdfTemplate.ts @@ -2,12 +2,16 @@ import { Inject, Service } from 'typedi'; import { mergePdfTemplateWithDefaultAttributes } from './utils'; import { GetPdfTemplate } from '@/services/PdfTemplate/GetPdfTemplate'; import { defaultEstimatePdfBrandingAttributes } from '../Estimates/constants'; +import { GetOrganizationBrandingAttributes } from '@/services/PdfTemplate/GetOrganizationBrandingAttributes'; @Service() export class SaleEstimatePdfTemplate { @Inject() private getPdfTemplateService: GetPdfTemplate; + @Inject() + private getOrgBrandingAttrs: GetOrganizationBrandingAttributes; + /** * Retrieves the estimate pdf template. * @param {number} tenantId @@ -19,9 +23,19 @@ export class SaleEstimatePdfTemplate { tenantId, estimateTemplateId ); + // Retreives the organization branding attributes. + const commonOrgBrandingAttrs = + await this.getOrgBrandingAttrs.getOrganizationBrandingAttributes( + tenantId + ); + // Merge the default branding attributes with organization attrs. + const orgainizationBrandingAttrs = { + ...defaultEstimatePdfBrandingAttributes, + ...commonOrgBrandingAttrs, + }; const attributes = mergePdfTemplateWithDefaultAttributes( template.attributes, - defaultEstimatePdfBrandingAttributes + orgainizationBrandingAttrs ); return { ...template, diff --git a/packages/server/src/services/Sales/Invoices/SaleInvoicePdfTemplate.ts b/packages/server/src/services/Sales/Invoices/SaleInvoicePdfTemplate.ts index 563fd3a20..ca1f8c142 100644 --- a/packages/server/src/services/Sales/Invoices/SaleInvoicePdfTemplate.ts +++ b/packages/server/src/services/Sales/Invoices/SaleInvoicePdfTemplate.ts @@ -2,26 +2,39 @@ import { Inject, Service } from 'typedi'; import { mergePdfTemplateWithDefaultAttributes } from './utils'; import { GetPdfTemplate } from '@/services/PdfTemplate/GetPdfTemplate'; import { defaultInvoicePdfTemplateAttributes } from './constants'; +import { GetOrganizationBrandingAttributes } from '@/services/PdfTemplate/GetOrganizationBrandingAttributes'; @Service() export class SaleInvoicePdfTemplate { @Inject() private getPdfTemplateService: GetPdfTemplate; + @Inject() + private getOrgBrandingAttributes: GetOrganizationBrandingAttributes; + /** * Retrieves the invoice pdf template. - * @param {number} tenantId - * @param {number} invoiceTemplateId - * @returns + * @param {number} tenantId + * @param {number} invoiceTemplateId + * @returns */ - async getInvoicePdfTemplate(tenantId: number, invoiceTemplateId: number){ + async getInvoicePdfTemplate(tenantId: number, invoiceTemplateId: number) { const template = await this.getPdfTemplateService.getPdfTemplate( tenantId, invoiceTemplateId ); + // Retrieves the organization branding attributes. + const commonOrgBrandingAttrs = + await this.getOrgBrandingAttributes.getOrganizationBrandingAttributes( + tenantId + ); + const organizationBrandingAttrs = { + ...defaultInvoicePdfTemplateAttributes, + ...commonOrgBrandingAttrs, + }; const attributes = mergePdfTemplateWithDefaultAttributes( template.attributes, - defaultInvoicePdfTemplateAttributes + organizationBrandingAttrs ); return { ...template, diff --git a/packages/server/src/services/Sales/Invoices/constants.ts b/packages/server/src/services/Sales/Invoices/constants.ts index f1da02b03..becd1ebcf 100644 --- a/packages/server/src/services/Sales/Invoices/constants.ts +++ b/packages/server/src/services/Sales/Invoices/constants.ts @@ -163,7 +163,7 @@ export const SaleInvoicesSampleData = [ }, ]; -export const defaultInvoicePdfTemplateAttributes = { +export const defaultInvoicePdfTemplateAttributes = { primaryColor: 'red', secondaryColor: 'red', @@ -179,13 +179,17 @@ export const defaultInvoicePdfTemplateAttributes = { dateIssueLabel: 'Date of issue', showDateIssue: true, - // dateIssue, + // # Invoice number, invoiceNumberLabel: 'Invoice number', showInvoiceNumber: true, - // Address - showBillingToAddress: true, - showBilledFromAddress: true, + // # Customer address + showCustomerAddress: true, + customerAddress: '', + + // # Company address + showCompanyAddress: true, + companyAddress: '', billedToLabel: 'Billed To', // Entries @@ -229,22 +233,7 @@ export const defaultInvoicePdfTemplateAttributes = { { label: 'Sample Tax2 (7.00%)', amount: '21.74' }, ], + // # Statement statementLabel: 'Statement', showStatement: true, - billedToAddress: [ - 'Bigcapital Technology, Inc.', - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - billedFromAddres: [ - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], -} - +}; diff --git a/packages/server/src/services/Sales/Invoices/utils.ts b/packages/server/src/services/Sales/Invoices/utils.ts index 8131ea2bd..833822459 100644 --- a/packages/server/src/services/Sales/Invoices/utils.ts +++ b/packages/server/src/services/Sales/Invoices/utils.ts @@ -1,5 +1,6 @@ import { pickBy } from 'lodash'; import { InvoicePdfTemplateAttributes, ISaleInvoice } from '@/interfaces'; +import { contactAddressTextFormat } from '@/utils/address-text-format'; export const mergePdfTemplateWithDefaultAttributes = ( brandingTemplate?: Record, @@ -42,5 +43,7 @@ export const transformInvoiceToPdfTemplate = ( label: tax.name, amount: tax.taxRateAmountFormatted, })), + + customerAddress: contactAddressTextFormat(invoice.customer), }; }; diff --git a/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedBrandingTemplate.ts b/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedBrandingTemplate.ts index 625b24d95..5e7c89fb7 100644 --- a/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedBrandingTemplate.ts +++ b/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedBrandingTemplate.ts @@ -3,29 +3,43 @@ import { Inject, Service } from 'typedi'; import { mergePdfTemplateWithDefaultAttributes } from '../Invoices/utils'; import { defaultPaymentReceivedPdfTemplateAttributes } from './constants'; import { PdfTemplate } from '@/models/PdfTemplate'; +import { GetOrganizationBrandingAttributes } from '@/services/PdfTemplate/GetOrganizationBrandingAttributes'; @Service() export class PaymentReceivedBrandingTemplate { @Inject() private getPdfTemplateService: GetPdfTemplate; + @Inject() + private getOrgBrandingAttributes: GetOrganizationBrandingAttributes; + /** * Retrieves the payment received pdf template. - * @param {number} tenantId - * @param {number} paymentTemplateId - * @returns + * @param {number} tenantId + * @param {number} paymentTemplateId + * @returns */ public async getPaymentReceivedPdfTemplate( tenantId: number, paymentTemplateId: number - ) { + ) { const template = await this.getPdfTemplateService.getPdfTemplate( tenantId, paymentTemplateId ); + // Retrieves the organization branding attributes. + const commonOrgBrandingAttrs = + await this.getOrgBrandingAttributes.getOrganizationBrandingAttributes( + tenantId + ); + // Merges the default branding attributes with common organization branding attrs. + const organizationBrandingAttrs = { + ...defaultPaymentReceivedPdfTemplateAttributes, + ...commonOrgBrandingAttrs, + }; const attributes = mergePdfTemplateWithDefaultAttributes( template.attributes, - defaultPaymentReceivedPdfTemplateAttributes + organizationBrandingAttrs ); return { ...template, diff --git a/packages/server/src/services/Sales/PaymentReceived/constants.ts b/packages/server/src/services/Sales/PaymentReceived/constants.ts index c9fef7c5f..739cea048 100644 --- a/packages/server/src/services/Sales/PaymentReceived/constants.ts +++ b/packages/server/src/services/Sales/PaymentReceived/constants.ts @@ -58,24 +58,13 @@ export const defaultPaymentReceivedPdfTemplateAttributes = { // # Company name companyName: 'Bigcapital Technology, Inc.', - // Address - billedToAddress: [ - 'Bigcapital Technology, Inc.', - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - billedFromAddress: [ - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - showBilledFromAddress: true, - showBillingToAddress: true, + // # Customer address + showCustomerAddress: true, + customerAddress: '', + + // # Company address + showCompanyAddress: true, + companyAddress: '', billedToLabel: 'Billed To', // Total diff --git a/packages/server/src/services/Sales/PaymentReceived/utils.ts b/packages/server/src/services/Sales/PaymentReceived/utils.ts index 540aab9ed..bfd1ad8ea 100644 --- a/packages/server/src/services/Sales/PaymentReceived/utils.ts +++ b/packages/server/src/services/Sales/PaymentReceived/utils.ts @@ -2,6 +2,7 @@ import { IPaymentReceived, PaymentReceivedPdfTemplateAttributes, } from '@/interfaces'; +import { contactAddressTextFormat } from '@/utils/address-text-format'; export const transformPaymentReceivedToPdfTemplate = ( payment: IPaymentReceived @@ -17,5 +18,6 @@ export const transformPaymentReceivedToPdfTemplate = ( invoiceAmount: entry.invoice.totalFormatted, paidAmount: entry.paymentAmountFormatted, })), + customerAddress: contactAddressTextFormat(payment.customer), }; }; diff --git a/packages/server/src/services/Sales/Receipts/SaleReceiptBrandingTemplate.ts b/packages/server/src/services/Sales/Receipts/SaleReceiptBrandingTemplate.ts index 5d7794421..1cef714b9 100644 --- a/packages/server/src/services/Sales/Receipts/SaleReceiptBrandingTemplate.ts +++ b/packages/server/src/services/Sales/Receipts/SaleReceiptBrandingTemplate.ts @@ -2,12 +2,15 @@ import { GetPdfTemplate } from '@/services/PdfTemplate/GetPdfTemplate'; import { Inject, Service } from 'typedi'; import { defaultSaleReceiptBrandingAttributes } from './constants'; import { mergePdfTemplateWithDefaultAttributes } from '../Invoices/utils'; +import { GetOrganizationBrandingAttributes } from '@/services/PdfTemplate/GetOrganizationBrandingAttributes'; @Service() export class SaleReceiptBrandingTemplate { @Inject() private getPdfTemplateService: GetPdfTemplate; + @Inject() + private getOrgBrandingAttributes: GetOrganizationBrandingAttributes; /** * Retrieves the sale receipt branding template. @@ -23,9 +26,20 @@ export class SaleReceiptBrandingTemplate { tenantId, templateId ); + // Retrieves the organization branding attributes. + const commonOrgBrandingAttrs = + await this.getOrgBrandingAttributes.getOrganizationBrandingAttributes( + tenantId + ); + + // Merges the default branding attributes with organization common branding attrs. + const organizationBrandingAttrs = { + ...defaultSaleReceiptBrandingAttributes, + ...commonOrgBrandingAttrs, + }; const attributes = mergePdfTemplateWithDefaultAttributes( template.attributes, - defaultSaleReceiptBrandingAttributes + organizationBrandingAttrs ); return { ...template, diff --git a/packages/server/src/services/Sales/Receipts/constants.ts b/packages/server/src/services/Sales/Receipts/constants.ts index 0b2f38bc1..547d91a56 100644 --- a/packages/server/src/services/Sales/Receipts/constants.ts +++ b/packages/server/src/services/Sales/Receipts/constants.ts @@ -76,26 +76,16 @@ export const defaultSaleReceiptBrandingAttributes = { companyLogoUri: '', companyLogoKey: '', - // # Address - billedToAddress: [ - 'Bigcapital Technology, Inc.', - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - billedFromAddress: [ - '131 Continental Dr Suite 305 Newark,', - 'Delaware 19713', - 'United States', - '+1 762-339-5634', - 'ahmed@bigcapital.app', - ], - showBilledFromAddress: true, - showBilledToAddress: true, + // # Customer address + showCustomerAddress: true, + customerAddress: '', + + // # Company address + showCompanyAddress: true, + companyAddress: '', billedToLabel: 'Billed To', + // # Total total: '$1000.00', totalLabel: 'Total', showTotal: true, diff --git a/packages/server/src/services/Sales/Receipts/utils.ts b/packages/server/src/services/Sales/Receipts/utils.ts index e1d9ac9d9..933de982a 100644 --- a/packages/server/src/services/Sales/Receipts/utils.ts +++ b/packages/server/src/services/Sales/Receipts/utils.ts @@ -1,4 +1,5 @@ import { ISaleReceipt, ISaleReceiptBrandingTemplateAttributes } from "@/interfaces"; +import { contactAddressTextFormat } from "@/utils/address-text-format"; @@ -13,8 +14,8 @@ export const transformReceiptToBrandingTemplateAttributes = (saleReceipt: ISaleR quantity: entry.quantityFormatted, total: entry.totalFormatted, })), - receiptNumber: saleReceipt.receiptNumber, receiptDate: saleReceipt.formattedReceiptDate, + customerAddress: contactAddressTextFormat(saleReceipt.customer), }; } \ No newline at end of file diff --git a/packages/server/src/system/models/TenantMetadata.ts b/packages/server/src/system/models/TenantMetadata.ts index 5ff89d84a..efc0d2840 100644 --- a/packages/server/src/system/models/TenantMetadata.ts +++ b/packages/server/src/system/models/TenantMetadata.ts @@ -1,5 +1,6 @@ -import { addressTextFormat } from '@/utils/address-text-format'; +import { organizationAddressTextFormat } from '@/utils/address-text-format'; import BaseModel from 'models/Model'; +import { getUploadedObjectUri } from '../../services/Attachments/utils'; export default class TenantMetadata extends BaseModel { baseCurrency!: string; @@ -58,9 +59,7 @@ export default class TenantMetadata extends BaseModel { * @returns {string | null} */ public get logoUri() { - return this.logoKey - ? `https://bigcapital.sfo3.digitaloceanspaces.com/${this.logoKey}` - : null; + return this.logoKey ? getUploadedObjectUri(this.logoKey) : null; } /** @@ -75,7 +74,7 @@ export default class TenantMetadata extends BaseModel { {POSTAL_CODE}, {COUNTRY} `; - return addressTextFormat(defaultMessage, { + return organizationAddressTextFormat(defaultMessage, { organizationName: this.name, address1: this.address?.address1, address2: this.address?.address2, diff --git a/packages/server/src/utils/address-text-format.ts b/packages/server/src/utils/address-text-format.ts index 73467aa9c..1b19d6301 100644 --- a/packages/server/src/utils/address-text-format.ts +++ b/packages/server/src/utils/address-text-format.ts @@ -1,3 +1,5 @@ +import { IContact } from '@/interfaces'; + interface OrganizationAddressFormatArgs { organizationName?: string; address1?: string; @@ -17,7 +19,19 @@ const defaultMessage = ` {COUNTRY} `; -export const addressTextFormat = ( +const formatText = (message: string, replacements: Record) => { + let formattedMessage = Object.entries(replacements).reduce( + (msg, [key, value]) => { + return msg.split(`{${key}}`).join(value || ''); + }, + message + ); + formattedMessage = formattedMessage.replace(/\n/g, '
'); + + return formattedMessage.trim(); +}; + +export const organizationAddressTextFormat = ( message: string, args: OrganizationAddressFormatArgs ) => { @@ -30,13 +44,53 @@ export const addressTextFormat = ( POSTAL_CODE: args.postalCode || '', COUNTRY: args.country || '', }; - let formattedMessage = Object.entries(replacements).reduce( - (msg, [key, value]) => { - return value ? msg.split(`{${key}}`).join(value) : msg; - }, - message - ); - formattedMessage = formattedMessage.replace(/\n/g, '
'); - - return formattedMessage.trim(); + return formatText(message, replacements); +}; + +interface ContactAddressTextFormatArgs { + displayName?: string; + state?: string; + postalCode?: string; + email?: string; + country?: string; + city?: string; + address2?: string; + address1?: string; +} + +const contactFormatMessage = `{CONTACT_NAME} +{ADDRESS_1} +{ADDRESS_2} +{CITY} {STATE} +{POSTAL_CODE} +{COUNTRY} +{EMAIL} +`; + +export const contactAddressTextFormat = ( + contact: IContact, + message: string = contactFormatMessage +) => { + const args = { + displayName: contact.displayName, + address1: contact.billingAddress1, + address2: contact.billingAddress2, + state: contact.billingAddressState, + country: contact.billingAddressCountry, + postalCode: contact?.billingAddressPostcode, + city: contact?.billingAddressCity, + email: contact?.email, + } as ContactAddressTextFormatArgs; + + const replacements: Record = { + CONTACT_NAME: args.displayName || '', + ADDRESS_1: args.address1 || '', + ADDRESS_2: args.address2 || '', + CITY: args.city || '', + STATE: args.state || '', + POSTAL_CODE: args.postalCode || '', + COUNTRY: args.country || '', + EMAIL: args?.email || '', + }; + return formatText(message, replacements); }; diff --git a/packages/webapp/src/constants/PdfTemplates.ts b/packages/webapp/src/constants/PdfTemplates.ts index 26c52b7f9..d1be6ba4f 100644 --- a/packages/webapp/src/constants/PdfTemplates.ts +++ b/packages/webapp/src/constants/PdfTemplates.ts @@ -17,10 +17,9 @@ United States,
ahmed@bigcapital.app `; - export const DefaultPdfTemplateAddressBilledFrom = `131 Continental Dr Suite 305 Newark,
Delaware 19713,
United States,
+1 762-339-5634,
ahmed@bigcapital.app -`; \ No newline at end of file +`; diff --git a/packages/webapp/src/containers/BrandingTemplates/BrandingTemplateBoot.tsx b/packages/webapp/src/containers/BrandingTemplates/BrandingTemplateBoot.tsx index 997436b07..58253ae36 100644 --- a/packages/webapp/src/containers/BrandingTemplates/BrandingTemplateBoot.tsx +++ b/packages/webapp/src/containers/BrandingTemplates/BrandingTemplateBoot.tsx @@ -1,7 +1,9 @@ import React, { createContext, useContext } from 'react'; import { + GetPdfTemplateBrandingStateResponse, GetPdfTemplateResponse, useGetPdfTemplate, + useGetPdfTemplateBrandingState, } from '@/hooks/query/pdf-templates'; import { Spinner } from '@blueprintjs/core'; @@ -9,6 +11,10 @@ interface PdfTemplateContextValue { templateId: number | string; pdfTemplate: GetPdfTemplateResponse | undefined; isPdfTemplateLoading: boolean; + + // Branding state. + brandingTemplateState: GetPdfTemplateBrandingStateResponse | undefined; + isBrandingTemplateLoading: boolean; } interface BrandingTemplateProps { @@ -28,15 +34,23 @@ export const BrandingTemplateBoot = ({ useGetPdfTemplate(templateId, { enabled: !!templateId, }); + // Retreives the branding template state. + const { data: brandingTemplateState, isLoading: isBrandingTemplateLoading } = + useGetPdfTemplateBrandingState(); const value = { templateId, pdfTemplate, isPdfTemplateLoading, + + brandingTemplateState, + isBrandingTemplateLoading, }; - if (isPdfTemplateLoading) { - return + const isLoading = isPdfTemplateLoading || isBrandingTemplateLoading; + + if (isLoading) { + return ; } return ( diff --git a/packages/webapp/src/containers/BrandingTemplates/_utils.ts b/packages/webapp/src/containers/BrandingTemplates/_utils.ts index 33a6dbdf2..2dfded317 100644 --- a/packages/webapp/src/containers/BrandingTemplates/_utils.ts +++ b/packages/webapp/src/containers/BrandingTemplates/_utils.ts @@ -44,15 +44,16 @@ export const useBrandingTemplateFormInitialValues = < >( initialValues = {}, ) => { - const { pdfTemplate } = useBrandingTemplateBoot(); + const { pdfTemplate, brandingTemplateState } = useBrandingTemplateBoot(); - const defaultPdfTemplate = { + const brandingAttributes = { templateName: pdfTemplate?.templateName, + ...brandingTemplateState, ...pdfTemplate?.attributes, }; return { ...initialValues, - ...(transformToForm(defaultPdfTemplate, initialValues) as T), + ...(transformToForm(brandingAttributes, initialValues) as T), }; }; diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/CreditNotePaperTemplate.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/CreditNotePaperTemplate.tsx index 0362a6ae3..f19a1fd54 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/CreditNotePaperTemplate.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/CreditNotePaperTemplate.tsx @@ -14,10 +14,12 @@ import { export interface CreditNotePaperTemplateProps extends PaperTemplateProps { // Address - billedToAddress?: string; - billedFromAddress?: string; - showBilledToAddress?: boolean; - showBilledFromAddress?: boolean; + showCustomerAddress?: boolean; + customerAddress?: string; + + showCompanyAddress?: boolean; + companyAddress?: string; + billedToLabel?: string; // Total @@ -72,11 +74,12 @@ export function CreditNotePaperTemplate({ companyName = 'Bigcapital Technology, Inc.', // Address - billedToAddress = DefaultPdfTemplateAddressBilledTo, - billedFromAddress = DefaultPdfTemplateAddressBilledFrom, + showCustomerAddress = true, + customerAddress = DefaultPdfTemplateAddressBilledTo, + + showCompanyAddress = true, + companyAddress = DefaultPdfTemplateAddressBilledFrom, - showBilledFromAddress = true, - showBilledToAddress = true, billedToLabel = 'Billed To', // Total @@ -141,16 +144,16 @@ export function CreditNotePaperTemplate({ - {showBilledFromAddress && ( + {showCompanyAddress && ( - {companyName} - + )} - {showBilledToAddress && ( + + {showCustomerAddress && ( {billedToLabel} - + )} diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/constants.ts b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/constants.ts index 67d421193..c426247d7 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/constants.ts +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteCustomize/constants.ts @@ -11,9 +11,10 @@ export const initialValues = { companyLogoUri: '', // Address - showBilledToAddress: true, - showBilledFromAddress: true, - billedToLabel: 'Bill To', + showCustomerAddress: true, + showCompanyAddress: true, + companyAddress: '', + billedToLabel: 'Billed To', // Entries itemNameLabel: 'Item', diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/EstimatePaperTemplate.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/EstimatePaperTemplate.tsx index 0426b9a30..af1bb9d11 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/EstimatePaperTemplate.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/EstimatePaperTemplate.tsx @@ -32,11 +32,11 @@ export interface EstimatePaperTemplateProps extends PaperTemplateProps { companyName?: string; // Address - showBilledToAddress?: boolean; - billedToAddress?: string; + showCustomerAddress?: boolean; + customerAddress?: string; - showBilledFromAddress?: boolean; - billedFromAddress?: string; + showCompanyAddress?: boolean; + companyAddress?: string; billedToLabel?: string; // Totals @@ -71,23 +71,27 @@ export function EstimatePaperTemplate({ primaryColor, secondaryColor, + // # Company logo showCompanyLogo = true, companyLogoUri = '', companyName, - // # Address - billedToAddress = DefaultPdfTemplateAddressBilledTo, - billedFromAddress = DefaultPdfTemplateAddressBilledFrom, - showBilledFromAddress = true, - showBilledToAddress = true, + // # Company address + companyAddress = DefaultPdfTemplateAddressBilledFrom, + showCompanyAddress = true, + + // # Customer address + customerAddress = DefaultPdfTemplateAddressBilledTo, + showCustomerAddress = true, billedToLabel = 'Billed To', - // #Total + // # Total total = '$1000.00', totalLabel = 'Total', showTotal = true, + // # Subtotal subtotal = '1000/00', subtotalLabel = 'Subtotal', showSubtotal = true, @@ -111,14 +115,18 @@ export function EstimatePaperTemplate({ total: '$1000.00', }, ], + + // Estimate number showEstimateNumber = true, estimateNumberLabel = 'Estimate Number', estimateNumebr = '346D3D40-0001', + // Estimate date estimateDate = 'September 3, 2024', showEstimateDate = true, estimateDateLabel = 'Estimate Date', + // Expiration date expirationDateLabel = 'Expiration Date', showExpirationDate = true, expirationDate = 'September 3, 2024', @@ -151,16 +159,15 @@ export function EstimatePaperTemplate({ - {showBilledFromAddress && ( + {showCompanyAddress && ( - {companyName} - + )} - {showBilledToAddress && ( + {showCustomerAddress && ( {billedToLabel} - + )} diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/constants.ts b/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/constants.ts index 8f5046849..7a471036e 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/constants.ts +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateCustomize/constants.ts @@ -23,9 +23,12 @@ export const initialValues = { // Company name companyName: 'Bigcapital Technology, Inc.', - // Addresses - showBilledFromAddress: true, - showBilledToAddress: true, + // Customer address + showCustomerAddress: true, + + // Company address + showCompanyAddress: true, + companyAddress: '', billedToLabel: 'Billed To', // Entries @@ -45,6 +48,7 @@ export const initialValues = { showCustomerNote: true, customerNoteLabel: 'Customer Note', + // Terms & Conditions showTermsConditions: true, termsConditionsLabel: 'Terms & Conditions', }; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoicePaperTemplate.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoicePaperTemplate.tsx index e2a469fe9..19b80a64b 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoicePaperTemplate.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoicePaperTemplate.tsx @@ -45,8 +45,12 @@ export interface InvoicePaperTemplateProps { bigtitle?: string; // Address - showBillingToAddress?: boolean; - showBilledFromAddress?: boolean; + showCustomerAddress?: boolean; + customerAddress?: string; + + showCompanyAddress?: boolean; + companyAddress?: string; + billedToLabel?: string; // Entries @@ -90,9 +94,6 @@ export interface InvoicePaperTemplateProps { lines?: Array; taxes?: Array; - - billedFromAddres?: string; - billedToAddress?: string; } export function InvoicePaperTemplate({ @@ -118,8 +119,12 @@ export function InvoicePaperTemplate({ showInvoiceNumber = true, // Address - showBillingToAddress = true, - showBilledFromAddress = true, + showCustomerAddress = true, + customerAddress = DefaultPdfTemplateAddressBilledTo, + + showCompanyAddress = true, + companyAddress = DefaultPdfTemplateAddressBilledFrom, + billedToLabel = 'Billed To', // Entries @@ -171,8 +176,6 @@ export function InvoicePaperTemplate({ statementLabel = 'Statement', showStatement = true, statement = DefaultPdfTemplateStatement, - billedToAddress = DefaultPdfTemplateAddressBilledTo, - billedFromAddres = DefaultPdfTemplateAddressBilledFrom, }: InvoicePaperTemplateProps) { return ( - {showBilledFromAddress && ( + {showCompanyAddress && ( - {companyName} - + )} - {showBillingToAddress && ( + + {showCustomerAddress && ( {billedToLabel} - + )} diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/PaperTemplate.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/PaperTemplate.tsx index a6b8411dd..07ae55d22 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/PaperTemplate.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/PaperTemplate.tsx @@ -120,19 +120,18 @@ PaperTemplate.MutedText = () => {}; PaperTemplate.Text = () => {}; PaperTemplate.AddressesGroup = (props: GroupProps) => { - return ; -}; -PaperTemplate.Address = ({ - children, -}: { - children: React.ReactNode; -}) => { return ( - - {children} - + ); }; +PaperTemplate.Address = ({ children }: { children: React.ReactNode }) => { + return {children}; +}; PaperTemplate.Statement = ({ label, diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/constants.ts b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/constants.ts index 964406c43..2d40522fc 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/constants.ts +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/constants.ts @@ -26,8 +26,9 @@ export const initialValues = { companyName: 'Bigcapital Technology, Inc.', // Addresses - showBilledFromAddress: true, - showBillingToAddress: true, + showCustomerAddress: true, + showCompanyAddress: true, + companyAddress: '', billedToLabel: 'Billed To', // Entries diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/PaymentReceivedPaperTemplate.tsx b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/PaymentReceivedPaperTemplate.tsx index 496afddd1..3ef62ed7f 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/PaymentReceivedPaperTemplate.tsx +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/PaymentReceivedPaperTemplate.tsx @@ -10,11 +10,14 @@ import { } from '@/constants/PdfTemplates'; export interface PaymentReceivedPaperTemplateProps extends PaperTemplateProps { - billedToAddress?: string; - showBilledToAddress?: boolean; + // Customer address + showCustomerAddress?: boolean; + customerAddress?: string; + + // Company address + showCompanyAddress?: boolean; + companyAddress?: string; - billedFromAddress?: string; - showBilledFromAddress?: boolean; billedToLabel?: string; // Total. @@ -56,10 +59,14 @@ export function PaymentReceivedPaperTemplate({ // # Company name companyName = 'Bigcapital Technology, Inc.', - billedToAddress = DefaultPdfTemplateAddressBilledTo, - billedFromAddress = DefaultPdfTemplateAddressBilledFrom, - showBilledFromAddress, - showBilledToAddress, + // # Customer address + showCustomerAddress = true, + customerAddress = DefaultPdfTemplateAddressBilledTo, + + // # Company address + showCompanyAddress = true, + companyAddress = DefaultPdfTemplateAddressBilledFrom, + billedToLabel = 'Billed To', total = '$1000.00', @@ -109,16 +116,16 @@ export function PaymentReceivedPaperTemplate({ - {showBilledFromAddress && ( + {showCompanyAddress && ( - {companyName} - + )} - {showBilledToAddress && ( + + {showCustomerAddress && ( {billedToLabel} - + )} diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/constants.ts b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/constants.ts index e9aef8a0e..19078b5fb 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/constants.ts +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/constants.ts @@ -14,15 +14,19 @@ export const initialValues = { showPaymentReceivedNumber: true, paymentReceivedNumberLabel: 'Payment number', + // Payment number showPaymentReceivedDate: true, paymentReceivedDateLabel: 'Date of Issue', // Company name companyName: 'Bigcapital Technology, Inc.', - // Addresses - showBilledFromAddress: true, - showBillingToAddress: true, + // Customer address + showCompanyAddress: true, + companyAddress: '', + + // Company address + showCustomerAddress: true, billedToLabel: 'Billed To', // Entries @@ -31,10 +35,11 @@ export const initialValues = { itemRateLabel: 'Rate', itemTotalLabel: 'Total', - // Totals + // Subtotal showSubtotal: true, subtotalLabel: 'Subtotal', + // Total showTotal: true, totalLabel: 'Total', }; diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/types.ts b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/types.ts index da5468a55..f26371cc6 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/types.ts +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedCustomize/types.ts @@ -12,18 +12,23 @@ export interface PaymentReceivedCustomizeValues extends BrandingTemplateValues { showInvoiceNumber?: boolean; invoiceNumberLabel?: string; + // # Issue date showDateIssue?: boolean; dateIssueLabel?: string; + // # Due date showDueDate?: boolean; dueDateLabel?: string; - // Company name + // # Company name companyName?: string; - // Addresses - showBilledFromAddress?: boolean; - showBillingToAddress?: boolean; + // # Customer address + showCustomerAddress?: boolean; + + // # Company address + showCompanyAddress?: boolean; + companyAddress?: string; billedToLabel?: string; // Entries @@ -54,6 +59,7 @@ export interface PaymentReceivedCustomizeValues extends BrandingTemplateValues { termsConditionsLabel?: string; showTermsConditions?: boolean; + // # Statement statementLabel?: string; showStatement?: boolean; } diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/ReceiptPaperTemplate.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/ReceiptPaperTemplate.tsx index 00faba13b..30bb31c1e 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/ReceiptPaperTemplate.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/ReceiptPaperTemplate.tsx @@ -14,10 +14,12 @@ import { export interface ReceiptPaperTemplateProps extends PaperTemplateProps { // Addresses - billedToAddress?: string; - billedFromAddress?: string; - showBilledFromAddress?: boolean; - showBilledToAddress?: boolean; + showCustomerAddress?: boolean; + customerAddress?: string; + + showCompanyAddress?: boolean; + companyAddress?: string; + billedToLabel?: string; // Total @@ -73,10 +75,12 @@ export function ReceiptPaperTemplate({ companyName = 'Bigcapital Technology, Inc.', // # Address - billedToAddress = DefaultPdfTemplateAddressBilledTo, - billedFromAddress = DefaultPdfTemplateAddressBilledFrom, - showBilledFromAddress = true, - showBilledToAddress = true, + showCustomerAddress = true, + customerAddress = DefaultPdfTemplateAddressBilledTo, + + showCompanyAddress = true, + companyAddress = DefaultPdfTemplateAddressBilledFrom, + billedToLabel = 'Billed To', total = '$1000.00', @@ -135,16 +139,16 @@ export function ReceiptPaperTemplate({ - {showBilledFromAddress && ( + {showCompanyAddress && ( - {companyName} - + )} - {showBilledToAddress && ( + + {showCustomerAddress && ( {billedToLabel} - + )} diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/constants.ts b/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/constants.ts index 6f67d5a48..07ae60a23 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/constants.ts +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptCustomize/constants.ts @@ -21,9 +21,12 @@ export const initialValues = { // Company name companyName: 'Bigcapital Technology, Inc.', - // Addresses - showBilledFromAddress: true, - showBilledToAddress: true, + // Customer address + showCustomerAddress: true, + + // Company address + companyAddress: '', + showCompanyAddress: true, billedToLabel: 'Billed To', // Entries diff --git a/packages/webapp/src/hooks/query/pdf-templates.ts b/packages/webapp/src/hooks/query/pdf-templates.ts index 6823b9cee..43e655b05 100644 --- a/packages/webapp/src/hooks/query/pdf-templates.ts +++ b/packages/webapp/src/hooks/query/pdf-templates.ts @@ -203,3 +203,28 @@ export const useAssignPdfTemplateAsDefault = ( }, ); }; + +// Retrieve organization branding state. +// -------------------------------------------------- +export interface GetPdfTemplateBrandingStateResponse { + companyName: string; + companyAddress: string; + companyLogoUri: string; + companyLogoKey: string; + primaryColor: string; +} + +export const useGetPdfTemplateBrandingState = ( + options?: UseQueryOptions, +): UseQueryResult => { + const apiRequest = useApiRequest(); + + return useQuery( + [PdfTemplatesQueryKey, 'state'], + () => + apiRequest + .get('/pdf-templates/state') + .then((res) => transformToCamelCase(res.data?.data)), + options, + ); +};