Merge pull request #340 from bigcapitalhq/big-65-get-realtime-exchange-rate-from-third-party-service

feat: get latest exchange rate from third party services
This commit is contained in:
Ahmed Bouhuolia
2024-01-29 18:44:05 +02:00
committed by GitHub
13 changed files with 327 additions and 414 deletions

View File

@@ -1,6 +1,5 @@
import { useExchangeRate } from '@/hooks/query';
import { useCurrentOrganization } from '@/hooks/state';
import React from 'react';
import { useLatestExchangeRate } from '@/hooks/query';
interface AutoExchangeRateProviderProps {
children: React.ReactNode;
@@ -18,16 +17,19 @@ const AutoExchangeRateContext = React.createContext(
function AutoExchangeRateProvider({ children }: AutoExchangeRateProviderProps) {
const [autoExRateCurrency, setAutoExRateCurrency] =
React.useState<string>('');
const currentOrganization = useCurrentOrganization();
// Retrieves the exchange rate.
const { data: autoExchangeRate, isLoading: isAutoExchangeRateLoading } =
useExchangeRate(autoExRateCurrency, currentOrganization.base_currency, {
enabled: Boolean(currentOrganization.base_currency && autoExRateCurrency),
refetchOnWindowFocus: false,
staleTime: 0,
cacheTime: 0,
});
useLatestExchangeRate(
{ fromCurrency: autoExRateCurrency },
{
enabled: Boolean(autoExRateCurrency),
refetchOnWindowFocus: false,
staleTime: 0,
cacheTime: 0,
retry: 0,
},
);
const value = {
autoExRateCurrency,

View File

@@ -98,24 +98,30 @@ interface UseSyncExRateToFormProps {
*/
export const useSyncExRateToForm = ({ onSynced }: UseSyncExRateToFormProps) => {
const { setFieldValue, values } = useFormikContext();
const { autoExRateCurrency, autoExchangeRate } = useAutoExRateContext();
const { autoExRateCurrency, autoExchangeRate, isAutoExchangeRateLoading } =
useAutoExRateContext();
const updateEntriesOnExChange = useUpdateEntriesOnExchangeRateChange();
// Sync the fetched real-time exchanage rate to the form.
useEffect(() => {
if (autoExchangeRate?.exchange_rate && autoExRateCurrency) {
setFieldValue('exchange_rate', autoExchangeRate?.exchange_rate + '');
if (!isAutoExchangeRateLoading && autoExRateCurrency) {
// Sets a default ex. rate to 1 in case the exchange rate service wasn't configured.
// or returned an error from the server-side.
const exchangeRate = autoExchangeRate?.exchange_rate || 1;
setFieldValue('exchange_rate', exchangeRate + '');
setFieldValue(
'entries',
updateEntriesOnExChange(
values.exchange_rate,
autoExchangeRate?.exchange_rate,
),
updateEntriesOnExChange(values.exchange_rate, exchangeRate),
);
onSynced?.();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [autoExchangeRate?.exchange_rate, autoExRateCurrency]);
}, [
autoExchangeRate?.exchange_rate,
autoExRateCurrency,
isAutoExchangeRateLoading,
]);
return null;
};

View File

@@ -1,34 +1,36 @@
// @ts-nocheck
import { useQuery } from 'react-query';
import QUERY_TYPES from './types';
import useApiRequest from '../useRequest';
function getRandomItemFromArray(arr) {
const randomIndex = Math.floor(Math.random() * arr.length);
return arr[randomIndex];
}
function delay(t, val) {
return new Promise((resolve) => setTimeout(resolve, t, val));
interface LatestExchangeRateQuery {
fromCurrency?: string;
toCurrency?: string;
}
/**
* Retrieves tax rates.
* Retrieves latest exchange rate.
* @param {number} customerId - Customer id.
*/
export function useExchangeRate(
fromCurrency: string,
toCurrency: string,
export function useLatestExchangeRate(
{ toCurrency, fromCurrency }: LatestExchangeRateQuery,
props,
) {
return useQuery(
[QUERY_TYPES.EXCHANGE_RATE, fromCurrency, toCurrency],
async () => {
await delay(100);
const apiRequest = useApiRequest();
return {
from_currency: fromCurrency,
to_currency: toCurrency,
exchange_rate: 1.00,
};
},
return useQuery(
[QUERY_TYPES.EXCHANGE_RATE, toCurrency, fromCurrency],
() =>
apiRequest
.http({
url: `/api/exchange_rates/latest`,
method: 'get',
params: {
to_currency: toCurrency,
from_currency: fromCurrency,
},
})
.then((res) => res.data),
props,
);
}