diff --git a/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts b/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts
index b85696497..87c4823c0 100644
--- a/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts
+++ b/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts
@@ -3,6 +3,7 @@ import { ItemEntryTransformer } from './ItemEntryTransformer';
import { SaleInvoiceTaxEntryTransformer } from './SaleInvoiceTaxEntryTransformer';
import { SaleInvoiceTransformer } from './SaleInvoiceTransformer';
import { Transformer } from '@/lib/Transformer/Transformer';
+import { contactAddressTextFormat } from '@/utils/address-text-format';
export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer {
/**
@@ -43,6 +44,7 @@ export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer
'organization',
'isReceivable',
'hasStripePaymentMethod',
+ 'formattedCustomerAddress',
];
};
@@ -101,6 +103,14 @@ export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer
(paymentMethod) => paymentMethod.paymentIntegration.service === 'Stripe'
);
}
+
+ protected formattedCustomerAddress(invoice) {
+ return contactAddressTextFormat(invoice.customer, `{ADDRESS_1}
+{ADDRESS_2}
+{CITY}, {STATE} {POSTAL_CODE}
+{COUNTRY}
+{PHONE}`);
+ }
}
class GetPaymentLinkOrganizationMetaTransformer extends Transformer {
diff --git a/packages/server/src/system/models/TenantMetadata.ts b/packages/server/src/system/models/TenantMetadata.ts
index efc0d2840..0b7ae3ce3 100644
--- a/packages/server/src/system/models/TenantMetadata.ts
+++ b/packages/server/src/system/models/TenantMetadata.ts
@@ -68,11 +68,11 @@ export default class TenantMetadata extends BaseModel {
*/
public get addressTextFormatted() {
const defaultMessage = `{ORGANIZATION_NAME}
- {ADDRESS_1},
- {ADDRESS_2},
- {CITY} {STATE},
- {POSTAL_CODE},
+ {ADDRESS_1}
+ {ADDRESS_2}
+ {CITY}, {STATE} {POSTAL_CODE}
{COUNTRY}
+ {PHONE}
`;
return organizationAddressTextFormat(defaultMessage, {
organizationName: this.name,
@@ -81,6 +81,7 @@ export default class TenantMetadata extends BaseModel {
state: this.address?.stateProvince,
city: this.address?.city,
postalCode: this.address?.postalCode,
+ phone: this.address?.phone,
country: 'United State',
});
}
diff --git a/packages/server/src/utils/address-text-format.ts b/packages/server/src/utils/address-text-format.ts
index 1b19d6301..d5f85c721 100644
--- a/packages/server/src/utils/address-text-format.ts
+++ b/packages/server/src/utils/address-text-format.ts
@@ -8,17 +8,27 @@ interface OrganizationAddressFormatArgs {
city?: string;
country?: string;
postalCode?: string;
+ phone?: string;
}
const defaultMessage = `
{ORGANIZATION_NAME}
- {ADDRESS_1},
- {ADDRESS_2},
- {CITY} {STATE},
- {POSTAL_CODE},
+ {ADDRESS_1}
+ {ADDRESS_2}
+ {CITY}, {STATE} {POSTAL_CODE}
{COUNTRY}
+ {PHONE}
`;
-
+/**
+ * Formats the address text based on the provided message and arguments.
+ * This function replaces placeholders in the message with actual values
+ * from the OrganizationAddressFormatArgs. It ensures that the final
+ * formatted message is clean and free of excessive newlines.
+ *
+ * @param {string} message - The message template containing placeholders.
+ * @param {Record} args - The arguments containing the values to replace in the message.
+ * @returns {string} - The formatted address text.
+ */
const formatText = (message: string, replacements: Record) => {
let formattedMessage = Object.entries(replacements).reduce(
(msg, [key, value]) => {
@@ -26,9 +36,11 @@ const formatText = (message: string, replacements: Record) => {
},
message
);
+ formattedMessage = formattedMessage.replace(/\n{2,}/g, '\n').trim();
formattedMessage = formattedMessage.replace(/\n/g, '
');
+ formattedMessage = formattedMessage.trim();
- return formattedMessage.trim();
+ return formattedMessage;
};
export const organizationAddressTextFormat = (
@@ -43,6 +55,7 @@ export const organizationAddressTextFormat = (
STATE: args.state || '',
POSTAL_CODE: args.postalCode || '',
COUNTRY: args.country || '',
+ PHONE: args.phone || '',
};
return formatText(message, replacements);
};
@@ -56,15 +69,15 @@ interface ContactAddressTextFormatArgs {
city?: string;
address2?: string;
address1?: string;
+ phone?: string;
}
const contactFormatMessage = `{CONTACT_NAME}
{ADDRESS_1}
{ADDRESS_2}
-{CITY} {STATE}
-{POSTAL_CODE}
+{CITY}, {STATE} {POSTAL_CODE}
{COUNTRY}
-{EMAIL}
+{PHONE}
`;
export const contactAddressTextFormat = (
@@ -80,6 +93,7 @@ export const contactAddressTextFormat = (
postalCode: contact?.billingAddressPostcode,
city: contact?.billingAddressCity,
email: contact?.email,
+ phone: contact?.billingAddressPhone,
} as ContactAddressTextFormatArgs;
const replacements: Record = {
@@ -91,6 +105,7 @@ export const contactAddressTextFormat = (
POSTAL_CODE: args.postalCode || '',
COUNTRY: args.country || '',
EMAIL: args?.email || '',
+ PHONE: args?.phone || '',
};
return formatText(message, replacements);
};
diff --git a/packages/webapp/src/constants/PdfTemplates.ts b/packages/webapp/src/constants/PdfTemplates.ts
index d1be6ba4f..c08cce9c5 100644
--- a/packages/webapp/src/constants/PdfTemplates.ts
+++ b/packages/webapp/src/constants/PdfTemplates.ts
@@ -10,11 +10,11 @@ export const DefaultPdfTemplateItemDescription =
'Website development with content and SEO optimization';
export const DefaultPdfTemplateAddressBilledTo = `Bigcapital Technology, Inc.
-131 Continental Dr Suite 305 Newark,
-Delaware 19713,
-United States,
-+1 762-339-5634,
-ahmed@bigcapital.app
+131 Continental Dr,
+Suite 305,
+Newark, Delaware 19713,
+United States,
++1 762-339-5634
`;
export const DefaultPdfTemplateAddressBilledFrom = `131 Continental Dr Suite 305 Newark,
diff --git a/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx b/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx
index 6bb2114ca..6e1080910 100644
--- a/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx
+++ b/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx
@@ -1,4 +1,4 @@
-import { Text, Classes, Button, Intent } from '@blueprintjs/core';
+import { Text, Classes, Button, Intent, Tag } from '@blueprintjs/core';
import clsx from 'classnames';
import { AppToaster, Box, Group, Stack } from '@/components';
import { usePaymentPortalBoot } from './PaymentPortalBoot';
@@ -54,20 +54,25 @@ export function PaymentPortal() {
{sharableLinkMeta?.organization?.name} Sent an Invoice for{' '}
{sharableLinkMeta?.totalFormatted}
-
- Invoice due {sharableLinkMeta?.dueDateFormatted}
-
+
+
+ Invoice due {sharableLinkMeta?.dueDateFormatted}{' '}
+
+
{sharableLinkMeta?.customerName}
- Bigcapital Technology, Inc.
- 131 Continental Dr Suite 305 Newark,
- Delaware 19713
- United States
- ahmed@bigcapital.app
+
+ {sharableLinkMeta?.formattedCustomerAddress && (
+
+ )}
diff --git a/packages/webapp/src/containers/PaymentPortal/drawers/PaymentInvoicePreviewDrawer/PaymentInvoicePreviewContent.tsx b/packages/webapp/src/containers/PaymentPortal/drawers/PaymentInvoicePreviewDrawer/PaymentInvoicePreviewContent.tsx
index d55bb9598..037c11b08 100644
--- a/packages/webapp/src/containers/PaymentPortal/drawers/PaymentInvoicePreviewDrawer/PaymentInvoicePreviewContent.tsx
+++ b/packages/webapp/src/containers/PaymentPortal/drawers/PaymentInvoicePreviewDrawer/PaymentInvoicePreviewContent.tsx
@@ -34,6 +34,10 @@ export function PaymentInvoicePreviewContent() {
label: tax.name,
amount: tax.taxRateAmountFormatted,
}))}
+ companyAddress={
+ sharableLinkMeta?.organization?.addressTextFormatted
+ }
+ customerAddress={sharableLinkMeta?.formattedCustomerAddress}
/>
diff --git a/packages/webapp/src/hooks/query/payment-link.ts b/packages/webapp/src/hooks/query/payment-link.ts
index 1eadbed73..96cce6c0f 100644
--- a/packages/webapp/src/hooks/query/payment-link.ts
+++ b/packages/webapp/src/hooks/query/payment-link.ts
@@ -108,6 +108,7 @@ export interface GetInvoicePaymentLinkResponse {
organization: GetInvoicePaymentLinkOrganizationRes;
hasStripePaymentMethod: boolean;
isReceivable: boolean;
+ formattedCustomerAddress: string;
}
/**