feat: implement auto entries rates re-calculation after change the exchange rate

This commit is contained in:
Ahmed Bouhuolia
2024-01-14 14:44:48 +02:00
parent 2cb8c2932f
commit 2b03ac7f16
24 changed files with 522 additions and 241 deletions

View File

@@ -1,44 +1,22 @@
// @ts-nocheck
import { useEffect, useRef } from 'react';
import { useRef } from 'react';
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 { useCurrentOrganization } from '@/hooks/state';
import {
useInvoiceEntriesOnExchangeRateChange,
useInvoiceIsForeignCustomer,
useInvoiceTotal,
} from './utils';
import { useInvoiceIsForeignCustomer, useInvoiceTotal } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import { useUpdateEffect } from '@/hooks';
import { transactionNumber } from '@/utils';
import { useInvoiceFormContext } from './InvoiceFormProvider';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { DialogsName } from '@/constants/dialogs';
/**
* Re-calculate the item entries prices based on the old exchange rate.
* @param {InvoiceExchangeRateInputFieldRoot} Component
* @returns {JSX.Element}
*/
const withExchangeRateItemEntriesPriceRecalc = (Component) => (props) => {
const { setFieldValue } = useFormikContext();
const composeChangeExRate = useInvoiceEntriesOnExchangeRateChange();
return (
<Component
onRecalcConfirm={({ exchangeRate, oldExchangeRate }) => {
setFieldValue(
'entries',
composeChangeExRate(oldExchangeRate, exchangeRate),
);
}}
{...props}
/>
);
};
import {
useSyncExRateToForm,
withExchangeRateFetchingLoading,
withExchangeRateItemEntriesPriceRecalc,
} from '@/containers/Entries/withExRateItemEntriesPriceRecalc';
/**
* Invoice exchange rate input field.
@@ -47,8 +25,6 @@ const withExchangeRateItemEntriesPriceRecalc = (Component) => (props) => {
const InvoiceExchangeRateInputFieldRoot = ({ ...props }) => {
const currentOrganization = useCurrentOrganization();
const { values } = useFormikContext();
const { isAutoExchangeRateLoading } = useInvoiceFormContext();
const isForeignCustomer = useInvoiceIsForeignCustomer();
// Can't continue if the customer is not foreign.
@@ -60,7 +36,8 @@ const InvoiceExchangeRateInputFieldRoot = ({ ...props }) => {
name={'exchange_rate'}
fromCurrency={values.currency_code}
toCurrency={currentOrganization.base_currency}
isLoading={isAutoExchangeRateLoading}
formGroupProps={{ label: ' ', inline: true }}
withPopoverRecalcConfirm
{...props}
/>
);
@@ -71,6 +48,7 @@ const InvoiceExchangeRateInputFieldRoot = ({ ...props }) => {
* @returns {JSX.Element}
*/
export const InvoiceExchangeRateInputField = R.compose(
withExchangeRateFetchingLoading,
withExchangeRateItemEntriesPriceRecalc,
)(InvoiceExchangeRateInputFieldRoot);
@@ -108,40 +86,26 @@ export const InvoiceNoSyncSettingsToForm = R.compose(
});
/**
* Syncs the fetched real-time exchange rate to the form.
* @returns {JSX.Element}
* Syncs the realtime exchange rate to the invoice form and shows up popup to the user
* as an indication the entries rates have been re-calculated.
* @returns {React.ReactNode}
*/
export const InvoiceExchangeRateSync = R.compose(withDialogActions)(
({ openDialog }) => {
const { setFieldValue, values } = useFormikContext();
const { autoExRateCurrency, autoExchangeRate } = useInvoiceFormContext();
const composeEntriesOnExChange = useInvoiceEntriesOnExchangeRateChange();
const total = useInvoiceTotal();
const timeout = useRef();
// Sync the fetched real-time exchanage rate to the form.
useEffect(() => {
if (autoExchangeRate?.exchange_rate && autoExRateCurrency) {
setFieldValue('exchange_rate', autoExchangeRate?.exchange_rate + '');
setFieldValue(
'entries',
composeEntriesOnExChange(
values.exchange_rate,
autoExchangeRate?.exchange_rate,
),
);
useSyncExRateToForm({
onSynced: () => {
// If the total bigger then zero show alert to the user after adjusting entries.
if (total > 0) {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => {
openDialog(DialogsName.InvoiceExchangeRateChange);
openDialog(DialogsName.InvoiceExchangeRateChangeNotice);
}, 500);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [autoExchangeRate?.exchange_rate, autoExRateCurrency]);
},
});
return null;
},
);