refactor!: support RUB only (WealthLedger/main#55)

Filter non-RUB data at ingest, collapse per-currency collections into single RUB Money, drop currency from TbankPortfolioValuePoint, remove NON_RUB_ACTIVITY and screener currency filter.

BREAKING CHANGE: per-currency API fields replaced with single RUB Money; stock screener currency param removed.
This commit is contained in:
2026-11-11 08:22:16 +03:00
parent fee61537b6
commit 3b55b611b5
60 changed files with 624 additions and 736 deletions
+7 -14
View File
@@ -103,7 +103,6 @@ describe('local income completeness and exact money (SQLite)', () => {
for (const [id, units, nano, currency, type] of [
['same', '10', 1, 'rub', 'OPERATION_TYPE_COUPON'],
['negative', '-2', -500000000, 'rub', 'OPERATION_TYPE_DIVIDEND'],
['usd', '3', 0, 'usd', 'OPERATION_TYPE_COUPON'],
] as const) {
await prisma.tbankOperation.create({
data: {
@@ -130,11 +129,8 @@ describe('local income completeness and exact money (SQLite)', () => {
assert(result.data);
expect(result.meta.availability).toBe('available');
expect(result.meta.completeness).toBe('complete');
expect(result.data.totalsByCurrency.map((row) => row.total)).toEqual([
{ currency: 'RUB', value: '15.000000002' },
{ currency: 'USD', value: '6' },
]);
expect(result.data.entries).toHaveLength(6);
expect(result.data.total.total).toEqual({ currency: 'RUB', value: '15.000000002' });
expect(result.data.entries).toHaveLength(4);
expect(
result.data.entries
.filter((row) => row.id === 'same')
@@ -185,7 +181,7 @@ describe('local income completeness and exact money (SQLite)', () => {
assert(after.data);
expect(after.data.entries.find((entry) => entry.account?.id === 'a' && entry.id === 'same')?.logoName).toBe('bond.png');
expect(after.data.entries.find((entry) => entry.account?.id === 'b' && entry.id === 'same')?.logoName).toBeNull();
expect(after.data.totalsByCurrency).toEqual(base.totalsByCurrency);
expect(after.data.total).toEqual(base.total);
expect(after.data.calculatedAt).toBe(base.calculatedAt);
expect(upstream.getOperationsByCursor).not.toHaveBeenCalled();
});
@@ -205,8 +201,8 @@ describe('local income completeness and exact money (SQLite)', () => {
new Date('2025-03-31T21:00:00Z'),
);
expect(
(await read('a', 'from=2025-03-01&to=2025-03-31')).data?.totalsByCurrency,
).toEqual([]);
(await read('a', 'from=2025-03-01&to=2025-03-31')).data?.total.total,
).toEqual({ currency: 'RUB', value: '0' });
expect(upstream.getOperationsByCursor).toHaveBeenCalledWith(
'synthetic', expect.objectContaining({ accountId: 'b' }),
);
@@ -225,11 +221,8 @@ describe('local income completeness and exact money (SQLite)', () => {
});
const result = await read();
assert(result.data);
expect(result.data.entries).toHaveLength(6);
expect(
result.data.totalsByCurrency.find(({ currency }) => currency === 'RUB')
?.total,
).toEqual({ currency: 'RUB', value: '25.000000002' });
expect(result.data.entries).toHaveLength(4);
expect(result.data.total.total).toEqual({ currency: 'RUB', value: '25.000000002' });
});
it('preserves the complete financial result and timestamp through failed atomic reconciliation', async () => {
const before = await read();