feat: Hook up company address to payment page

This commit is contained in:
Ahmed Bouhuolia
2024-09-28 20:19:05 +02:00
parent e506a7ba35
commit 9b63c176cd
6 changed files with 123 additions and 23 deletions

View File

@@ -45,6 +45,7 @@ export class GetInvoicePaymentLinkMetadata {
.withGraphFetched('entries.item') .withGraphFetched('entries.item')
.withGraphFetched('customer') .withGraphFetched('customer')
.withGraphFetched('taxes.taxRate') .withGraphFetched('taxes.taxRate')
.withGraphFetched('paymentMethods.paymentIntegration')
.throwIfNotFound(); .throwIfNotFound();
return this.transformer.transform( return this.transformer.transform(

View File

@@ -41,6 +41,8 @@ export class GetInvoicePaymentLinkMetaTransformer extends SaleInvoiceTransformer
'entries', 'entries',
'taxes', 'taxes',
'organization', 'organization',
'isReceivable',
'hasStripePaymentMethod',
]; ];
}; };
@@ -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 { class GetPaymentLinkOrganizationMetaTransformer extends Transformer {
@@ -97,12 +109,26 @@ class GetPaymentLinkOrganizationMetaTransformer extends Transformer {
* @returns {Array} * @returns {Array}
*/ */
public includeAttributes = (): string[] => { public includeAttributes = (): string[] => {
return ['primaryColor', 'name', 'address', 'logoUri']; return [
'primaryColor',
'name',
'address',
'logoUri',
'addressTextFormatted',
];
}; };
public excludeAttributes = (): string[] => { public excludeAttributes = (): string[] => {
return ['*']; return ['*'];
}; };
/**
* Retrieves the formatted text of organization address.
* @returns {string}
*/
public addressTextFormatted() {
return this.context.organization.addressTextFormatted;
}
} }
class GetInvoicePaymentLinkEntryMetaTransformer extends ItemEntryTransformer { class GetInvoicePaymentLinkEntryMetaTransformer extends ItemEntryTransformer {

View File

@@ -1,3 +1,4 @@
import { addressTextFormat } from '@/utils/address-text-format';
import BaseModel from 'models/Model'; import BaseModel from 'models/Model';
export default class TenantMetadata extends BaseModel { export default class TenantMetadata extends BaseModel {
@@ -12,8 +13,11 @@ export default class TenantMetadata extends BaseModel {
fiscalYear!: string; fiscalYear!: string;
primaryColor!: string; primaryColor!: string;
logoKey!: string; logoKey!: string;
address!: object; address!: Record<string, any>;
/**
* Json schema.
*/
static get jsonSchema() { static get jsonSchema() {
return { return {
type: 'object', type: 'object',
@@ -50,9 +54,35 @@ export default class TenantMetadata extends BaseModel {
} }
/** /**
* * Organization logo url.
* @returns {string | null}
*/ */
public get logoUri() { 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 = `<strong>{ORGANIZATION_NAME}</strong>
{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',
});
} }
} }

View File

@@ -0,0 +1,42 @@
interface OrganizationAddressFormatArgs {
organizationName?: string;
address1?: string;
address2?: string;
state?: string;
city?: string;
country?: string;
postalCode?: string;
}
const defaultMessage = `
<strong>{ORGANIZATION_NAME}</strong>
{ADDRESS_1},
{ADDRESS_2},
{CITY} {STATE},
{POSTAL_CODE},
{COUNTRY}
`;
export const addressTextFormat = (
message: string,
args: OrganizationAddressFormatArgs
) => {
const replacements: Record<string, string> = {
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, '<br />');
return formattedMessage.trim();
};

View File

@@ -96,7 +96,6 @@ export function PaymentPortal() {
<Text>{tax?.taxRateAmountFormatted}</Text> <Text>{tax?.taxRateAmountFormatted}</Text>
</Group> </Group>
))} ))}
<Group <Group
position={'apart'} position={'apart'}
className={clsx(styles.totalItem, styles.borderBottomGray)} className={clsx(styles.totalItem, styles.borderBottomGray)}
@@ -132,14 +131,17 @@ export function PaymentPortal() {
View Invoice View Invoice
</Button> </Button>
<Button {sharableLinkMeta?.isReceivable &&
intent={Intent.PRIMARY} sharableLinkMeta?.hasStripePaymentMethod && (
className={clsx(styles.footerButton, styles.buyButton)} <Button
loading={isStripeCheckoutLoading} intent={Intent.PRIMARY}
onClick={handlePayButtonClick} className={clsx(styles.footerButton, styles.buyButton)}
> loading={isStripeCheckoutLoading}
Pay {sharableLinkMeta?.totalFormatted} onClick={handlePayButtonClick}
</Button> >
Pay {sharableLinkMeta?.totalFormatted}
</Button>
)}
</Stack> </Stack>
<Text className={clsx(Classes.TEXT_MUTED, styles.buyNote)}> <Text className={clsx(Classes.TEXT_MUTED, styles.buyNote)}>
@@ -150,15 +152,11 @@ export function PaymentPortal() {
</Stack> </Stack>
<Stack spacing={18} className={styles.footer}> <Stack spacing={18} className={styles.footer}>
<Stack spacing={0}> <Box
<Box> dangerouslySetInnerHTML={{
<strong>Bigcapital Technology, Inc.</strong> __html: sharableLinkMeta?.organization?.addressTextFormatted || '',
</Box> }}
<Box>131 Continental Dr Suite 305 Newark,</Box> ></Box>
<Box>Delaware 19713</Box>
<Box>United States</Box>
<Box>ahmed@bigcapital.app</Box>
</Stack>
<Stack spacing={0} className={styles.footerText}> <Stack spacing={0} className={styles.footerText}>
© 2024 Bigcapital Technology, Inc. © 2024 Bigcapital Technology, Inc.

View File

@@ -104,8 +104,11 @@ export interface GetInvoicePaymentLinkResponse {
name: string; name: string;
primaryColor: string; primaryColor: string;
logoUri: string; logoUri: string;
addressTextFormatted: string;
} }
>; >;
hasStripePaymentMethod: boolean;
isReceivable: boolean;
} }
/** /**