Files
sure/test/models/enable_banking_account_processor_test.rb
Stephen Jolly ba0e169f6b Don't persist zero balances when a provider balance fetch fails (#2617)
* fix(sync): don't persist zero balances when a provider balance fetch fails

A nil current_balance means the sync's balance fetch did not succeed
(the snapshot upsert clears it; only a successful fetch repopulates it).
The Lunchflow and Enable Banking processors coerced nil to 0 and write
it (plus a currency fallback) onto the linked account, so any transient
provider failure persists wrong data with no user-visible signal.
Instead, treat nil as no-data: skip the account update. Also stop the
Lunchflow snapshot upsert resetting an established account's currency to
USD when the accounts endpoint omits currency.

* fix(lunchflow): normalize the preserved currency in snapshot upsert

Addresses the review comment on #2617: the preserved fallback reused the
record's raw in-memory currency, so a blank value would fail the presence
validation and break import, and an invalid code would persist instead of
falling back to USD. Run it through parse_currency like the payload value.
Regression test added.

* fix(lunchflow,eb): review round 2 — failure visibility and currency parity

Addresses the three review findings on #2617:
1. Capture the Lunch Flow balance-fetch failure via DebugLogEntry (the sync
   otherwise reports success with no mention of the skip).
   This is Lunch Flow only: Enable Banking's importer already surfaces the
   failure through transactions_failed/@sync_error.
2. Apply the currency-preservation fix to Enable Banking's snapshot upsert
   (same shape as the Lunch Flow fix: parity/safety). Regression test added.
3. Label the Enable Banking processor currency assertion as a parity check —
   it also passes on main, since the reset defect was Lunch Flow-specific.
2026-07-08 08:08:10 +02:00

62 lines
2.3 KiB
Ruby

require "test_helper"
class EnableBankingAccountProcessorTest < ActiveSupport::TestCase
setup do
@family = families(:dylan_family)
@item = EnableBankingItem.new(family: @family, name: "Enable Banking",
country_code: "GB", application_id: "test-app")
@item.save!(validate: false)
end
test "skips the account update when current_balance is nil (failed balance fetch)" do
eb_acct = @item.enable_banking_accounts.create!(
name: "Checking",
uid: "eb_1",
currency: "GBP",
current_balance: nil
)
acct = accounts(:depository)
acct.update!(balance: 500, cash_balance: 500, currency: "GBP")
AccountProvider.create!(account: acct, provider: eb_acct)
EnableBankingAccount::Processor.new(eb_acct).send(:process_account!)
acct.reload
assert_equal BigDecimal("500"), acct.cash_balance,
"a sync whose balance fetch failed must not zero the account"
assert_equal BigDecimal("500"), acct.balance
# Parity/invariant check, not regression coverage: unlike Lunch Flow, the
# EB *processor* never had a currency-reset defect (its fallback chain
# already preferred the stored value), so this assertion also passes on
# main. The EB currency regression test lives at the model layer below.
assert_equal "GBP", acct.currency,
"a sync whose balance fetch failed must not change the account currency"
end
test "still updates the account when current_balance is present" do
eb_acct = @item.enable_banking_accounts.create!(
name: "Checking",
uid: "eb_2",
currency: "GBP",
current_balance: BigDecimal("250")
)
acct = accounts(:depository)
acct.update!(balance: 500, cash_balance: 500, currency: "GBP")
AccountProvider.create!(account: acct, provider: eb_acct)
EnableBankingAccount::Processor.new(eb_acct).send(:process_account!)
assert_equal BigDecimal("250"), acct.reload.cash_balance
end
test "snapshot upsert preserves an established currency when the payload omits it" do
eb_acct = @item.enable_banking_accounts.create!(name: "Checking", uid: "eb_3", currency: "GBP")
eb_acct.upsert_enable_banking_snapshot!({ uid: "eb_3", name: "Checking" })
assert_equal "GBP", eb_acct.reload.currency,
"an omitted payload currency must not reset an established account to EUR"
end
end