Files
sure/test/models/transaction_test.rb
Juan José Mata b48cec3a2e fix: Transfers were not syncing between accounts (#987)
* fix: Include investment_contribution in transfer? check and protect transfer entries from sync

Transfer transactions with kind "investment_contribution" were not recognized
as transfers by the UI, causing missing +/- indicators, "Transfer" labels,
and showing regular transaction forms instead of transfer details.

Also adds user_modified: true to entries created via TransferMatchesController
and SetAsTransferOrPayment rule action to protect them from provider sync
overwrites, matching the existing behavior in Transfer::Creator.

https://claude.ai/code/session_019BZ5Z1aqKSK3cRdR81P5Jg

* fix: Centralize transfer/budget kind constants for consistent investment_contribution handling

Define TRANSFER_KINDS and BUDGET_EXCLUDED_KINDS on Transaction to eliminate
hard-coded kind lists scattered across filters, rules, and analytics code.

investment_contribution is now consistently treated as a transfer in search
filters, rule conditions, and UI display (via TRANSFER_KINDS), while budget
analytics correctly continue treating it as an expense (via BUDGET_EXCLUDED_KINDS).

https://claude.ai/code/session_019BZ5Z1aqKSK3cRdR81P5Jg

* fix: Update tests for consistent investment_contribution as transfer kind

- search_test: loan_payment is now in TRANSFER_KINDS, so uncategorized
  filter correctly excludes it (same as funds_movement/cc_payment)
- condition_test: investment_contribution is now a transfer kind, so it
  matches the transfer filter rather than expense filter

https://claude.ai/code/session_019BZ5Z1aqKSK3cRdR81P5Jg

* fix: Eliminate SQL injection warnings in Transaction::Search

Replace string-interpolated SQL with parameterized queries:
- totals: use sanitize_sql_array with ? placeholders
- apply_category_filter: pass TRANSFER_KINDS as bind parameter
- apply_type_filter: use where(kind:)/where.not(kind:) and
  parameterized IN (?) for compound OR conditions
- Remove unused transfer_kinds_sql helper

https://claude.ai/code/session_019BZ5Z1aqKSK3cRdR81P5Jg

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-16 13:50:06 +01:00

71 lines
2.6 KiB
Ruby

require "test_helper"
class TransactionTest < ActiveSupport::TestCase
test "pending? is true when extra.simplefin.pending is truthy" do
transaction = Transaction.new(extra: { "simplefin" => { "pending" => true } })
assert transaction.pending?
end
test "pending? is true when extra.plaid.pending is truthy" do
transaction = Transaction.new(extra: { "plaid" => { "pending" => "true" } })
assert transaction.pending?
end
test "pending? is true when extra.lunchflow.pending is truthy" do
transaction = Transaction.new(extra: { "lunchflow" => { "pending" => true } })
assert transaction.pending?
end
test "pending? is false when no provider pending metadata is present" do
transaction = Transaction.new(extra: { "plaid" => { "pending" => false } })
assert_not transaction.pending?
end
test "investment_contribution is a valid kind" do
transaction = Transaction.new(kind: "investment_contribution")
assert_equal "investment_contribution", transaction.kind
assert transaction.investment_contribution?
end
test "TRANSFER_KINDS constant matches transfer? method" do
Transaction::TRANSFER_KINDS.each do |kind|
assert Transaction.new(kind: kind).transfer?, "#{kind} should be a transfer kind"
end
non_transfer_kinds = Transaction.kinds.keys - Transaction::TRANSFER_KINDS
non_transfer_kinds.each do |kind|
assert_not Transaction.new(kind: kind).transfer?, "#{kind} should NOT be a transfer kind"
end
end
test "all transaction kinds are valid" do
valid_kinds = %w[standard funds_movement cc_payment loan_payment one_time investment_contribution]
valid_kinds.each do |kind|
transaction = Transaction.new(kind: kind)
assert_equal kind, transaction.kind, "#{kind} should be a valid transaction kind"
end
end
test "ACTIVITY_LABELS contains all valid labels" do
assert_includes Transaction::ACTIVITY_LABELS, "Buy"
assert_includes Transaction::ACTIVITY_LABELS, "Sell"
assert_includes Transaction::ACTIVITY_LABELS, "Sweep In"
assert_includes Transaction::ACTIVITY_LABELS, "Sweep Out"
assert_includes Transaction::ACTIVITY_LABELS, "Dividend"
assert_includes Transaction::ACTIVITY_LABELS, "Reinvestment"
assert_includes Transaction::ACTIVITY_LABELS, "Interest"
assert_includes Transaction::ACTIVITY_LABELS, "Fee"
assert_includes Transaction::ACTIVITY_LABELS, "Transfer"
assert_includes Transaction::ACTIVITY_LABELS, "Contribution"
assert_includes Transaction::ACTIVITY_LABELS, "Withdrawal"
assert_includes Transaction::ACTIVITY_LABELS, "Exchange"
assert_includes Transaction::ACTIVITY_LABELS, "Other"
end
end