Show inflow/outflow totals for transfer filter (#1134)

* Show inflow/outflow totals when filtering by transfers

When filtering transactions by "Transfer" type, the summary bar previously
showed $0 for both Income and Expenses because transfers were excluded from
those sums. Now computes transfer inflow/outflow in the same SQL pass and
switches labels to "Inflow"/"Outflow" when transfer amounts are non-zero.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add mixed filter comment and transfer-only test coverage

Document the intentional mixed filter behavior where transfer amounts
are excluded from the summary bar when non-transfer types are present.
Add test exercising Inflow/Outflow label switching for transfer-only results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Juan Manuel Reyes
2026-03-26 13:12:01 -07:00
committed by GitHub
parent f1991eaefe
commit f42b593b9e
4 changed files with 79 additions and 14 deletions

View File

@@ -52,7 +52,7 @@ class Transaction::Search
# because those transactions are retirement savings, not daily income/expenses.
def totals
@totals ||= begin
Rails.cache.fetch("transaction_search_totals/#{cache_key_base}") do
Rails.cache.fetch("transaction_search_totals/v2/#{cache_key_base}") do
scope = transactions_scope
# Exclude tax-advantaged accounts from totals calculation
@@ -69,6 +69,14 @@ class Transaction::Search
"COALESCE(SUM(CASE WHEN entries.amount < 0 AND transactions.kind NOT IN (?) THEN ABS(entries.amount * COALESCE(er.rate, 1)) ELSE 0 END), 0) as income_total",
Transaction::TRANSFER_KINDS
]),
ActiveRecord::Base.sanitize_sql_array([
"COALESCE(SUM(CASE WHEN entries.amount < 0 AND transactions.kind IN (?) THEN ABS(entries.amount * COALESCE(er.rate, 1)) ELSE 0 END), 0) as transfer_inflow_total",
Transaction::TRANSFER_KINDS
]),
ActiveRecord::Base.sanitize_sql_array([
"COALESCE(SUM(CASE WHEN entries.amount >= 0 AND transactions.kind IN (?) THEN ABS(entries.amount * COALESCE(er.rate, 1)) ELSE 0 END), 0) as transfer_outflow_total",
Transaction::TRANSFER_KINDS
]),
"COUNT(entries.id) as transactions_count"
)
.joins(
@@ -82,7 +90,9 @@ class Transaction::Search
Totals.new(
count: result.transactions_count.to_i,
income_money: Money.new(result.income_total, family.currency),
expense_money: Money.new(result.expense_total, family.currency)
expense_money: Money.new(result.expense_total, family.currency),
transfer_inflow_money: Money.new(result.transfer_inflow_total, family.currency),
transfer_outflow_money: Money.new(result.transfer_outflow_total, family.currency)
)
end
end
@@ -99,7 +109,7 @@ class Transaction::Search
end
private
Totals = Data.define(:count, :income_money, :expense_money)
Totals = Data.define(:count, :income_money, :expense_money, :transfer_inflow_money, :transfer_outflow_money)
def apply_active_accounts_filter(query, active_accounts_only_filter)
if active_accounts_only_filter