fix: loan transfer kind assignment to use destination account (#874)

* fix: loan transfer kind assignment to use destination account

* fix: update system test to use depository account instead of investment account
This commit is contained in:
BitToby
2026-02-07 08:06:30 -03:00
committed by GitHub
parent c6d3d85922
commit 5239c3c11a
3 changed files with 58 additions and 4 deletions

View File

@@ -69,8 +69,12 @@ module Family::AutoTransferMatchable
# Another concurrent job created the transfer; safe to ignore
end
Transaction.find(match.inflow_transaction_id).update!(kind: "funds_movement")
Transaction.find(match.outflow_transaction_id).update!(kind: Transfer.kind_for_account(Transaction.find(match.outflow_transaction_id).entry.account))
inflow_transaction = Transaction.find(match.inflow_transaction_id)
outflow_transaction = Transaction.find(match.outflow_transaction_id)
# The kind is determined by the DESTINATION account (inflow), matching Transfer::Creator logic
inflow_transaction.update!(kind: "funds_movement")
outflow_transaction.update!(kind: Transfer.kind_for_account(inflow_transaction.entry.account))
used_transaction_ids << match.inflow_transaction_id
used_transaction_ids << match.outflow_transaction_id

View File

@@ -7,6 +7,7 @@ class Family::AutoTransferMatchableTest < ActiveSupport::TestCase
@family = families(:dylan_family)
@depository = accounts(:depository)
@credit_card = accounts(:credit_card)
@loan = accounts(:loan)
end
test "auto-matches transfers" do
@@ -117,6 +118,54 @@ class Family::AutoTransferMatchableTest < ActiveSupport::TestCase
end
end
# Regression tests for loan transfer kind assignment bug
# The kind should be determined by the DESTINATION account (inflow), not the source (outflow)
test "loan payment (cash to loan) assigns loan_payment kind to outflow" do
# Cash → Loan: outflow from depository, inflow to loan
outflow_entry = create_transaction(date: Date.current, account: @depository, amount: 500)
inflow_entry = create_transaction(date: Date.current, account: @loan, amount: -500)
@family.auto_match_transfers!
outflow_entry.reload
inflow_entry.reload
# Destination is loan account, so outflow should be loan_payment
assert_equal "loan_payment", outflow_entry.entryable.kind
assert_equal "funds_movement", inflow_entry.entryable.kind
end
test "loan disbursement (loan to cash) assigns funds_movement kind to outflow" do
# Loan → Cash: outflow from loan, inflow to depository
outflow_entry = create_transaction(date: Date.current, account: @loan, amount: 500)
inflow_entry = create_transaction(date: Date.current, account: @depository, amount: -500)
@family.auto_match_transfers!
outflow_entry.reload
inflow_entry.reload
# Destination is depository (not loan), so outflow should be funds_movement
# This ensures loan disbursements don't incorrectly appear in cashflow
assert_equal "funds_movement", outflow_entry.entryable.kind
assert_equal "funds_movement", inflow_entry.entryable.kind
end
test "credit card payment (cash to credit card) assigns cc_payment kind to outflow" do
# Cash → Credit Card: outflow from depository, inflow to credit card
outflow_entry = create_transaction(date: Date.current, account: @depository, amount: 500)
inflow_entry = create_transaction(date: Date.current, account: @credit_card, amount: -500)
@family.auto_match_transfers!
outflow_entry.reload
inflow_entry.reload
# Destination is credit card, so outflow should be cc_payment
assert_equal "cc_payment", outflow_entry.entryable.kind
assert_equal "funds_movement", inflow_entry.entryable.kind
end
private
def load_exchange_prices
rates = {

View File

@@ -201,10 +201,11 @@ class TransactionsTest < ApplicationSystemTestCase
end
test "transfers should always sum to zero" do
# Use two accounts that result in funds_movement kind (not investment/crypto which become investment_contribution)
asset_account = accounts(:other_asset)
investment_account = accounts(:investment)
depository_account = accounts(:depository)
outflow_entry = create_transaction("outflow", Date.current, 500, account: asset_account)
inflow_entry = create_transaction("inflow", 1.day.ago.to_date, -500, account: investment_account)
inflow_entry = create_transaction("inflow", 1.day.ago.to_date, -500, account: depository_account)
@user.family.auto_match_transfers!
visit transactions_url