mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
Merge pull request #678 from bigcapitalhq/pdf-templates-company-customer-address
feat: Pdf templates customer/company addresses
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
7
packages/server/src/services/Attachments/utils.ts
Normal file
7
packages/server/src/services/Attachments/utils.ts
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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<CommonOrganizationBrandingAttributes>}
|
||||
*/
|
||||
async getOrganizationBrandingAttributes(
|
||||
tenantId: number
|
||||
): Promise<CommonOrganizationBrandingAttributes> {
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
: '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,3 +65,12 @@ export interface ICreateInvoicePdfTemplateDTO {
|
||||
statementLabel?: string;
|
||||
showStatement?: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface CommonOrganizationBrandingAttributes {
|
||||
companyName?: string;
|
||||
primaryColor?: string;
|
||||
companyLogoKey?: string;
|
||||
companyLogoUri?: string;
|
||||
companyAddress?: string;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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<string, any>,
|
||||
@@ -42,5 +43,7 @@ export const transformInvoiceToPdfTemplate = (
|
||||
label: tax.name,
|
||||
amount: tax.taxRateAmountFormatted,
|
||||
})),
|
||||
|
||||
customerAddress: contactAddressTextFormat(invoice.customer),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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<string, string>) => {
|
||||
let formattedMessage = Object.entries(replacements).reduce(
|
||||
(msg, [key, value]) => {
|
||||
return msg.split(`{${key}}`).join(value || '');
|
||||
},
|
||||
message
|
||||
);
|
||||
formattedMessage = formattedMessage.replace(/\n/g, '<br />');
|
||||
|
||||
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, '<br />');
|
||||
|
||||
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<string, string> = {
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -17,10 +17,9 @@ United States, <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
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -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 <Spinner size={20} />
|
||||
const isLoading = isPdfTemplateLoading || isBrandingTemplateLoading;
|
||||
|
||||
if (isLoading) {
|
||||
return <Spinner size={20} />;
|
||||
}
|
||||
return (
|
||||
<PdfTemplateContext.Provider value={value}>
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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({
|
||||
</PaperTemplate.TermsList>
|
||||
|
||||
<PaperTemplate.AddressesGroup>
|
||||
{showBilledFromAddress && (
|
||||
{showCompanyAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{companyName}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
{showBilledToAddress && (
|
||||
|
||||
{showCustomerAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{billedToLabel}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
</PaperTemplate.AddressesGroup>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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({
|
||||
</PaperTemplate.TermsList>
|
||||
|
||||
<PaperTemplate.AddressesGroup>
|
||||
{showBilledFromAddress && (
|
||||
{showCompanyAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{companyName}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
{showBilledToAddress && (
|
||||
{showCustomerAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{billedToLabel}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
</PaperTemplate.AddressesGroup>
|
||||
|
||||
@@ -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',
|
||||
};
|
||||
|
||||
@@ -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<PapaerLine>;
|
||||
taxes?: Array<PaperTax>;
|
||||
|
||||
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 (
|
||||
<PaperTemplate
|
||||
@@ -202,16 +205,16 @@ export function InvoicePaperTemplate({
|
||||
</PaperTemplate.TermsList>
|
||||
|
||||
<PaperTemplate.AddressesGroup>
|
||||
{showBilledFromAddress && (
|
||||
{showCompanyAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{companyName}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedFromAddres }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
{showBillingToAddress && (
|
||||
|
||||
{showCustomerAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{billedToLabel}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
</PaperTemplate.AddressesGroup>
|
||||
|
||||
@@ -120,19 +120,18 @@ PaperTemplate.MutedText = () => {};
|
||||
PaperTemplate.Text = () => {};
|
||||
|
||||
PaperTemplate.AddressesGroup = (props: GroupProps) => {
|
||||
return <Group spacing={10} {...props} className={styles.addressRoot} />;
|
||||
};
|
||||
PaperTemplate.Address = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<Box>
|
||||
{children}
|
||||
</Box>
|
||||
<Group
|
||||
spacing={10}
|
||||
align={'flex-start'}
|
||||
{...props}
|
||||
className={styles.addressRoot}
|
||||
/>
|
||||
);
|
||||
};
|
||||
PaperTemplate.Address = ({ children }: { children: React.ReactNode }) => {
|
||||
return <Box>{children}</Box>;
|
||||
};
|
||||
|
||||
PaperTemplate.Statement = ({
|
||||
label,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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({
|
||||
</PaperTemplate.TermsList>
|
||||
|
||||
<PaperTemplate.AddressesGroup>
|
||||
{showBilledFromAddress && (
|
||||
{showCompanyAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{companyName}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
{showBilledToAddress && (
|
||||
|
||||
{showCustomerAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{billedToLabel}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
</PaperTemplate.AddressesGroup>
|
||||
|
||||
@@ -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',
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
</PaperTemplate.TermsList>
|
||||
|
||||
<PaperTemplate.AddressesGroup>
|
||||
{showBilledFromAddress && (
|
||||
{showCompanyAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{companyName}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedFromAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
{showBilledToAddress && (
|
||||
|
||||
{showCustomerAddress && (
|
||||
<PaperTemplate.Address>
|
||||
<strong>{billedToLabel}</strong>
|
||||
<Box dangerouslySetInnerHTML={{ __html: billedToAddress }} />
|
||||
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
|
||||
</PaperTemplate.Address>
|
||||
)}
|
||||
</PaperTemplate.AddressesGroup>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<GetPdfTemplateBrandingStateResponse, Error>,
|
||||
): UseQueryResult<GetPdfTemplateBrandingStateResponse, Error> => {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useQuery<GetPdfTemplateBrandingStateResponse, Error>(
|
||||
[PdfTemplatesQueryKey, 'state'],
|
||||
() =>
|
||||
apiRequest
|
||||
.get('/pdf-templates/state')
|
||||
.then((res) => transformToCamelCase(res.data?.data)),
|
||||
options,
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user