fix(portfolio): publish new complete forecast regardless of request window (WealthLedger/backend#55) #156

Merged
codex-bot merged 1 commits from fix/55-forecast-latest-selection into develop 2026-11-02 22:42:46 +03:00
Owner

Summary

Новый полный forecast становится latest независимо от пересечения окон; GET с from/to читает latest и фильтрует, сохраняя исходные calculatedAt/окно.

Linked Issue

Refs WealthLedger/backend#55 (audit 2026-10-11: BE-001, BE-013)

Changes

  • ForecastRepository.resolve: убран ранний возврат первого пересекающегося fallback до validation/upsert кандидата. Latest выбирается детерминированно (calculatedAt desc, scopeKey asc) в пределах account + текущей membership revision, включая непересекающиеся окна (успешный пустой результат вместо null).
  • Публикует кандидат только запрос с default-окном (hourly и GET без from/to: replacesLatest). Явный from/to публикует лишь при отсутствии сохранённого forecast. Это решение владельца по BE-013.
  • Failed/неполный кандидат: возвращается previous complete forecast (решение владельца по BE-013), смешанная база не публикуется.
  • ForecastService.filterEvents добавляет в ответ исходное окно сохранённого forecast.
  • Ключ scopeKey и схема БД не менялись: миграции нет, старые строки не трогаются.
  • Stock dividends и bond coupons: их exact-key логика не изменена, регрессия покрыта существующими тестами.

Verification

  • Падающие на старом коде (5 из 26) тесты test/upcoming-events.e2e-spec.ts: W0→W1 с изменённой quantity, disjoint = пустой результат, narrow GET не заменяет latest, failed calendar после сдвига окна, публикация без зависимостей.
  • npm run verify: 42 suites / 310 tests, lint, typecheck app+test, build — OK.
  • npm run test:e2e (все SQLite-suites): OK. upcoming-events.e2e-spec.ts 26/26.
  • npm run openapi:generate: openapi.json в .gitignore; schema содержит UpcomingEventsDto.window.
  • Не проверено в runtime: реальный T-Bank/MOEX (live-вызовы запрещены), PostgreSQL/prod-данные.

Breaking Changes (если есть)

Нет. Additive изменение контракта: UpcomingEventsDto.window: { from: 'YYYY-MM-DD', to: 'YYYY-MM-DD' } (required в ответе). Frontend нужно регенерировать типы; текущий клиент не ломается.

## Summary Новый полный forecast становится latest независимо от пересечения окон; GET с `from`/`to` читает latest и фильтрует, сохраняя исходные `calculatedAt`/окно. ## Linked Issue Refs WealthLedger/backend#55 (audit 2026-10-11: BE-001, BE-013) ## Changes - `ForecastRepository.resolve`: убран ранний возврат первого пересекающегося fallback до validation/upsert кандидата. Latest выбирается детерминированно (`calculatedAt desc, scopeKey asc`) в пределах account + текущей membership revision, включая непересекающиеся окна (успешный пустой результат вместо `null`). - Публикует кандидат только запрос с default-окном (hourly и GET без `from`/`to`: `replacesLatest`). Явный `from`/`to` публикует лишь при отсутствии сохранённого forecast. Это решение владельца по BE-013. - Failed/неполный кандидат: возвращается previous complete forecast (решение владельца по BE-013), смешанная база не публикуется. - `ForecastService.filterEvents` добавляет в ответ исходное окно сохранённого forecast. - Ключ `scopeKey` и схема БД не менялись: миграции нет, старые строки не трогаются. - Stock dividends и bond coupons: их exact-key логика не изменена, регрессия покрыта существующими тестами. ## Verification - Падающие на старом коде (5 из 26) тесты `test/upcoming-events.e2e-spec.ts`: W0→W1 с изменённой quantity, disjoint = пустой результат, narrow GET не заменяет latest, failed calendar после сдвига окна, публикация без зависимостей. - `npm run verify`: 42 suites / 310 tests, lint, typecheck app+test, build — OK. - `npm run test:e2e` (все SQLite-suites): OK. `upcoming-events.e2e-spec.ts` 26/26. - `npm run openapi:generate`: `openapi.json` в `.gitignore`; schema содержит `UpcomingEventsDto.window`. - Не проверено в runtime: реальный T-Bank/MOEX (live-вызовы запрещены), PostgreSQL/prod-данные. ## Breaking Changes (если есть) Нет. Additive изменение контракта: `UpcomingEventsDto.window: { from: 'YYYY-MM-DD', to: 'YYYY-MM-DD' }` (required в ответе). Frontend нужно регенерировать типы; текущий клиент не ломается.
codex-bot added 1 commit 2026-11-02 22:23:15 +03:00
fix(portfolio): publish new complete forecast regardless of request window (WealthLedger/backend#55)
Backend verify / commits (pull_request) Successful in 1m22s
Backend verify / security (pull_request) Successful in 1m6s
Backend verify / verify (pull_request) Successful in 6m7s
e9e0ff8ee6
codex-bot merged commit 169bee1da5 into develop 2026-11-02 22:42:46 +03:00
codex-bot deleted branch fix/55-forecast-latest-selection 2026-11-02 22:42:47 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: WealthLedger/backend#156