Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cleanup] Number Precision And Decimal Separator Adjusting #2069

Merged
25 changes: 25 additions & 0 deletions src/common/helpers/dates/date-format-resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

import { useStaticsQuery } from '../../queries/statics';

export function useResolveDateFormat() {
const statics = useStaticsQuery();

return (id: string) => {
if (statics) {
return statics.data?.date_formats.find(
(dateFormat) => dateFormat.id === id
);
}

return undefined;
};
}
106 changes: 66 additions & 40 deletions src/common/hooks/useGetCurrencySeparators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useResolveCountry } from './useResolveCountry';
import { useVendorResolver } from './vendors/useVendorResolver';

export function useGetCurrencySeparators(
setInputCurrencySeparators: React.Dispatch<
setInputCurrencySeparators?: React.Dispatch<
React.SetStateAction<DecimalInputSeparators | undefined>
>
) {
Expand All @@ -33,61 +33,87 @@ export function useGetCurrencySeparators(
const currencyResolver = useCurrencyResolver();
const resolveCountry = useResolveCountry();

return (relationId: string, relationType: RelationType) => {
return async (relationId: string, relationType: RelationType) => {
let separators: DecimalInputSeparators | undefined;

if (relationId.length >= 1 && relationType === 'client_id') {
clientResolver.find(relationId).then((client: Client) =>
currencyResolver
await clientResolver.find(relationId).then(async (client: Client) => {
await currencyResolver
.find(client.settings.currency_id || company.settings?.currency_id)
.then((currency: Currency | undefined) => {
const companyCountry = resolveCountry(company.settings.country_id);

currency &&
setInputCurrencySeparators({
thousandSeparator:
companyCountry?.thousand_separator ||
currency.thousand_separator,
decimalSeparator:
companyCountry?.decimal_separator ||
currency.decimal_separator,
precision: currency.precision,
});
})
);
const currentSeparators = {
thousandSeparator:
companyCountry?.thousand_separator ||
currency?.thousand_separator ||
',',
decimalSeparator:
companyCountry?.decimal_separator ||
currency?.decimal_separator ||
'.',
precision: currency?.precision || 2,
};

if (setInputCurrencySeparators) {
setInputCurrencySeparators(currentSeparators);
} else {
separators = currentSeparators;
}
});
});
} else if (relationId.length >= 1 && relationType === 'vendor_id') {
vendorResolver.find(relationId).then((vendor: Vendor) =>
currencyResolver
await vendorResolver.find(relationId).then(async (vendor: Vendor) => {
await currencyResolver
.find(vendor.currency_id || company.settings?.currency_id)
.then((currency: Currency | undefined) => {
const companyCountry = resolveCountry(company.settings.country_id);

currency &&
setInputCurrencySeparators({
thousandSeparator:
companyCountry?.thousand_separator ||
currency.thousand_separator,
decimalSeparator:
companyCountry?.decimal_separator ||
currency.decimal_separator,
precision: currency.precision,
});
})
);
const currentSeparators = {
thousandSeparator:
companyCountry?.thousand_separator ||
currency?.thousand_separator ||
',',
decimalSeparator:
companyCountry?.decimal_separator ||
currency?.decimal_separator ||
'.',
precision: currency?.precision || 2,
};

if (setInputCurrencySeparators) {
setInputCurrencySeparators(currentSeparators);
} else {
separators = currentSeparators;
}
});
});
} else {
currencyResolver
await currencyResolver
.find(company.settings?.currency_id)
.then((currency: Currency | undefined) => {
const companyCountry = resolveCountry(company.settings.country_id);

currency &&
setInputCurrencySeparators({
thousandSeparator:
companyCountry?.thousand_separator ||
currency.thousand_separator,
decimalSeparator:
companyCountry?.decimal_separator || currency.decimal_separator,
precision: currency.precision,
});
const currentSeparators = {
thousandSeparator:
companyCountry?.thousand_separator ||
currency?.thousand_separator ||
',',
decimalSeparator:
companyCountry?.decimal_separator ||
currency?.decimal_separator ||
'.',
precision: currency?.precision || 2,
};

if (setInputCurrencySeparators) {
setInputCurrencySeparators(currentSeparators);
} else {
separators = currentSeparators;
}
});
}

return separators;
};
}
57 changes: 57 additions & 0 deletions src/common/hooks/useNumericFormatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

import { numericFormatter } from 'react-number-format';
import { useCurrentCompany } from './useCurrentCompany';
import { useUserNumberPrecision } from './useUserNumberPrecision';

