3 Commits
Author SHA1 Message Date
ksv741 4a17f1fffd fix(performance): ignore non-RUB cash flows (WealthLedger/main#55)
Backend verify / commits (pull_request) Failing after 1m39s
Backend verify / security (pull_request) Skipped
Backend verify / verify (pull_request) Skipped
2026-11-11 09:00:25 +03:00
ksv741 b4c83e7462 fix: rebuild RUB-only snapshots on next tick (WealthLedger/main#55) 2026-11-11 08:51:34 +03:00
ksv741 3b55b611b5 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.
2026-11-11 08:22:16 +03:00
5 changed files with 4 additions and 52 deletions
-18
View File
@@ -1,23 +1,5 @@
# Changelog
## [3.0.0](https://git.personal.ksv741.ru/WealthLedger/backend/compare/v2.4.1...v3.0.0) (2026-11-11)
### ⚠ BREAKING CHANGES
* per-currency API fields replaced with single RUB Money.
### Features
* **performance:** investment performance vs Moscow Exchange index (WealthLedger/main[#54](https://git.personal.ksv741.ru/WealthLedger/backend/issues/54)) ([#200](https://git.personal.ksv741.ru/WealthLedger/backend/issues/200)) ([fee6153](https://git.personal.ksv741.ru/WealthLedger/backend/commit/fee61537b612cb5d1d0056e9e1b8044c91180b3b))
### Bug Fixes
* **sync:** start hourly operations after portfolio works finish ([#201](https://git.personal.ksv741.ru/WealthLedger/backend/issues/201)) ([#202](https://git.personal.ksv741.ru/WealthLedger/backend/issues/202)) ([85d65f8](https://git.personal.ksv741.ru/WealthLedger/backend/commit/85d65f899790e9bf303619f3b13e4f04a45baa34))
### Refactoring
* support RUB only (WealthLedger/main[#55](https://git.personal.ksv741.ru/WealthLedger/backend/issues/55)) ([#204](https://git.personal.ksv741.ru/WealthLedger/backend/issues/204)) ([809936e](https://git.personal.ksv741.ru/WealthLedger/backend/commit/809936e62df40a5519ba7bebf900b0322e0c285a))
## [2.4.1](https://git.personal.ksv741.ru/WealthLedger/backend/compare/v2.4.0...v2.4.1) (2026-11-06)
### Bug Fixes
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "wealth-ledger-backend",
"version": "3.0.0",
"version": "2.4.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wealth-ledger-backend",
"version": "3.0.0",
"version": "2.4.1",
"license": "UNLICENSED",
"dependencies": {
"@grpc/grpc-js": "1.14.6",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wealth-ledger-backend",
"version": "3.0.0",
"version": "2.4.1",
"description": "",
"author": "",
"private": true,
@@ -244,23 +244,16 @@ export class TbankHourlyScheduler implements OnModuleDestroy, OnModuleInit {
dispatchProblems: HourlySection[],
walkStartedAt: Date,
) {
const portfolios: string[] = [];
for (const account of accounts) {
await this.dispatchPortfolio(
userId,
revision,
account.accountId,
async (child) => {
portfolios.push(child.id);
await dispatch(child);
},
dispatch,
dispatchProblems,
walkStartedAt,
);
}
// Operations coverage must end after the Portfolio valuation it explains:
// performance requires coverage up to the snapshot fetchedAt.
await this.waitWorks(userId, portfolios);
for (const account of accounts) {
await this.dispatchOperations(
userId,
-23
View File
@@ -167,29 +167,6 @@ describe('hourly attempt lifecycle (SQLite)', () => {
expect(read?.state).toBe('succeeded');
});
it('starts operations only after every portfolio work finished', async () => {
const portfolios: string[] = [];
portfolio.request.mockImplementation(
async (_userId: string, _revision: string, accountId: string) => {
const row = await child('running', null, `portfolio:${accountId}`);
portfolios.push(row.id);
return { id: row.id, done: Promise.resolve() };
},
);
const scheduler = createScheduler();
await scheduler.tick();
await pump();
expect(portfolios).toHaveLength(2);
expect(operations.request).not.toHaveBeenCalled();
await prisma.tbankSyncWork.updateMany({
where: { id: { in: portfolios } },
data: { state: 'complete' },
});
const row = await runWalk(scheduler);
expect(operations.request).toHaveBeenCalledTimes(2);
expect(row.state).toBe('complete');
});
it('settles partial and keeps successful steps when one account fails', async () => {
portfolio.request.mockImplementation(
async (_userId: string, _revision: string, accountId: string) => {