feat: link discount to mail receipts

This commit is contained in:
Ahmed Bouhuolia
2024-12-02 18:45:16 +02:00
parent 05cf94940e
commit 5b75fa9286
14 changed files with 294 additions and 18 deletions

View File

@@ -20,6 +20,16 @@ export class GetSaleEstimateMailStateTransformer extends SaleEstimateTransfromer
'subtotal', 'subtotal',
'subtotalFormatted', 'subtotalFormatted',
'discountAmount',
'discountAmountFormatted',
'discountPercentage',
'discountPercentageFormatted',
'discountLabel',
'adjustment',
'adjustmentFormatted',
'adjustmentLabel',
'estimateNumber', 'estimateNumber',
'entries', 'entries',
@@ -97,6 +107,17 @@ export class GetSaleEstimateMailStateTransformer extends SaleEstimateTransfromer
return estimate.amount; return estimate.amount;
} }
/**
* Retrieves the discount label of the estimate.
* @param estimate
* @returns {string}
*/
protected discountLabel(estimate) {
return estimate.discountType === 'percentage'
? `Discount [${estimate.discountPercentageFormatted}]`
: 'Discount';
}
/** /**
* Retrieves the formatted total of the estimate. * Retrieves the formatted total of the estimate.
* @param estimate * @param estimate

View File

@@ -28,6 +28,15 @@ export class GetSaleInvoiceMailStateTransformer extends SaleInvoiceTransformer {
'total', 'total',
'totalFormatted', 'totalFormatted',
'discountAmount',
'discountAmountFormatted',
'discountPercentage',
'discountPercentageFormatted',
'discountLabel',
'adjustment',
'adjustmentFormatted',
'subtotal', 'subtotal',
'subtotalFormatted', 'subtotalFormatted',
@@ -76,6 +85,17 @@ export class GetSaleInvoiceMailStateTransformer extends SaleInvoiceTransformer {
return invoice.pdfTemplate?.attributes?.primaryColor; return invoice.pdfTemplate?.attributes?.primaryColor;
}; };
/**
* Retrieves the discount label of the estimate.
* @param estimate
* @returns {string}
*/
protected discountLabel(invoice) {
return invoice.discountType === 'percentage'
? `Discount [${invoice.discountPercentageFormatted}]`
: 'Discount';
}
/** /**
* *
* @param invoice * @param invoice

View File

@@ -1,7 +1,9 @@
import { Transformer } from '@/lib/Transformer/Transformer'; import { Transformer } from '@/lib/Transformer/Transformer';
import { ItemEntryTransformer } from '../Invoices/ItemEntryTransformer'; import { ItemEntryTransformer } from '../Invoices/ItemEntryTransformer';
import { DiscountType } from '@/interfaces';
import { SaleReceiptTransformer } from './SaleReceiptTransformer';
export class GetSaleReceiptMailStateTransformer extends Transformer { export class GetSaleReceiptMailStateTransformer extends SaleReceiptTransformer {
/** /**
* Exclude these attributes from user object. * Exclude these attributes from user object.
* @returns {Array} * @returns {Array}
@@ -20,14 +22,28 @@ export class GetSaleReceiptMailStateTransformer extends Transformer {
'companyLogoUri', 'companyLogoUri',
'primaryColor', 'primaryColor',
'customerName', 'customerName',
'total', 'total',
'totalFormatted', 'totalFormatted',
'discountAmount',
'discountAmountFormatted',
'discountPercentage',
'discountPercentageFormatted',
'discountLabel',
'adjustment',
'adjustmentFormatted',
'subtotal', 'subtotal',
'subtotalFormatted', 'subtotalFormatted',
'receiptDate', 'receiptDate',
'receiptDateFormatted', 'receiptDateFormatted',
'closedAtDate', 'closedAtDate',
'closedAtDateFormatted', 'closedAtDateFormatted',
'receiptNumber', 'receiptNumber',
'entries', 'entries',
]; ];
@@ -86,7 +102,18 @@ export class GetSaleReceiptMailStateTransformer extends Transformer {
}; };
/** /**
* * Retrieves the discount label of the estimate.
* @param estimate
* @returns {string}
*/
protected discountLabel(receipt) {
return receipt.discountType === DiscountType.Percentage
? `Discount [${receipt.discountPercentageFormatted}]`
: 'Discount';
}
/**
* Retrieves the subtotal of the receipt.
* @param receipt * @param receipt
* @returns * @returns
*/ */
@@ -95,7 +122,7 @@ export class GetSaleReceiptMailStateTransformer extends Transformer {
}; };
/** /**
* * Retrieves the formatted subtotal of the receipt.
* @param receipt * @param receipt
* @returns * @returns
*/ */
@@ -106,7 +133,7 @@ export class GetSaleReceiptMailStateTransformer extends Transformer {
}; };
/** /**
* * Retrieves the receipt date.
* @param receipt * @param receipt
* @returns * @returns
*/ */
@@ -115,7 +142,7 @@ export class GetSaleReceiptMailStateTransformer extends Transformer {
}; };
/** /**
* * Retrieves the formatted receipt date.
* @param {ISaleReceipt} invoice * @param {ISaleReceipt} invoice
* @returns {string} * @returns {string}
*/ */

