Skip to content

Commit

Permalink
#228 Stores SEPA msg_id in transaction. Extracts SEPA msg_id from ban…
Browse files Browse the repository at this point in the history
…k_statement and stores it in statement.
  • Loading branch information
Andreas Finke committed Apr 14, 2022
1 parent 101a5d6 commit 46bf02b
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ source 'https://rubygems.org'
ruby '2.5.8'

gem 'activesupport'
gem 'camt_parser', git: 'https://github.com/railslove/camt_parser.git'
gem 'camt_parser', git: 'https://github.com/railslove/camt_parser.git', ref: '23e99b7'
gem 'cmxl'
gem 'epics', '~> 1.8.1'
gem 'faraday'
Expand Down
3 changes: 2 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
GIT
remote: https://github.com/railslove/camt_parser.git
revision: 90780332f60caa9d5d0e92fef7974f1f0b5338cc
revision: 23e99b772253150f2ff4edff0d7123b810af32db
ref: 23e99b7
specs:
camt_parser (1.0.2)
nokogiri
Expand Down
3 changes: 2 additions & 1 deletion box/business_processes/direct_debit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def self.create!(account, params, user)
payload: Base64.strict_encode64(sdd.to_xml),
amount: params[:amount],
eref: params[:eref],
instrument: params[:instrument]
instrument: params[:instrument],
message_identification: sdd.message_identification
)
else
raise Box::BusinessProcessFailure, sdd.errors
Expand Down
8 changes: 6 additions & 2 deletions box/business_processes/import_statements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ def self.create_statement(bank_statement, bank_transaction, upcoming = false)

