fix(sync): store EnableBanking credit card debt as balance instead of available credit (#2459)

* fix(sync): store EnableBanking credit card debt as balance instead of available credit

Previously, the EnableBanking processor forcibly overrode the primary account balance for credit cards to be the available credit (credit_limit - debt) rather than the actual outstanding debt. Since credit cards are modeled as Liability accounts, this caused the balance sheet (net worth) to treat available credit mathematically as a debt.

This PR aligns the EnableBanking processor with the Plaid and SimpleFIN processors by storing the absolute debt as the account balance, while tracking the available credit via accountable metadata.

Fixes #2458

* docs(sync): update EnableBanking credit card processor documentation

Updates the inline processor comments to reflect the new behavior introduced by the previous commit, clarifying that outstanding debt is stored sequentially as the primary balance rather than the UX available credit overriding it.

* refactor(sync): clarify balance and available credit calculations in EnableBanking processor

Refactors the debt polarity assignments to clarify why liability balances are strictly parsed as absolute positive numbers. Replaces the implicit ordering dependency between the '.abs' conversion and the 'available_credit' math with an explicit 'outstanding_debt' variable to prevent regression by future maintainers.

* style: remove trailing whitespace in EnableBanking processor
This commit is contained in:
Markus Laaksonen
2026-06-27 07:20:50 +03:00
committed by GitHub
parent f79926abee
commit 112b09f425
2 changed files with 31 additions and 27 deletions

View File

@@ -42,7 +42,7 @@ class EnableBankingAccount::ProcessorTest < ActiveSupport::TestCase
assert_nil result
end
test "sets CC balance to available_credit when credit_limit is present" do
test "sets CC balance as absolute debt and tracks available_credit when limit is present" do
cc_account = accounts(:credit_card)
@enable_banking_account.update!(
current_balance: 450.00,
@@ -53,13 +53,13 @@ class EnableBankingAccount::ProcessorTest < ActiveSupport::TestCase
EnableBankingAccount::Processor.new(@enable_banking_account).process
assert_equal 550.0, cc_account.reload.cash_balance
assert_equal 450.0, cc_account.reload.cash_balance
if cc_account.accountable.respond_to?(:available_credit)
assert_equal 550.0, cc_account.accountable.reload.available_credit
end
end
test "falls back to stored available_credit when credit_limit is absent" do
test "sets CC balance as absolute debt and keeps stored available_credit when limit absent" do
cc_account = accounts(:credit_card)
cc_account.accountable.update!(available_credit: 1000.0)
@@ -70,10 +70,11 @@ class EnableBankingAccount::ProcessorTest < ActiveSupport::TestCase
EnableBankingAccount::Processor.new(@enable_banking_account).process
assert_equal 700.0, cc_account.reload.cash_balance
assert_equal 300.0, cc_account.reload.cash_balance
assert_equal 1000.0, cc_account.accountable.reload.available_credit
end
test "sets CC balance to raw outstanding when credit_limit is absent" do
test "sets CC balance to absolute debt when both limit and stored available_credit are absent" do
cc_account = accounts(:credit_card)
cc_account.accountable.update!(available_credit: nil)