View File

@@ -1,4 +1,5 @@
import { x } from '@xstyled/emotion'; import { x } from '@xstyled/emotion';
import { isEmpty } from 'lodash';
import { Group, Stack } from '@/components'; import { Group, Stack } from '@/components';
import { import {
SendMailReceipt, SendMailReceipt,
@@ -14,6 +15,14 @@ export interface EstimateSendMailReceiptProps extends SendMailReceiptProps {
estimateNumberLabel?: string; estimateNumberLabel?: string;
estimateNumber: string; estimateNumber: string;
// # Discount
discount?: string;
discountLabel?: string;
// # Adjustment
adjustment?: string;
adjsutmentLabel?: string;
// # Total. // # Total.
total: string; total: string;
totalLabel?: string; totalLabel?: string;
@@ -47,10 +56,6 @@ export function EstimateSendMailReceipt({
estimateNumberLabel = 'Estimate #', estimateNumberLabel = 'Estimate #',
estimateNumber, estimateNumber,
// # Total.
total,
totalLabel = 'Total',
// # Expiration date. // # Expiration date.
expirationDateLabel = 'Expiration Date', expirationDateLabel = 'Expiration Date',
expirationDate, expirationDate,
@@ -65,6 +70,18 @@ export function EstimateSendMailReceipt({
subtotal, subtotal,
subtotalLabel = 'Subtotal', subtotalLabel = 'Subtotal',
// # Discount
discount,
discountLabel = 'Discount',
// # Adjustment
adjustment,
adjsutmentLabel = 'Adjustment',
// # Total.
total,
totalLabel = 'Total',
// # View estimate button // # View estimate button
showViewEstimateButton = true, showViewEstimateButton = true,
viewEstimateButtonLabel = 'View Estimate', viewEstimateButtonLabel = 'View Estimate',
@@ -142,6 +159,36 @@ export function EstimateSendMailReceipt({
</x.span> </x.span>
</Group> </Group>
{!isEmpty(discount) && (
<Group
h={'40px'}
position={'apart'}
borderBottomStyle="solid"
borderBottomWidth={'1px'}
borderBottomColor={'#D9D9D9'}
>
<x.span fontWeight={500}>{discountLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{discount}
</x.span>
</Group>
)}
{!isEmpty(adjustment) && (
<Group
h={'40px'}
position={'apart'}
borderBottomStyle="solid"
borderBottomWidth={'1px'}
borderBottomColor={'#D9D9D9'}
>
<x.span fontWeight={500}>{adjsutmentLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{adjustment}
</x.span>
</Group>
)}
<Group <Group
h={'40px'} h={'40px'}
position={'apart'} position={'apart'}

View File

@@ -35,6 +35,9 @@ export const withEstimateMailReceiptPreviewProps = <
expirationDate: estimateMailState?.expirationDateFormatted, expirationDate: estimateMailState?.expirationDateFormatted,
estimateNumber: estimateMailState?.estimateNumber, estimateNumber: estimateMailState?.estimateNumber,
estimateDate: estimateMailState?.estimateDateFormatted, estimateDate: estimateMailState?.estimateDateFormatted,
subtotal: estimateMailState?.subtotalFormatted,
discount: estimateMailState?.discountFormatted,
adjustment: estimateMailState?.adjustmentFormatted,
items, items,
message, message,
}; };

View File

@@ -3,6 +3,7 @@ import { css } from '@emotion/css';
import { x } from '@xstyled/emotion'; import { x } from '@xstyled/emotion';
import { lighten } from 'polished'; import { lighten } from 'polished';
import { Group, Stack, StackProps } from '@/components'; import { Group, Stack, StackProps } from '@/components';
import { isEmpty } from 'lodash';
export interface InvoiceMailReceiptProps extends StackProps { export interface InvoiceMailReceiptProps extends StackProps {
// # Company // # Company
@@ -16,6 +17,18 @@ export interface InvoiceMailReceiptProps extends StackProps {
dueDate: string; dueDate: string;
dueDateLabel?: string; dueDateLabel?: string;
// # Subtotal
subtotal: string;
subtotalLabel?: string;
// # Discount amount
discount?: string;
discountLabel?: string;
// # Adjustment
adjustment?: string;
adjustmentLabel?: string;
// # Due amount // # Due amount
dueAmountLabel?: string; dueAmountLabel?: string;
dueAmount: string; dueAmount: string;
@@ -52,14 +65,26 @@ export function InvoiceMailReceipt({
dueDate, dueDate,
dueDateLabel = 'Due', dueDateLabel = 'Due',
// # Due amount // # Subtotal
dueAmountLabel = 'Due Amount', subtotal,
dueAmount, subtotalLabel = 'Subtotal',
// # Discount amount
discount,
discountLabel = 'Discount',
// # Adjustment
adjustment,
adjustmentLabel = 'Adjustment',
// # Total // # Total
total, total,
totalLabel = 'Total', totalLabel = 'Total',
// # Due amount
dueAmountLabel = 'Due Amount',
dueAmount,
// # Invoice number // # Invoice number
invoiceNumber, invoiceNumber,
invoiceNumberLabel = 'Invoice #', invoiceNumberLabel = 'Invoice #',
@@ -166,6 +191,53 @@ export function InvoiceMailReceipt({
</Group> </Group>
))} ))}
{/*---- Subtotal ----*/}
<Group
h={'40px'}
position={'apart'}
borderBottomStyle="solid"
borderBottomWidth={'1px'}
borderColor={'#000'}
>
<x.span fontWeight={500}>{subtotalLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{subtotal}
</x.span>
</Group>
{/*---- Discount ----*/}
{!isEmpty(discount) && (
<Group
h="40px"
position="apart"
borderBottomStyle="solid"
borderBottomWidth="1px"
borderColor="#000"
>
<x.span fontWeight={500}>{discountLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{discount}
</x.span>
</Group>
)}
{/*---- Adjustment ----*/}
{!isEmpty(adjustment) && (
<Group
h="40px"
position="apart"
borderBottomStyle="solid"
borderBottomWidth="1px"
borderColor="#000"
>
<x.span fontWeight={500}>{adjustmentLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{adjustment}
</x.span>
</Group>
)}
{/*---- Total ----*/}
<Group <Group
h={'40px'} h={'40px'}
position={'apart'} position={'apart'}
@@ -179,6 +251,7 @@ export function InvoiceMailReceipt({
</x.span> </x.span>
</Group> </Group>
{/*---- Due amount ----*/}
<Group <Group
h={'40px'} h={'40px'}
position={'apart'} position={'apart'}

View File

@@ -29,6 +29,7 @@ export function InvoiceMailReceiptPreview(
total: '$1,000.00', total: '$1,000.00',
invoiceNumber: 'INV-0001', invoiceNumber: 'INV-0001',
dueDate: '2 Oct 2024', dueDate: '2 Oct 2024',
subtotal: '$1,000.00',
dueAmount: '$1,000.00', dueAmount: '$1,000.00',
items: [{ label: 'Web development', total: '$1000.00', quantity: 1 }], items: [{ label: 'Web development', total: '$1000.00', quantity: 1 }],
companyLogoUri: ' ', companyLogoUri: ' ',

View File

@@ -56,9 +56,12 @@ const withInvoiceMailReceiptPreviewProps = <
companyLogoUri: invoiceMailState?.companyLogoUri, companyLogoUri: invoiceMailState?.companyLogoUri,
primaryColor: invoiceMailState?.primaryColor, primaryColor: invoiceMailState?.primaryColor,
total: invoiceMailState?.totalFormatted, total: invoiceMailState?.totalFormatted,
subtotal: invoiceMailState?.subtotalFormatted,
dueDate: invoiceMailState?.dueDateFormatted, dueDate: invoiceMailState?.dueDateFormatted,
dueAmount: invoiceMailState?.dueAmountFormatted, dueAmount: invoiceMailState?.dueAmountFormatted,
invoiceNumber: invoiceMailState?.invoiceNo, invoiceNumber: invoiceMailState?.invoiceNo,
discount: invoiceMailState?.discountAmountFormatted,
adjustment: invoiceMailState?.adjustmentFormatted,
items, items,
message, message,
}; };

View File

@@ -2,7 +2,10 @@
import React, { createContext, useContext } from 'react'; import React, { createContext, useContext } from 'react';
import { Spinner } from '@blueprintjs/core'; import { Spinner } from '@blueprintjs/core';
import { useDrawerContext } from '@/components/Drawer/DrawerProvider'; import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
import { GetSaleReceiptMailStateResponse, useSaleInvoiceMailState, useSaleReceiptMailState } from '@/hooks/query'; import {
GetSaleReceiptMailStateResponse,
useSaleReceiptMailState,
} from '@/hooks/query';
interface ReceiptSendMailBootValues { interface ReceiptSendMailBootValues {
receiptId: number; receiptId: number;

View File

@@ -4,6 +4,7 @@ import {
SendMailReceipt, SendMailReceipt,
SendMailReceiptProps, SendMailReceiptProps,
} from '../../Estimates/SendMailViewDrawer/SendMailViewReceiptPreview'; } from '../../Estimates/SendMailViewDrawer/SendMailViewReceiptPreview';
import { isEmpty } from 'lodash';
export interface ReceiptSendMailReceiptProps extends SendMailReceiptProps { export interface ReceiptSendMailReceiptProps extends SendMailReceiptProps {
// # Company name. // # Company name.
@@ -14,10 +15,6 @@ export interface ReceiptSendMailReceiptProps extends SendMailReceiptProps {
receiptNumberLabel?: string; receiptNumberLabel?: string;
receiptNumber: string; receiptNumber: string;
// # Total.
total: string;
totalLabel?: string;
// # Message // # Message
message: string; message: string;
@@ -27,6 +24,18 @@ export interface ReceiptSendMailReceiptProps extends SendMailReceiptProps {
// # Subtotal // # Subtotal
subtotal: string; subtotal: string;
subtotalLabel?: string; subtotalLabel?: string;
// # Discount
discount?: string;
discountLabel?: string;
// # Adjustment
adjustment?: string;
adjustmentLabel?: string;
// # Total.
total: string;
totalLabel?: string;
} }
export function ReceiptSendMailReceipt({ export function ReceiptSendMailReceipt({
@@ -42,6 +51,14 @@ export function ReceiptSendMailReceipt({
total, total,
totalLabel = 'Total', totalLabel = 'Total',
// # Discount
discount,
discountLabel = 'Discount',
// # Adjustment
adjustment,
adjustmentLabel = 'Adjustment',
// # Message // # Message
message, message,
@@ -49,7 +66,6 @@ export function ReceiptSendMailReceipt({
items, items,
subtotal, subtotal,
subtotalLabel = 'Subtotal', subtotalLabel = 'Subtotal',
...rest ...rest
}: ReceiptSendMailReceiptProps) { }: ReceiptSendMailReceiptProps) {
return ( return (
@@ -109,6 +125,36 @@ export function ReceiptSendMailReceipt({
</x.span> </x.span>
</Group> </Group>
{!isEmpty(discount) && (
<Group
h={'40px'}
position={'apart'}
borderBottomStyle="solid"
borderBottomWidth={'1px'}
borderBottomColor={'#D9D9D9'}
>
<x.span fontWeight={500}>{discountLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{discount}
</x.span>
</Group>
)}
{!isEmpty(adjustment) && (
<Group
h={'40px'}
position={'apart'}
borderBottomStyle="solid"
borderBottomWidth={'1px'}
borderBottomColor={'#D9D9D9'}
>
<x.span fontWeight={500}>{adjustmentLabel}</x.span>
<x.span fontWeight={600} fontSize={15}>
{adjustment}
</x.span>
</Group>
)}
<Group <Group
h={'40px'} h={'40px'}
position={'apart'} position={'apart'}

View File

@@ -37,6 +37,8 @@ export const withReceiptMailReceiptPreviewProps = <
total: receiptMailState?.totalFormatted, total: receiptMailState?.totalFormatted,
subtotal: receiptMailState?.subtotalFormatted, subtotal: receiptMailState?.subtotalFormatted,
receiptNumber: receiptMailState?.receiptNumber, receiptNumber: receiptMailState?.receiptNumber,
discount: receiptMailState?.discountAmountFormatted,
adjustment: receiptMailState?.adjustmentFormatted,
items, items,
message, message,
}; };

View File

@@ -284,6 +284,15 @@ export interface SaleEstimateMailStateResponse {
subtotal: number; subtotal: number;
subtotalFormatted: string; subtotalFormatted: string;
discount: number;
discountFormatted: string;
discountLabel: string;
discountPercentage: number | null;
discountPercentageFormatted: string;
adjustment: number;
adjustmentFormatted: string;
estimateNumber: string; estimateNumber: string;
formatArgs: { formatArgs: {

View File

@@ -434,6 +434,15 @@ export interface GetSaleInvoiceDefaultOptionsResponse {
subtotal: number; subtotal: number;
subtotalFormatted: string; subtotalFormatted: string;
discountAmount: number;
discountAmountFormatted: string;
discountLabel: string;
discountPercentage: number;
discountPercentageFormatted: string;
adjustment: number;
adjustmentFormatted: string;
total: number; total: number;
totalFormatted: string; totalFormatted: string;

View File

@@ -263,6 +263,18 @@ export interface GetSaleReceiptMailStateResponse {
to: string[]; to: string[];
toOptions: Array<{ mail: string; label: string; primary: boolean; }>; toOptions: Array<{ mail: string; label: string; primary: boolean; }>;
// # Discount
discountAmount: number;
discountAmountFormatted: string;
discountLabel: string;
discountPercentage: number | null;
discountPercentageFormatted: string;
// # Adjustment
adjustment: number,
adjustmentFormatted: string,
// # Total
total: number; total: number;
totalFormatted: string; totalFormatted: string;