Retry Enable Banking sync with provider-corrected date range (#1801)

* Clamp Enable Banking sync window

* Pipelock noise

---------

Co-authored-by: KiloClaw <kiloclaw@openclaw.ai>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
This commit is contained in:
Sure Admin (bot)
2026-05-17 12:09:51 +02:00
committed by GitHub
parent eb92890a9b
commit 2df10ca4ef
3 changed files with 103 additions and 4 deletions

View File

@@ -29,3 +29,4 @@ jobs:
config/locales/views/reports/
docs/hosting/ai.md
app/models/provider/binance.rb
workers/preview/package-lock.json

View File

@@ -160,7 +160,7 @@ class Provider::EnableBanking
# @param psu_headers [Hash] Optional PSU context headers required by some ASPSPs
# @return [Hash] Transactions and continuation_key for pagination
def get_account_transactions(account_id:, date_from: nil, date_to: nil,
continuation_key: nil, transaction_status: nil, psu_headers: {})
continuation_key: nil, transaction_status: nil, psu_headers: {}, retried_date_from: false)
encoded_id = CGI.escape(account_id.to_s)
query_params = {}
query_params[:transaction_status] = transaction_status if transaction_status.present?
@@ -175,6 +175,22 @@ class Provider::EnableBanking
)
handle_response(response)
rescue EnableBankingError => e
corrected_date_from = e.corrected_date_from
if !retried_date_from && e.wrong_transactions_period? && corrected_date_from.present? && corrected_date_from != date_from
get_account_transactions(
account_id: account_id,
date_from: corrected_date_from,
date_to: date_to,
continuation_key: continuation_key,
transaction_status: transaction_status,
psu_headers: psu_headers,
retried_date_from: true
)
else
raise
end
rescue SocketError, Net::OpenTimeout, Net::ReadTimeout => e
raise EnableBankingError.new("Exception during GET request: #{e.message}", :request_failed)
end
@@ -237,7 +253,8 @@ class Provider::EnableBanking
when 408
raise EnableBankingError.new("Request timeout from Enable Banking API", :timeout)
when 422
raise EnableBankingError.new("Validation error from Enable Banking API: #{response.body}", :validation_error)
response_data = parse_response_body(response)
raise EnableBankingError.new("Validation error from Enable Banking API: #{response.body}", :validation_error, response_data: response_data)
when 429
raise EnableBankingError.new("Rate limit exceeded. Please try again later.", :rate_limited)
else
@@ -255,11 +272,28 @@ class Provider::EnableBanking
end
class EnableBankingError < StandardError
attr_reader :error_type
attr_reader :error_type, :response_data
def initialize(message, error_type = :unknown)
def initialize(message, error_type = :unknown, response_data: nil)
super(message)
@error_type = error_type
@response_data = response_data
end
def wrong_transactions_period?
error_type == :validation_error && response_data.is_a?(Hash) && response_data[:error] == "WRONG_TRANSACTIONS_PERIOD"
end
def corrected_date_from
value = response_data&.dig(:detail, :date_from)
if value.is_a?(Date)
value
elsif value.present?
Date.iso8601(value)
end
rescue ArgumentError
nil
end
end
end

View File

@@ -0,0 +1,64 @@
require "test_helper"
require "ostruct"
require "openssl"
class Provider::EnableBankingTest < ActiveSupport::TestCase
setup do
key = OpenSSL::PKey::RSA.new(2048)
@provider = Provider::EnableBanking.new(application_id: "test_app_id", client_certificate: key.to_pem)
end
test "get_account_transactions retries with corrected date_from from WRONG_TRANSACTIONS_PERIOD" do
requested_queries = []
validation_response = OpenStruct.new(
code: 422,
body: {
error: "WRONG_TRANSACTIONS_PERIOD",
detail: {
message: "Maximum days in the past allowed for transaction list is 120",
date_from: "2026-01-17"
}
}.to_json
)
success_response = OpenStruct.new(
code: 200,
body: { transactions: [] }.to_json
)
Provider::EnableBanking.expects(:get).twice.with do |_url, options|
requested_queries << options[:query].dup
true
end.returns(validation_response, success_response)
result = @provider.get_account_transactions(
account_id: "acct_123",
date_from: Date.new(2025, 12, 1),
transaction_status: "BOOK"
)
assert_equal [], result[:transactions]
assert_equal "2025-12-01", requested_queries.first[:date_from]
assert_equal "2026-01-17", requested_queries.second[:date_from]
end
test "validation errors expose parsed response data" do
response = OpenStruct.new(
code: 422,
body: {
error: "WRONG_TRANSACTIONS_PERIOD",
detail: { date_from: "2026-01-17" }
}.to_json
)
error = assert_raises Provider::EnableBanking::EnableBankingError do
@provider.send(:handle_response, response)
end
assert_equal :validation_error, error.error_type
assert_equal "WRONG_TRANSACTIONS_PERIOD", error.response_data[:error]
assert_equal Date.new(2026, 1, 17), error.corrected_date_from
assert error.wrong_transactions_period?
end
end