Skip to content

Commit

Permalink
Add basic pain002 support
Browse files Browse the repository at this point in the history
Main use case at this time is retrieving the message id
  • Loading branch information
Tobias Schoknecht committed May 28, 2024
1 parent fd8f9a6 commit 9c6df0b
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
sepa_file_parser (0.1.0)
sepa_file_parser (0.2.0)
bigdecimal
nokogiri
time
Expand Down
2 changes: 2 additions & 0 deletions lib/sepa_file_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
require_relative 'sepa_file_parser/camt054/base'
require_relative 'sepa_file_parser/pain001/payment_information'
require_relative 'sepa_file_parser/pain001/base'
require_relative 'sepa_file_parser/pain002/report'
require_relative 'sepa_file_parser/pain002/base'
require_relative 'sepa_file_parser/pain008/payment_information'
require_relative 'sepa_file_parser/pain008/base'
require_relative 'sepa_file_parser/file'
Expand Down
18 changes: 18 additions & 0 deletions lib/sepa_file_parser/pain002/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module SepaFileParser
module Pain002
class Base
attr_reader :group_header, :reports, :xml_data

def initialize(xml_data)
@xml_data = xml_data
# CstmrPmtStsRpt = Customer Payment Status Report
grphdr = xml_data.xpath('CstmrPmtStsRpt/GrpHdr')
@group_header = SepaFileParser::GroupHeader.new(grphdr)
reports = xml_data.xpath('CstmrPmtStsRpt/OrgnlPmtInfAndSts')
@reports = reports.map { |x| Report.new(x) }
end
end
end
end
31 changes: 31 additions & 0 deletions lib/sepa_file_parser/pain002/report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

module SepaFileParser
module Pain002
class Report

attr_reader :xml_data

def initialize(xml_data)
@xml_data = xml_data
end

def original_identification
@original_identification ||= xml_data.xpath('OrgnlPmtInfId/text()').text
end

def status_id
@status_id ||= xml_data.xpath('TxInfAndSts/StsId/text()').text
end

def transaction_status
@transaction_status ||= xml_data.xpath('TxInfAndSts/TxSts/text()').text
end

def source
xml_data.to_s
end

end
end
end
3 changes: 3 additions & 0 deletions lib/sepa_file_parser/register.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@
## PAIN001
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:pain.001.001.03', :pain001)

## PAIN002
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:pain.002.001.03', :pain002)

## PAIN008
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:pain.008.003.02', :pain008)
2 changes: 1 addition & 1 deletion lib/sepa_file_parser/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module SepaFileParser
VERSION = '0.1.0'.freeze
VERSION = '0.2.0'.freeze
end
1 change: 1 addition & 0 deletions lib/sepa_file_parser/xml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Xml
camt053: SepaFileParser::Camt053::Base,
camt054: SepaFileParser::Camt054::Base,
pain001: SepaFileParser::Pain001::Base,
pain002: SepaFileParser::Pain002::Base,
pain008: SepaFileParser::Pain008::Base,
}.freeze

Expand Down
101 changes: 101 additions & 0 deletions spec/fixtures/pain002/valid_example.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03 pain.002.001.03.xsd">
<CstmrPmtStsRpt>
<GrpHdr>
<MsgId>Message-ID-12346</MsgId>
<CreDtTm>2024-05-22T09:30:47.000Z</CreDtTm>
<CdtrAgt>
<FinInstnId>
<BIC>KKKKDEFFXXX</BIC>
</FinInstnId>
</CdtrAgt>
</GrpHdr>
<OrgnlGrpInfAndSts>
<OrgnlMsgId>Message-ID-12345</OrgnlMsgId>
<OrgnlMsgNmId>pain.008</OrgnlMsgNmId>
</OrgnlGrpInfAndSts>
<OrgnlPmtInfAndSts>
<OrgnlPmtInfId>Payment-Information-ID-12345</OrgnlPmtInfId>
<TxInfAndSts>
<StsId>Status-ID</StsId>
<OrgnlEndToEndId>Source1234</OrgnlEndToEndId>
<TxSts>RJCT</TxSts>
<StsRsnInf>
<Orgtr>
<Id>
<OrgId>
<BICOrBEI>KKKKDEFFXXX</BICOrBEI>
</OrgId>
</Id>
</Orgtr>
<Rsn>
<Cd>AC01</Cd>
</Rsn>
</StsRsnInf>
<OrgnlTxRef>
<Amt>
<InstdAmt Ccy="EUR">6543.14</InstdAmt>
</Amt>
<ReqdColltnDt>2024-05-03</ReqdColltnDt>
<CdtrSchmeId>
<Id>
<PrvtId>
<Othr>
<Id>DE99ZZZ100001234567</Id>
<SchmeNm>
<Prtry>SEPA</Prtry>
</SchmeNm>
</Othr>
</PrvtId>
</Id>
</CdtrSchmeId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<LclInstrm>
<Cd>CORE</Cd>
</LclInstrm>
<SeqTp>FRST</SeqTp>
</PmtTpInf>
<MndtRltdInf>
<MndtId>Mandate-Id</MndtId>
<DtOfSgntr>2024-05-20</DtOfSgntr>
</MndtRltdInf>
<RmtInf>
<Ustrd>Unstructured Remittance Information</Ustrd>
</RmtInf>
<UltmtDbtr>
<Nm>Ultimate Debtor Name</Nm>
</UltmtDbtr>
<Dbtr>
<Nm>Debtor Name</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>DE89370400440532013000</IBAN>
</Id>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC>COBADEFFXXX</BIC>
</FinInstnId>
</DbtrAgt>
<CdtrAgt>
<FinInstnId>
<BIC>COBADEFFXXX</BIC>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm>Creditor Name</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>DE75512108001245126199</IBAN>
</Id>
</CdtrAcct>
</OrgnlTxRef>
</TxInfAndSts>
</OrgnlPmtInfAndSts>
</CstmrPmtStsRpt>
</Document>
23 changes: 23 additions & 0 deletions spec/lib/sepa_file_parser/pain002/base_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe SepaFileParser::Pain002::Base do

context 'initialization' do
after do
SepaFileParser::File.parse 'spec/fixtures/pain002/valid_example.xml'
end

specify { expect(SepaFileParser::GroupHeader).to receive(:new).and_call_original }
specify do
expect(SepaFileParser::Pain002::Report).to receive(:new).and_call_original
end
end

let(:pain) { SepaFileParser::File.parse 'spec/fixtures/pain002/valid_example.xml' }
specify { expect(pain.group_header).to_not be_nil }
specify { expect(pain.reports).to_not eq([]) }
specify { expect(pain.xml_data).to_not be_nil }

end
18 changes: 18 additions & 0 deletions spec/lib/sepa_file_parser/pain002/report_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe SepaFileParser::Pain002::Report do
let(:pain) { SepaFileParser::File.parse('spec/fixtures/pain002/valid_example.xml') }

let(:reports) { pain.reports }
let(:ex_report) { pain.reports[0] }
let(:entry) { ex_report.entries[0] }

specify { expect(reports).to all(be_kind_of(described_class)) }
specify { expect(ex_report.original_identification).to eq('Payment-Information-ID-12345') }
specify { expect(ex_report.status_id).to eq('Status-ID') }
specify { expect(ex_report.transaction_status).to eq('RJCT') }

specify { expect(pain.xml_data.nil?).to eq(false) }
end

0 comments on commit 9c6df0b

Please sign in to comment.