mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
fix: wrong invoice due amount
This commit is contained in:
@@ -10,18 +10,16 @@ import {
|
|||||||
TotalLineBorderStyle,
|
TotalLineBorderStyle,
|
||||||
TotalLineTextStyle,
|
TotalLineTextStyle,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useInvoiceAggregatedTaxRates, useInvoiceTotals } from './utils';
|
import { useInvoiceAggregatedTaxRates } from './utils';
|
||||||
import { TaxType } from '@/interfaces/TaxRates';
|
import { TaxType } from '@/interfaces/TaxRates';
|
||||||
|
import {
|
||||||
|
InvoiceDueAmountFormatted,
|
||||||
|
InvoicePaidAmountFormatted,
|
||||||
|
InvoiceSubTotalFormatted,
|
||||||
|
InvoiceTotalFormatted,
|
||||||
|
} from './components';
|
||||||
|
|
||||||
export function InvoiceFormFooterRight() {
|
export function InvoiceFormFooterRight() {
|
||||||
// Calculate the total due amount of invoice entries.
|
|
||||||
const {
|
|
||||||
formattedSubtotal,
|
|
||||||
formattedTotal,
|
|
||||||
formattedDueTotal,
|
|
||||||
formattedPaymentTotal,
|
|
||||||
} = useInvoiceTotals();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
values: { inclusive_exclusive_tax, currency_code },
|
values: { inclusive_exclusive_tax, currency_code },
|
||||||
} = useFormikContext();
|
} = useFormikContext();
|
||||||
@@ -38,7 +36,7 @@ export function InvoiceFormFooterRight() {
|
|||||||
: 'Subtotal'}
|
: 'Subtotal'}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
value={formattedSubtotal}
|
value={<InvoiceSubTotalFormatted />}
|
||||||
/>
|
/>
|
||||||
{taxEntries.map((tax, index) => (
|
{taxEntries.map((tax, index) => (
|
||||||
<TotalLine
|
<TotalLine
|
||||||
@@ -50,18 +48,18 @@ export function InvoiceFormFooterRight() {
|
|||||||
))}
|
))}
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={`Total (${currency_code})`}
|
title={`Total (${currency_code})`}
|
||||||
value={formattedTotal}
|
value={<InvoiceTotalFormatted />}
|
||||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'invoice_form.label.payment_amount'} />}
|
title={<T id={'invoice_form.label.payment_amount'} />}
|
||||||
value={formattedPaymentTotal}
|
value={<InvoicePaidAmountFormatted />}
|
||||||
borderStyle={TotalLineBorderStyle.None}
|
borderStyle={TotalLineBorderStyle.None}
|
||||||
/>
|
/>
|
||||||
<TotalLine
|
<TotalLine
|
||||||
title={<T id={'invoice_form.label.due_amount'} />}
|
title={<T id={'invoice_form.label.due_amount'} />}
|
||||||
value={formattedDueTotal}
|
value={<InvoiceDueAmountFormatted />}
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
/>
|
/>
|
||||||
</InvoiceTotalLines>
|
</InvoiceTotalLines>
|
||||||
|
|||||||
@@ -4,14 +4,21 @@ import intl from 'react-intl-universal';
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { Button } from '@blueprintjs/core';
|
import { Button } from '@blueprintjs/core';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import { ExchangeRateInputGroup } from '@/components';
|
import { ExchangeRateInputGroup, FormatNumber } from '@/components';
|
||||||
import { useCurrentOrganization } from '@/hooks/state';
|
import { useCurrentOrganization } from '@/hooks/state';
|
||||||
import { useInvoiceIsForeignCustomer, useInvoiceTotal } from './utils';
|
import {
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
useInvoiceCurrencyCode,
|
||||||
|
useInvoiceDueAmount,
|
||||||
|
useInvoiceIsForeignCustomer,
|
||||||
|
useInvoicePaidAmount,
|
||||||
|
useInvoiceSubtotal,
|
||||||
|
useInvoiceTotal,
|
||||||
|
} from './utils';
|
||||||
import { useUpdateEffect } from '@/hooks';
|
import { useUpdateEffect } from '@/hooks';
|
||||||
import { transactionNumber } from '@/utils';
|
import { transactionNumber } from '@/utils';
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
|
||||||
import { DialogsName } from '@/constants/dialogs';
|
import { DialogsName } from '@/constants/dialogs';
|
||||||
|
import withSettings from '@/containers/Settings/withSettings';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
import {
|
import {
|
||||||
useSyncExRateToForm,
|
useSyncExRateToForm,
|
||||||
withExchangeRateFetchingLoading,
|
withExchangeRateFetchingLoading,
|
||||||
@@ -109,3 +116,47 @@ export const InvoiceExchangeRateSync = R.compose(withDialogActions)(
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Renders the invoice formatted total.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
export const InvoiceTotalFormatted = () => {
|
||||||
|
const currencyCode = useInvoiceCurrencyCode();
|
||||||
|
const total = useInvoiceTotal();
|
||||||
|
|
||||||
|
return <FormatNumber value={total} currency={currencyCode} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the invoice formatted subtotal.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
export const InvoiceSubTotalFormatted = () => {
|
||||||
|
const currencyCode = useInvoiceCurrencyCode();
|
||||||
|
const subTotal = useInvoiceSubtotal();
|
||||||
|
|
||||||
|
return <FormatNumber value={subTotal} currency={currencyCode} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the invoice formatted due amount.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
export const InvoiceDueAmountFormatted = () => {
|
||||||
|
const currencyCode = useInvoiceCurrencyCode();
|
||||||
|
const dueAmount = useInvoiceDueAmount();
|
||||||
|
|
||||||
|
return <FormatNumber value={dueAmount} currency={currencyCode} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the invoice formatted paid amount.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
export const InvoicePaidAmountFormatted = () => {
|
||||||
|
const currencyCode = useInvoiceCurrencyCode();
|
||||||
|
const paidAmount = useInvoicePaidAmount();
|
||||||
|
|
||||||
|
return <FormatNumber value={paidAmount} currency={currencyCode} />;
|
||||||
|
};
|
||||||
|
|||||||
@@ -269,59 +269,6 @@ export const useInvoiceSubtotal = () => {
|
|||||||
return React.useMemo(() => getEntriesTotal(entries), [entries]);
|
return React.useMemo(() => getEntriesTotal(entries), [entries]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Retreives the invoice totals.
|
|
||||||
*/
|
|
||||||
export const useInvoiceTotals = () => {
|
|
||||||
const {
|
|
||||||
values: { entries, currency_code: currencyCode },
|
|
||||||
} = useFormikContext();
|
|
||||||
|
|
||||||
// Retrieves the invoice entries total.
|
|
||||||
const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
|
|
||||||
|
|
||||||
const total_ = useInvoiceTotal();
|
|
||||||
|
|
||||||
// Retrieves the formatted total money.
|
|
||||||
const formattedTotal = React.useMemo(
|
|
||||||
() => formattedAmount(total_, currencyCode),
|
|
||||||
[total_, currencyCode],
|
|
||||||
);
|
|
||||||
// Retrieves the formatted subtotal.
|
|
||||||
const formattedSubtotal = React.useMemo(
|
|
||||||
() => formattedAmount(total, currencyCode, { money: false }),
|
|
||||||
[total, currencyCode],
|
|
||||||
);
|
|
||||||
// Retrieves the payment total.
|
|
||||||
const paymentTotal = React.useMemo(() => 0, []);
|
|
||||||
|
|
||||||
// Retireves the formatted payment total.
|
|
||||||
const formattedPaymentTotal = React.useMemo(
|
|
||||||
() => formattedAmount(paymentTotal, currencyCode),
|
|
||||||
[paymentTotal, currencyCode],
|
|
||||||
);
|
|
||||||
// Retrieves the formatted due total.
|
|
||||||
const dueTotal = React.useMemo(
|
|
||||||
() => total_ - paymentTotal,
|
|
||||||
[total_, paymentTotal],
|
|
||||||
);
|
|
||||||
// Retrieves the formatted due total.
|
|
||||||
const formattedDueTotal = React.useMemo(
|
|
||||||
() => formattedAmount(dueTotal, currencyCode),
|
|
||||||
[dueTotal, currencyCode],
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
total,
|
|
||||||
paymentTotal,
|
|
||||||
dueTotal,
|
|
||||||
formattedTotal,
|
|
||||||
formattedSubtotal,
|
|
||||||
formattedPaymentTotal,
|
|
||||||
formattedDueTotal,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detarmines whether the invoice has foreign customer.
|
* Detarmines whether the invoice has foreign customer.
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
@@ -409,14 +356,25 @@ export const useInvoiceTotal = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the paid amount of the invoice.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export const useInvoicePaidAmount = () => {
|
||||||
|
const { invoice } = useInvoiceFormContext();
|
||||||
|
|
||||||
|
return invoice?.payment_amount || 0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retreives the invoice due amount.
|
* Retreives the invoice due amount.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export const useInvoiceDueAmount = () => {
|
export const useInvoiceDueAmount = () => {
|
||||||
const total = useInvoiceTotal();
|
const total = useInvoiceTotal();
|
||||||
|
const paidAmount = useInvoicePaidAmount();
|
||||||
|
|
||||||
return total;
|
return Math.max(total - paidAmount, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -438,3 +396,13 @@ export const useIsInvoiceTaxExclusive = () => {
|
|||||||
|
|
||||||
return values.inclusive_exclusive_tax === TaxType.Exclusive;
|
return values.inclusive_exclusive_tax === TaxType.Exclusive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the invoice currency code.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const useInvoiceCurrencyCode = () => {
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
|
return values.currency_code;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user