The net and savings-rate derivation was byte-identical in
DashboardController::calculateCashflowSummary and
CashflowAnalyticsController::cashflowSummaryFromTransactions, so the two
screens could silently diverge if one formula were ever edited.
Extract a single CashflowSummaryService::summarize(income, expense) that
owns the net and savings-rate math, and have both call sites consume it.
Behaviour-preserving: each controller still computes income/expense its
own way (single-currency SQL on the dashboard, multi-currency in-memory
on the analytics endpoint) and only the shared derivation moves.