cmxl 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -2
- data/CHANGELOG.mdown +28 -18
- data/README.md +45 -26
- data/cmxl.gemspec +15 -16
- data/lib/cmxl.rb +9 -9
- data/lib/cmxl/field.rb +25 -18
- data/lib/cmxl/fields/account_balance.rb +7 -7
- data/lib/cmxl/fields/account_identification.rb +1 -1
- data/lib/cmxl/fields/floor_limit_indicator.rb +20 -0
- data/lib/cmxl/fields/reference.rb +3 -4
- data/lib/cmxl/fields/statement_details.rb +13 -13
- data/lib/cmxl/fields/transaction.rb +10 -1
- data/lib/cmxl/fields/transaction_supplementary.rb +11 -8
- data/lib/cmxl/fields/vmk_summary.rb +33 -0
- data/lib/cmxl/statement.rb +52 -22
- data/lib/cmxl/version.rb +1 -1
- data/spec/field_spec.rb +8 -9
- data/spec/fields/account_balance_spec.rb +18 -18
- data/spec/fields/account_identification_spec.rb +2 -6
- data/spec/fields/available_balance_spec.rb +1 -3
- data/spec/fields/closing_balance_spec.rb +2 -4
- data/spec/fields/entry_date_spec.rb +1 -1
- data/spec/fields/floor_limit_indicator_spec.rb +30 -0
- data/spec/fields/reference_spec.rb +2 -3
- data/spec/fields/statement_details_spec.rb +61 -56
- data/spec/fields/statement_number_spec.rb +0 -2
- data/spec/fields/transaction_spec.rb +4 -4
- data/spec/fields/transaction_supplementary_spec.rb +4 -4
- data/spec/fields/unknown_spec.rb +1 -2
- data/spec/fields/vmk_summary_spec.rb +23 -0
- data/spec/fixtures/lines/floor_limit_indicator_both.txt +1 -0
- data/spec/fixtures/lines/floor_limit_indicator_credit.txt +1 -0
- data/spec/fixtures/lines/floor_limit_indicator_debit.txt +1 -0
- data/spec/fixtures/lines/vmk_summary_credit.txt +1 -0
- data/spec/fixtures/lines/vmk_summary_debit.txt +1 -0
- data/spec/fixtures/mt942.txt +9 -0
- data/spec/fixtures/statement-details-mt942.txt +4 -0
- data/spec/mt940_parsing_spec.rb +13 -14
- data/spec/spec_helper.rb +3 -6
- data/spec/statement_spec.rb +119 -99
- data/spec/support/fixtures.rb +1 -1
- metadata +39 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a9d2c6d5faed6e357abd5459811d43764a89448fc46763993938b1519b17a2a
|
4
|
+
data.tar.gz: 3861abc066158de7c4468d9df01a57331d1913b1d84645b7618f2d146c419a47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 716ee9967921b4539174032223aae5eb996ada741c2181b556e7bb8ec5355668aedd8167ba564836ee73a8a8fa7256d83a74c4f6d8309496cde600c7d631b66c
|
7
|
+
data.tar.gz: 4395610ac7de16b264b309940eda9a2727cfce3c49f8cf051b91f4ab0f8f0486c2caf0528a8efd995fd327f31ccefc288a860f8e458b6ba7b0f1ffe7be85939e
|
data/.travis.yml
CHANGED
@@ -6,8 +6,11 @@ rvm:
|
|
6
6
|
- 2.4.3
|
7
7
|
- 2.5.0
|
8
8
|
- jruby-9.1.10.0
|
9
|
-
before_install:
|
10
|
-
gem update --system
|
9
|
+
before_install: if [[ `ruby -v` =~ 2.2.8 ]];
|
10
|
+
then gem update --system 2.7.8;
|
11
|
+
else gem update --system;
|
12
|
+
fi
|
13
|
+
|
11
14
|
after_success:
|
12
15
|
- bundle exec codeclimate-test-reporter
|
13
16
|
addons:
|
data/CHANGELOG.mdown
CHANGED
@@ -1,35 +1,45 @@
|
|
1
|
+
# 1.3.0
|
2
|
+
|
3
|
+
- [FEATURE] adds MT942 compatibility
|
4
|
+
|
1
5
|
# 1.2.0
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
+
|
7
|
+
- [FEATURE] strips mt940 header if configured ([#9](https://github.com/railslove/cmxl/issues/9))
|
8
|
+
```ruby
|
9
|
+
Cmxl.config[:strip_headers] = true
|
10
|
+
```
|
6
11
|
|
7
12
|
# 1.1.1
|
8
|
-
|
13
|
+
|
14
|
+
- [BUGFIX] prevents short bank references from swallowing supplementary details delimiter
|
9
15
|
|
10
16
|
# 1.1.0
|
11
|
-
|
17
|
+
|
18
|
+
- [FEATURE] adds support for supplementary details in transactions (Field 61, Subfield 9) ([#18](https://github.com/railslove/cmxl/issues/18))
|
12
19
|
|
13
20
|
# 1.0.0
|
14
|
-
|
15
|
-
|
16
|
-
|
21
|
+
|
22
|
+
- [FEATURE] adds support for storno transactions ([#14](https://github.com/railslove/cmxl/issues/14))
|
23
|
+
- [NOTE] full backwards compatibility
|
24
|
+
- [NOTE] same as release 0.2.2, fixing versioning
|
17
25
|
|
18
26
|
# 0.2.1
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
27
|
+
|
28
|
+
- addressing an bug that occoured for transactions submitted end of
|
29
|
+
but were fetched in the new year -> those ended up with the wrong year
|
30
|
+
on the entry date
|
31
|
+
- MT942 support for field 13
|
23
32
|
|
24
33
|
# 0.2.0
|
25
|
-
|
26
|
-
|
27
|
-
|
34
|
+
|
35
|
+
- added several balance related accessors ([#7](https://github.com/railslove/cmxl/issues/7))
|
36
|
+
- configuration option for `statement separator` ([#5](https://github.com/railslove/cmxl/issues/5))
|
37
|
+
- improvement for general compatibility
|
28
38
|
|
29
39
|
# 0.1.3
|
30
40
|
|
31
|
-
|
41
|
+
- [BUGFIX] fixed the statement details parser. It failed in case of empty values in the SEPA details
|
32
42
|
|
33
43
|
# 0.1.2
|
34
44
|
|
35
|
-
|
45
|
+
- [BUGFIX] fixed the statement details parser. It failed in case of empty values in the sub fields
|
data/README.md
CHANGED
@@ -2,24 +2,24 @@
|
|
2
2
|
|
3
3
|
# Cmxl - your friendly ruby MT940 parser
|
4
4
|
|
5
|
-
At [Railslove](http://railslove.com) we build a lot of financial applications and work on integrating applications with banks and banking functionality.
|
5
|
+
At [Railslove](http://railslove.com) we build a lot of financial applications and work on integrating applications with banks and banking functionality.
|
6
6
|
Our goal is to make simple solutions for what often looks complicated.
|
7
7
|
|
8
|
-
Cmxl is a friendly and extendible MT940 bank statement file parser that helps your extracting data from the bank statement files.
|
8
|
+
Cmxl is a friendly and extendible MT940 bank statement file parser that helps your extracting data from the bank statement files.
|
9
9
|
|
10
|
-
## What is MT940?
|
10
|
+
## What is MT940 & MT942?
|
11
11
|
|
12
|
-
MT940 (MT = Message Type) is the SWIFT-Standard for the electronic transfer of bank statement files.
|
13
|
-
When integrating with banks you often get MT940 files as interface.
|
12
|
+
MT940 (MT = Message Type) is the SWIFT-Standard for the electronic transfer of bank statement files.
|
13
|
+
When integrating with banks you often get MT940 or MT942 files as interface.
|
14
14
|
For more information have a look at the different [SWIFT message types](http://en.wikipedia.org/wiki/SWIFT_message_types)
|
15
15
|
|
16
16
|
At some point in the future MT940 file should be exchanged with newer XML documents - but banking institutions are slow so MT940 will stick around for a while.
|
17
17
|
|
18
18
|
## Reqirements
|
19
19
|
|
20
|
-
Cmxl is a pure ruby parser and has no dependency on native extensions.
|
20
|
+
Cmxl is a pure ruby parser and has no dependency on native extensions.
|
21
21
|
|
22
|
-
|
22
|
+
- Ruby 1.9.3 or newer (jruby, etc.)
|
23
23
|
|
24
24
|
## Installation
|
25
25
|
|
@@ -37,7 +37,7 @@ Or install it yourself as:
|
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
40
|
-
Simple usage:
|
40
|
+
Simple usage:
|
41
41
|
|
42
42
|
```ruby
|
43
43
|
|
@@ -55,14 +55,14 @@ Cmxl.config[:strip_headers] = true
|
|
55
55
|
|
56
56
|
# Statment parsing:
|
57
57
|
|
58
|
-
statements = Cmxl.parse(File.read('mt940.txt'), :encoding => 'ISO-8859-1') # parses the file and returns an array of statement objects. Please note: if no encoding is given Cmxl tries to guess the encoding from the content and converts it to UTF-8.
|
58
|
+
statements = Cmxl.parse(File.read('mt940.txt'), :encoding => 'ISO-8859-1') # parses the file and returns an array of statement objects. Please note: if no encoding is given Cmxl tries to guess the encoding from the content and converts it to UTF-8.
|
59
59
|
statements.each do |s|
|
60
60
|
puts s.reference
|
61
61
|
puts s.generation_date
|
62
62
|
puts s.opening_balance.amount
|
63
63
|
puts s.closing_balance.amount
|
64
64
|
puts s.sha # SHA of the statement source - could be used as an unique identifier
|
65
|
-
|
65
|
+
|
66
66
|
s.transactions.each do |t|
|
67
67
|
puts t.information
|
68
68
|
puts t.description
|
@@ -87,14 +87,14 @@ Every object responds to `to_h` and let's you easily convert the data to a hash.
|
|
87
87
|
|
88
88
|
#### A note about encoding and file wirednesses
|
89
89
|
|
90
|
-
You probably will encounter encoding issues (hey, you are building banking applications!).
|
91
|
-
We try to handle encoding and format wirednesses as much as possible. If no encoding is passed we try to guess the encoding of the data and convert it to UTF8.
|
92
|
-
In the likely case that you encouter encoding issues you can pass encoding options to the `Cmxl.parse(<string>, <options hash>)` it accepts the same options as [String#encode](http://ruby-doc.org/core-2.1.3/String.html#method-i-encode)
|
90
|
+
You probably will encounter encoding issues (hey, you are building banking applications!).
|
91
|
+
We try to handle encoding and format wirednesses as much as possible. If no encoding is passed we try to guess the encoding of the data and convert it to UTF8.
|
92
|
+
In the likely case that you encouter encoding issues you can pass encoding options to the `Cmxl.parse(<string>, <options hash>)` it accepts the same options as [String#encode](http://ruby-doc.org/core-2.1.3/String.html#method-i-encode)
|
93
93
|
If that fails try to motify the file before you pass it to the parser - and please create an issue.
|
94
94
|
|
95
95
|
### MT940 SWIFT header data
|
96
96
|
|
97
|
-
Cmxl currently does not support parsing of the SWIFT headers (like {1:F01AXISINBBA ....)
|
97
|
+
Cmxl currently does not support parsing of the SWIFT headers (like {1:F01AXISINBBA ....)
|
98
98
|
If your file comes with these headers try the `strip_headers` configuration option to strip data execpt the actual MT940 fields.
|
99
99
|
|
100
100
|
```ruby
|
@@ -102,9 +102,31 @@ Cmxl.config[:strip_headers] = true
|
|
102
102
|
Cmxl.parse(...)
|
103
103
|
```
|
104
104
|
|
105
|
+
### MT942 data
|
106
|
+
|
107
|
+
CMXL is now also capable of parsing MT942 data. Just pass the data and the parser will identify the type automatically.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
first_statement = Cmxl.parse(File.read('mt940.txt'), :encoding => 'ISO-8859-1').first
|
111
|
+
puts first_statement.mt942?
|
112
|
+
#=> false
|
113
|
+
|
114
|
+
first_statement = Cmxl.parse(File.read('mt942.txt'), :encoding => 'ISO-8859-1').first
|
115
|
+
puts first_statement.mt942?
|
116
|
+
#=> true
|
117
|
+
|
118
|
+
p first_statement.vmk_credit_summary.to_h
|
119
|
+
#=> { type: 'credit', entries: 1, amount: 9792.0, currency: 'EUR' }
|
120
|
+
|
121
|
+
p first_statement.vmk_dedit_summary.to_h
|
122
|
+
#=> { type: 'debit', entries: 0, amount: 0.0, currency: 'EUR' }
|
123
|
+
|
124
|
+
first_statement.transactions # same as for MT940
|
125
|
+
```
|
126
|
+
|
105
127
|
### Custom field parsers
|
106
128
|
|
107
|
-
Because a lot of banks implement the MT940 format slightly different one of the design goals of this library is to be able to customize the individual field parsers.
|
129
|
+
Because a lot of banks implement the MT940 format slightly different one of the design goals of this library is to be able to customize the individual field parsers.
|
108
130
|
Every line get parsed with a special parser. Here is how to write your own parser:
|
109
131
|
|
110
132
|
```ruby
|
@@ -128,23 +150,20 @@ my_field_parser.data #=> {'world' => 'hello from mt940'} - data is the accessor
|
|
128
150
|
|
129
151
|
## Parsing issues? - please create an issue with your file
|
130
152
|
|
131
|
-
The Mt940 format often looks different for the different banks and the different countries. Especially the not strict defined fields are often used for custom bank data.
|
153
|
+
The Mt940 format often looks different for the different banks and the different countries. Especially the not strict defined fields are often used for custom bank data.
|
132
154
|
If you have a file that can not be parsed please open an issue. We hope to build a parser that handles most of the files.
|
133
155
|
|
134
|
-
|
135
156
|
## ToDo
|
136
157
|
|
137
|
-
|
138
|
-
|
139
|
-
* better header data handling
|
140
|
-
|
158
|
+
- collect MT940 files from different banks and use them as example for specs
|
159
|
+
- better header data handling
|
141
160
|
|
142
161
|
## Looking for other Banking and EBICS tools?
|
143
162
|
|
144
163
|
Maybe these are also interesting for you.
|
145
164
|
|
146
|
-
|
147
|
-
|
165
|
+
- [EPICS: Open Source SEPA EBICS client](https://railslove.github.io/epics/) full implementation to manage all the banking activities like direct debits, credits, etc. (SEPA Lastschrift, Überweisungen, etc.)
|
166
|
+
- [EBICS::Box: out of the box solution to automate banking activities](http://www.railslove.com/ebics-box) - The missing API for your bank
|
148
167
|
|
149
168
|
## Contributing
|
150
169
|
|
@@ -161,9 +180,9 @@ Automated tests: We use rspec to test Cmxl. Simply run `rake` to execute the who
|
|
161
180
|
Cmxl is inspired and borrows ideas from the `mt940_parser` by the great people at [betterplace](https://www.betterplace.org/).
|
162
181
|
|
163
182
|
other parsers:
|
164
|
-
* [betterplace/mt940_parser](https://github.com/betterplace/mt940_parser)
|
165
|
-
* [gmitrev/mt940parser](https://github.com/gmitrev/mt940parser)
|
166
183
|
|
184
|
+
- [betterplace/mt940_parser](https://github.com/betterplace/mt940_parser)
|
185
|
+
- [gmitrev/mt940parser](https://github.com/gmitrev/mt940parser)
|
167
186
|
|
168
187
|
## Stats
|
169
188
|
|
@@ -172,6 +191,6 @@ other parsers:
|
|
172
191
|
[![Test Coverage](https://codeclimate.com/github/railslove/cmxl/badges/coverage.svg)](https://codeclimate.com/github/railslove/cmxl)
|
173
192
|
[![Gem Version](https://badge.fury.io/rb/cmxl.svg)](http://badge.fury.io/rb/cmxl)
|
174
193
|
|
175
|
-
|
194
|
+
---
|
176
195
|
|
177
196
|
2014 - built with love by [Railslove](http://railslove.com) and released under the MIT-Licence. We have built quite a number of FinTech products. If you need support we are happy to help. Please contact us at team@railslove.com.
|
data/cmxl.gemspec
CHANGED
@@ -1,30 +1,29 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'cmxl/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'cmxl'
|
8
7
|
spec.version = Cmxl::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
8
|
+
spec.authors = ['Michael Bumann']
|
9
|
+
spec.email = ['michael@railslove.com']
|
10
|
+
spec.summary = 'Cmxl is your friendly MT940 bank statement parser'
|
11
|
+
spec.description = 'Cmxl provides an friendly, extensible and customizable parser for the MT940 bank statement format.'
|
12
|
+
spec.homepage = 'https://github.com/railslove/cmxl'
|
13
|
+
spec.license = 'MIT'
|
15
14
|
|
16
15
|
spec.post_install_message = "Thanks for using Cmxl - your friendly MT940 parser!\nWe hope we can make dealing with MT940 files a bit more fun. :) \nPlease create an issue on github if anything is not as expected.\n\n"
|
17
16
|
|
18
17
|
spec.files = `git ls-files -z`.split("\x0")
|
19
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
22
21
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
22
|
+
spec.add_development_dependency 'bundler'
|
23
|
+
spec.add_development_dependency 'pry'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec', '~>3.0'
|
26
|
+
spec.add_development_dependency 'simplecov'
|
28
27
|
|
29
|
-
spec.add_dependency
|
28
|
+
spec.add_dependency 'rchardet19'
|
30
29
|
end
|
data/lib/cmxl.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require 'cmxl/version'
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'rchardet19'
|
4
4
|
|
5
5
|
require 'cmxl/field'
|
6
6
|
require 'cmxl/statement'
|
@@ -11,9 +11,9 @@ module Cmxl
|
|
11
11
|
@config
|
12
12
|
end
|
13
13
|
@config = {
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
14
|
+
statement_separator: /\n-\s*\n/m,
|
15
|
+
raise_line_format_errors: true,
|
16
|
+
strip_headers: false
|
17
17
|
}
|
18
18
|
|
19
19
|
# Public: Parse a MT940 string
|
@@ -28,8 +28,8 @@ module Cmxl
|
|
28
28
|
# Cmxl.parse(mt940_string)
|
29
29
|
#
|
30
30
|
# Returns an array of Statement objects
|
31
|
-
def self.parse(data, options={})
|
32
|
-
options[:statement_separator] ||=
|
31
|
+
def self.parse(data, options = {})
|
32
|
+
options[:statement_separator] ||= config[:statement_separator]
|
33
33
|
# if no encoding is provided we try to guess using CharDet
|
34
34
|
if options[:encoding].nil? && cd = CharDet.detect(data, silent: true)
|
35
35
|
options[:encoding] = cd.encoding
|
@@ -38,9 +38,9 @@ module Cmxl
|
|
38
38
|
if options[:encoding]
|
39
39
|
data.encode!('UTF-8', options.delete(:encoding), options)
|
40
40
|
else
|
41
|
-
data.encode!('UTF-8', options)
|
41
|
+
data.encode!('UTF-8', options) unless options.empty?
|
42
42
|
end
|
43
43
|
|
44
|
-
data.split(options[:statement_separator]).reject { |s| s.strip.empty? }.collect {|s| Cmxl::Statement.new(s.strip) }
|
44
|
+
data.split(options[:statement_separator]).reject { |s| s.strip.empty? }.collect { |s| Cmxl::Statement.new(s.strip) }
|
45
45
|
end
|
46
46
|
end
|
data/lib/cmxl/field.rb
CHANGED
@@ -2,13 +2,13 @@ require 'date'
|
|
2
2
|
module Cmxl
|
3
3
|
class Field
|
4
4
|
class LineFormatError < StandardError; end
|
5
|
-
class Unknown < Field
|
6
|
-
@parser= /(?<source>.*)/
|
5
|
+
class Unknown < Field
|
6
|
+
@parser = /(?<source>.*)/
|
7
7
|
def to_h
|
8
8
|
{ tag: tag, modifier: modifier, source: source }
|
9
9
|
end
|
10
10
|
end
|
11
|
-
DATE = /(?<year>\d{0,2})(?<month>\d{2})(?<day>\d{2})
|
11
|
+
DATE = /(?<year>\d{0,2})(?<month>\d{2})(?<day>\d{2})/.freeze
|
12
12
|
attr_accessor :source, :modifier, :match, :data, :tag
|
13
13
|
|
14
14
|
# The parser class variable is the registry of all available parser.
|
@@ -16,7 +16,9 @@ module Cmxl
|
|
16
16
|
# When parsing a statment line we look for a matching entry or use the Unknown class as default
|
17
17
|
@@parsers = {}
|
18
18
|
@@parsers.default = Unknown
|
19
|
-
def self.parsers
|
19
|
+
def self.parsers
|
20
|
+
@@parsers
|
21
|
+
end
|
20
22
|
|
21
23
|
# Class accessor for the parser
|
22
24
|
# Every sub class should have its own parser (regex to parse a MT940 field/line)
|
@@ -30,8 +32,9 @@ module Cmxl
|
|
30
32
|
@tag = tag.to_s
|
31
33
|
@@parsers[tag.to_s] = self
|
32
34
|
end
|
33
|
-
|
34
|
-
|
35
|
+
|
36
|
+
class << self
|
37
|
+
attr_reader :tag
|
35
38
|
end
|
36
39
|
|
37
40
|
# Public: Parses a statement line and initiates a matching Field class
|
@@ -44,23 +47,25 @@ module Cmxl
|
|
44
47
|
# Cmxl::Field.parse(':60F:C031002PLN40000,00') #=> returns an AccountBalance instance
|
45
48
|
#
|
46
49
|
def self.parse(line)
|
47
|
-
if line
|
48
|
-
tag
|
50
|
+
if line =~ /\A:(\d{2,2})(\w)?:(.*)\z/m
|
51
|
+
tag = Regexp.last_match(1)
|
52
|
+
modifier = Regexp.last_match(2)
|
53
|
+
content = Regexp.last_match(3).delete("\r").gsub(/\n\z/, '') # remove trailing line break to prevent empty field parsing
|
49
54
|
Field.parsers[tag.to_s].new(content, modifier, tag)
|
50
55
|
else
|
51
56
|
raise LineFormatError, "Wrong line format: #{line.dump}" if Cmxl.config[:raise_line_format_errors]
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
|
-
def initialize(source, modifier=nil, tag=nil)
|
60
|
+
def initialize(source, modifier = nil, tag = nil)
|
56
61
|
self.tag = tag
|
57
62
|
self.modifier = modifier
|
58
63
|
self.source = source
|
59
64
|
self.data = {}
|
60
65
|
|
61
66
|
if self.match = self.source.match(self.class.parser)
|
62
|
-
|
63
|
-
|
67
|
+
match.names.each do |name|
|
68
|
+
data[name] = match[name]
|
64
69
|
end
|
65
70
|
end
|
66
71
|
end
|
@@ -70,11 +75,13 @@ module Cmxl
|
|
70
75
|
end
|
71
76
|
|
72
77
|
def to_h
|
73
|
-
|
78
|
+
data.merge('tag' => tag)
|
74
79
|
end
|
80
|
+
|
75
81
|
def to_hash
|
76
82
|
to_h
|
77
83
|
end
|
84
|
+
|
78
85
|
def to_json(*args)
|
79
86
|
to_h.to_json(*args)
|
80
87
|
end
|
@@ -89,9 +96,9 @@ module Cmxl
|
|
89
96
|
# to_date('0909', 2014)
|
90
97
|
#
|
91
98
|
# Retuns a date object or the provided date value if it is not parseable.
|
92
|
-
def to_date(date, year=nil)
|
99
|
+
def to_date(date, year = nil)
|
93
100
|
if match = date.to_s.match(DATE)
|
94
|
-
year ||= "20#{match['year'] || Date.today.strftime(
|
101
|
+
year ||= "20#{match['year'] || Date.today.strftime('%y')}"
|
95
102
|
month = match['month']
|
96
103
|
day = match['day']
|
97
104
|
Date.new(year.to_i, month.to_i, day.to_i)
|
@@ -103,18 +110,18 @@ module Cmxl
|
|
103
110
|
end
|
104
111
|
|
105
112
|
def to_amount_in_cents(value)
|
106
|
-
value.gsub(/[,|\.](\d*)/) {
|
113
|
+
value.gsub(/[,|\.](\d*)/) { Regexp.last_match(1).ljust(2, '0') }.to_i
|
107
114
|
end
|
108
115
|
|
109
116
|
def to_amount(value)
|
110
|
-
value.
|
117
|
+
value.tr(',', '.').to_f
|
111
118
|
end
|
112
119
|
|
113
120
|
def method_missing(m, *value)
|
114
121
|
if m =~ /=\z/
|
115
|
-
|
122
|
+
data[m] = value.first
|
116
123
|
else
|
117
|
-
|
124
|
+
data[m.to_s]
|
118
125
|
end
|
119
126
|
end
|
120
127
|
end
|