diff --git a/packages/server/src/services/PaymentLinks/GetInvoicePaymentLinkMetadata.ts b/packages/server/src/services/PaymentLinks/GetInvoicePaymentLinkMetadata.ts index b63b67901..d12adca4b 100644 --- a/packages/server/src/services/PaymentLinks/GetInvoicePaymentLinkMetadata.ts +++ b/packages/server/src/services/PaymentLinks/GetInvoicePaymentLinkMetadata.ts @@ -45,6 +45,7 @@ export class GetInvoicePaymentLinkMetadata { .withGraphFetched('entries.item') .withGraphFetched('customer') .withGraphFetched('taxes.taxRate') + .withGraphFetched('paymentMethods.paymentIntegration') .throwIfNotFound(); return this.transformer.transform( diff --git a/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts b/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts index 65e42f8dd..b85696497 100644 --- a/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts +++ b/packages/server/src/services/Sales/Invoices/GetInvoicePaymentLinkTransformer.ts @@ -41,6 +41,8 @@ export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer 'entries', 'taxes', 'organization', + 'isReceivable', + 'hasStripePaymentMethod', ]; }; @@ -50,7 +52,7 @@ export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer /** * Retrieves the organization metadata for the payment link. - * @returns + * @returns */ public organization(invoice) { return this.item( @@ -89,6 +91,16 @@ export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer } ); }; + + protected isReceivable(invoice) { + return invoice.dueAmount > 0; + } + + protected hasStripePaymentMethod(invoice) { + return invoice.paymentMethods.some( + (paymentMethod) => paymentMethod.paymentIntegration.service === 'Stripe' + ); + } } class GetPaymentLinkOrganizationMetaTransformer extends Transformer { @@ -97,12 +109,26 @@ class GetPaymentLinkOrganizationMetaTransformer extends Transformer { * @returns {Array} */ public includeAttributes = (): string[] => { - return ['primaryColor', 'name', 'address', 'logoUri']; + return [ + 'primaryColor', + 'name', + 'address', + 'logoUri', + 'addressTextFormatted', + ]; }; public excludeAttributes = (): string[] => { return ['*']; }; + + /** + * Retrieves the formatted text of organization address. + * @returns {string} + */ + public addressTextFormatted() { + return this.context.organization.addressTextFormatted; + } } class GetInvoicePaymentLinkEntryMetaTransformer extends ItemEntryTransformer { diff --git a/packages/server/src/system/models/TenantMetadata.ts b/packages/server/src/system/models/TenantMetadata.ts index 2618a53c6..5ff89d84a 100644 --- a/packages/server/src/system/models/TenantMetadata.ts +++ b/packages/server/src/system/models/TenantMetadata.ts @@ -1,3 +1,4 @@ +import { addressTextFormat } from '@/utils/address-text-format'; import BaseModel from 'models/Model'; export default class TenantMetadata extends BaseModel { @@ -12,8 +13,11 @@ export default class TenantMetadata extends BaseModel { fiscalYear!: string; primaryColor!: string; logoKey!: string; - address!: object; + address!: Record; + /** + * Json schema. + */ static get jsonSchema() { return { type: 'object', @@ -50,9 +54,35 @@ export default class TenantMetadata extends BaseModel { } /** - * + * Organization logo url. + * @returns {string | null} */ public get logoUri() { - return this.logoKey ? `https://bigcapital.sfo3.digitaloceanspaces.com/${this.logoKey}` : null; + return this.logoKey + ? `https://bigcapital.sfo3.digitaloceanspaces.com/${this.logoKey}` + : null; + } + + /** + * Retrieves the organization address formatted text. + * @returns {string} + */ + public get addressTextFormatted() { + const defaultMessage = `{ORGANIZATION_NAME} + {ADDRESS_1}, + {ADDRESS_2}, + {CITY} {STATE}, + {POSTAL_CODE}, + {COUNTRY} +`; + return addressTextFormat(defaultMessage, { + organizationName: this.name, + address1: this.address?.address1, + address2: this.address?.address2, + state: this.address?.stateProvince, + city: this.address?.city, + postalCode: this.address?.postalCode, + country: 'United State', + }); } } diff --git a/packages/server/src/utils/address-text-format.ts b/packages/server/src/utils/address-text-format.ts new file mode 100644 index 000000000..73467aa9c --- /dev/null +++ b/packages/server/src/utils/address-text-format.ts @@ -0,0 +1,42 @@ +interface OrganizationAddressFormatArgs { + organizationName?: string; + address1?: string; + address2?: string; + state?: string; + city?: string; + country?: string; + postalCode?: string; +} + +const defaultMessage = ` + {ORGANIZATION_NAME} + {ADDRESS_1}, + {ADDRESS_2}, + {CITY} {STATE}, + {POSTAL_CODE}, + {COUNTRY} +`; + +export const addressTextFormat = ( + message: string, + args: OrganizationAddressFormatArgs +) => { + const replacements: Record = { + ORGANIZATION_NAME: args.organizationName || '', + ADDRESS_1: args.address1 || '', + ADDRESS_2: args.address2 || '', + CITY: args.city || '', + STATE: args.state || '', + 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(); +}; diff --git a/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx b/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx index 7f8d661a1..6bb2114ca 100644 --- a/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx +++ b/packages/webapp/src/containers/PaymentPortal/PaymentPortal.tsx @@ -96,7 +96,6 @@ export function PaymentPortal() { {tax?.taxRateAmountFormatted} ))} - - + {sharableLinkMeta?.isReceivable && + sharableLinkMeta?.hasStripePaymentMethod && ( + + )} @@ -150,15 +152,11 @@ export function PaymentPortal() { - - - Bigcapital Technology, Inc. - - 131 Continental Dr Suite 305 Newark, - Delaware 19713 - United States - ahmed@bigcapital.app - + © 2024 Bigcapital Technology, Inc. diff --git a/packages/webapp/src/hooks/query/payment-link.ts b/packages/webapp/src/hooks/query/payment-link.ts index 641fe10f8..34244676f 100644 --- a/packages/webapp/src/hooks/query/payment-link.ts +++ b/packages/webapp/src/hooks/query/payment-link.ts @@ -104,8 +104,11 @@ export interface GetInvoicePaymentLinkResponse { name: string; primaryColor: string; logoUri: string; + addressTextFormatted: string; } >; + hasStripePaymentMethod: boolean; + isReceivable: boolean; } /**