total_in 0.5.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 +7 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +21 -0
- data/Rakefile +1 -0
- data/lib/total_in/attribute_methods.rb +62 -0
- data/lib/total_in/contexts.rb +54 -0
- data/lib/total_in/document.rb +114 -0
- data/lib/total_in/line_handlers.rb +35 -0
- data/lib/total_in/line_parser.rb +42 -0
- data/lib/total_in/line_parsers.rb +80 -0
- data/lib/total_in/line_processors.rb +138 -0
- data/lib/total_in/parser.rb +48 -0
- data/lib/total_in/string_helpers.rb +10 -0
- data/lib/total_in/typecaster.rb +18 -0
- data/lib/total_in/version.rb +3 -0
- data/lib/total_in.rb +8 -0
- data/spec/fixtures/total_in_full.txt +61 -0
- data/spec/full_file_parse_spec.rb +501 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/shared_examples_for_values_line_parsers.rb +15 -0
- data/spec/total_in/line_parsers/account_end_spec.rb +23 -0
- data/spec/total_in/line_parsers/account_start_spec.rb +24 -0
- data/spec/total_in/line_parsers/addresses_spec.rb +10 -0
- data/spec/total_in/line_parsers/deduction_start_spec.rb +50 -0
- data/spec/total_in/line_parsers/document_end_spec.rb +15 -0
- data/spec/total_in/line_parsers/document_start_spec.rb +32 -0
- data/spec/total_in/line_parsers/international_spec.rb +32 -0
- data/spec/total_in/line_parsers/locality_spec.rb +23 -0
- data/spec/total_in/line_parsers/messages_spec.rb +10 -0
- data/spec/total_in/line_parsers/names_spec.rb +11 -0
- data/spec/total_in/line_parsers/payment_start_spec.rb +45 -0
- data/spec/total_in/line_parsers/reference_numbers_spec.rb +11 -0
- data/spec/total_in/line_parsers/sender_account_spec.rb +23 -0
- data/spec/total_in/line_processors/account_end_spec.rb +35 -0
- data/spec/total_in/line_processors/account_start_spec.rb +50 -0
- data/spec/total_in/line_processors/addresses_spec.rb +44 -0
- data/spec/total_in/line_processors/deduction_start_spec.rb +54 -0
- data/spec/total_in/line_processors/document_end_spec.rb +32 -0
- data/spec/total_in/line_processors/document_start_spec.rb +29 -0
- data/spec/total_in/line_processors/international_spec.rb +46 -0
- data/spec/total_in/line_processors/locality_spec.rb +46 -0
- data/spec/total_in/line_processors/messages_spec.rb +25 -0
- data/spec/total_in/line_processors/names_spec.rb +45 -0
- data/spec/total_in/line_processors/payment_start_spec.rb +53 -0
- data/spec/total_in/line_processors/reference_numbers_spec.rb +24 -0
- data/spec/total_in/line_processors/sender_account_spec.rb +46 -0
- data/spec/total_in_spec.rb +13 -0
- data/total-in.gemspec +25 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 58ddedbe4d914ccb31dafda36de258488e2ad768
|
4
|
+
data.tar.gz: 1d9deb3b756e9c5f974c231d6992688c8b1f321d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a4ed13121596580de19c2dc78abbd7ac60e4543986bb8132fdf0891a30335ed20600a7204b5c2f76dbeae0486a8970aff8c42a6e30853905879bccfadc4ec7b9
|
7
|
+
data.tar.gz: 57ac3813d93ac77374a1de9e7b48d2ec4a94b1e98a28cf37b417fcb87e8f98b7e34e84e8b43184e36120a34345a65949477b8cdc2d6ef5d6f0017208a8bb5a48
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.4
|
data/.travis.yml
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.1.5
|
4
|
+
- 2.0.0-p598
|
5
|
+
script: rspec spec
|
6
|
+
addons:
|
7
|
+
code_climate:
|
8
|
+
repo_token:
|
9
|
+
secure: "MVPl+PV2Ewts0sumoKdjJxIX2A1jPJ80wXrFEEbeJMX3f3ST3PQtj2/XTRU4BBq1N2KzJL6ZUffpI9yKqSVsEHPhZan/ngixj5Z4pEEd59dWSJoC7ZxCWAq32qdoq2IAD2fRA7uvs34wo/D0BukTHqAFJXCfbpcoxskH/uzkLP8="
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Joel Junström
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Total-IN file parser
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/Oktavilla/total-in-ruby)
|
4
|
+
[](https://codeclimate.com/github/Oktavilla/total-in-ruby)
|
5
|
+
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require "total_in"
|
11
|
+
|
12
|
+
result = TotalIn.parse total_in_file_contents
|
13
|
+
```
|
14
|
+
|
15
|
+
## Contributing
|
16
|
+
|
17
|
+
1. Fork it ( http://github.com/oktavilla/total-in-ruby/fork )
|
18
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
19
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
20
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
21
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module AttributeMethods
|
2
|
+
def self.included base
|
3
|
+
base.send :include, InstanceMethods
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def attribute name
|
9
|
+
register_attribute name
|
10
|
+
define_attribute_reader name
|
11
|
+
define_attribute_writer name
|
12
|
+
end
|
13
|
+
|
14
|
+
def register_attribute name
|
15
|
+
self.attribute_names.push name
|
16
|
+
end
|
17
|
+
|
18
|
+
def attribute_names
|
19
|
+
@attribute_names ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_attribute_reader name
|
23
|
+
define_method name do
|
24
|
+
read_attribute name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def define_attribute_writer name
|
29
|
+
define_method "#{name}=" do |value|
|
30
|
+
write_attribute name, value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module InstanceMethods
|
36
|
+
def initialize attrs = {}
|
37
|
+
self.assign_attributes attrs
|
38
|
+
end
|
39
|
+
|
40
|
+
def assign_attributes attrs
|
41
|
+
attrs.each do |name, value|
|
42
|
+
write_attribute name, value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def attributes
|
47
|
+
@attributes ||= {}
|
48
|
+
end
|
49
|
+
|
50
|
+
def read_attribute name
|
51
|
+
attributes[name]
|
52
|
+
end
|
53
|
+
|
54
|
+
def write_attribute name, value
|
55
|
+
attributes[name] = value if attribute_names.include?(name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def attribute_names
|
59
|
+
self.class.attribute_names
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module TotalIn
|
2
|
+
class Contexts
|
3
|
+
def initialize containers = nil
|
4
|
+
Array(containers).compact.each do |container|
|
5
|
+
add container
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def result
|
10
|
+
contexts.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def current
|
14
|
+
contexts.last
|
15
|
+
end
|
16
|
+
|
17
|
+
def add container
|
18
|
+
contexts.push container
|
19
|
+
end
|
20
|
+
|
21
|
+
def move_up
|
22
|
+
contexts.pop
|
23
|
+
end
|
24
|
+
|
25
|
+
def move_to container_class
|
26
|
+
until current.is_a?(container_class)
|
27
|
+
move_up
|
28
|
+
end if contexts.any?
|
29
|
+
end
|
30
|
+
|
31
|
+
def move_to_or_add_to_parent container_class, parent_container_class
|
32
|
+
return self if current.is_a?(container_class)
|
33
|
+
|
34
|
+
until current.kind_of?(parent_container_class)
|
35
|
+
move_up
|
36
|
+
end
|
37
|
+
|
38
|
+
entity = container_class.new
|
39
|
+
|
40
|
+
setter_name = StringHelpers.underscore container_class.name.split("::").last
|
41
|
+
current.public_send "#{setter_name}=", entity
|
42
|
+
|
43
|
+
add entity
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def contexts
|
51
|
+
@contexts ||= []
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require "total_in/string_helpers"
|
2
|
+
require "total_in/attribute_methods"
|
3
|
+
|
4
|
+
module TotalIn
|
5
|
+
class Document
|
6
|
+
include AttributeMethods
|
7
|
+
attribute :id
|
8
|
+
attribute :created_at
|
9
|
+
attribute :delivery_number
|
10
|
+
attribute :file_type
|
11
|
+
attribute :name
|
12
|
+
attribute :number_of_lines
|
13
|
+
|
14
|
+
def accounts
|
15
|
+
@accounts ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
class Account
|
19
|
+
include AttributeMethods
|
20
|
+
attribute :account_number
|
21
|
+
attribute :currency
|
22
|
+
attribute :date
|
23
|
+
attribute :number_of_transactions
|
24
|
+
attribute :amount
|
25
|
+
attribute :statement_reference
|
26
|
+
|
27
|
+
def payments
|
28
|
+
@payments ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
def deductions
|
32
|
+
@deductions ||= []
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Transaction
|
37
|
+
include AttributeMethods
|
38
|
+
def reference_numbers
|
39
|
+
@reference_numbers ||= []
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor :sender
|
43
|
+
attr_accessor :sender_account
|
44
|
+
attr_accessor :international
|
45
|
+
|
46
|
+
def message
|
47
|
+
messages.join "\n" if messages.any?
|
48
|
+
end
|
49
|
+
|
50
|
+
def messages
|
51
|
+
@messages ||= []
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_message message
|
55
|
+
messages.push message
|
56
|
+
end
|
57
|
+
|
58
|
+
def international?
|
59
|
+
!!self.international
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Payment < Transaction
|
64
|
+
attribute :amount
|
65
|
+
attribute :serial_number
|
66
|
+
attribute :receiving_bankgiro_number
|
67
|
+
end
|
68
|
+
|
69
|
+
class Deduction < Transaction
|
70
|
+
attribute :amount
|
71
|
+
attribute :serial_number
|
72
|
+
attribute :receiving_bankgiro_number
|
73
|
+
attribute :code
|
74
|
+
end
|
75
|
+
|
76
|
+
class Sender
|
77
|
+
include AttributeMethods
|
78
|
+
attribute :name
|
79
|
+
attribute :address
|
80
|
+
attribute :postal_code
|
81
|
+
attribute :city
|
82
|
+
attribute :country_code
|
83
|
+
|
84
|
+
def self.add_to_contexts contexts
|
85
|
+
contexts.move_to_or_add_to_parent self, Transaction
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class SenderAccount
|
90
|
+
include AttributeMethods
|
91
|
+
attribute :name
|
92
|
+
attribute :address
|
93
|
+
attribute :postal_code
|
94
|
+
attribute :city
|
95
|
+
attribute :country_code
|
96
|
+
attribute :account_number
|
97
|
+
attribute :origin_code
|
98
|
+
attribute :company_organization_number
|
99
|
+
|
100
|
+
def self.add_to_contexts contexts
|
101
|
+
contexts.move_to_or_add_to_parent self, Transaction
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class International
|
106
|
+
include AttributeMethods
|
107
|
+
attribute :cost
|
108
|
+
attribute :cost_currency
|
109
|
+
attribute :amount
|
110
|
+
attribute :amount_currency
|
111
|
+
attribute :exchange_rate
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "total_in/line_parsers"
|
2
|
+
require "total_in/line_processors"
|
3
|
+
|
4
|
+
module TotalIn
|
5
|
+
module LineHandlers
|
6
|
+
Handler = Struct.new :parser, :processor do
|
7
|
+
def handle line, contexts
|
8
|
+
line_parser = self.parser.new(line)
|
9
|
+
|
10
|
+
processor.call line_parser, contexts
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.all
|
15
|
+
{
|
16
|
+
"00" => Handler.new(LineParsers::DocumentStart, LineProcessors::DocumentStart),
|
17
|
+
"99" => Handler.new(LineParsers::DocumentEnd, LineProcessors::DocumentEnd),
|
18
|
+
"10" => Handler.new(LineParsers::AccountStart, LineProcessors::AccountStart),
|
19
|
+
"90" => Handler.new(LineParsers::AccountEnd, LineProcessors::AccountEnd),
|
20
|
+
"20" => Handler.new(LineParsers::PaymentStart, LineProcessors::PaymentStart),
|
21
|
+
"25" => Handler.new(LineParsers::DeductionStart, LineProcessors::DeductionStart),
|
22
|
+
"30" => Handler.new(LineParsers::ReferenceNumbers, LineProcessors::ReferenceNumbers),
|
23
|
+
"40" => Handler.new(LineParsers::Messages, LineProcessors::Messages),
|
24
|
+
"50" => Handler.new(LineParsers::Names, LineProcessors::Names.new(Document::Sender)),
|
25
|
+
"51" => Handler.new(LineParsers::Addresses, LineProcessors::Addresses.new(Document::Sender)),
|
26
|
+
"52" => Handler.new(LineParsers::Locality, LineProcessors::Locality.new(Document::Sender)),
|
27
|
+
"60" => Handler.new(LineParsers::SenderAccount, LineProcessors::SenderAccount),
|
28
|
+
"61" => Handler.new(LineParsers::Names, LineProcessors::Names.new(Document::SenderAccount)),
|
29
|
+
"62" => Handler.new(LineParsers::Addresses, LineProcessors::Addresses.new(Document::SenderAccount)),
|
30
|
+
"63" => Handler.new(LineParsers::Locality, LineProcessors::Locality.new(Document::SenderAccount)),
|
31
|
+
"70" => Handler.new(LineParsers::International, LineProcessors::International)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "total_in/typecaster"
|
2
|
+
|
3
|
+
module TotalIn
|
4
|
+
class LineParser
|
5
|
+
attr_reader :line
|
6
|
+
def initialize line
|
7
|
+
@line = line
|
8
|
+
end
|
9
|
+
|
10
|
+
def attributes
|
11
|
+
self.class.field_names.each_with_object({}) do |field, attrs|
|
12
|
+
attrs[field] = self.public_send(field)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.field name, range, type = :string
|
17
|
+
self.field_names.push name
|
18
|
+
|
19
|
+
define_method name do
|
20
|
+
if range.is_a?(Array)
|
21
|
+
range.map { |r| value_at_position(r, type) }.compact
|
22
|
+
else
|
23
|
+
value_at_position range, type
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.field_names
|
31
|
+
@field_names ||= []
|
32
|
+
end
|
33
|
+
|
34
|
+
def value_at_position range, type
|
35
|
+
typecast line[range].strip, type
|
36
|
+
end
|
37
|
+
|
38
|
+
def typecast value, type
|
39
|
+
Typecaster.cast value, type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "total_in/line_parser"
|
2
|
+
|
3
|
+
module TotalIn
|
4
|
+
module LineParsers
|
5
|
+
class DocumentStart < LineParser
|
6
|
+
field :id, 2..13
|
7
|
+
field :created_at, 14..33, :time
|
8
|
+
field :delivery_number, 34..35, :integer
|
9
|
+
field :file_type, 36..38
|
10
|
+
field :name, 39..48
|
11
|
+
end
|
12
|
+
|
13
|
+
class DocumentEnd < LineParser
|
14
|
+
field :number_of_lines, 2..16, :integer
|
15
|
+
end
|
16
|
+
|
17
|
+
class AccountStart < LineParser
|
18
|
+
field :account_number, 2..37
|
19
|
+
field :currency, 38..40
|
20
|
+
field :date, 41..48, :date
|
21
|
+
end
|
22
|
+
|
23
|
+
class AccountEnd < LineParser
|
24
|
+
field :number_of_transactions, 2..9, :integer
|
25
|
+
field :amount, 10..26, :integer
|
26
|
+
field :statement_reference, 27..37
|
27
|
+
end
|
28
|
+
|
29
|
+
class PaymentStart < LineParser
|
30
|
+
field :reference_number, 2..36
|
31
|
+
field :amount, 37..51, :integer
|
32
|
+
field :serial_number, 52..68, :integer
|
33
|
+
field :receiving_bankgiro_number, 69..76
|
34
|
+
end
|
35
|
+
|
36
|
+
class DeductionStart < LineParser
|
37
|
+
field :reference_number, 2..36
|
38
|
+
field :amount, 37..51, :integer
|
39
|
+
field :serial_number, 52..68, :integer
|
40
|
+
field :code, 69..69, :integer
|
41
|
+
field :receiving_bankgiro_number, 70..77
|
42
|
+
end
|
43
|
+
|
44
|
+
class Values < LineParser
|
45
|
+
field :values, [2..36, 37..71]
|
46
|
+
end
|
47
|
+
|
48
|
+
class ReferenceNumbers < Values
|
49
|
+
end
|
50
|
+
|
51
|
+
class Messages < Values
|
52
|
+
end
|
53
|
+
|
54
|
+
class Names < Values
|
55
|
+
end
|
56
|
+
|
57
|
+
class Addresses < Values
|
58
|
+
end
|
59
|
+
|
60
|
+
class Locality < LineParser
|
61
|
+
field :postal_code, 2..10
|
62
|
+
field :city, 11..45
|
63
|
+
field :country_code, 46..47
|
64
|
+
end
|
65
|
+
|
66
|
+
class SenderAccount < LineParser
|
67
|
+
field :account_number, 2..37
|
68
|
+
field :origin_code, 38..38, :integer
|
69
|
+
field :company_organization_number, 39..58
|
70
|
+
end
|
71
|
+
|
72
|
+
class International < LineParser
|
73
|
+
field :cost, 2..16, :integer
|
74
|
+
field :cost_currency, 17..19
|
75
|
+
field :amount, 38..52, :integer
|
76
|
+
field :amount_currency, 53..55
|
77
|
+
field :exchange_rate, 56..67, :integer
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require "total_in/document"
|
2
|
+
|
3
|
+
module TotalIn
|
4
|
+
module LineProcessors
|
5
|
+
DocumentStart = ->(line, contexts) {
|
6
|
+
document = Document.new line.attributes
|
7
|
+
|
8
|
+
contexts.add document
|
9
|
+
|
10
|
+
contexts
|
11
|
+
}
|
12
|
+
|
13
|
+
DocumentEnd = ->(line, contexts) {
|
14
|
+
contexts.move_to Document
|
15
|
+
|
16
|
+
contexts.current.number_of_lines = line.number_of_lines
|
17
|
+
|
18
|
+
contexts
|
19
|
+
}
|
20
|
+
|
21
|
+
AccountStart = ->(line, contexts) {
|
22
|
+
contexts.move_to Document
|
23
|
+
|
24
|
+
account = Document::Account.new line.attributes
|
25
|
+
|
26
|
+
contexts.current.accounts << account
|
27
|
+
contexts.add account
|
28
|
+
|
29
|
+
contexts
|
30
|
+
}
|
31
|
+
|
32
|
+
AccountEnd = ->(line, contexts) {
|
33
|
+
contexts.move_to Document::Account
|
34
|
+
|
35
|
+
contexts.current.assign_attributes line.attributes
|
36
|
+
|
37
|
+
contexts
|
38
|
+
}
|
39
|
+
|
40
|
+
PaymentStart = ->(line, contexts) {
|
41
|
+
contexts.move_to Document::Account
|
42
|
+
|
43
|
+
payment = Document::Payment.new line.attributes
|
44
|
+
payment.reference_numbers << line.reference_number if line.reference_number
|
45
|
+
|
46
|
+
contexts.current.payments << payment
|
47
|
+
|
48
|
+
contexts.add payment
|
49
|
+
|
50
|
+
contexts
|
51
|
+
}
|
52
|
+
|
53
|
+
DeductionStart = ->(line, contexts) {
|
54
|
+
contexts.move_to Document::Account
|
55
|
+
|
56
|
+
deduction = Document::Deduction.new line.attributes
|
57
|
+
deduction.reference_numbers << line.reference_number if line.reference_number
|
58
|
+
|
59
|
+
contexts.current.deductions << deduction
|
60
|
+
contexts.add deduction
|
61
|
+
|
62
|
+
contexts
|
63
|
+
}
|
64
|
+
|
65
|
+
ReferenceNumbers = ->(line, contexts) {
|
66
|
+
contexts.current.reference_numbers.concat line.values
|
67
|
+
|
68
|
+
contexts
|
69
|
+
}
|
70
|
+
|
71
|
+
Messages = ->(line, contexts) {
|
72
|
+
line.values.each do |message|
|
73
|
+
contexts.current.add_message message
|
74
|
+
end
|
75
|
+
|
76
|
+
contexts
|
77
|
+
}
|
78
|
+
|
79
|
+
class WithTargetClass
|
80
|
+
def initialize target_class
|
81
|
+
@target_class = target_class
|
82
|
+
end
|
83
|
+
|
84
|
+
attr_reader :target_class
|
85
|
+
end
|
86
|
+
|
87
|
+
class Names < WithTargetClass
|
88
|
+
def call line, contexts
|
89
|
+
contexts = target_class.add_to_contexts contexts
|
90
|
+
|
91
|
+
contexts.current.name = line.values.join " "
|
92
|
+
|
93
|
+
contexts
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
class Addresses < WithTargetClass
|
99
|
+
def call line, contexts
|
100
|
+
contexts = target_class.add_to_contexts contexts
|
101
|
+
|
102
|
+
contexts.current.address = line.values.join " "
|
103
|
+
|
104
|
+
contexts
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Locality < WithTargetClass
|
109
|
+
def call line, contexts
|
110
|
+
contexts = target_class.add_to_contexts contexts
|
111
|
+
|
112
|
+
contexts.current.assign_attributes line.attributes
|
113
|
+
|
114
|
+
contexts
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
SenderAccount = ->(line, contexts) {
|
119
|
+
contexts = Document::SenderAccount.add_to_contexts contexts
|
120
|
+
|
121
|
+
contexts.current.assign_attributes line.attributes
|
122
|
+
|
123
|
+
contexts
|
124
|
+
}
|
125
|
+
|
126
|
+
International = ->(line, contexts) {
|
127
|
+
until contexts.current.kind_of?(Document::Transaction)
|
128
|
+
contexts.move_up
|
129
|
+
end
|
130
|
+
|
131
|
+
international = Document::International.new line.attributes
|
132
|
+
|
133
|
+
contexts.current.international = international
|
134
|
+
|
135
|
+
contexts
|
136
|
+
}
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "total_in/line_handlers"
|
2
|
+
require "total_in/contexts"
|
3
|
+
|
4
|
+
module TotalIn
|
5
|
+
class Parser
|
6
|
+
attr_reader :text
|
7
|
+
|
8
|
+
def initialize text
|
9
|
+
@text = text
|
10
|
+
end
|
11
|
+
|
12
|
+
def result
|
13
|
+
contexts = parse_lines text.each_line.to_a, Contexts.new
|
14
|
+
|
15
|
+
contexts.result
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parse_lines lines, contexts
|
21
|
+
if line = lines.shift
|
22
|
+
parse_lines lines, parse_line(line, contexts)
|
23
|
+
else
|
24
|
+
contexts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_line line, contexts
|
29
|
+
handler = handler_for_line line
|
30
|
+
|
31
|
+
handler.handle line, contexts
|
32
|
+
end
|
33
|
+
|
34
|
+
def handler_for_line line
|
35
|
+
self.class.handlers.fetch line[0..1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.handlers
|
39
|
+
@handlers ||= {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.register_handlers handlers
|
43
|
+
@handlers = handlers
|
44
|
+
end
|
45
|
+
|
46
|
+
register_handlers LineHandlers.all
|
47
|
+
end
|
48
|
+
end
|