mirror of
https://github.com/frappe/books.git
synced 2024-11-09 15:20:56 +00:00
refactor: use NaN safe Number parsing where applicable
This commit is contained in:
parent
2bc3df90a1
commit
d73d331a87
@ -8,7 +8,7 @@ import { PurchaseInvoice } from 'models/baseModels/PurchaseInvoice/PurchaseInvoi
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import setupInstance from 'src/setup/setupInstance';
|
||||
import { getMapFromList } from 'utils';
|
||||
import { getMapFromList, safeParseInt } from 'utils';
|
||||
import { getFiscalYear } from 'utils/misc';
|
||||
import {
|
||||
flow,
|
||||
@ -256,7 +256,7 @@ async function getSalesInvoices(
|
||||
|
||||
notifier?.(
|
||||
`Creating Sales Invoices, ${d} out of ${dates.length}`,
|
||||
parseInt(d) / dates.length
|
||||
safeParseInt(d) / dates.length
|
||||
);
|
||||
const customer = sample(customers);
|
||||
|
||||
@ -531,7 +531,7 @@ async function syncAndSubmit(docs: Doc[], notifier?: Notifier) {
|
||||
const doc = docs[i];
|
||||
notifier?.(
|
||||
`Syncing ${nameMap[doc.schemaName]}, ${i} out of ${total}`,
|
||||
parseInt(i) / total
|
||||
safeParseInt(i) / total
|
||||
);
|
||||
await doc.sync();
|
||||
await doc.submit();
|
||||
|
@ -5,7 +5,7 @@ import { ValueError } from 'fyo/utils/errors';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Money } from 'pesa';
|
||||
import { Field, FieldTypeEnum, RawValue, TargetField } from 'schemas/types';
|
||||
import { getIsNullOrUndef } from 'utils';
|
||||
import { getIsNullOrUndef, safeParseFloat, safeParseInt } from 'utils';
|
||||
import { DatabaseHandler } from './dbHandler';
|
||||
import { Attachment, DocValue, DocValueMap, RawValueMap } from './types';
|
||||
|
||||
@ -231,7 +231,7 @@ function toDocInt(value: RawValue, field: Field): number {
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
value = parseInt(value);
|
||||
value = safeParseInt(value);
|
||||
}
|
||||
|
||||
return toDocFloat(value, field);
|
||||
@ -247,7 +247,7 @@ function toDocFloat(value: RawValue, field: Field): number {
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
value = parseFloat(value);
|
||||
value = safeParseFloat(value);
|
||||
}
|
||||
|
||||
if (value === null) {
|
||||
@ -267,7 +267,7 @@ function toDocCheck(value: RawValue, field: Field): boolean {
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return !!parseFloat(value);
|
||||
return !!safeParseFloat(value);
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
@ -317,7 +317,7 @@ function toRawCurrency(value: DocValue, fyo: Fyo, field: Field): string {
|
||||
|
||||
function toRawInt(value: DocValue, field: Field): number {
|
||||
if (typeof value === 'string') {
|
||||
return parseInt(value);
|
||||
return safeParseInt(value);
|
||||
}
|
||||
|
||||
if (getIsNullOrUndef(value)) {
|
||||
@ -333,7 +333,7 @@ function toRawInt(value: DocValue, field: Field): number {
|
||||
|
||||
function toRawFloat(value: DocValue, field: Field): number {
|
||||
if (typeof value === 'string') {
|
||||
return parseFloat(value);
|
||||
return safeParseFloat(value);
|
||||
}
|
||||
|
||||
if (getIsNullOrUndef(value)) {
|
||||
|
@ -4,7 +4,7 @@ import { Doc } from 'fyo/model/doc';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Money } from 'pesa';
|
||||
import { Field, FieldType, FieldTypeEnum } from 'schemas/types';
|
||||
import { getIsNullOrUndef } from 'utils';
|
||||
import { getIsNullOrUndef, safeParseFloat } from 'utils';
|
||||
import {
|
||||
DEFAULT_CURRENCY,
|
||||
DEFAULT_DATE_FORMAT,
|
||||
@ -95,11 +95,11 @@ function formatNumber(value: DocValue, fyo: Fyo): string {
|
||||
}
|
||||
|
||||
if ((value as Money).round) {
|
||||
const floatValue = parseFloat((value as Money).round());
|
||||
const floatValue = safeParseFloat((value as Money).round());
|
||||
return numberFormatter.format(floatValue);
|
||||
}
|
||||
|
||||
const floatValue = parseFloat(value as string);
|
||||
const floatValue = safeParseFloat(value as string);
|
||||
const formattedNumber = numberFormatter.format(floatValue);
|
||||
|
||||
if (formattedNumber === 'NaN') {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Fyo } from 'fyo';
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { Action, DocStatus } from 'fyo/model/types';
|
||||
import { Action } from 'fyo/model/types';
|
||||
import { Money } from 'pesa';
|
||||
import { Field, OptionField, SelectOption } from 'schemas/types';
|
||||
import { getIsNullOrUndef } from 'utils';
|
||||
import { getIsNullOrUndef, safeParseInt } from 'utils';
|
||||
|
||||
export function slug(str: string) {
|
||||
return str
|
||||
@ -24,7 +24,7 @@ export function unique<T>(list: T[], key = (it: T) => String(it)) {
|
||||
export function getDuplicates(array: unknown[]) {
|
||||
const duplicates: unknown[] = [];
|
||||
for (const i in array) {
|
||||
const previous = array[parseInt(i) - 1];
|
||||
const previous = array[safeParseInt(i) - 1];
|
||||
const current = array[i];
|
||||
|
||||
if (current === previous) {
|
||||
|
@ -14,7 +14,7 @@ import { Transactional } from 'models/Transactional/Transactional';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { Money } from 'pesa';
|
||||
import { FieldTypeEnum, Schema } from 'schemas/types';
|
||||
import { getIsNullOrUndef } from 'utils';
|
||||
import { getIsNullOrUndef, safeParseFloat } from 'utils';
|
||||
import { Defaults } from '../Defaults/Defaults';
|
||||
import { InvoiceItem } from '../InvoiceItem/InvoiceItem';
|
||||
import { Party } from '../Party/Party';
|
||||
@ -157,7 +157,7 @@ export abstract class Invoice extends Transactional {
|
||||
toCurrency: currency as string,
|
||||
});
|
||||
|
||||
return parseFloat(exchangeRate.toFixed(2));
|
||||
return safeParseFloat(exchangeRate.toFixed(2));
|
||||
}
|
||||
|
||||
async getTaxSummary() {
|
||||
|
@ -3,6 +3,7 @@ import { Doc } from 'fyo/model/doc';
|
||||
import { Action, ColumnConfig, DocStatus, RenderData } from 'fyo/model/types';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Money } from 'pesa';
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import { Router } from 'vue-router';
|
||||
import {
|
||||
AccountRootType,
|
||||
@ -211,7 +212,7 @@ export async function getExchangeRate({
|
||||
|
||||
let exchangeRate = 0;
|
||||
if (localStorage) {
|
||||
exchangeRate = parseFloat(
|
||||
exchangeRate = safeParseFloat(
|
||||
localStorage.getItem(cacheKey as string) as string
|
||||
);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { ModelNameEnum } from 'models/types';
|
||||
import { Report } from 'reports/Report';
|
||||
import { GroupedMap, LedgerEntry, RawLedgerEntry } from 'reports/types';
|
||||
import { QueryFilter } from 'utils/db/types';
|
||||
import { safeParseFloat, safeParseInt } from 'utils/index';
|
||||
import getCommonExportActions from './commonExporter';
|
||||
|
||||
type GroupByKey = 'account' | 'party' | 'referenceName';
|
||||
@ -101,11 +102,11 @@ export abstract class LedgerReport extends Report {
|
||||
|
||||
this._rawData = entries.map((entry) => {
|
||||
return {
|
||||
name: parseInt(entry.name),
|
||||
name: safeParseInt(entry.name),
|
||||
account: entry.account,
|
||||
date: new Date(entry.date),
|
||||
debit: parseFloat(entry.debit),
|
||||
credit: parseFloat(entry.credit),
|
||||
debit: safeParseFloat(entry.debit),
|
||||
credit: safeParseFloat(entry.credit),
|
||||
balance: 0,
|
||||
referenceType: entry.referenceType,
|
||||
referenceName: entry.referenceName,
|
||||
|
@ -35,6 +35,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
@ -58,7 +59,7 @@ export default defineComponent({
|
||||
value = e.target.value;
|
||||
}
|
||||
|
||||
value = parseFloat(value);
|
||||
value = safeParseFloat(value);
|
||||
|
||||
let exchangeRate = value / this.fromValue;
|
||||
if (this.isSwapped) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
<script>
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import Int from './Int.vue';
|
||||
|
||||
export default {
|
||||
@ -11,8 +12,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
parse(value) {
|
||||
const parsedValue = parseFloat(value);
|
||||
return isNaN(parsedValue) ? 0 : parsedValue;
|
||||
return safeParseFloat(value)
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -193,6 +193,7 @@ import { docsPathMap } from 'src/utils/misc';
|
||||
import { getGroupLabelMap, searchGroups } from 'src/utils/search';
|
||||
import { useKeys } from 'src/utils/vueUtils';
|
||||
import { getIsNullOrUndef } from 'utils/';
|
||||
import { safeParseInt } from 'utils/index';
|
||||
import { nextTick, watch } from 'vue';
|
||||
import Button from './Button.vue';
|
||||
import Modal from './Modal.vue';
|
||||
@ -268,7 +269,7 @@ export default {
|
||||
}
|
||||
|
||||
const digit = matches[1];
|
||||
const index = parseInt(digit) - 1;
|
||||
const index = safeParseInt(digit) - 1;
|
||||
const group = searchGroups[index];
|
||||
const value = this.searcher.filters.groupFilters[group];
|
||||
if (!group || typeof value !== 'boolean') {
|
||||
|
@ -114,6 +114,7 @@ import { fyo } from 'src/initFyo';
|
||||
import { uicolors } from 'src/utils/colors';
|
||||
import { getDatesAndPeriodList } from 'src/utils/misc';
|
||||
import { routeTo } from 'src/utils/ui';
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import PeriodSelector from './PeriodSelector.vue';
|
||||
import SectionHeader from './SectionHeader.vue';
|
||||
|
||||
@ -213,7 +214,7 @@ export default {
|
||||
});
|
||||
|
||||
const isOutstanding = outstandingAmounts.map((o) =>
|
||||
parseFloat(o.outstandingAmount)
|
||||
safeParseFloat(o.outstandingAmount)
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -3,7 +3,7 @@ import { RawValueMap } from 'fyo/core/types';
|
||||
import { Field, FieldTypeEnum, RawValue, TargetField } from 'schemas/types';
|
||||
import { generateCSV } from 'utils/csvParser';
|
||||
import { GetAllOptions, QueryFilter } from 'utils/db/types';
|
||||
import { getMapFromList } from 'utils/index';
|
||||
import { getMapFromList, safeParseFloat } from 'utils/index';
|
||||
import { ExportField, ExportTableField } from './types';
|
||||
|
||||
const excludedFieldTypes = [
|
||||
@ -328,7 +328,7 @@ function convertRawPesaToFloat(data: RawValueMap[], fields: Field[]) {
|
||||
|
||||
for (const row of data) {
|
||||
for (const { fieldname } of currencyFields) {
|
||||
row[fieldname] = parseFloat((row[fieldname] ?? '0') as string);
|
||||
row[fieldname] = safeParseFloat((row[fieldname] ?? '0') as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { reports } from 'reports';
|
||||
import { OptionField } from 'schemas/types';
|
||||
import { getEntryRoute } from 'src/router';
|
||||
import { GetAllOptions } from 'utils/db/types';
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import { fuzzyMatch } from '.';
|
||||
import { routeTo } from './ui';
|
||||
|
||||
@ -520,7 +521,7 @@ export class Search {
|
||||
keys.push('0');
|
||||
}
|
||||
|
||||
keys.sort((a, b) => parseFloat(b) - parseFloat(a));
|
||||
keys.sort((a, b) => safeParseFloat(b) - safeParseFloat(a));
|
||||
const array: SearchItems = [];
|
||||
for (const key of keys) {
|
||||
const keywords = groupedKeywords[key];
|
||||
|
@ -157,3 +157,32 @@ export function deleteKeys<T>(
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
function safeParseNumber(value: unknown, parser: (v: string) => number) {
|
||||
let parsed: number;
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
parsed = parser(value);
|
||||
break;
|
||||
case 'number':
|
||||
parsed = value;
|
||||
break;
|
||||
default:
|
||||
parsed = Number(value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Number.isNaN(parsed)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
export function safeParseFloat(value: unknown): number {
|
||||
return safeParseNumber(value, parseFloat);
|
||||
}
|
||||
|
||||
export function safeParseInt(value: unknown): number {
|
||||
return safeParseNumber(value, parseInt);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user