chore: strengthen backend eslint profile
This commit is contained in:
@@ -22,10 +22,10 @@ export function bankBalance(
|
||||
cardId: string,
|
||||
opening: bigint,
|
||||
operations: Array<{
|
||||
kind: string;
|
||||
cardId: string;
|
||||
targetCardId: string | null;
|
||||
amountKopecks: bigint;
|
||||
cardId: string;
|
||||
kind: string;
|
||||
targetCardId: null | string;
|
||||
}>,
|
||||
): bigint {
|
||||
// ponytail: O(N) history fold; optimize only after measuring growing histories.
|
||||
@@ -35,19 +35,21 @@ export function bankBalance(
|
||||
if (
|
||||
operation.kind === BankOperationKind.Expense ||
|
||||
operation.kind === BankOperationKind.Transfer
|
||||
)
|
||||
) {
|
||||
balance -= operation.amountKopecks;
|
||||
else if (
|
||||
} else if (
|
||||
operation.kind === BankOperationKind.Topup ||
|
||||
operation.kind === BankOperationKind.Refund
|
||||
)
|
||||
) {
|
||||
balance += operation.amountKopecks;
|
||||
}
|
||||
}
|
||||
if (
|
||||
operation.kind === BankOperationKind.Transfer &&
|
||||
operation.targetCardId === cardId
|
||||
)
|
||||
) {
|
||||
balance += operation.amountKopecks;
|
||||
}
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
@@ -55,17 +57,17 @@ export function bankBalance(
|
||||
export function bankSummary(
|
||||
period: { from: string; to: string },
|
||||
operations: Array<{
|
||||
kind: string;
|
||||
date: string;
|
||||
amountKopecks: bigint;
|
||||
categoryId: string | null;
|
||||
categoryId: null | string;
|
||||
date: string;
|
||||
kind: string;
|
||||
}>,
|
||||
) {
|
||||
let expenses = 0n;
|
||||
let refunds = 0n;
|
||||
const categories = new Map<
|
||||
string,
|
||||
{ categoryId: string; expenses: bigint; refunds: bigint; net: bigint }
|
||||
{ categoryId: string; expenses: bigint; net: bigint; refunds: bigint }
|
||||
>();
|
||||
// ponytail: O(N) history fold; optimize only after measuring growing histories.
|
||||
for (const operation of operations) {
|
||||
@@ -73,16 +75,17 @@ export function bankSummary(
|
||||
if (
|
||||
operation.kind !== BankOperationKind.Expense &&
|
||||
operation.kind !== BankOperationKind.Refund
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const expense =
|
||||
operation.kind === BankOperationKind.Expense
|
||||
? operation.amountKopecks
|
||||
: 0n;
|
||||
operation.kind === BankOperationKind.Expense ?
|
||||
operation.amountKopecks :
|
||||
0n;
|
||||
const refund =
|
||||
operation.kind === BankOperationKind.Refund
|
||||
? operation.amountKopecks
|
||||
: 0n;
|
||||
operation.kind === BankOperationKind.Refund ?
|
||||
operation.amountKopecks :
|
||||
0n;
|
||||
expenses += expense;
|
||||
refunds += refund;
|
||||
if (operation.categoryId !== null) {
|
||||
|
||||
@@ -39,8 +39,9 @@ describe('RUB money', () => {
|
||||
});
|
||||
|
||||
it('requires positive operation amounts, including at the maximum', () => {
|
||||
for (const value of ['0', '-0.00', '-0.01'])
|
||||
for (const value of ['0', '-0.00', '-0.01']) {
|
||||
expect(() => parseRubMoney({ currency: 'RUB', value }, true)).toThrow();
|
||||
}
|
||||
expect(parseRubMoney({ currency: 'RUB', value: '0.01' }, true)).toBe(1n);
|
||||
expect(
|
||||
parseRubMoney({ currency: 'RUB', value: '92233720368547758.07' }, true),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { decimalFromString, formatDecimal } from '../../../../common/decimal';
|
||||
import type { Money } from '../../../../common/money.types';
|
||||
|
||||
import { decimalFromString, formatDecimal } from '../../../../common/decimal';
|
||||
|
||||
const MIN_KOPECKS = -9_223_372_036_854_775_808n;
|
||||
const MAX_KOPECKS = 9_223_372_036_854_775_807n;
|
||||
|
||||
@@ -9,16 +10,20 @@ export function parseRubMoney(money: Money, positive = false): bigint {
|
||||
money?.currency !== 'RUB' ||
|
||||
typeof money.value !== 'string' ||
|
||||
money.value !== money.value.trim()
|
||||
)
|
||||
) {
|
||||
throw new TypeError('Expected RUB money with a decimal string');
|
||||
}
|
||||
const amount = decimalFromString(money.value);
|
||||
if (amount.scale > 2)
|
||||
if (amount.scale > 2) {
|
||||
throw new RangeError('RUB money supports at most two decimal places');
|
||||
}
|
||||
const kopecks = amount.value * 10n ** BigInt(2 - amount.scale);
|
||||
if (kopecks < MIN_KOPECKS || kopecks > MAX_KOPECKS)
|
||||
if (kopecks < MIN_KOPECKS || kopecks > MAX_KOPECKS) {
|
||||
throw new RangeError('RUB money is outside the signed 64-bit range');
|
||||
if (positive && kopecks <= 0n)
|
||||
}
|
||||
if (positive && kopecks <= 0n) {
|
||||
throw new RangeError('Operation amount must be positive');
|
||||
}
|
||||
return kopecks;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user