export function useNumericFormatter() {
const company = useCurrentCompany();
const userNumberPrecision = useUserNumberPrecision();

const getThousandSeparator = (
currentThousandSeparator: string | undefined
) => {
if (currentThousandSeparator) {
return currentThousandSeparator;
}

if (company?.use_comma_as_decimal_place) {
return '.';
}

return ',';
};

const getDecimalSeparator = (currentDecimalSeparator: string | undefined) => {
if (currentDecimalSeparator) {
return currentDecimalSeparator;
}

if (company?.use_comma_as_decimal_place) {
return ',';
}

return '.';
};

return (
numStr: string,
thousandSeparator?: string,
decimalSeparator?: string,
precision?: number
) => {
return numericFormatter(numStr, {
thousandSeparator: getThousandSeparator(thousandSeparator),
decimalSeparator: getDecimalSeparator(decimalSeparator),
decimalScale: precision || userNumberPrecision,
});
};
}
21 changes: 21 additions & 0 deletions src/common/hooks/useUserNumberPrecision.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

import { useReactSettings } from './useReactSettings';

export function useUserNumberPrecision() {
const reactSettings = useReactSettings();

return reactSettings?.number_precision &&
reactSettings?.number_precision > 0 &&
reactSettings?.number_precision <= 100
? reactSettings.number_precision
: 2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

import { useResolveDateFormat } from '$app/common/helpers/dates/date-format-resolver';
import { useClientResolver } from '$app/common/hooks/clients/useClientResolver';
import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import { Client } from '$app/common/interfaces/client';

export function useResolveDateAndTimeClientFormat() {
const company = useCurrentCompany();
const clientResolver = useClientResolver();

const resolveDateFormat = useResolveDateFormat();

const getTimeFormat = (militaryTime: boolean) => {
return militaryTime ? 'HH:mm:ss' : 'hh:mm:ss A';
};

return async (relationId: string) => {
const dateFormat = resolveDateFormat(company?.settings.date_format_id);

const dateTimeFormats = {
dateFormat,
timeFormat: getTimeFormat(Boolean(company?.settings.military_time)),
};

if (relationId.length >= 1) {
await clientResolver.find(relationId).then((client: Client) => {
if (client.settings.date_format_id) {
dateTimeFormats.dateFormat = resolveDateFormat(
client.settings.date_format_id
);
}

dateTimeFormats.timeFormat = getTimeFormat(
Boolean(client.settings.military_time)
);
});
}

return dateTimeFormats;
};
}
10 changes: 7 additions & 3 deletions src/pages/products/common/hooks/useInvoiceProducts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import { blankLineItem } from '$app/common/constants/blank-line-item';
import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import { useUserNumberPrecision } from '$app/common/hooks/useUserNumberPrecision';
import { InvoiceItemType } from '$app/common/interfaces/invoice-item';
import { Product } from '$app/common/interfaces/product';
import { useBlankInvoiceQuery } from '$app/common/queries/invoices';
Expand All @@ -22,11 +23,12 @@ interface Params {
}

export const useInvoiceProducts = (params?: Params) => {
const navigate = useNavigate();

const { onlyAddToInvoice } = params || {};

const navigate = useNavigate();

const company = useCurrentCompany();
const userNumberPrecision = useUserNumberPrecision();

const { data: blankInvoice } = useBlankInvoiceQuery();

Expand All @@ -40,7 +42,9 @@ export const useInvoiceProducts = (params?: Params) => {
product_key: product.product_key,
quantity: company?.fill_products ? product.quantity : 1,
...(company?.fill_products && {
line_total: Number((product.price * product.quantity).toFixed(2)),
line_total: Number(
(product.price * product.quantity).toFixed(userNumberPrecision)
),
cost: product.price,
notes: product.notes,
tax_name1: product.tax_name1,
Expand Down
6 changes: 5 additions & 1 deletion src/pages/products/common/hooks/usePurchaseOrderProducts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import { blankLineItem } from '$app/common/constants/blank-line-item';
import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import { useUserNumberPrecision } from '$app/common/hooks/useUserNumberPrecision';
import { InvoiceItemType } from '$app/common/interfaces/invoice-item';
import { Product } from '$app/common/interfaces/product';
import { useBlankPurchaseOrderQuery } from '$app/common/queries/purchase-orders';
Expand All @@ -21,6 +22,7 @@ export const usePurchaseOrderProducts = () => {
const navigate = useNavigate();

const company = useCurrentCompany();
const userNumberPrecision = useUserNumberPrecision();

const { data: blankPurchaseOrder } = useBlankPurchaseOrderQuery();

Expand All @@ -34,7 +36,9 @@ export const usePurchaseOrderProducts = () => {
product_key: product.product_key,
quantity: company?.fill_products ? product.quantity : 1,
...(company?.fill_products && {
line_total: Number((product.price * product.quantity).toFixed(2)),
line_total: Number(
(product.price * product.quantity).toFixed(userNumberPrecision)
),
cost: product.price,
notes: product.notes,
tax_name1: product.tax_name1,
Expand Down
Loading
Loading