* feat(balance): incremental ForwardCalculator — only recalculate from changed date forward
When a Sync record carries a window_start_date, ForwardCalculator now
seeds its starting balances from the persisted DB balance for
window_start_date - 1, then iterates only from window_start_date to
calc_end_date. This avoids recomputing every daily balance on a
long-lived account when a single transaction changes.
Key changes:
- Account::Syncer passes sync.window_start_date to Balance::Materializer
- Balance::Materializer accepts window_start_date and forwards it to
ForwardCalculator; purge_stale_balances uses opening_anchor_date as the
lower bound in incremental mode so pre-window balances are not deleted
- Balance::ForwardCalculator accepts window_start_date; resolve_starting_balances
loads end_cash_balance/end_non_cash_balance from the prior DB record and
falls back to full recalculation when no prior record exists
- Tests added for incremental correctness, fallback behaviour, and purge safety
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Conflicts:
# app/models/balance/materializer.rb
* Enhance fallback logic on ForwardCalculator and Materializer
* fix(balance): address CodeRabbit review issues on incremental ForwardCalculator
- materializer.rb: handle empty sorted_balances in incremental mode by still
purging stale tail balances beyond window_start_date - 1, preventing orphaned
future rows when a transaction is deleted and the recalc window produces no rows
- materializer_test.rb: stub incremental? alongside calculate in the incremental
sync test so the guard in ForwardCalculator#incremental? doesn't raise when
@fell_back is nil (never set because calculate was stubbed out)
- materializer_test.rb: correct window_start_date in the fallback test from
3.days.ago to 2.days.ago so window_start_date - 1 hits a date with no
persisted balance, correctly triggering full recalculation instead of
accidentally seeding from the stale wrong_pre_window balance
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(balance): multi-currency fallback to full recalculation and add corresponding tests
* address coderabbit comment about test
* Make the foreign-currency precondition explicit in the test setup.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Feat: Implement manual sync prices functionality and enhance holdings display
* Feat: Enhance sync prices functionality with error handling and update UI components
* Feat: Update sync prices error handling and enhance Spanish locale messages
* Fix: Address CodeRabbit review feedback
- Set fallback @provider_error when prices_updated == 0 so turbo stream
never fails silently without a visible error message
- Move attr_reader :provider_error to class header in Price::Importer
for conventional placement alongside other attribute declarations
- Precompute @last_price_updated in controller (show + sync_prices)
instead of running a DB query directly inside ERB templates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Replace bare rescue with explicit exception handling in turbo stream view
Bare `rescue` silently swallows all exceptions, making debugging impossible.
Match the pattern already used in show.html.erb: rescue ActiveRecord::RecordInvalid
explicitly, then catch StandardError with logging (message + backtrace) before
falling back to the unknown label.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Update test assertion to expect actual provider error message
The stub returns "Yahoo Finance rate limit exceeded" as the provider error.
After the @provider_error fallback fix, the controller now correctly surfaces
the real provider error when present (using .presence || fallback), so the
flash[:alert] is the actual error string, not the generic fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix: Assert scoped security_ids in sync_prices materializer test
Replace loose stub with constructor expectation to verify that
Balance::Materializer is instantiated with the single-security scope.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix: Assert holding remap in remap_security test
Add assertion that @holding.security_id is updated to the target
security after remap, covering the core command outcome.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix: CI test failure - Update disconnect external assistant test to use env overrides
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Balance reconcilations with new components
* Fix materializer and test assumptions
* Fix investment valuation calculations and recon display
* Lint fixes
* Balance series uses new component fields