mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat: enhance discount handling in financial forms
- Implemented discount and adjustment fields in Bill, Credit Note, Estimate, Invoice, and Receipt forms. - Created new components for displaying discount and adjustment totals, improving clarity in financial documents. - Updated utility functions to format discount and adjustment amounts consistently across various forms. - Enhanced user experience by integrating discount functionality into the form context, allowing for better data management and display. This update improves the overall functionality and user experience related to discounts in financial transactions.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// @ts-nocheck
|
||||
import { css } from '@emotion/css';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import clsx from 'classnames';
|
||||
import {
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
TotalLinePrimitive,
|
||||
} from '@/components';
|
||||
|
||||
const inputGroupCss = css`
|
||||
& .bp4-input {
|
||||
max-width: 110px;
|
||||
color: rgb(17, 17, 17);
|
||||
padding-left: 8px;
|
||||
}
|
||||
`;
|
||||
const formGroupCss = css`
|
||||
margin-bottom: 0;
|
||||
`;
|
||||
|
||||
interface AdjustmentTotalLineProps {
|
||||
adjustmentAmount: number;
|
||||
}
|
||||
|
||||
export function AdjustmentTotalLine({
|
||||
adjustmentAmount,
|
||||
}: AdjustmentTotalLineProps) {
|
||||
return (
|
||||
<TotalLinePrimitive>
|
||||
<x.div
|
||||
display={'table-cell'}
|
||||
padding={'8px'}
|
||||
borderBottom={'1px solid rgb(210, 221, 226)'}
|
||||
>
|
||||
<x.div
|
||||
display={'flex'}
|
||||
alignItems={'center'}
|
||||
justifyContent={'space-between'}
|
||||
>
|
||||
<x.span>Adjustment</x.span>
|
||||
<FFormGroup
|
||||
name={'adjustment'}
|
||||
label={''}
|
||||
inline
|
||||
fastField
|
||||
className={formGroupCss}
|
||||
>
|
||||
<FInputGroup
|
||||
name={'adjustment'}
|
||||
fastField
|
||||
className={clsx(
|
||||
inputGroupCss,
|
||||
css`
|
||||
& .bp4-input {
|
||||
border-style: dashed;
|
||||
}
|
||||
`,
|
||||
)}
|
||||
/>
|
||||
</FFormGroup>
|
||||
</x.div>
|
||||
</x.div>
|
||||
|
||||
<x.div
|
||||
display={'table-cell'}
|
||||
borderBottom={'1px solid rgb(210, 221, 226)'}
|
||||
textAlign={'right'}
|
||||
padding={'8px'}
|
||||
>
|
||||
{adjustmentAmount}
|
||||
</x.div>
|
||||
</TotalLinePrimitive>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// @ts-nocheck
|
||||
import { css } from '@emotion/css';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import {
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
FSelect,
|
||||
TotalLinePrimitive,
|
||||
} from '@/components';
|
||||
import { Button } from '@blueprintjs/core';
|
||||
|
||||
const inputGroupCss = css`
|
||||
& .bp4-input {
|
||||
max-width: 110px;
|
||||
color: rgb(17, 17, 17);
|
||||
padding-left: 8px;
|
||||
}
|
||||
`;
|
||||
const formGroupCss = css`
|
||||
margin-bottom: 0;
|
||||
`;
|
||||
|
||||
interface DiscountTotalLineProps {
|
||||
currencyCode: string;
|
||||
discountAmount: number;
|
||||
}
|
||||
|
||||
export function DiscountTotalLine({
|
||||
currencyCode,
|
||||
discountAmount,
|
||||
}: DiscountTotalLineProps) {
|
||||
const discountButtonInput = ({ text }) => (
|
||||
<Button
|
||||
small
|
||||
minimal
|
||||
className={css`
|
||||
&.bp4-small {
|
||||
font-size: 12px;
|
||||
}
|
||||
`}
|
||||
>
|
||||
{text}
|
||||
</Button>
|
||||
);
|
||||
|
||||
const discountTypeItems = [
|
||||
{ text: currencyCode, value: 'amount', label: 'Fixed Amount' },
|
||||
{ text: '%', value: 'percentage', label: 'Percentage' },
|
||||
];
|
||||
|
||||
return (
|
||||
<TotalLinePrimitive>
|
||||
<TotalLinePrimitive.Title borderBottom={'1px solid rgb(210, 221, 226)'}>
|
||||
<x.div
|
||||
display={'flex'}
|
||||
alignItems={'center'}
|
||||
justifyContent={'space-between'}
|
||||
>
|
||||
<x.span pr={2}>Discount</x.span>
|
||||
<FFormGroup
|
||||
name={'discount'}
|
||||
className={formGroupCss}
|
||||
inline
|
||||
fastField
|
||||
>
|
||||
<FInputGroup
|
||||
name={'discount'}
|
||||
rightElement={
|
||||
<FSelect
|
||||
name={'discount_type'}
|
||||
items={discountTypeItems}
|
||||
input={discountButtonInput}
|
||||
filterable={false}
|
||||
/>
|
||||
}
|
||||
fastField
|
||||
className={inputGroupCss}
|
||||
/>
|
||||
</FFormGroup>
|
||||
</x.div>
|
||||
</TotalLinePrimitive.Title>
|
||||
|
||||
<TotalLinePrimitive.Amount
|
||||
textAlign={'right'}
|
||||
borderBottom={'1px solid rgb(210, 221, 226)'}
|
||||
>
|
||||
{discountAmount}
|
||||
</TotalLinePrimitive.Amount>
|
||||
</TotalLinePrimitive>
|
||||
);
|
||||
}
|
||||
@@ -2,18 +2,18 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useFormikContext } from 'formik';
|
||||
|
||||
import {
|
||||
T,
|
||||
TotalLines,
|
||||
TotalLine,
|
||||
TotalLineBorderStyle,
|
||||
TotalLineTextStyle,
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
FSelect,
|
||||
} from '@/components';
|
||||
import { useInvoiceAggregatedTaxRates } from './utils';
|
||||
import {
|
||||
useInvoiceAdjustmentAmountFormatted,
|
||||
useInvoiceAggregatedTaxRates,
|
||||
useInvoiceDiscountAmountFormatted,
|
||||
} from './utils';
|
||||
import { TaxType } from '@/interfaces/TaxRates';
|
||||
import {
|
||||
InvoiceDueAmountFormatted,
|
||||
@@ -21,7 +21,8 @@ import {
|
||||
InvoiceSubTotalFormatted,
|
||||
InvoiceTotalFormatted,
|
||||
} from './components';
|
||||
import { Button } from '@blueprintjs/core';
|
||||
import { AdjustmentTotalLine } from './AdjustmentTotalLine';
|
||||
import { DiscountTotalLine } from './DiscountTotalLine';
|
||||
|
||||
export function InvoiceFormFooterRight() {
|
||||
const {
|
||||
@@ -29,6 +30,8 @@ export function InvoiceFormFooterRight() {
|
||||
} = useFormikContext();
|
||||
|
||||
const taxEntries = useInvoiceAggregatedTaxRates();
|
||||
const adjustmentAmount = useInvoiceAdjustmentAmountFormatted();
|
||||
const discountAmount = useInvoiceDiscountAmountFormatted();
|
||||
|
||||
return (
|
||||
<InvoiceTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||
@@ -42,30 +45,11 @@ export function InvoiceFormFooterRight() {
|
||||
}
|
||||
value={<InvoiceSubTotalFormatted />}
|
||||
/>
|
||||
<FFormGroup name={'discount'} label={'Discount'} inline>
|
||||
<FInputGroup
|
||||
name={'discount'}
|
||||
rightElement={
|
||||
<FSelect
|
||||
name={'discount_type'}
|
||||
items={[
|
||||
{ text: 'USD', value: 'amount' },
|
||||
{ text: '%', value: 'percentage' },
|
||||
]}
|
||||
input={({ text }) => (
|
||||
<Button small minimal>
|
||||
{text}
|
||||
</Button>
|
||||
)}
|
||||
filterable={false}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</FFormGroup>
|
||||
|
||||
<FFormGroup name={'adjustment'} label={'Adjustment'} inline>
|
||||
<FInputGroup name={'adjustment'} />
|
||||
</FFormGroup>
|
||||
<DiscountTotalLine
|
||||
currencyCode={currency_code}
|
||||
discountAmount={discountAmount}
|
||||
/>
|
||||
<AdjustmentTotalLine adjustmentAmount={adjustmentAmount} />
|
||||
|
||||
{taxEntries.map((tax, index) => (
|
||||
<TotalLine
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
transformToForm,
|
||||
repeatValue,
|
||||
defaultFastFieldShouldUpdate,
|
||||
formattedAmount,
|
||||
} from '@/utils';
|
||||
import { ERROR } from '@/constants/errors';
|
||||
import { AppToaster } from '@/components';
|
||||
@@ -318,6 +319,43 @@ export const useInvoiceDiscountAmount = () => {
|
||||
: discount;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice discount amount formatted.
|
||||
* @returns {string}
|
||||
*/
|
||||
export const useInvoiceDiscountAmountFormatted = () => {
|
||||
const discountAmount = useInvoiceDiscountAmount();
|
||||
const {
|
||||
values: { currency_code },
|
||||
} = useFormikContext();
|
||||
|
||||
return formattedAmount(discountAmount, currency_code);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice adjustment amount.
|
||||
* @returns {number}
|
||||
*/
|
||||
export const useInvoiceAdjustmentAmount = () => {
|
||||
const { values } = useFormikContext();
|
||||
const adjustment = parseFloat(values.adjustment);
|
||||
|
||||
return adjustment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice adjustment amount formatted.
|
||||
* @returns {string}
|
||||
*/
|
||||
export const useInvoiceAdjustmentAmountFormatted = () => {
|
||||
const adjustmentAmount = useInvoiceAdjustmentAmount();
|
||||
const {
|
||||
values: { currency_code },
|
||||
} = useFormikContext();
|
||||
|
||||
return formattedAmount(adjustmentAmount, currency_code);
|
||||
};
|
||||
|
||||
/**
|
||||
* Detarmines whether the invoice has foreign customer.
|
||||
* @returns {boolean}
|
||||
|
||||
Reference in New Issue
Block a user