mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
fix: wrong invoice due amount
This commit is contained in:
@@ -10,18 +10,16 @@ import {
|
||||
TotalLineBorderStyle,
|
||||
TotalLineTextStyle,
|
||||
} from '@/components';
|
||||
import { useInvoiceAggregatedTaxRates, useInvoiceTotals } from './utils';
|
||||
import { useInvoiceAggregatedTaxRates } from './utils';
|
||||
import { TaxType } from '@/interfaces/TaxRates';
|
||||
import {
|
||||
InvoiceDueAmountFormatted,
|
||||
InvoicePaidAmountFormatted,
|
||||
InvoiceSubTotalFormatted,
|
||||
InvoiceTotalFormatted,
|
||||
} from './components';
|
||||
|
||||
export function InvoiceFormFooterRight() {
|
||||
// Calculate the total due amount of invoice entries.
|
||||
const {
|
||||
formattedSubtotal,
|
||||
formattedTotal,
|
||||
formattedDueTotal,
|
||||
formattedPaymentTotal,
|
||||
} = useInvoiceTotals();
|
||||
|
||||
const {
|
||||
values: { inclusive_exclusive_tax, currency_code },
|
||||
} = useFormikContext();
|
||||
@@ -38,7 +36,7 @@ export function InvoiceFormFooterRight() {
|
||||
: 'Subtotal'}
|
||||
</>
|
||||
}
|
||||
value={formattedSubtotal}
|
||||
value={<InvoiceSubTotalFormatted />}
|
||||
/>
|
||||
{taxEntries.map((tax, index) => (
|
||||
<TotalLine
|
||||
@@ -50,18 +48,18 @@ export function InvoiceFormFooterRight() {
|
||||
))}
|
||||
<TotalLine
|
||||
title={`Total (${currency_code})`}
|
||||
value={formattedTotal}
|
||||
value={<InvoiceTotalFormatted />}
|
||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||
textStyle={TotalLineTextStyle.Bold}
|
||||
/>
|
||||
<TotalLine
|
||||
title={<T id={'invoice_form.label.payment_amount'} />}
|
||||
value={formattedPaymentTotal}
|
||||
value={<InvoicePaidAmountFormatted />}
|
||||
borderStyle={TotalLineBorderStyle.None}
|
||||
/>
|
||||
<TotalLine
|
||||
title={<T id={'invoice_form.label.due_amount'} />}
|
||||
value={formattedDueTotal}
|
||||
value={<InvoiceDueAmountFormatted />}
|
||||
textStyle={TotalLineTextStyle.Bold}
|
||||
/>
|
||||
</InvoiceTotalLines>
|
||||
|
||||
@@ -4,14 +4,21 @@ import intl from 'react-intl-universal';
|
||||
import * as R from 'ramda';
|
||||
import { Button } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { ExchangeRateInputGroup } from '@/components';
|
||||
import { ExchangeRateInputGroup, FormatNumber } from '@/components';
|
||||
import { useCurrentOrganization } from '@/hooks/state';
|
||||
import { useInvoiceIsForeignCustomer, useInvoiceTotal } from './utils';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import {
|
||||
useInvoiceCurrencyCode,
|
||||
useInvoiceDueAmount,
|
||||
useInvoiceIsForeignCustomer,
|
||||
useInvoicePaidAmount,
|
||||
useInvoiceSubtotal,
|
||||
useInvoiceTotal,
|
||||
} from './utils';
|
||||
import { useUpdateEffect } from '@/hooks';
|
||||
import { transactionNumber } from '@/utils';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import {
|
||||
useSyncExRateToForm,
|
||||
withExchangeRateFetchingLoading,
|
||||
@@ -109,3 +116,47 @@ export const InvoiceExchangeRateSync = R.compose(withDialogActions)(
|
||||
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]);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @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.
|
||||
* @returns {number}
|
||||
*/
|
||||
export const useInvoiceDueAmount = () => {
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice currency code.
|
||||
* @returns {string}
|
||||
*/
|
||||
export const useInvoiceCurrencyCode = () => {
|
||||
const { values } = useFormikContext();
|
||||
|
||||
return values.currency_code;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user