feat: Pdf template address

This commit is contained in:
Ahmed Bouhuolia
2024-09-29 13:43:09 +02:00
parent 9b63c176cd
commit be2049ca6e
9 changed files with 122 additions and 169 deletions

View File

@@ -56,10 +56,10 @@ export default class OrganizationController extends BaseController {
} }
/** /**
* Organization setup schema. * Build organization validation schema.
* @return {ValidationChain[]} * @returns {ValidationChain[]}
*/ */
private get commonOrganizationValidationSchema(): ValidationChain[] { private get buildOrganizationValidationSchema(): ValidationChain[] {
return [ return [
check('name').exists().trim(), check('name').exists().trim(),
check('industry').optional({ nullable: true }).isString().trim(), check('industry').optional({ nullable: true }).isString().trim(),
@@ -69,30 +69,9 @@ export default class OrganizationController extends BaseController {
check('fiscal_year').exists().isIn(MONTHS), check('fiscal_year').exists().isIn(MONTHS),
check('language').exists().isString().isIn(ACCEPTED_LOCALES), check('language').exists().isString().isIn(ACCEPTED_LOCALES),
check('date_format').optional().isIn(DATE_FORMATS), check('date_format').optional().isIn(DATE_FORMATS),
// # Address
check('address').optional({ nullable: true }),
check('address.address_1').optional().isString().trim(),
check('address.address_2').optional().isString().trim(),
check('address.postal_code').optional().isString().trim(),
check('address.city').optional().isString().trim(),
check('address.state_province').optional().isString().trim(),
check('address.phone').optional().isString().trim(),
// # Branding
check('primary_color').optional().isString().trim(),
check('company_logo_key').optional().isString().trim(),
]; ];
} }
/**
* Build organization validation schema.
* @returns {ValidationChain[]}
*/
private get buildOrganizationValidationSchema(): ValidationChain[] {
return [...this.commonOrganizationValidationSchema];
}
/** /**
* Update organization validation schema. * Update organization validation schema.
* @returns {ValidationChain[]} * @returns {ValidationChain[]}

View File

@@ -1,4 +1,5 @@
export const DefaultPdfTemplateTerms = 'All services provided are non-refundable. For any disputes, please contact us within 7 days of receiving this invoice.'; export const DefaultPdfTemplateTerms =
'All services provided are non-refundable. For any disputes, please contact us within 7 days of receiving this invoice.';
export const DefaultPdfTemplateStatement = export const DefaultPdfTemplateStatement =
'Thank you for your business. We look forward to working with you again!'; 'Thank you for your business. We look forward to working with you again!';
@@ -7,3 +8,19 @@ export const DefaultPdfTemplateItemName = 'Web development';
export const DefaultPdfTemplateItemDescription = export const DefaultPdfTemplateItemDescription =
'Website development with content and SEO optimization'; 'Website development with content and SEO optimization';
export const DefaultPdfTemplateAddressBilledTo = `Bigcapital Technology, Inc.<br />
131 Continental Dr Suite 305 Newark, <br />
Delaware 19713, <br />
United States, <br />
+1 762-339-5634, <br />
ahmed@bigcapital.app
`;
export const DefaultPdfTemplateAddressBilledFrom = `131 Continental Dr Suite 305 Newark, <br />
Delaware 19713,<br />
United States, <br />
+1 762-339-5634, <br />
ahmed@bigcapital.app
`;

View File

@@ -1,4 +1,4 @@
import { Stack } from '@/components'; import { Box, Stack } from '@/components';
import { import {
PaperTemplate, PaperTemplate,
PaperTemplateProps, PaperTemplateProps,
@@ -8,12 +8,14 @@ import {
DefaultPdfTemplateItemDescription, DefaultPdfTemplateItemDescription,
DefaultPdfTemplateStatement, DefaultPdfTemplateStatement,
DefaultPdfTemplateItemName, DefaultPdfTemplateItemName,
DefaultPdfTemplateAddressBilledTo,
DefaultPdfTemplateAddressBilledFrom,
} from '@/constants/PdfTemplates'; } from '@/constants/PdfTemplates';
export interface CreditNotePaperTemplateProps extends PaperTemplateProps { export interface CreditNotePaperTemplateProps extends PaperTemplateProps {
// Address // Address
billedToAddress?: Array<string>; billedToAddress?: string;
billedFromAddress?: Array<string>; billedFromAddress?: string;
showBilledToAddress?: boolean; showBilledToAddress?: boolean;
showBilledFromAddress?: boolean; showBilledFromAddress?: boolean;
billedToLabel?: string; billedToLabel?: string;
@@ -70,23 +72,11 @@ export function CreditNotePaperTemplate({
companyName = 'Bigcapital Technology, Inc.', companyName = 'Bigcapital Technology, Inc.',
// Address // Address
billedToAddress = [ billedToAddress = DefaultPdfTemplateAddressBilledTo,
'Bigcapital Technology, Inc.', billedFromAddress = DefaultPdfTemplateAddressBilledFrom,
'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, showBilledFromAddress = true,
showBilledToAddress = true,
billedToLabel = 'Billed To', billedToLabel = 'Billed To',
// Total // Total
@@ -152,14 +142,16 @@ export function CreditNotePaperTemplate({
<PaperTemplate.AddressesGroup> <PaperTemplate.AddressesGroup>
{showBilledFromAddress && ( {showBilledFromAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{companyName}</strong>, ...billedFromAddress]} <strong>{companyName}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
</PaperTemplate.Address>
)} )}
{showBilledToAddress && ( {showBilledToAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{billedToLabel}</strong>, ...billedToAddress]} <strong>{billedToLabel}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
</PaperTemplate.Address>
)} )}
</PaperTemplate.AddressesGroup> </PaperTemplate.AddressesGroup>

View File

@@ -1,4 +1,4 @@
import { Stack } from '@/components'; import { Box, Stack } from '@/components';
import { import {
PaperTemplate, PaperTemplate,
PaperTemplateProps, PaperTemplateProps,
@@ -8,6 +8,8 @@ import {
DefaultPdfTemplateItemDescription, DefaultPdfTemplateItemDescription,
DefaultPdfTemplateStatement, DefaultPdfTemplateStatement,
DefaultPdfTemplateItemName, DefaultPdfTemplateItemName,
DefaultPdfTemplateAddressBilledTo,
DefaultPdfTemplateAddressBilledFrom,
} from '@/constants/PdfTemplates'; } from '@/constants/PdfTemplates';
export interface EstimatePaperTemplateProps extends PaperTemplateProps { export interface EstimatePaperTemplateProps extends PaperTemplateProps {
@@ -31,10 +33,10 @@ export interface EstimatePaperTemplateProps extends PaperTemplateProps {
// Address // Address
showBilledToAddress?: boolean; showBilledToAddress?: boolean;
billedToAddress?: Array<string>; billedToAddress?: string;
showBilledFromAddress?: boolean; showBilledFromAddress?: boolean;
billedFromAddress?: Array<string>; billedFromAddress?: string;
billedToLabel?: string; billedToLabel?: string;
// Totals // Totals
@@ -74,25 +76,14 @@ export function EstimatePaperTemplate({
companyName, companyName,
billedToAddress = [ // # Address
'Bigcapital Technology, Inc.', billedToAddress = DefaultPdfTemplateAddressBilledTo,
'131 Continental Dr Suite 305 Newark,', billedFromAddress = DefaultPdfTemplateAddressBilledFrom,
'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, showBilledFromAddress = true,
showBilledToAddress = true, showBilledToAddress = true,
billedToLabel = 'Billed To', billedToLabel = 'Billed To',
// #Total
total = '$1000.00', total = '$1000.00',
totalLabel = 'Total', totalLabel = 'Total',
showTotal = true, showTotal = true,
@@ -101,10 +92,12 @@ export function EstimatePaperTemplate({
subtotalLabel = 'Subtotal', subtotalLabel = 'Subtotal',
showSubtotal = true, showSubtotal = true,
// # Customer Note
showCustomerNote = true, showCustomerNote = true,
customerNote = DefaultPdfTemplateStatement, customerNote = DefaultPdfTemplateStatement,
customerNoteLabel = 'Customer Note', customerNoteLabel = 'Customer Note',
// # Terms & Conditions
showTermsConditions = true, showTermsConditions = true,
termsConditions = DefaultPdfTemplateTerms, termsConditions = DefaultPdfTemplateTerms,
termsConditionsLabel = 'Terms & Conditions', termsConditionsLabel = 'Terms & Conditions',
@@ -145,13 +138,11 @@ export function EstimatePaperTemplate({
{estimateNumebr} {estimateNumebr}
</PaperTemplate.TermsItem> </PaperTemplate.TermsItem>
)} )}
{showEstimateDate && ( {showEstimateDate && (
<PaperTemplate.TermsItem label={estimateDateLabel}> <PaperTemplate.TermsItem label={estimateDateLabel}>
{estimateDate} {estimateDate}
</PaperTemplate.TermsItem> </PaperTemplate.TermsItem>
)} )}
{showExpirationDate && ( {showExpirationDate && (
<PaperTemplate.TermsItem label={expirationDateLabel}> <PaperTemplate.TermsItem label={expirationDateLabel}>
{expirationDate} {expirationDate}
@@ -161,14 +152,16 @@ export function EstimatePaperTemplate({
<PaperTemplate.AddressesGroup> <PaperTemplate.AddressesGroup>
{showBilledFromAddress && ( {showBilledFromAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{companyName}</strong>, ...billedFromAddress]} <strong>{companyName}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
</PaperTemplate.Address>
)} )}
{showBilledToAddress && ( {showBilledToAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{billedToLabel}</strong>, ...billedToAddress]} <strong>{billedToLabel}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
</PaperTemplate.Address>
)} )}
</PaperTemplate.AddressesGroup> </PaperTemplate.AddressesGroup>

View File

@@ -1,11 +1,13 @@
import React from 'react'; import React from 'react';
import { PaperTemplate, PaperTemplateTotalBorder } from './PaperTemplate'; import { PaperTemplate, PaperTemplateTotalBorder } from './PaperTemplate';
import { Stack } from '@/components'; import { Box, Stack } from '@/components';
import { import {
DefaultPdfTemplateTerms, DefaultPdfTemplateTerms,
DefaultPdfTemplateItemDescription, DefaultPdfTemplateItemDescription,
DefaultPdfTemplateStatement, DefaultPdfTemplateStatement,
DefaultPdfTemplateItemName, DefaultPdfTemplateItemName,
DefaultPdfTemplateAddressBilledTo,
DefaultPdfTemplateAddressBilledFrom,
} from '@/constants/PdfTemplates'; } from '@/constants/PdfTemplates';
interface PapaerLine { interface PapaerLine {
item?: string; item?: string;
@@ -89,8 +91,8 @@ export interface InvoicePaperTemplateProps {
lines?: Array<PapaerLine>; lines?: Array<PapaerLine>;
taxes?: Array<PaperTax>; taxes?: Array<PaperTax>;
billedFromAddres?: Array<string | React.ReactNode>; billedFromAddres?: string;
billedToAddress?: Array<string | React.ReactNode>; billedToAddress?: string;
} }
export function InvoicePaperTemplate({ export function InvoicePaperTemplate({
@@ -169,21 +171,8 @@ export function InvoicePaperTemplate({
statementLabel = 'Statement', statementLabel = 'Statement',
showStatement = true, showStatement = true,
statement = DefaultPdfTemplateStatement, statement = DefaultPdfTemplateStatement,
billedToAddress = [ billedToAddress = DefaultPdfTemplateAddressBilledTo,
'Bigcapital Technology, Inc.', billedFromAddres = DefaultPdfTemplateAddressBilledFrom,
'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',
],
}: InvoicePaperTemplateProps) { }: InvoicePaperTemplateProps) {
return ( return (
<PaperTemplate <PaperTemplate
@@ -214,14 +203,16 @@ export function InvoicePaperTemplate({
<PaperTemplate.AddressesGroup> <PaperTemplate.AddressesGroup>
{showBilledFromAddress && ( {showBilledFromAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{companyName}</strong>, ...billedFromAddres]} <strong>{companyName}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedFromAddres }} />
</PaperTemplate.Address>
)} )}
{showBillingToAddress && ( {showBillingToAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{billedToLabel}</strong>, ...billedToAddress]} <strong>{billedToLabel}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
</PaperTemplate.Address>
)} )}
</PaperTemplate.AddressesGroup> </PaperTemplate.AddressesGroup>

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import clsx from 'classnames'; import clsx from 'classnames';
import { get } from 'lodash'; import { get } from 'lodash';
import { Group, GroupProps, Stack } from '@/components'; import { Box, Group, GroupProps, Stack } from '@/components';
import styles from './InvoicePaperTemplate.module.scss'; import styles from './InvoicePaperTemplate.module.scss';
export interface PaperTemplateProps { export interface PaperTemplateProps {
@@ -123,16 +123,14 @@ PaperTemplate.AddressesGroup = (props: GroupProps) => {
return <Group spacing={10} {...props} className={styles.addressRoot} />; return <Group spacing={10} {...props} className={styles.addressRoot} />;
}; };
PaperTemplate.Address = ({ PaperTemplate.Address = ({
items, children,
}: { }: {
items: Array<string | React.ReactNode>; children: React.ReactNode;
}) => { }) => {
return ( return (
<Stack spacing={0}> <Box>
{items.map((item, index) => ( {children}
<div key={index}>{item}</div> </Box>
))}
</Stack>
); );
}; };

View File

@@ -1,15 +1,19 @@
import { Stack } from '@/components'; import { Box, Stack } from '@/components';
import { import {
PaperTemplate, PaperTemplate,
PaperTemplateProps, PaperTemplateProps,
PaperTemplateTotalBorder, PaperTemplateTotalBorder,
} from '../../Invoices/InvoiceCustomize/PaperTemplate'; } from '../../Invoices/InvoiceCustomize/PaperTemplate';
import {
DefaultPdfTemplateAddressBilledFrom,
DefaultPdfTemplateAddressBilledTo,
} from '@/constants/PdfTemplates';
export interface PaymentReceivedPaperTemplateProps extends PaperTemplateProps { export interface PaymentReceivedPaperTemplateProps extends PaperTemplateProps {
billedToAddress?: Array<string>; billedToAddress?: string;
showBillingToAddress?: boolean; showBilledToAddress?: boolean;
billedFromAddress?: Array<string>; billedFromAddress?: string;
showBilledFromAddress?: boolean; showBilledFromAddress?: boolean;
billedToLabel?: string; billedToLabel?: string;
@@ -52,23 +56,10 @@ export function PaymentReceivedPaperTemplate({
// # Company name // # Company name
companyName = 'Bigcapital Technology, Inc.', companyName = 'Bigcapital Technology, Inc.',
billedToAddress = [ billedToAddress = DefaultPdfTemplateAddressBilledTo,
'Bigcapital Technology, Inc.', billedFromAddress = DefaultPdfTemplateAddressBilledFrom,
'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, showBilledFromAddress,
showBillingToAddress, showBilledToAddress,
billedToLabel = 'Billed To', billedToLabel = 'Billed To',
total = '$1000.00', total = '$1000.00',
@@ -119,14 +110,16 @@ export function PaymentReceivedPaperTemplate({
<PaperTemplate.AddressesGroup> <PaperTemplate.AddressesGroup>
{showBilledFromAddress && ( {showBilledFromAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{companyName}</strong>, ...billedFromAddress]} <strong>{companyName}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
</PaperTemplate.Address>
)} )}
{showBillingToAddress && ( {showBilledToAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{billedToLabel}</strong>, ...billedToAddress]} <strong>{billedToLabel}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
</PaperTemplate.Address>
)} )}
</PaperTemplate.AddressesGroup> </PaperTemplate.AddressesGroup>

View File

@@ -1,4 +1,4 @@
import { Stack } from '@/components'; import { Box, Stack } from '@/components';
import { import {
PaperTemplate, PaperTemplate,
PaperTemplateProps, PaperTemplateProps,
@@ -8,12 +8,14 @@ import {
DefaultPdfTemplateItemDescription, DefaultPdfTemplateItemDescription,
DefaultPdfTemplateStatement, DefaultPdfTemplateStatement,
DefaultPdfTemplateItemName, DefaultPdfTemplateItemName,
DefaultPdfTemplateAddressBilledTo,
DefaultPdfTemplateAddressBilledFrom,
} from '@/constants/PdfTemplates'; } from '@/constants/PdfTemplates';
export interface ReceiptPaperTemplateProps extends PaperTemplateProps { export interface ReceiptPaperTemplateProps extends PaperTemplateProps {
// Addresses // Addresses
billedToAddress?: Array<string>; billedToAddress?: string;
billedFromAddress?: Array<string>; billedFromAddress?: string;
showBilledFromAddress?: boolean; showBilledFromAddress?: boolean;
showBilledToAddress?: boolean; showBilledToAddress?: boolean;
billedToLabel?: string; billedToLabel?: string;
@@ -71,21 +73,8 @@ export function ReceiptPaperTemplate({
companyName = 'Bigcapital Technology, Inc.', companyName = 'Bigcapital Technology, Inc.',
// # Address // # Address
billedToAddress = [ billedToAddress = DefaultPdfTemplateAddressBilledTo,
'Bigcapital Technology, Inc.', billedFromAddress = DefaultPdfTemplateAddressBilledFrom,
'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, showBilledFromAddress = true,
showBilledToAddress = true, showBilledToAddress = true,
billedToLabel = 'Billed To', billedToLabel = 'Billed To',
@@ -147,14 +136,16 @@ export function ReceiptPaperTemplate({
<PaperTemplate.AddressesGroup> <PaperTemplate.AddressesGroup>
{showBilledFromAddress && ( {showBilledFromAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{companyName}</strong>, ...billedFromAddress]} <strong>{companyName}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
</PaperTemplate.Address>
)} )}
{showBilledToAddress && ( {showBilledToAddress && (
<PaperTemplate.Address <PaperTemplate.Address>
items={[<strong>{billedToLabel}</strong>, ...billedToAddress]} <strong>{billedToLabel}</strong>
/> <Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
</PaperTemplate.Address>
)} )}
</PaperTemplate.AddressesGroup> </PaperTemplate.AddressesGroup>

View File

@@ -63,6 +63,14 @@ interface GetInvoicePaymentLinkAddressResponse {
phone: string; phone: string;
} }
interface GetInvoicePaymentLinkOrganizationRes {
address: Record<string, GetInvoicePaymentLinkAddressResponse>;
name: string;
primaryColor: string;
logoUri: string;
addressTextFormatted: string;
}
export interface GetInvoicePaymentLinkResponse { export interface GetInvoicePaymentLinkResponse {
dueAmount: number; dueAmount: number;
dueAmountFormatted: string; dueAmountFormatted: string;
@@ -97,16 +105,7 @@ export interface GetInvoicePaymentLinkResponse {
taxRateAmountFormatted: string; taxRateAmountFormatted: string;
taxRateCode: string; taxRateCode: string;
}>; }>;
organization: Record< organization: GetInvoicePaymentLinkOrganizationRes;
string,
{
address: Record<string, GetInvoicePaymentLinkAddressResponse>;
name: string;
primaryColor: string;
logoUri: string;
addressTextFormatted: string;
}
>;
hasStripePaymentMethod: boolean; hasStripePaymentMethod: boolean;
isReceivable: boolean; isReceivable: boolean;
} }