diff --git a/app/models/enable_banking_item/importer.rb b/app/models/enable_banking_item/importer.rb index 9facd18d2..e35f8c59d 100644 --- a/app/models/enable_banking_item/importer.rb +++ b/app/models/enable_banking_item/importer.rb @@ -3,6 +3,10 @@ class EnableBankingItem::Importer # Enable Banking typically returns ~100 transactions per page, so 100 pages = ~10,000 transactions MAX_PAGINATION_PAGES = 100 + # Balance type priority: prefer booked balances over available balances. + # Available types (CLAV, ITAV) include overdraft/credit capacity and inflate balances. + BALANCE_TYPE_PRIORITY = %w[CLBD XPCD ITBD CLAV ITAV].freeze + attr_reader :enable_banking_item, :enable_banking_provider def initialize(enable_banking_item, enable_banking_provider:) @@ -161,12 +165,8 @@ class EnableBankingItem::Importer balances = balance_data[:balances] || [] return if balances.empty? - # Find the most relevant balance (prefer "ITAV" or "CLAV" types) - balance = balances.find { |b| b[:balance_type] == "ITAV" } || - balances.find { |b| b[:balance_type] == "CLAV" } || - balances.find { |b| b[:balance_type] == "ITBD" } || - balances.find { |b| b[:balance_type] == "CLBD" } || - balances.first + # Find the most relevant balance (prefer booked over available types) + balance = select_balance(balances) if balance.present? amount = balance.dig(:balance_amount, :amount) || balance[:amount] @@ -183,6 +183,14 @@ class EnableBankingItem::Importer Rails.logger.error "EnableBankingItem::Importer - Error fetching balance for account #{enable_banking_account.uid}: #{e.message}" end + def select_balance(balances) + BALANCE_TYPE_PRIORITY.each do |type| + found = balances.find { |b| b[:balance_type] == type } + return found if found + end + balances.first + end + def fetch_and_store_transactions(enable_banking_account) start_date = determine_sync_start_date(enable_banking_account) diff --git a/test/models/enable_banking_item/importer_balance_selection_test.rb b/test/models/enable_banking_item/importer_balance_selection_test.rb new file mode 100644 index 000000000..c26f86723 --- /dev/null +++ b/test/models/enable_banking_item/importer_balance_selection_test.rb @@ -0,0 +1,88 @@ +require "test_helper" + +class EnableBankingItem::ImporterBalanceSelectionTest < ActiveSupport::TestCase + setup do + @family = families(:dylan_family) + @enable_banking_item = EnableBankingItem.create!( + family: @family, + name: "Test Enable Banking", + country_code: "AT", + application_id: "test_app_id", + client_certificate: "test_cert", + session_id: "test_session", + session_expires_at: 1.day.from_now + ) + + mock_provider = mock() + @importer = EnableBankingItem::Importer.new(@enable_banking_item, enable_banking_provider: mock_provider) + end + + test "prefers CLBD when multiple balance types are present" do + balances = [ + { balance_type: "ITAV", balance_amount: { amount: "4332.81", currency: "EUR" } }, + { balance_type: "CLAV", balance_amount: { amount: "4332.81", currency: "EUR" } }, + { balance_type: "ITBD", balance_amount: { amount: "232.81", currency: "EUR" } }, + { balance_type: "CLBD", balance_amount: { amount: "232.81", currency: "EUR" } } + ] + + result = @importer.send(:select_balance, balances) + + assert_equal "CLBD", result[:balance_type] + assert_equal "232.81", result[:balance_amount][:amount] + end + + test "prefers XPCD over ITBD" do + balances = [ + { balance_type: "ITBD", balance_amount: { amount: "100.00", currency: "EUR" } }, + { balance_type: "XPCD", balance_amount: { amount: "150.00", currency: "EUR" } } + ] + + result = @importer.send(:select_balance, balances) + + assert_equal "XPCD", result[:balance_type] + end + + test "falls back through priority chain" do + balances = [ + { balance_type: "ITAV", balance_amount: { amount: "5000.00", currency: "EUR" } }, + { balance_type: "ITBD", balance_amount: { amount: "900.00", currency: "EUR" } } + ] + + result = @importer.send(:select_balance, balances) + + assert_equal "ITBD", result[:balance_type] + end + + test "CLAV is preferred over ITAV" do + balances = [ + { balance_type: "ITAV", balance_amount: { amount: "5000.00", currency: "EUR" } }, + { balance_type: "CLAV", balance_amount: { amount: "4800.00", currency: "EUR" } } + ] + + result = @importer.send(:select_balance, balances) + + assert_equal "CLAV", result[:balance_type] + end + + test "falls back to first balance when no known types present" do + balances = [ + { balance_type: "PRCD", balance_amount: { amount: "500.00", currency: "EUR" } }, + { balance_type: "INFO", balance_amount: { amount: "600.00", currency: "EUR" } } + ] + + result = @importer.send(:select_balance, balances) + + assert_equal "PRCD", result[:balance_type] + assert_equal "500.00", result[:balance_amount][:amount] + end + + test "returns single balance regardless of type" do + balances = [ + { balance_type: "ITAV", balance_amount: { amount: "1000.00", currency: "EUR" } } + ] + + result = @importer.send(:select_balance, balances) + + assert_equal "ITAV", result[:balance_type] + end +end