mirror of
https://github.com/we-promise/sure.git
synced 2026-05-10 14:15:01 +00:00
feat(enable-banking): safe pending transaction merge with sync re-import prevention (#1709)
* feat(enable-banking): safe pending transaction merge with sync re-import prevention * preserve all merged pending IDs across syncs * fix(enable-banking): harden merge locking, safe logging, and non-blocking index * fix(enable-banking): use safe external ID in invalid currency log * refactor(models): centralize pending transaction SQL logic Move the SQL fragment used to identify pending transactions from the `Entry` model to a constant in the `Transaction` model. This improves maintainability and ensures that the logic for determining if a transaction is pending is defined in a single location. * fix(enable-banking): drop dead manual_merge index, use lateral join for excluded IDs * No net schema changes --------- Co-authored-by: Juan José Mata <jjmata@jjmata.com>
This commit is contained in:
@@ -10,6 +10,12 @@ class EnableBankingEntry::Processor
|
||||
# transaction_amount: { amount, currency },
|
||||
# creditor_name, debtor_name, remittance_information, ...
|
||||
# }
|
||||
def self.compute_external_id(raw_transaction_data)
|
||||
data = raw_transaction_data.with_indifferent_access
|
||||
id = data[:transaction_id].presence || data[:entry_reference].presence
|
||||
id ? "enable_banking_#{id}" : nil
|
||||
end
|
||||
|
||||
def initialize(enable_banking_transaction, enable_banking_account:, import_adapter: nil)
|
||||
@enable_banking_transaction = enable_banking_transaction
|
||||
@enable_banking_account = enable_banking_account
|
||||
@@ -17,8 +23,12 @@ class EnableBankingEntry::Processor
|
||||
end
|
||||
|
||||
def process
|
||||
# Cache a safe diagnostic id upfront — used in all logging paths so rescue
|
||||
# blocks never call the potentially-raising private external_id method.
|
||||
safe_id = self.class.compute_external_id(@enable_banking_transaction) || "unknown"
|
||||
|
||||
unless account.present?
|
||||
Rails.logger.warn "EnableBankingEntry::Processor - No linked account for enable_banking_account #{enable_banking_account.id}, skipping transaction #{external_id}"
|
||||
Rails.logger.warn "EnableBankingEntry::Processor - No linked account for enable_banking_account #{enable_banking_account.id}, skipping transaction #{safe_id}"
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -35,13 +45,13 @@ class EnableBankingEntry::Processor
|
||||
extra: extra
|
||||
)
|
||||
rescue ArgumentError => e
|
||||
Rails.logger.error "EnableBankingEntry::Processor - Validation error for transaction #{external_id}: #{e.message}"
|
||||
Rails.logger.error "EnableBankingEntry::Processor - Validation error for transaction #{safe_id}: #{e.message}"
|
||||
raise
|
||||
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved => e
|
||||
Rails.logger.error "EnableBankingEntry::Processor - Failed to save transaction #{external_id}: #{e.message}"
|
||||
Rails.logger.error "EnableBankingEntry::Processor - Failed to save transaction #{safe_id}: #{e.message}"
|
||||
raise StandardError.new("Failed to import transaction: #{e.message}")
|
||||
rescue => e
|
||||
Rails.logger.error "EnableBankingEntry::Processor - Unexpected error processing transaction #{external_id}: #{e.class} - #{e.message}"
|
||||
Rails.logger.error "EnableBankingEntry::Processor - Unexpected error processing transaction #{safe_id}: #{e.class} - #{e.message}"
|
||||
Rails.logger.error e.backtrace.join("\n")
|
||||
raise StandardError.new("Unexpected error importing transaction: #{e.message}")
|
||||
end
|
||||
@@ -64,9 +74,9 @@ class EnableBankingEntry::Processor
|
||||
end
|
||||
|
||||
def external_id
|
||||
id = data[:transaction_id].presence || data[:entry_reference].presence
|
||||
id = self.class.compute_external_id(data)
|
||||
raise ArgumentError, "Enable Banking transaction missing required field 'transaction_id'" unless id
|
||||
"enable_banking_#{id}"
|
||||
id
|
||||
end
|
||||
|
||||
def name
|
||||
@@ -220,7 +230,8 @@ class EnableBankingEntry::Processor
|
||||
end
|
||||
|
||||
def log_invalid_currency(currency_value)
|
||||
Rails.logger.warn("Invalid currency code '#{currency_value}' in Enable Banking transaction #{external_id}, falling back to account currency")
|
||||
safe_id = self.class.compute_external_id(data) || "unknown"
|
||||
Rails.logger.warn("Invalid currency code '#{currency_value}' in Enable Banking transaction #{safe_id}, falling back to account currency")
|
||||
end
|
||||
|
||||
def date
|
||||
|
||||
Reference in New Issue
Block a user