sepa_file_parser 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/sepa_file_parser/camt052/base.rb +18 -0
- data/lib/sepa_file_parser/camt052/report.rb +73 -0
- data/lib/sepa_file_parser/camt053/base.rb +18 -0
- data/lib/sepa_file_parser/camt053/statement.rb +75 -0
- data/lib/sepa_file_parser/camt054/base.rb +18 -0
- data/lib/sepa_file_parser/camt054/notification.rb +54 -0
- data/lib/sepa_file_parser/errors.rb +12 -0
- data/lib/sepa_file_parser/file.rb +10 -0
- data/lib/sepa_file_parser/general/account.rb +66 -0
- data/lib/sepa_file_parser/general/account_balance.rb +61 -0
- data/lib/sepa_file_parser/general/batch_detail.rb +24 -0
- data/lib/sepa_file_parser/general/charges.rb +25 -0
- data/lib/sepa_file_parser/general/creditor.rb +46 -0
- data/lib/sepa_file_parser/general/debitor.rb +46 -0
- data/lib/sepa_file_parser/general/entry.rb +117 -0
- data/lib/sepa_file_parser/general/group_header.rb +38 -0
- data/lib/sepa_file_parser/general/pain_entry.rb +46 -0
- data/lib/sepa_file_parser/general/postal_address.rb +45 -0
- data/lib/sepa_file_parser/general/record.rb +49 -0
- data/lib/sepa_file_parser/general/transaction.rb +139 -0
- data/lib/sepa_file_parser/general/type/builder.rb +20 -0
- data/lib/sepa_file_parser/general/type/code.rb +13 -0
- data/lib/sepa_file_parser/general/type/proprietary.rb +13 -0
- data/lib/sepa_file_parser/misc.rb +28 -0
- data/lib/sepa_file_parser/pain001/base.rb +18 -0
- data/lib/sepa_file_parser/pain001/payment_information.rb +44 -0
- data/lib/sepa_file_parser/pain008/base.rb +18 -0
- data/lib/sepa_file_parser/pain008/payment_information.rb +44 -0
- data/lib/sepa_file_parser/register.rb +23 -0
- data/lib/sepa_file_parser/string.rb +10 -0
- data/lib/sepa_file_parser/version.rb +5 -0
- data/lib/sepa_file_parser/xml.rb +45 -0
- data/lib/sepa_file_parser.rb +38 -0
- metadata +160 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module SepaFileParser
|
6
|
+
class GroupHeader
|
7
|
+
|
8
|
+
attr_reader :message_id,
|
9
|
+
:creation_date_time,
|
10
|
+
:additional_information,
|
11
|
+
:message_pagination,
|
12
|
+
:xml_data
|
13
|
+
|
14
|
+
def initialize(xml_data)
|
15
|
+
@xml_data = xml_data
|
16
|
+
@message_id = xml_data.xpath('MsgId/text()').text
|
17
|
+
@creation_date_time = Time.parse(xml_data.xpath('CreDtTm/text()').text)
|
18
|
+
@message_pagination = (x = xml_data.xpath('MsgPgntn')).empty? ? nil : MessagePagination.new(x)
|
19
|
+
@additional_information = xml_data.xpath('AddtlInf/text()').text
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class MessagePagination
|
24
|
+
|
25
|
+
attr_reader :page_number,
|
26
|
+
:xml_data
|
27
|
+
|
28
|
+
def initialize(xml_data)
|
29
|
+
@xml_data = xml_data
|
30
|
+
@page_number = xml_data.xpath('PgNb/text()').text.to_i
|
31
|
+
@last_page_indicator = xml_data.xpath('LastPgInd/text()').text == 'true'
|
32
|
+
end
|
33
|
+
|
34
|
+
def last_page?
|
35
|
+
@last_page_indicator
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
class PainEntry
|
5
|
+
|
6
|
+
attr_reader :xml_data
|
7
|
+
|
8
|
+
def initialize(xml_data)
|
9
|
+
@xml_data = xml_data
|
10
|
+
|
11
|
+
@amount = [
|
12
|
+
xml_data.xpath('Amt/InstdAmt').first,
|
13
|
+
xml_data.xpath('InstdAmt').first,
|
14
|
+
].find { |a| a != nil }.text
|
15
|
+
end
|
16
|
+
|
17
|
+
def amount
|
18
|
+
SepaFileParser::Misc.to_amount(@amount)
|
19
|
+
end
|
20
|
+
|
21
|
+
def amount_in_cents
|
22
|
+
SepaFileParser::Misc.to_amount_in_cents(@amount)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [String]
|
26
|
+
def currency
|
27
|
+
@currency ||= [
|
28
|
+
xml_data.xpath('Amt/InstdAmt/@Ccy').first,
|
29
|
+
xml_data.xpath('InstdAmt/@Ccy').first,
|
30
|
+
].find { |a| a != nil }.text
|
31
|
+
end
|
32
|
+
|
33
|
+
def account
|
34
|
+
@account ||= SepaFileParser::Account.from_pain_data(
|
35
|
+
xml_data,
|
36
|
+
currency,
|
37
|
+
'Cdtr',
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def remittance_information
|
42
|
+
@remittance_information ||= xml_data.xpath('RmtInf/Ustrd').text
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
class PostalAddress
|
5
|
+
|
6
|
+
attr_reader :xml_data
|
7
|
+
|
8
|
+
def initialize(xml_data)
|
9
|
+
@xml_data = xml_data
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Array<String>]
|
13
|
+
def lines # May be empty
|
14
|
+
xml_data.xpath('AdrLine').map do |x|
|
15
|
+
x.xpath('text()').text
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
def street_name # May be missing
|
21
|
+
xml_data.xpath('StrtNm/text()').text
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
def building_number # May be missing
|
26
|
+
xml_data.xpath('BldgNb/text()').text
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String]
|
30
|
+
def postal_code # May be missing
|
31
|
+
xml_data.xpath('PstCd/text()').text
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [String]
|
35
|
+
def town_name # May be missing
|
36
|
+
xml_data.xpath('TwnNm/text()').text
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
def country # May be missing
|
41
|
+
xml_data.xpath('Ctry/text()').text
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
class Record
|
5
|
+
|
6
|
+
attr_reader :xml_data
|
7
|
+
|
8
|
+
def initialize(xml_data)
|
9
|
+
@xml_data = xml_data
|
10
|
+
@amount = xml_data.xpath('Amt/text()').text
|
11
|
+
end
|
12
|
+
|
13
|
+
def amount
|
14
|
+
SepaFileParser::Misc.to_amount(@amount)
|
15
|
+
end
|
16
|
+
|
17
|
+
def amount_in_cents
|
18
|
+
SepaFileParser::Misc.to_amount_in_cents(@amount)
|
19
|
+
end
|
20
|
+
|
21
|
+
def currency
|
22
|
+
@currency ||= xml_data.xpath('Amt/@Ccy').text
|
23
|
+
end
|
24
|
+
|
25
|
+
def type
|
26
|
+
@type ||= SepaFileParser::Type::Builder.build_type(xml_data.xpath('Tp'))
|
27
|
+
end
|
28
|
+
|
29
|
+
def charges_included?
|
30
|
+
@charges_included ||= xml_data.xpath('ChrgInclInd/text()').text.downcase == 'true'
|
31
|
+
end
|
32
|
+
|
33
|
+
def debit
|
34
|
+
@debit ||= xml_data.xpath('CdtDbtInd/text()').text.upcase == 'DBIT'
|
35
|
+
end
|
36
|
+
|
37
|
+
def credit?
|
38
|
+
!debit
|
39
|
+
end
|
40
|
+
|
41
|
+
def debit?
|
42
|
+
debit
|
43
|
+
end
|
44
|
+
|
45
|
+
def sign
|
46
|
+
credit? ? 1 : -1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
class Transaction
|
5
|
+
|
6
|
+
attr_reader :xml_data
|
7
|
+
|
8
|
+
def initialize(xml_data, debit, amount = nil, currency = nil)
|
9
|
+
@xml_data = xml_data
|
10
|
+
@debit = debit
|
11
|
+
@amount = parse_amount || amount
|
12
|
+
@currency = parse_currency || currency
|
13
|
+
end
|
14
|
+
|
15
|
+
def amount
|
16
|
+
SepaFileParser::Misc.to_amount(@amount)
|
17
|
+
end
|
18
|
+
|
19
|
+
def amount_in_cents
|
20
|
+
SepaFileParser::Misc.to_amount_in_cents(@amount)
|
21
|
+
end
|
22
|
+
|
23
|
+
def currency
|
24
|
+
@currency
|
25
|
+
end
|
26
|
+
|
27
|
+
def creditor
|
28
|
+
@creditor ||= SepaFileParser::Creditor.new(xml_data)
|
29
|
+
end
|
30
|
+
|
31
|
+
def debitor
|
32
|
+
@debitor ||= SepaFileParser::Debitor.new(xml_data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def name
|
36
|
+
credit? ? debitor.name : creditor.name
|
37
|
+
end
|
38
|
+
|
39
|
+
def iban
|
40
|
+
credit? ? debitor.iban : creditor.iban
|
41
|
+
end
|
42
|
+
|
43
|
+
def bic
|
44
|
+
credit? ? debitor.bic : creditor.bic
|
45
|
+
end
|
46
|
+
|
47
|
+
def postal_address
|
48
|
+
credit? ? debitor.postal_address : creditor.postal_address
|
49
|
+
end
|
50
|
+
|
51
|
+
def credit?
|
52
|
+
!debit
|
53
|
+
end
|
54
|
+
|
55
|
+
def debit?
|
56
|
+
debit
|
57
|
+
end
|
58
|
+
|
59
|
+
def debit
|
60
|
+
@debit
|
61
|
+
end
|
62
|
+
|
63
|
+
def sign
|
64
|
+
credit? ? 1 : -1
|
65
|
+
end
|
66
|
+
|
67
|
+
def remittance_information
|
68
|
+
@remittance_information ||= begin
|
69
|
+
if (x = xml_data.xpath('RmtInf/Ustrd')).empty?
|
70
|
+
nil
|
71
|
+
else
|
72
|
+
x.collect(&:content).join(' ')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def swift_code
|
78
|
+
@swift_code ||= xml_data.xpath('BkTxCd/Prtry/Cd/text()').text.split('+')[0]
|
79
|
+
end
|
80
|
+
|
81
|
+
def reference
|
82
|
+
@reference ||= xml_data.xpath('Refs/InstrId/text()').text
|
83
|
+
end
|
84
|
+
|
85
|
+
def bank_reference # May be missing
|
86
|
+
@bank_reference ||= xml_data.xpath('Refs/AcctSvcrRef/text()').text
|
87
|
+
end
|
88
|
+
|
89
|
+
def end_to_end_reference # May be missing
|
90
|
+
@end_to_end_reference ||= xml_data.xpath('Refs/EndToEndId/text()').text
|
91
|
+
end
|
92
|
+
|
93
|
+
def mandate_reference # May be missing
|
94
|
+
@mandate_reference ||= xml_data.xpath('Refs/MndtId/text()').text
|
95
|
+
end
|
96
|
+
|
97
|
+
def creditor_reference # May be missing
|
98
|
+
@creditor_reference ||= xml_data.xpath('RmtInf/Strd/CdtrRefInf/Ref/text()').text
|
99
|
+
end
|
100
|
+
|
101
|
+
def transaction_id # May be missing
|
102
|
+
@transaction_id ||= xml_data.xpath('Refs/TxId/text()').text
|
103
|
+
end
|
104
|
+
|
105
|
+
def creditor_identifier # May be missing
|
106
|
+
@creditor_identifier ||= xml_data.xpath('RltdPties/Cdtr/Id/PrvtId/Othr/Id/text()').text
|
107
|
+
end
|
108
|
+
|
109
|
+
def payment_information # May be missing
|
110
|
+
@payment_information ||= xml_data.xpath('Refs/PmtInfId/text()').text
|
111
|
+
end
|
112
|
+
|
113
|
+
def additional_information # May be missing
|
114
|
+
@addition_information ||= xml_data.xpath('AddtlTxInf/text()').text
|
115
|
+
end
|
116
|
+
|
117
|
+
def reason_code # May be missing
|
118
|
+
@reason_code ||= xml_data.xpath('RtrInf/Rsn/Cd/text()').text
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def parse_amount
|
124
|
+
if xml_data.xpath('Amt').any?
|
125
|
+
xml_data.xpath('Amt/text()').text
|
126
|
+
elsif xml_data.xpath('AmtDtls').any?
|
127
|
+
xml_data.xpath('AmtDtls//Amt/text()').first.text
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def parse_currency
|
132
|
+
if xml_data.xpath('Amt').any?
|
133
|
+
xml_data.xpath('Amt/@Ccy').text
|
134
|
+
elsif xml_data.xpath('AmtDtls').any?
|
135
|
+
xml_data.xpath('AmtDtls//Amt/@Ccy').first.text
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
module Type
|
5
|
+
class Builder
|
6
|
+
def self.build_type(xml_data)
|
7
|
+
if xml_data.xpath('Prtry').any?
|
8
|
+
Proprietary.new(
|
9
|
+
xml_data.xpath('Prtry/Id/text()').text,
|
10
|
+
xml_data.xpath('Prtry/Issr/text()').text
|
11
|
+
)
|
12
|
+
elsif xml_data.xpath('Cd').any?
|
13
|
+
Code.new(xml_data.xpath('Cd/text()').text)
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
class Misc
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# @param value [nil, String]
|
8
|
+
# @return [Integer, nil]
|
9
|
+
def to_amount_in_cents(value)
|
10
|
+
return nil if value == nil || value.strip == ''
|
11
|
+
|
12
|
+
# Using dollars and cents as representation for parts before and after the decimal separator
|
13
|
+
dollars, cents = value.split(/,|\./)
|
14
|
+
cents ||= '0'
|
15
|
+
format('%s%s', dollars, cents.ljust(2, '0')).to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param value [nil, String]
|
19
|
+
# @return [BigDecimal, nil]
|
20
|
+
def to_amount(value)
|
21
|
+
return nil if value == nil || value.strip == ''
|
22
|
+
|
23
|
+
BigDecimal(value.tr(',', '.'))
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
module Pain001
|
5
|
+
class Base
|
6
|
+
attr_reader :group_header, :payment_informations, :xml_data
|
7
|
+
|
8
|
+
def initialize(xml_data)
|
9
|
+
@xml_data = xml_data
|
10
|
+
# CstmrCdtTrfInitn = Customer Credit Transaction Initiation
|
11
|
+
grphdr = xml_data.xpath('CstmrCdtTrfInitn/GrpHdr')
|
12
|
+
@group_header = SepaFileParser::GroupHeader.new(grphdr)
|
13
|
+
payment_informations = xml_data.xpath('CstmrCdtTrfInitn/PmtInf')
|
14
|
+
@payment_informations = payment_informations.map{ |x| PaymentInformation.new(x) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
module Pain001
|
5
|
+
class PaymentInformation
|
6
|
+
|
7
|
+
attr_reader :xml_data
|
8
|
+
|
9
|
+
def initialize(xml_data)
|
10
|
+
@xml_data = xml_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def identification
|
14
|
+
@identification ||= xml_data.xpath('PmtInfId/text()').text
|
15
|
+
end
|
16
|
+
|
17
|
+
def requested_execution_date
|
18
|
+
@requested_execution_date ||= Time.parse(xml_data.xpath('ReqdExctnDt/text()').text)
|
19
|
+
end
|
20
|
+
|
21
|
+
def account
|
22
|
+
@account ||= SepaFileParser::Account.from_pain_data(
|
23
|
+
xml_data,
|
24
|
+
entries.first.currency,
|
25
|
+
'Dbtr',
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def entries
|
30
|
+
@entries ||= xml_data.xpath('CdtTrfTxInf').map do |x|
|
31
|
+
SepaFileParser::PainEntry.new(x)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def source
|
36
|
+
xml_data.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse(xml)
|
40
|
+
self.new(Nokogiri::XML(xml).xpath('PmtInf'))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
module Pain008
|
5
|
+
class Base
|
6
|
+
attr_reader :group_header, :payment_informations, :xml_data
|
7
|
+
|
8
|
+
def initialize(xml_data)
|
9
|
+
@xml_data = xml_data
|
10
|
+
# CstmrDrctDbtInitn = Customer Direct Debig Initiation
|
11
|
+
grphdr = xml_data.xpath('CstmrDrctDbtInitn/GrpHdr')
|
12
|
+
@group_header = SepaFileParser::GroupHeader.new(grphdr)
|
13
|
+
payment_informations = xml_data.xpath('CstmrDrctDbtInitn/PmtInf')
|
14
|
+
@payment_informations = payment_informations.map{ |x| PaymentInformation.new(x) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
module Pain008
|
5
|
+
class PaymentInformation
|
6
|
+
|
7
|
+
attr_reader :xml_data
|
8
|
+
|
9
|
+
def initialize(xml_data)
|
10
|
+
@xml_data = xml_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def identification
|
14
|
+
@identification ||= xml_data.xpath('PmtInfId/text()').text
|
15
|
+
end
|
16
|
+
|
17
|
+
def requested_collection_date
|
18
|
+
@requested_collection_date ||= Time.parse(xml_data.xpath('ReqdColltnDt/text()').text)
|
19
|
+
end
|
20
|
+
|
21
|
+
def account
|
22
|
+
@account ||= SepaFileParser::Account.from_pain_data(
|
23
|
+
xml_data,
|
24
|
+
entries.first.currency,
|
25
|
+
'Cdtr',
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def entries
|
30
|
+
@entries ||= xml_data.xpath('DrctDbtTxInf').map do |x|
|
31
|
+
SepaFileParser::PainEntry.new(x)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def source
|
36
|
+
xml_data.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse(xml)
|
40
|
+
self.new(Nokogiri::XML(xml).xpath('PmtInf'))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './xml'
|
4
|
+
|
5
|
+
# Add registrations
|
6
|
+
## CAMT052
|
7
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.052.001.02', :camt052)
|
8
|
+
|
9
|
+
## CAMT053
|
10
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.02', :camt053)
|
11
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.04', :camt053)
|
12
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.08', :camt053)
|
13
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.10', :camt053)
|
14
|
+
|
15
|
+
## CAMT054
|
16
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.054.001.02', :camt054)
|
17
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.054.001.04', :camt054)
|
18
|
+
|
19
|
+
## PAIN001
|
20
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:pain.001.001.03', :pain001)
|
21
|
+
|
22
|
+
## PAIN008
|
23
|
+
SepaFileParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:pain.008.003.02', :pain008)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SepaFileParser
|
4
|
+
class Xml
|
5
|
+
PARSER_MAPPING = {
|
6
|
+
camt052: SepaFileParser::Camt052::Base,
|
7
|
+
camt053: SepaFileParser::Camt053::Base,
|
8
|
+
camt054: SepaFileParser::Camt054::Base,
|
9
|
+
pain001: SepaFileParser::Pain001::Base,
|
10
|
+
pain008: SepaFileParser::Pain008::Base,
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
SUPPORTED_PARSERS = PARSER_MAPPING.keys.freeze
|
14
|
+
|
15
|
+
@namespace_parsers = {}
|
16
|
+
|
17
|
+
def self.register(namespace, parser)
|
18
|
+
if !SUPPORTED_PARSERS.include?(parser)
|
19
|
+
raise SepaFileParser::Errors::UnsupportedParserClass, parser.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
if @namespace_parsers.key?(namespace) # Prevent overwriting existing registrations
|
23
|
+
raise SepaFileParser::Errors::NamespaceAlreadyRegistered, namespace
|
24
|
+
end
|
25
|
+
|
26
|
+
@namespace_parsers[namespace] = PARSER_MAPPING[parser]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse(doc)
|
30
|
+
if !doc.is_a?(Nokogiri::XML::Document)
|
31
|
+
raise SepaFileParser::Errors::NotXMLError, doc.class
|
32
|
+
end
|
33
|
+
|
34
|
+
namespace = doc.namespaces['xmlns']
|
35
|
+
doc.remove_namespaces!
|
36
|
+
|
37
|
+
parser_class = @namespace_parsers[namespace]
|
38
|
+
if parser_class == nil
|
39
|
+
raise SepaFileParser::Errors::UnsupportedNamespaceError, namespace
|
40
|
+
end
|
41
|
+
|
42
|
+
return parser_class.new(doc.xpath('Document'))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'time'
|
5
|
+
require 'bigdecimal'
|
6
|
+
|
7
|
+
require_relative 'sepa_file_parser/misc'
|
8
|
+
require_relative 'sepa_file_parser/version'
|
9
|
+
require_relative 'sepa_file_parser/errors'
|
10
|
+
require_relative 'sepa_file_parser/general/account_balance'
|
11
|
+
require_relative 'sepa_file_parser/general/creditor'
|
12
|
+
require_relative 'sepa_file_parser/general/debitor'
|
13
|
+
require_relative 'sepa_file_parser/general/entry'
|
14
|
+
require_relative 'sepa_file_parser/general/record'
|
15
|
+
require_relative 'sepa_file_parser/general/charges'
|
16
|
+
require_relative 'sepa_file_parser/general/account'
|
17
|
+
require_relative 'sepa_file_parser/general/batch_detail'
|
18
|
+
require_relative 'sepa_file_parser/general/group_header'
|
19
|
+
require_relative 'sepa_file_parser/general/pain_entry'
|
20
|
+
require_relative 'sepa_file_parser/general/postal_address'
|
21
|
+
require_relative 'sepa_file_parser/general/transaction'
|
22
|
+
require_relative 'sepa_file_parser/general/type/builder'
|
23
|
+
require_relative 'sepa_file_parser/general/type/code'
|
24
|
+
require_relative 'sepa_file_parser/general/type/proprietary'
|
25
|
+
require_relative 'sepa_file_parser/camt052/report'
|
26
|
+
require_relative 'sepa_file_parser/camt052/base'
|
27
|
+
require_relative 'sepa_file_parser/camt053/statement'
|
28
|
+
require_relative 'sepa_file_parser/camt053/base'
|
29
|
+
require_relative 'sepa_file_parser/camt054/notification'
|
30
|
+
require_relative 'sepa_file_parser/camt054/base'
|
31
|
+
require_relative 'sepa_file_parser/pain001/payment_information'
|
32
|
+
require_relative 'sepa_file_parser/pain001/base'
|
33
|
+
require_relative 'sepa_file_parser/pain008/payment_information'
|
34
|
+
require_relative 'sepa_file_parser/pain008/base'
|
35
|
+
require_relative 'sepa_file_parser/file'
|
36
|
+
require_relative 'sepa_file_parser/string'
|
37
|
+
require_relative 'sepa_file_parser/register'
|
38
|
+
require_relative 'sepa_file_parser/xml'
|