Skip to content

Commit

Permalink
Add method to parse bank transactions as JSON
Browse files Browse the repository at this point in the history
This implements parsing of the Account Information Service format as
defined in the Berlin Group Group NextGenPSD2 XS2A Framework, which
is widely used across various European banks.

This is a first step to replace the current bank import features with
a standardized JSON interface.
  • Loading branch information
paroga committed Feb 24, 2021
1 parent f7c7b56 commit b99fdd1
Show file tree
Hide file tree
Showing 3 changed files with 471 additions and 0 deletions.
4 changes: 4 additions & 0 deletions app/models/bank_account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ def assign_unlinked_transactions
end
count
end

def last_transaction_date
bank_transactions.order(date: :desc).first&.date
end
end
55 changes: 55 additions & 0 deletions lib/bank_account_information_importer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class BankAccountInformationImporter

def initialize(bank_account)
@bank_account = bank_account
end

def import!(content)
return nil if content.empty?
data = JSON.parse content, symbolize_names: true

return 0 if data.empty?
booked = data.fetch(:transactions, {}).fetch(:booked, [])

ret = 0
booked.each do |t|
amount = parse_account_information_amount t[:transactionAmount]
entityName = amount < 0 ? t[:creditorName] : t[:debtorName]
entityAccount = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]

@bank_account.bank_transactions.where(external_id: t[:transactionId]).first_or_create.update({
date: t[:bookingDate],
amount: amount,
iban: entityAccount && entityAccount[:iban],
reference: t[:remittanceInformationUnstructured],
text: entityName,
receipt: t[:additionalInformation],
})
ret += 1
end

balances = Hash[ data[:balances] ? data[:balances].map { |b| [b[:balanceType], b[:balanceAmount]] } : [] ]
balance = balances.values.first
%w(closingBooked expected authorised openingBooked interimAvailable forwardAvailable nonInvoiced).each do |type|
value = balances[type]
if value then
balance = value
break
end
end

@bank_account.balance = parse_account_information_amount(balance) || @bank_account.bank_transactions.sum(:amount)
@bank_account.import_continuation_point = booked.first&.fetch(:entryReference, nil)
@bank_account.last_import = Time.now
@bank_account.save!

ret
end

private

def parse_account_information_amount(value)
value && value[:amount].to_f
end

end
Loading

0 comments on commit b99fdd1

Please sign in to comment.