camt_parser 2.14.0 → 2.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/camt_parser/052/base.rb +2 -1
- data/lib/camt_parser/052/report.rb +13 -10
- data/lib/camt_parser/053/base.rb +3 -1
- data/lib/camt_parser/053/statement.rb +14 -11
- data/lib/camt_parser/054/base.rb +3 -1
- data/lib/camt_parser/054/notification.rb +18 -7
- data/lib/camt_parser/general/account.rb +17 -5
- data/lib/camt_parser/general/account_balance.rb +12 -0
- data/lib/camt_parser/general/batch_detail.rb +6 -3
- data/lib/camt_parser/general/charges.rb +5 -2
- data/lib/camt_parser/general/creditor.rb +13 -4
- data/lib/camt_parser/general/debitor.rb +13 -4
- data/lib/camt_parser/general/entry.rb +43 -18
- data/lib/camt_parser/general/group_header.rb +11 -2
- data/lib/camt_parser/general/record.rb +8 -5
- data/lib/camt_parser/general/transaction.rb +25 -22
- data/lib/camt_parser/misc.rb +5 -0
- data/lib/camt_parser/register.rb +2 -0
- data/lib/camt_parser/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5aeab74fdc7446d278695d00616a5449870180088c7dc8daf1aa52a83897cfc
|
4
|
+
data.tar.gz: f032bd706926a5314a2c7f110f6053962b91f6a0e4222bb633c2094f98ac3d6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a59f2634bf67b442365cc7b32dd5c7c4295872e536af30dc8901a2a30a7499100a785f6a09df9e2b08494a4356b3227eb3622a747aa4f3ff6def6476f4132ab7
|
7
|
+
data.tar.gz: febcbdb49b56ac81342cd31ab5e6252071769a167a8221850e47b817f850e90ef6fb25a3920f360be550fc58209e024a76b56678b3cd327d7367f54769412829
|
data/lib/camt_parser/052/base.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module CamtParser
|
2
2
|
module Format052
|
3
3
|
class Base
|
4
|
-
attr_reader :group_header, :reports
|
4
|
+
attr_reader :group_header, :reports, :xml_data
|
5
5
|
|
6
6
|
def initialize(xml_data)
|
7
|
+
@xml_data = xml_data
|
7
8
|
# BkToCstmrAccptRpt = Bank to Customer Account Report
|
8
9
|
grphdr = xml_data.xpath('BkToCstmrAcctRpt/GrpHdr')
|
9
10
|
@group_header = CamtParser::GroupHeader.new(grphdr)
|
@@ -1,41 +1,44 @@
|
|
1
1
|
module CamtParser
|
2
2
|
module Format052
|
3
3
|
class Report
|
4
|
+
|
5
|
+
attr_reader :xml_data
|
6
|
+
|
4
7
|
def initialize(xml_data)
|
5
8
|
@xml_data = xml_data
|
6
9
|
end
|
7
10
|
|
8
11
|
def identification
|
9
|
-
@identification ||=
|
12
|
+
@identification ||= xml_data.xpath('Id/text()').text
|
10
13
|
end
|
11
14
|
|
12
15
|
def generation_date
|
13
|
-
@generation_date ||= Time.parse(
|
16
|
+
@generation_date ||= Time.parse(xml_data.xpath('CreDtTm/text()').text)
|
14
17
|
end
|
15
18
|
|
16
19
|
def account
|
17
|
-
@account ||= CamtParser::Account.new(
|
20
|
+
@account ||= CamtParser::Account.new(xml_data.xpath('Acct').first)
|
18
21
|
end
|
19
22
|
|
20
23
|
def entries
|
21
|
-
@entries ||=
|
24
|
+
@entries ||= xml_data.xpath('Ntry').map{ |x| CamtParser::Entry.new(x) }
|
22
25
|
end
|
23
26
|
|
24
27
|
def legal_sequence_number
|
25
|
-
@legal_sequence_number ||=
|
28
|
+
@legal_sequence_number ||= xml_data.xpath('LglSeqNb/text()').text
|
26
29
|
end
|
27
30
|
|
28
31
|
def from_date_time
|
29
|
-
@from_date_time ||= (x =
|
32
|
+
@from_date_time ||= (x = xml_data.xpath('FrToDt/FrDtTm')).empty? ? nil : Time.parse(x.first.content)
|
30
33
|
end
|
31
34
|
|
32
35
|
def to_date_time
|
33
|
-
@to_date_time ||= (x =
|
36
|
+
@to_date_time ||= (x = xml_data.xpath('FrToDt/ToDtTm')).empty? ? nil : Time.parse(x.first.content)
|
34
37
|
end
|
35
38
|
|
36
39
|
def opening_balance
|
37
40
|
@opening_balance ||= begin
|
38
|
-
bal =
|
41
|
+
bal = xml_data.xpath('Bal/Tp//Cd[contains(text(), "PRCD")]').first.ancestors('Bal')
|
39
42
|
date = bal.xpath('Dt/Dt/text()').text
|
40
43
|
credit = bal.xpath('CdtDbtInd/text()').text == 'CRDT'
|
41
44
|
currency = bal.xpath('Amt').attribute('Ccy').value
|
@@ -46,7 +49,7 @@ module CamtParser
|
|
46
49
|
|
47
50
|
def closing_balance
|
48
51
|
@closing_balance ||= begin
|
49
|
-
bal =
|
52
|
+
bal = xml_data.xpath('Bal/Tp//Cd[contains(text(), "CLBD")]').first.ancestors('Bal')
|
50
53
|
date = bal.xpath('Dt/Dt/text()').text
|
51
54
|
credit = bal.xpath('CdtDbtInd/text()').text == 'CRDT'
|
52
55
|
currency = bal.xpath('Amt').attribute('Ccy').value
|
@@ -57,7 +60,7 @@ module CamtParser
|
|
57
60
|
|
58
61
|
|
59
62
|
def source
|
60
|
-
|
63
|
+
xml_data.to_s
|
61
64
|
end
|
62
65
|
|
63
66
|
def self.parse(xml)
|
data/lib/camt_parser/053/base.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
module CamtParser
|
2
2
|
module Format053
|
3
3
|
class Base
|
4
|
-
attr_reader :group_header, :statements
|
4
|
+
attr_reader :group_header, :statements, :xml_data
|
5
5
|
|
6
6
|
def initialize(xml_data)
|
7
|
+
@xml_data = xml_data
|
8
|
+
|
7
9
|
grphdr = xml_data.xpath('BkToCstmrStmt/GrpHdr')
|
8
10
|
@group_header = GroupHeader.new(grphdr)
|
9
11
|
statements = xml_data.xpath('BkToCstmrStmt/Stmt')
|
@@ -1,45 +1,48 @@
|
|
1
1
|
module CamtParser
|
2
2
|
module Format053
|
3
3
|
class Statement
|
4
|
+
|
5
|
+
attr_reader :xml_data
|
6
|
+
|
4
7
|
def initialize(xml_data)
|
5
8
|
@xml_data = xml_data
|
6
9
|
end
|
7
10
|
|
8
11
|
def identification
|
9
|
-
@identification ||=
|
12
|
+
@identification ||= xml_data.xpath('Id/text()').text
|
10
13
|
end
|
11
14
|
|
12
15
|
def generation_date
|
13
|
-
@generation_date ||= Time.parse(
|
16
|
+
@generation_date ||= Time.parse(xml_data.xpath('CreDtTm/text()').text)
|
14
17
|
end
|
15
18
|
|
16
19
|
def from_date_time
|
17
|
-
@from_date_time ||= (x =
|
20
|
+
@from_date_time ||= (x = xml_data.xpath('FrToDt/FrDtTm')).empty? ? nil : Time.parse(x.first.content)
|
18
21
|
end
|
19
22
|
|
20
23
|
def to_date_time
|
21
|
-
@to_date_time ||= (x =
|
24
|
+
@to_date_time ||= (x = xml_data.xpath('FrToDt/ToDtTm')).empty? ? nil : Time.parse(x.first.content)
|
22
25
|
end
|
23
26
|
|
24
27
|
def account
|
25
|
-
@account ||= Account.new(
|
28
|
+
@account ||= Account.new(xml_data.xpath('Acct').first)
|
26
29
|
end
|
27
30
|
|
28
31
|
def entries
|
29
|
-
@entries ||=
|
32
|
+
@entries ||= xml_data.xpath('Ntry').map{ |x| Entry.new(x) }
|
30
33
|
end
|
31
34
|
|
32
35
|
def legal_sequence_number
|
33
|
-
@legal_sequence_number ||=
|
36
|
+
@legal_sequence_number ||= xml_data.xpath('LglSeqNb/text()').text
|
34
37
|
end
|
35
38
|
|
36
39
|
def electronic_sequence_number
|
37
|
-
@electronic_sequence_number ||=
|
40
|
+
@electronic_sequence_number ||= xml_data.xpath('ElctrncSeqNb/text()').text
|
38
41
|
end
|
39
42
|
|
40
43
|
def opening_balance
|
41
44
|
@opening_balance ||= begin
|
42
|
-
bal =
|
45
|
+
bal = xml_data.xpath('Bal/Tp//Cd[contains(text(), "OPBD") or contains(text(), "PRCD")]').first.ancestors('Bal')
|
43
46
|
date = bal.xpath('Dt/Dt/text()').text
|
44
47
|
credit = bal.xpath('CdtDbtInd/text()').text == 'CRDT'
|
45
48
|
currency = bal.xpath('Amt').attribute('Ccy').value
|
@@ -49,7 +52,7 @@ module CamtParser
|
|
49
52
|
|
50
53
|
def closing_balance
|
51
54
|
@closing_balance ||= begin
|
52
|
-
bal =
|
55
|
+
bal = xml_data.xpath('Bal/Tp//Cd[contains(text(), "CLBD")]').first.ancestors('Bal')
|
53
56
|
date = bal.xpath('Dt/Dt/text()').text
|
54
57
|
credit = bal.xpath('CdtDbtInd/text()').text == 'CRDT'
|
55
58
|
currency = bal.xpath('Amt').attribute('Ccy').value
|
@@ -59,7 +62,7 @@ module CamtParser
|
|
59
62
|
alias_method :closing_or_intermediary_balance, :closing_balance
|
60
63
|
|
61
64
|
def source
|
62
|
-
|
65
|
+
xml_data.to_s
|
63
66
|
end
|
64
67
|
|
65
68
|
def self.parse(xml)
|
data/lib/camt_parser/054/base.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
module CamtParser
|
2
2
|
module Format054
|
3
3
|
class Base
|
4
|
-
attr_reader :group_header, :notifications
|
4
|
+
attr_reader :group_header, :notifications, :xml_data
|
5
5
|
|
6
6
|
def initialize(xml_data)
|
7
|
+
@xml_data = xml_data
|
8
|
+
|
7
9
|
grphdr = xml_data.xpath('BkToCstmrDbtCdtNtfctn/GrpHdr')
|
8
10
|
@group_header = GroupHeader.new(grphdr)
|
9
11
|
notifications = xml_data.xpath('BkToCstmrDbtCdtNtfctn/Ntfctn')
|
@@ -1,38 +1,49 @@
|
|
1
1
|
module CamtParser
|
2
2
|
module Format054
|
3
3
|
class Notification
|
4
|
+
|
5
|
+
attr_reader :xml_data
|
6
|
+
|
4
7
|
def initialize(xml_data)
|
5
8
|
@xml_data = xml_data
|
6
9
|
end
|
7
10
|
|
11
|
+
# @return [String]
|
8
12
|
def identification
|
9
|
-
@identification ||=
|
13
|
+
@identification ||= xml_data.xpath('Id/text()').text
|
10
14
|
end
|
11
15
|
|
16
|
+
# @return [Time]
|
12
17
|
def generation_date
|
13
|
-
@generation_date ||= Time.parse(
|
18
|
+
@generation_date ||= Time.parse(xml_data.xpath('CreDtTm/text()').text)
|
14
19
|
end
|
15
20
|
|
21
|
+
# @return [Time, nil]
|
16
22
|
def from_date_time
|
17
|
-
@from_date_time ||= (x =
|
23
|
+
@from_date_time ||= (x = xml_data.xpath('FrToDt/FrDtTm')).empty? ? nil : Time.parse(x.first.content)
|
18
24
|
end
|
19
25
|
|
26
|
+
# @return [Time, nil]
|
20
27
|
def to_date_time
|
21
|
-
@to_date_time ||= (x =
|
28
|
+
@to_date_time ||= (x = xml_data.xpath('FrToDt/ToDtTm')).empty? ? nil : Time.parse(x.first.content)
|
22
29
|
end
|
23
30
|
|
31
|
+
# @return [Account]
|
24
32
|
def account
|
25
|
-
@account ||= Account.new(
|
33
|
+
@account ||= Account.new(xml_data.xpath('Acct').first)
|
26
34
|
end
|
27
35
|
|
36
|
+
# @return [Array<Entry>]
|
28
37
|
def entries
|
29
|
-
@entries ||=
|
38
|
+
@entries ||= xml_data.xpath('Ntry').map{ |x| Entry.new(x) }
|
30
39
|
end
|
31
40
|
|
41
|
+
# @return [String]
|
32
42
|
def source
|
33
|
-
|
43
|
+
xml_data.to_s
|
34
44
|
end
|
35
45
|
|
46
|
+
# @return [CamtParser::Format054::Notification]
|
36
47
|
def self.parse(xml)
|
37
48
|
self.new Nokogiri::XML(xml).xpath('Ntfctn')
|
38
49
|
end
|
@@ -1,31 +1,43 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Account
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
8
|
end
|
6
9
|
|
10
|
+
# @return [String]
|
7
11
|
def iban
|
8
|
-
@iban ||=
|
12
|
+
@iban ||= xml_data.xpath('Id/IBAN/text()').text
|
9
13
|
end
|
10
14
|
|
15
|
+
# @return [String]
|
11
16
|
def other_id
|
12
|
-
@other_id ||=
|
17
|
+
@other_id ||= xml_data.xpath('Id/Othr/Id/text()').text
|
13
18
|
end
|
14
19
|
|
20
|
+
# @return [String]
|
15
21
|
def account_number
|
16
22
|
!iban.nil? && !iban.empty? ? iban : other_id
|
17
23
|
end
|
18
24
|
|
25
|
+
# @return [String]
|
19
26
|
def bic
|
20
|
-
@bic ||=
|
27
|
+
@bic ||= [
|
28
|
+
xml_data.xpath('Svcr/FinInstnId/BIC/text()').text,
|
29
|
+
xml_data.xpath('Svcr/FinInstnId/BICFI/text()').text,
|
30
|
+
].reject(&:empty?).first.to_s
|
21
31
|
end
|
22
32
|
|
33
|
+
# @return [String]
|
23
34
|
def bank_name
|
24
|
-
@bank_name ||=
|
35
|
+
@bank_name ||= xml_data.xpath('Svcr/FinInstnId/Nm/text()').text
|
25
36
|
end
|
26
37
|
|
38
|
+
# @return [String]
|
27
39
|
def currency
|
28
|
-
@currency ||=
|
40
|
+
@currency ||= xml_data.xpath('Ccy/text()').text
|
29
41
|
end
|
30
42
|
end
|
31
43
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class AccountBalance
|
3
3
|
|
4
|
+
# @param amount [String]
|
5
|
+
# @param currency [String]
|
6
|
+
# @param date [String]
|
7
|
+
# @param credit [Boolean]
|
4
8
|
def initialize(amount, currency, date, credit = false)
|
5
9
|
@amount = amount
|
6
10
|
@currency = currency
|
@@ -8,34 +12,42 @@ module CamtParser
|
|
8
12
|
@credit = credit
|
9
13
|
end
|
10
14
|
|
15
|
+
# @return [String]
|
11
16
|
def currency
|
12
17
|
@currency
|
13
18
|
end
|
14
19
|
|
20
|
+
# @return [Date]
|
15
21
|
def date
|
16
22
|
Date.parse @date
|
17
23
|
end
|
18
24
|
|
25
|
+
# @return [Integer] either 1 or -1
|
19
26
|
def sign
|
20
27
|
credit? ? 1 : -1
|
21
28
|
end
|
22
29
|
|
30
|
+
# @return [Boolean]
|
23
31
|
def credit?
|
24
32
|
@credit
|
25
33
|
end
|
26
34
|
|
35
|
+
# @return [BigDecimal]
|
27
36
|
def amount
|
28
37
|
CamtParser::Misc.to_amount(@amount)
|
29
38
|
end
|
30
39
|
|
40
|
+
# @return [Integer]
|
31
41
|
def amount_in_cents
|
32
42
|
CamtParser::Misc.to_amount_in_cents(@amount)
|
33
43
|
end
|
34
44
|
|
45
|
+
# @return [BigDecimal]
|
35
46
|
def signed_amount
|
36
47
|
amount * sign
|
37
48
|
end
|
38
49
|
|
50
|
+
# @return [Hash{String => BigDecimal, Integer}]
|
39
51
|
def to_h
|
40
52
|
{
|
41
53
|
'amount' => amount,
|
@@ -1,19 +1,22 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class BatchDetail
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
8
|
end
|
6
9
|
|
7
10
|
def payment_information_identification
|
8
|
-
@payment_information_identification ||=
|
11
|
+
@payment_information_identification ||= xml_data.xpath('PmtInfId/text()').text
|
9
12
|
end
|
10
13
|
|
11
14
|
def msg_id # may be missing
|
12
|
-
@msg_id ||=
|
15
|
+
@msg_id ||= xml_data.xpath('MsgId/text()').text
|
13
16
|
end
|
14
17
|
|
15
18
|
def number_of_transactions
|
16
|
-
@number_of_transactions ||=
|
19
|
+
@number_of_transactions ||= xml_data.xpath('NbOfTxs/text()').text
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Charges
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
|
-
@total_charges_and_tax_amount =
|
8
|
+
@total_charges_and_tax_amount = xml_data.xpath('TtlChrgsAndTaxAmt/text()').text
|
6
9
|
end
|
7
10
|
|
8
11
|
def total_charges_and_tax_amount
|
@@ -14,7 +17,7 @@ module CamtParser
|
|
14
17
|
end
|
15
18
|
|
16
19
|
def records
|
17
|
-
@records ||=
|
20
|
+
@records ||= xml_data.xpath('Rcrd').map{ |x| CamtParser::Record.new(x) }
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -1,23 +1,32 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Creditor
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
8
|
end
|
6
9
|
|
7
10
|
def name
|
8
|
-
@name ||=
|
11
|
+
@name ||= [
|
12
|
+
xml_data.xpath('RltdPties/Cdtr/Nm/text()').text,
|
13
|
+
xml_data.xpath('RltdPties/Cdtr/Pty/Nm/text()').text,
|
14
|
+
].reject(&:empty?).first.to_s
|
9
15
|
end
|
10
16
|
|
11
17
|
def iban
|
12
|
-
@iban ||=
|
18
|
+
@iban ||= xml_data.xpath('RltdPties/CdtrAcct/Id/IBAN/text()').text
|
13
19
|
end
|
14
20
|
|
15
21
|
def bic
|
16
|
-
@bic ||=
|
22
|
+
@bic ||= [
|
23
|
+
xml_data.xpath('RltdAgts/CdtrAgt/FinInstnId/BIC/text()').text,
|
24
|
+
xml_data.xpath('RltdAgts/CdtrAgt/FinInstnId/BICFI/text()').text,
|
25
|
+
].reject(&:empty?).first.to_s
|
17
26
|
end
|
18
27
|
|
19
28
|
def bank_name
|
20
|
-
@bank_name ||=
|
29
|
+
@bank_name ||= xml_data.xpath('RltdAgts/CdtrAgt/FinInstnId/Nm/text()').text
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -1,23 +1,32 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Debitor
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
8
|
end
|
6
9
|
|
7
10
|
def name
|
8
|
-
@name ||=
|
11
|
+
@name ||= [
|
12
|
+
xml_data.xpath('RltdPties/Dbtr/Nm/text()').text,
|
13
|
+
xml_data.xpath('RltdPties/Dbtr/Pty/Nm/text()').text,
|
14
|
+
].reject(&:empty?).first.to_s
|
9
15
|
end
|
10
16
|
|
11
17
|
def iban
|
12
|
-
@iban ||=
|
18
|
+
@iban ||= xml_data.xpath('RltdPties/DbtrAcct/Id/IBAN/text()').text
|
13
19
|
end
|
14
20
|
|
15
21
|
def bic
|
16
|
-
@bic ||=
|
22
|
+
@bic ||= [
|
23
|
+
xml_data.xpath('RltdAgts/DbtrAgt/FinInstnId/BIC/text()').text,
|
24
|
+
xml_data.xpath('RltdAgts/DbtrAgt/FinInstnId/BICFI/text()').text,
|
25
|
+
].reject(&:empty?).first.to_s
|
17
26
|
end
|
18
27
|
|
19
28
|
def bank_name
|
20
|
-
@bank_name ||=
|
29
|
+
@bank_name ||= xml_data.xpath('RltdAgts/DbtrAgt/FinInstnId/Nm/text()').text
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Entry
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
|
-
@amount =
|
8
|
+
@amount = xml_data.xpath('Amt/text()').text
|
6
9
|
end
|
7
10
|
|
8
11
|
def amount
|
@@ -13,78 +16,100 @@ module CamtParser
|
|
13
16
|
CamtParser::Misc.to_amount_in_cents(@amount)
|
14
17
|
end
|
15
18
|
|
19
|
+
# @return [String]
|
16
20
|
def currency
|
17
|
-
@currency ||=
|
21
|
+
@currency ||= xml_data.xpath('Amt/@Ccy').text
|
18
22
|
end
|
19
23
|
|
24
|
+
# @return [Boolean]
|
20
25
|
def debit
|
21
|
-
@debit ||=
|
26
|
+
@debit ||= xml_data.xpath('CdtDbtInd/text()').text.upcase == 'DBIT'
|
22
27
|
end
|
23
28
|
|
29
|
+
# @return [Date]
|
24
30
|
def value_date
|
25
|
-
@value_date ||=
|
31
|
+
@value_date ||= ((date = xml_data.xpath('ValDt/Dt/text()').text).empty? ? nil : Date.parse(date))
|
26
32
|
end
|
27
33
|
|
34
|
+
# @return [Date]
|
28
35
|
def booking_date
|
29
|
-
@booking_date ||=
|
36
|
+
@booking_date ||= ((date = xml_data.xpath('BookgDt/Dt/text()').text).empty? ? nil : Date.parse(date))
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [DateTime]
|
40
|
+
def value_datetime
|
41
|
+
@value_datetime ||= ((datetime = xml_data.xpath('ValDt/DtTm/text()').text).empty? ? nil : DateTime.parse(datetime))
|
30
42
|
end
|
31
43
|
|
44
|
+
# @return [DateTime]
|
45
|
+
def booking_datetime
|
46
|
+
@booking_datetime ||= ((datetime = xml_data.xpath('BookgDt/DtTm/text()').text).empty? ? nil : DateTime.parse(datetime))
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [String]
|
32
50
|
def bank_reference # May be missing
|
33
|
-
@bank_reference ||=
|
51
|
+
@bank_reference ||= xml_data.xpath('AcctSvcrRef/text()').text
|
34
52
|
end
|
35
53
|
|
54
|
+
# @return [Array<CamtParser::Transaction>]
|
36
55
|
def transactions
|
37
56
|
@transactions ||= parse_transactions
|
38
57
|
end
|
39
58
|
|
59
|
+
# @return [Boolean]
|
40
60
|
def credit?
|
41
61
|
!debit
|
42
62
|
end
|
43
63
|
|
64
|
+
# @return [Boolean]
|
44
65
|
def debit?
|
45
66
|
debit
|
46
67
|
end
|
47
68
|
|
69
|
+
# @return [Integer] either 1 or -1
|
48
70
|
def sign
|
49
71
|
credit? ? 1 : -1
|
50
72
|
end
|
51
73
|
|
74
|
+
# @return [Boolean]
|
52
75
|
def reversal?
|
53
|
-
@reversal ||=
|
76
|
+
@reversal ||= xml_data.xpath('RvslInd/text()').text.downcase == 'true'
|
54
77
|
end
|
55
78
|
|
79
|
+
# @return [Boolean]
|
56
80
|
def booked?
|
57
|
-
@booked ||=
|
81
|
+
@booked ||= xml_data.xpath('Sts/text()').text.upcase == 'BOOK'
|
58
82
|
end
|
59
83
|
|
84
|
+
# @return [String]
|
60
85
|
def additional_information
|
61
|
-
@additional_information ||=
|
86
|
+
@additional_information ||= xml_data.xpath('AddtlNtryInf/text()').text
|
62
87
|
end
|
63
88
|
alias_method :description, :additional_information
|
64
89
|
|
90
|
+
# @return [CamtParser::Charges]
|
65
91
|
def charges
|
66
|
-
@charges ||= CamtParser::Charges.new(
|
92
|
+
@charges ||= CamtParser::Charges.new(xml_data.xpath('Chrgs'))
|
67
93
|
end
|
68
|
-
|
94
|
+
# @return [CamtParser::BatchDetail, nil]
|
69
95
|
def batch_detail
|
70
|
-
@batch_detail ||=
|
71
|
-
end
|
96
|
+
@batch_detail ||= xml_data.xpath('NtryDtls/Btch').empty? ? nil : CamtParser::BatchDetail.new(@xml_data.xpath('NtryDtls/Btch'))
|
97
|
+
end
|
72
98
|
|
73
99
|
private
|
74
100
|
|
75
101
|
def parse_transactions
|
76
|
-
transaction_details =
|
102
|
+
transaction_details = xml_data.xpath('NtryDtls/TxDtls')
|
77
103
|
|
78
104
|
amt = nil
|
79
105
|
ccy = nil
|
80
106
|
|
81
107
|
if transaction_details.length == 1
|
82
|
-
amt =
|
83
|
-
ccy =
|
108
|
+
amt = xml_data.xpath('Amt/text()').text
|
109
|
+
ccy = xml_data.xpath('Amt/@Ccy').text
|
84
110
|
end
|
85
111
|
|
86
|
-
|
112
|
+
xml_data.xpath('NtryDtls/TxDtls').map { |x| Transaction.new(x, debit?, amt, ccy) }
|
87
113
|
end
|
88
|
-
|
89
114
|
end
|
90
115
|
end
|
@@ -2,9 +2,15 @@ require 'time'
|
|
2
2
|
|
3
3
|
module CamtParser
|
4
4
|
class GroupHeader
|
5
|
-
|
5
|
+
|
6
|
+
attr_reader :message_id,
|
7
|
+
:creation_date_time,
|
8
|
+
:additional_information,
|
9
|
+
:message_pagination,
|
10
|
+
:xml_data
|
6
11
|
|
7
12
|
def initialize(xml_data)
|
13
|
+
@xml_data = xml_data
|
8
14
|
@message_id = xml_data.xpath('MsgId/text()').text
|
9
15
|
@creation_date_time = Time.parse(xml_data.xpath('CreDtTm/text()').text)
|
10
16
|
@message_pagination = (x = xml_data.xpath('MsgPgntn')).empty? ? nil : MessagePagination.new(x)
|
@@ -13,9 +19,12 @@ module CamtParser
|
|
13
19
|
end
|
14
20
|
|
15
21
|
class MessagePagination
|
16
|
-
|
22
|
+
|
23
|
+
attr_reader :page_number,
|
24
|
+
:xml_data
|
17
25
|
|
18
26
|
def initialize(xml_data)
|
27
|
+
@xml_data = xml_data
|
19
28
|
@page_number = xml_data.xpath('PgNb/text()').text.to_i
|
20
29
|
@last_page_indicator = xml_data.xpath('LastPgInd/text()').text == 'true'
|
21
30
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Record
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data)
|
4
7
|
@xml_data = xml_data
|
5
|
-
@amount =
|
8
|
+
@amount = xml_data.xpath('Amt/text()').text
|
6
9
|
end
|
7
10
|
|
8
11
|
def amount
|
@@ -14,19 +17,19 @@ module CamtParser
|
|
14
17
|
end
|
15
18
|
|
16
19
|
def currency
|
17
|
-
@currency ||=
|
20
|
+
@currency ||= xml_data.xpath('Amt/@Ccy').text
|
18
21
|
end
|
19
22
|
|
20
23
|
def type
|
21
|
-
@type ||= CamtParser::Type::Builder.build_type(
|
24
|
+
@type ||= CamtParser::Type::Builder.build_type(xml_data.xpath('Tp'))
|
22
25
|
end
|
23
26
|
|
24
27
|
def charges_included?
|
25
|
-
@charges_included ||=
|
28
|
+
@charges_included ||= xml_data.xpath('ChrgInclInd/text()').text.downcase == 'true'
|
26
29
|
end
|
27
30
|
|
28
31
|
def debit
|
29
|
-
@debit ||=
|
32
|
+
@debit ||= xml_data.xpath('CdtDbtInd/text()').text.upcase == 'DBIT'
|
30
33
|
end
|
31
34
|
|
32
35
|
def credit?
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Transaction
|
3
|
+
|
4
|
+
attr_reader :xml_data
|
5
|
+
|
3
6
|
def initialize(xml_data, debit, amount = nil, currency = nil)
|
4
7
|
@xml_data = xml_data
|
5
8
|
@debit = debit
|
@@ -20,11 +23,11 @@ module CamtParser
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def creditor
|
23
|
-
@creditor ||= CamtParser::Creditor.new(
|
26
|
+
@creditor ||= CamtParser::Creditor.new(xml_data)
|
24
27
|
end
|
25
28
|
|
26
29
|
def debitor
|
27
|
-
@debitor ||= CamtParser::Debitor.new(
|
30
|
+
@debitor ||= CamtParser::Debitor.new(xml_data)
|
28
31
|
end
|
29
32
|
|
30
33
|
def name
|
@@ -57,7 +60,7 @@ module CamtParser
|
|
57
60
|
|
58
61
|
def remittance_information
|
59
62
|
@remittance_information ||= begin
|
60
|
-
if (x =
|
63
|
+
if (x = xml_data.xpath('RmtInf/Ustrd')).empty?
|
61
64
|
nil
|
62
65
|
else
|
63
66
|
x.collect(&:content).join(' ')
|
@@ -66,64 +69,64 @@ module CamtParser
|
|
66
69
|
end
|
67
70
|
|
68
71
|
def swift_code
|
69
|
-
@swift_code ||=
|
72
|
+
@swift_code ||= xml_data.xpath('BkTxCd/Prtry/Cd/text()').text.split('+')[0]
|
70
73
|
end
|
71
74
|
|
72
75
|
def reference
|
73
|
-
@reference ||=
|
76
|
+
@reference ||= xml_data.xpath('Refs/InstrId/text()').text
|
74
77
|
end
|
75
78
|
|
76
79
|
def bank_reference # May be missing
|
77
|
-
@bank_reference ||=
|
80
|
+
@bank_reference ||= xml_data.xpath('Refs/AcctSvcrRef/text()').text
|
78
81
|
end
|
79
82
|
|
80
83
|
def end_to_end_reference # May be missing
|
81
|
-
@end_to_end_reference ||=
|
84
|
+
@end_to_end_reference ||= xml_data.xpath('Refs/EndToEndId/text()').text
|
82
85
|
end
|
83
86
|
|
84
87
|
def mandate_reference # May be missing
|
85
|
-
@mandate_reference ||=
|
88
|
+
@mandate_reference ||= xml_data.xpath('Refs/MndtId/text()').text
|
86
89
|
end
|
87
90
|
|
88
91
|
def creditor_reference # May be missing
|
89
|
-
@creditor_reference ||=
|
92
|
+
@creditor_reference ||= xml_data.xpath('RmtInf/Strd/CdtrRefInf/Ref/text()').text
|
90
93
|
end
|
91
94
|
|
92
95
|
def transaction_id # May be missing
|
93
|
-
@transaction_id ||=
|
96
|
+
@transaction_id ||= xml_data.xpath('Refs/TxId/text()').text
|
94
97
|
end
|
95
98
|
|
96
99
|
def creditor_identifier # May be missing
|
97
|
-
@creditor_identifier ||=
|
100
|
+
@creditor_identifier ||= xml_data.xpath('RltdPties/Cdtr/Id/PrvtId/Othr/Id/text()').text
|
98
101
|
end
|
99
102
|
|
100
103
|
def payment_information # May be missing
|
101
|
-
@payment_information ||=
|
104
|
+
@payment_information ||= xml_data.xpath('Refs/PmtInfId/text()').text
|
102
105
|
end
|
103
106
|
|
104
107
|
def additional_information # May be missing
|
105
|
-
@addition_information ||=
|
108
|
+
@addition_information ||= xml_data.xpath('AddtlTxInf/text()').text
|
106
109
|
end
|
107
110
|
|
108
111
|
def reason_code # May be missing
|
109
|
-
@reason_code ||=
|
112
|
+
@reason_code ||= xml_data.xpath('RtrInf/Rsn/Cd/text()').text
|
110
113
|
end
|
111
114
|
|
112
115
|
private
|
113
116
|
|
114
117
|
def parse_amount
|
115
|
-
if
|
116
|
-
|
117
|
-
elsif
|
118
|
-
|
118
|
+
if xml_data.xpath('Amt').any?
|
119
|
+
xml_data.xpath('Amt/text()').text
|
120
|
+
elsif xml_data.xpath('AmtDtls').any?
|
121
|
+
xml_data.xpath('AmtDtls//Amt/text()').first.text
|
119
122
|
end
|
120
123
|
end
|
121
124
|
|
122
125
|
def parse_currency
|
123
|
-
if
|
124
|
-
|
125
|
-
elsif
|
126
|
-
|
126
|
+
if xml_data.xpath('Amt').any?
|
127
|
+
xml_data.xpath('Amt/@Ccy').text
|
128
|
+
elsif xml_data.xpath('AmtDtls').any?
|
129
|
+
xml_data.xpath('AmtDtls//Amt/@Ccy').first.text
|
127
130
|
end
|
128
131
|
end
|
129
132
|
end
|
data/lib/camt_parser/misc.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module CamtParser
|
2
2
|
class Misc
|
3
3
|
class << self
|
4
|
+
|
5
|
+
# @param value [nil, String]
|
6
|
+
# @return [Integer, nil]
|
4
7
|
def to_amount_in_cents(value)
|
5
8
|
return nil if value == nil || value.strip == ''
|
6
9
|
|
@@ -10,6 +13,8 @@ module CamtParser
|
|
10
13
|
format('%s%s', dollars, cents.ljust(2, '0')).to_i
|
11
14
|
end
|
12
15
|
|
16
|
+
# @param value [nil, String]
|
17
|
+
# @return [BigDecimal, nil]
|
13
18
|
def to_amount(value)
|
14
19
|
return nil if value == nil || value.strip == ''
|
15
20
|
|
data/lib/camt_parser/register.rb
CHANGED
@@ -7,6 +7,8 @@ CamtParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.052.001.02', :camt
|
|
7
7
|
## CAMT053
|
8
8
|
CamtParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.02', :camt053)
|
9
9
|
CamtParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.04', :camt053)
|
10
|
+
CamtParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.08', :camt053)
|
11
|
+
CamtParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.053.001.10', :camt053)
|
10
12
|
|
11
13
|
## CAMT054
|
12
14
|
CamtParser::Xml.register('urn:iso:std:iso:20022:tech:xsd:camt.054.001.02', :camt054)
|
data/lib/camt_parser/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: camt_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Schoknecht
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
119
|
- !ruby/object:Gem::Version
|
120
120
|
version: '0'
|
121
121
|
requirements: []
|
122
|
-
rubygems_version: 3.
|
122
|
+
rubygems_version: 3.4.13
|
123
123
|
signing_key:
|
124
124
|
specification_version: 4
|
125
125
|
summary: Gem for parsing camt files into a speaking object.
|