camt_parser 2.14.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|