def self.link_statement_to_transaction(account, statement)
# find transactions via EREF
transaction = account.transactions_dataset.where(eref: statement.eref).first
transaction = account.transactions_dataset.where(eref: statement.eref).first unless statement.eref.nil?
# find transactions via SEPA msg_id
# ToDo: This fallback works at the moment, because we only add one transaction to each CDD batch.
transaction = account.transactions_dataset.where(msg_id: statement.msg_id).first unless statement.msg_id.nil?
# fallback to finding via statement information
transaction ||= account.transactions_dataset.where { created_at > 14.days.ago }.detect { |t| statement.information =~ /#{t.eref}/i }
transaction ||= account.transactions_dataset.where { created_at > 14.days.ago }.detect { |t| statement.information =~ /#{t.eref}/i } unless statement.information.nil?

return unless transaction

Expand Down Expand Up @@ -112,6 +115,7 @@ def self.statement_attributes_from_bank_transaction(transaction, bank_statement)
eref: transaction.respond_to?(:eref) ? transaction.eref : transaction.sepa['EREF'],
mref: transaction.respond_to?(:mref) ? transaction.mref : transaction.sepa['MREF'],
svwz: transaction.respond_to?(:svwz) ? transaction.svwz : transaction.sepa['SVWZ'],
msg_id: transaction.try(:msg_id),
tx_id: transaction.try(:transaction_id),
creditor_identifier: transaction.respond_to?(:creditor_identifier) ? transaction.creditor_identifier : transaction.sepa['CRED']
}
Expand Down
1 change: 1 addition & 0 deletions box/jobs/debit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def perform(message)
trx.account_id = message[:account_id]
trx.payload = Base64.strict_decode64(message[:payload])
trx.status = 'created'
trx.msg_id = message[:message_identification]
end

return false unless transaction.status == 'created'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

Sequel.migration do
up do
add_column :statements, :msg_id, String
add_column :transactions, :msg_id, String
end

end
33 changes: 31 additions & 2 deletions spec/business_processes/import_statement_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ def exec_create_action
it 'imports camt statements' do
parsed_camt = CamtParser::String.parse(camt).statements
bank_statement = ImportBankStatement.from_cmxl(parsed_camt.first, camt_account)
expect { described_class.from_bank_statement(bank_statement) }.to change { Statement.count }.by(4)
expect { described_class.from_bank_statement(bank_statement) }.to change { Statement.count }.by(5)
expect( Statement.last.msg_id ).to eq("EBICS-BOX/123")
end
end

Expand Down Expand Up @@ -205,7 +206,7 @@ def exec_link_action
end
end

describe '.link_statement_to_transaction fallback' do
describe '.link_statement_to_transaction fallback eref in information' do
let(:statement) { Statement.create(information: 'fallback-eref', account_id: account.id) }

def exec_link_action
Expand Down Expand Up @@ -243,6 +244,34 @@ def exec_link_action
end
end

describe '.link_statement_to_transaction fallback msg_id for debits' do
let(:statement) { Statement.create(msg_id: 'EBICS-BOX/123', account_id: account.id) }

def exec_link_action
described_class.link_statement_to_transaction(account, statement)
end

context 'no transaction could be found' do
it 'does not trigger a webhook' do
expect(Event).to_not receive(:statement_created)
exec_link_action
end
end

context 'transaction exists for debits' do
let!(:transaction) { Transaction.create(account_id: account.id, msg_id: 'EBICS-BOX/123', created_at: Date.today) }
let(:event) { object_double(Event).as_stubbed_const }

context 'statement is a debit' do
before { statement.update(debit: true) }

it 'sets correct transaction state' do
expect_any_instance_of(Transaction).to receive(:update_status).with('debit_received')
exec_link_action
end
end
end
end

describe 'duplicates' do
let(:mt940) { File.read('spec/fixtures/similar_but_not_dup_transactions.mt940') }
Expand Down
108 changes: 108 additions & 0 deletions spec/fixtures/camt_statement.xml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,114 @@
</TxDtls>
</NtryDtls>
</Ntry>
<Ntry>
<Amt Ccy="EUR">8.00</Amt>
<CdtDbtInd>DBIT</CdtDbtInd>
<Sts>BOOK</Sts>
<BookgDt>
<Dt>2013-12-27</Dt>
</BookgDt>
<ValDt>
<Dt>2013-12-27</Dt>
</ValDt>
<AcctSvcrRef>2013122711513230000</AcctSvcrRef>
<BkTxCd/>
<NtryDtls>
<Btch>
<MsgId>EBICS-BOX/123</MsgId>
<PmtInfId>STZV-PmInf27122013-11:02-2</PmtInfId>
<NbOfTxs>2</NbOfTxs>
</Btch>
<TxDtls>
<Refs>
<MsgId>STZV-Msg27122013-11:02</MsgId>
<EndToEndId>STZV-EtE27122013-11:02-1</EndToEndId>
</Refs>
<AmtDtls>
<TxAmt>
<Amt Ccy="EUR">3.50</Amt>
</TxAmt>
</AmtDtls>
<BkTxCd>
<Prtry>
<Cd>NMSC+201</Cd>
<Issr>ZKA</Issr>
</Prtry>
</BkTxCd>
<RltdPties>
<Dbtr>
<Nm>Testkonto Nummer 2</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>DE58740618130100033626</IBAN>
</Id>
</DbtrAcct>
<UltmtDbtr>
<Nm>keine Information vorhanden</Nm>
</UltmtDbtr>
<Cdtr>
<Nm>Testkonto Nummer 1</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>DE14740618130000033626</IBAN>
</Id>
</CdtrAcct>
<UltmtCdtr>
<Nm>Testkonto</Nm>
</UltmtCdtr>
</RltdPties>
<RmtInf>
<Ustrd>Sammelueberwseisung 2. Zahlung TAN:283044 </Ustrd>
</RmtInf>
</TxDtls>
<TxDtls>
<Refs>
<MsgId>STZV-Msg27122013-11:02</MsgId>
<EndToEndId>STZV-EtE27122013-11:02-2</EndToEndId>
</Refs>
<AmtDtls>
<TxAmt>
<Amt Ccy="EUR">2.50</Amt>
</TxAmt>
</AmtDtls>
<BkTxCd>
<Prtry>
<Cd>NMSC+201</Cd>
<Issr>ZKA</Issr>
</Prtry>
</BkTxCd>
<RltdPties>
<Dbtr>
<Nm>Testkonto Nummer 2</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>DE58740618130100033626</IBAN>
</Id>
</DbtrAcct>
<UltmtDbtr>
<Nm>keine Information vorhanden</Nm>
</UltmtDbtr>
<Cdtr>
<Nm>Testkonto Nummer 1</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>DE14740618130000033626</IBAN>
</Id>
</CdtrAcct>
<UltmtCdtr>
<Nm>Testkonto</Nm>
</UltmtCdtr>
</RltdPties>
<RmtInf>
<Ustrd>Sammelueberweisung 1. Zahlung TAN:283044 </Ustrd>
</RmtInf>
</TxDtls>
</NtryDtls>
</Ntry>
</Stmt>
</BkToCstmrStmt>
</Document>

0 comments on commit 46bf02b

Please sign in to comment.