From 8cab01232445f689a4e02d615a5df02b2f16cdb3 Mon Sep 17 00:00:00 2001 From: Sachin Date: Sat, 3 Aug 2024 23:56:02 +0530 Subject: [PATCH 1/2] fix: due Amount on edit page is calculated wrong with "Exclusive of Tax" Invoice mode --- .../Sales/Invoices/InvoiceForm/InvoiceFormHeader.tsx | 4 ++-- .../src/containers/Sales/Invoices/InvoiceForm/utils.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeader.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeader.tsx index 66d1ed48c7..8ee7401bd8 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeader.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeader.tsx @@ -8,7 +8,7 @@ import InvoiceFormHeaderFields from './InvoiceFormHeaderFields'; import { CLASSES } from '@/constants/classes'; import { PageFormBigNumber } from '@/components'; -import { useInvoiceSubtotal } from './utils'; +import { useInvoiceDueAmount } from './utils'; /** * Invoice form header section. @@ -32,7 +32,7 @@ function InvoiceFormBigTotal() { } = useFormikContext(); // Calculate the total due amount of invoice entries. - const totalDueAmount = useInvoiceSubtotal(); + const totalDueAmount = useInvoiceDueAmount(); return ( { ); // Retrieves the formatted due total. const dueTotal = React.useMemo( - () => total - paymentTotal, - [total, paymentTotal], + () => total_ - paymentTotal, + [total_, paymentTotal], ); // Retrieves the formatted due total. const formattedDueTotal = React.useMemo( From 3d200f4d7df07529a52b2b78ce9b32934d7e0937 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 7 Aug 2024 18:52:36 +0200 Subject: [PATCH 2/2] fix: wrong invoice due amount --- .../InvoiceForm/InvoiceFormFooterRight.tsx | 24 +++--- .../Sales/Invoices/InvoiceForm/components.tsx | 59 +++++++++++++- .../Sales/Invoices/InvoiceForm/utils.tsx | 76 ++++++------------- 3 files changed, 88 insertions(+), 71 deletions(-) diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx index 5c152e26ba..68bc368725 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormFooterRight.tsx @@ -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={} /> {taxEntries.map((tax, index) => ( } borderStyle={TotalLineBorderStyle.SingleDark} textStyle={TotalLineTextStyle.Bold} /> } - value={formattedPaymentTotal} + value={} borderStyle={TotalLineBorderStyle.None} /> } - value={formattedDueTotal} + value={} textStyle={TotalLineTextStyle.Bold} /> diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/components.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/components.tsx index 788cd2c5c7..b96678cefc 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/components.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/components.tsx @@ -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 ; +}; + +/** + * Renders the invoice formatted subtotal. + * @returns {JSX.Element} + */ +export const InvoiceSubTotalFormatted = () => { + const currencyCode = useInvoiceCurrencyCode(); + const subTotal = useInvoiceSubtotal(); + + return ; +}; + +/** + * Renders the invoice formatted due amount. + * @returns {JSX.Element} + */ +export const InvoiceDueAmountFormatted = () => { + const currencyCode = useInvoiceCurrencyCode(); + const dueAmount = useInvoiceDueAmount(); + + return ; +}; + +/** + * Renders the invoice formatted paid amount. + * @returns {JSX.Element} + */ +export const InvoicePaidAmountFormatted = () => { + const currencyCode = useInvoiceCurrencyCode(); + const paidAmount = useInvoicePaidAmount(); + + return ; +}; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx index 51d4139720..c031ce74c9 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx @@ -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; +};