Files
sure/test/models/simplefin_account_processor_test.rb
LPW 6e240a2332 Add test for dormant credit cards with zero balance and adjust processor logic (#630)
- Added a new test to validate how dormant credit cards with zero balance and negative available balance are processed.
- Updated processor logic to ensure `current_balance` takes precedence when explicitly set to zero, preventing incorrect usage of `available_balance`.

Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
2026-01-13 09:32:05 +01:00

202 lines
6.0 KiB
Ruby

require "test_helper"
class SimplefinAccountProcessorTest < ActiveSupport::TestCase
setup do
@family = families(:dylan_family)
@item = SimplefinItem.create!(
family: @family,
name: "SimpleFIN",
access_url: "https://example.com/token"
)
end
test "inverts negative balance for credit card liabilities" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Chase Credit",
account_id: "cc_1",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("-123.45")
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("123.45"), acct.reload.balance
end
test "does not invert balance for asset accounts (depository)" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Checking",
account_id: "dep_1",
currency: "USD",
account_type: "checking",
current_balance: BigDecimal("1000.00")
)
acct = accounts(:depository)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("1000.00"), acct.reload.balance
end
test "inverts negative balance for loan liabilities" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Mortgage",
account_id: "loan_1",
currency: "USD",
account_type: "mortgage",
current_balance: BigDecimal("-50000")
)
acct = accounts(:loan)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("50000"), acct.reload.balance
end
test "positive provider balance (overpayment) becomes negative for credit card liabilities" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Chase Credit",
account_id: "cc_overpay",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("75.00") # provider sends positive for overpayment
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("-75.00"), acct.reload.balance
end
test "liability debt with both fields negative becomes positive (you owe)" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "BofA Visa",
account_id: "cc_bofa_1",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("-1200"),
available_balance: BigDecimal("-5000")
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("1200"), acct.reload.balance
end
test "liability overpayment with both fields positive becomes negative (credit)" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "BofA Visa",
account_id: "cc_bofa_2",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("75"),
available_balance: BigDecimal("5000")
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("-75"), acct.reload.balance
end
test "mixed signs falls back to invert observed (balance positive, avail negative => negative)" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Chase Freedom",
account_id: "cc_chase_1",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("50"),
available_balance: BigDecimal("-5000")
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("-50"), acct.reload.balance
end
test "only available-balance present positive → negative (credit) for liability" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Chase Visa",
account_id: "cc_chase_2",
currency: "USD",
account_type: "credit",
current_balance: nil,
available_balance: BigDecimal("25")
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
assert_equal BigDecimal("-25"), acct.reload.balance
end
test "mislinked as asset but mapper infers credit → normalize as liability" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Visa Signature",
account_id: "cc_mislinked",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("100.00"),
available_balance: BigDecimal("5000.00")
)
# Link to an asset account intentionally
acct = accounts(:depository)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
# Mapper should infer liability from name; final should be negative
assert_equal BigDecimal("-100.00"), acct.reload.balance
end
test "dormant credit card with zero balance and negative available-balance shows zero debt" do
sfin_acct = SimplefinAccount.create!(
simplefin_item: @item,
name: "Discover Card",
account_id: "cc_dormant",
currency: "USD",
account_type: "credit",
current_balance: BigDecimal("0"),
available_balance: BigDecimal("-3800") # credit limit reported as negative
)
acct = accounts(:credit_card)
acct.update!(simplefin_account: sfin_acct)
SimplefinAccount::Processor.new(sfin_acct).send(:process_account!)
# Should use explicit zero balance, not negative available_balance
assert_equal BigDecimal("0"), acct.reload.balance
end
end