norma43_parser 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +85 -0
- data/Rakefile +1 -0
- data/doc/classes.jpg +0 -0
- data/doc/cuaderno_43_-_junio_2012.pdf +800 -1
- data/lib/norma43/line_handlers.rb +54 -0
- data/lib/norma43/line_parsers/file_format_validator.rb +19 -0
- data/lib/norma43/line_parsers/line_parser.rb +42 -0
- data/lib/norma43/line_parsers/line_parsers.rb +69 -0
- data/lib/norma43/line_processors.rb +60 -0
- data/lib/norma43/models.rb +85 -0
- data/lib/norma43/parser.rb +79 -0
- data/lib/norma43/utils/contexts.rb +54 -0
- data/lib/norma43/utils/string_helpers.rb +10 -0
- data/lib/norma43/utils/typecaster.rb +19 -0
- data/lib/norma43/version.rb +3 -0
- data/lib/norma43.rb +8 -0
- data/norma43_parser.gemspec +27 -0
- data/spec/example1_parse_spec.rb +91 -0
- data/spec/fixtures/example1.n43 +10 -0
- data/spec/norma43/line_parsers/account_end_spec.rb +51 -0
- data/spec/norma43/line_parsers/account_start_spec.rb +55 -0
- data/spec/norma43/line_parsers/additional_currency_spec.rb +27 -0
- data/spec/norma43/line_parsers/additional_items_spec.rb +23 -0
- data/spec/norma43/line_parsers/document_end_spec.rb +16 -0
- data/spec/norma43/line_parsers/document_start_spec.rb +32 -0
- data/spec/norma43/line_parsers/transaction_spec.rb +55 -0
- data/spec/norma43/line_processors/account_end_spec.rb +34 -0
- data/spec/norma43/line_processors/account_start_spec.rb +40 -0
- data/spec/norma43/line_processors/additional_currency_spec.rb +42 -0
- data/spec/norma43/line_processors/additional_items_spec.rb +42 -0
- data/spec/norma43/line_processors/document_end_spec.rb +30 -0
- data/spec/norma43/line_processors/document_start_spec.rb +27 -0
- data/spec/norma43/line_processors/transaction_spec.rb +42 -0
- data/spec/norma43/parser_spec.rb +23 -0
- data/spec/norma43_spec.rb +13 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/shared_examples_for_values_line_parsers.rb +15 -0
- metadata +173 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require "norma43/line_parsers/line_parsers"
|
2
|
+
require "norma43/line_processors"
|
3
|
+
|
4
|
+
module Norma43
|
5
|
+
module LineHandlers
|
6
|
+
def self.mapping
|
7
|
+
{
|
8
|
+
"00" => self.document_start,
|
9
|
+
"88" => self.document_end,
|
10
|
+
"11" => self.account_start,
|
11
|
+
"33" => self.account_end,
|
12
|
+
"22" => self.transaction,
|
13
|
+
"23" => self.additional_item,
|
14
|
+
"24" => self.additional_currency
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.document_start
|
19
|
+
Handler.new LineParsers::DocumentStart, LineProcessors::DocumentStart
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.document_end
|
23
|
+
Handler.new LineParsers::DocumentEnd, LineProcessors::DocumentEnd
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.account_start
|
27
|
+
Handler.new LineParsers::AccountStart, LineProcessors::AccountStart
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.account_end
|
31
|
+
Handler.new LineParsers::AccountEnd, LineProcessors::AccountEnd
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.transaction
|
35
|
+
Handler.new LineParsers::Transaction, LineProcessors::Transaction
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.additional_item
|
39
|
+
Handler.new LineParsers::AdditionalItem, LineProcessors::AdditionalItem
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.additional_currency
|
43
|
+
Handler.new LineParsers::AdditionalCurrency, LineProcessors::AdditionalCurrency
|
44
|
+
end
|
45
|
+
|
46
|
+
Handler = Struct.new :parser, :processor do
|
47
|
+
def process line, contexts
|
48
|
+
line_parser = self.parser.new(line)
|
49
|
+
|
50
|
+
processor.call line_parser, contexts
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "norma43/line_parsers/line_parser"
|
2
|
+
module Norma43
|
3
|
+
class FileFormatValidator < LineParser
|
4
|
+
field :record_type, 0..1, :raw
|
5
|
+
field :file_type, 36..38
|
6
|
+
|
7
|
+
def has_document?; file_type=="00" end
|
8
|
+
|
9
|
+
def valid?
|
10
|
+
errors.empty?
|
11
|
+
end
|
12
|
+
|
13
|
+
def errors
|
14
|
+
errors = []
|
15
|
+
%w(11 00).include? record_type or errors << "Must start with 00 (was ”#{record_type}”)"
|
16
|
+
errors
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "norma43/utils/typecaster"
|
2
|
+
|
3
|
+
module Norma43
|
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) # let multivalued attribute
|
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].to_s.strip, type
|
36
|
+
end
|
37
|
+
|
38
|
+
def typecast value, type
|
39
|
+
Typecaster.cast value, type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "norma43/line_parsers/line_parser"
|
2
|
+
|
3
|
+
module Norma43
|
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 :record_number, 20..25, :integer
|
15
|
+
end
|
16
|
+
|
17
|
+
class AccountStart < LineParser
|
18
|
+
field :bank_code, 2..5, :integer
|
19
|
+
field :branch_code, 6..9, :integer
|
20
|
+
field :account_number, 10..19, :integer
|
21
|
+
field :start_date, 20..25, :date
|
22
|
+
field :end_date, 26..31, :date
|
23
|
+
field :balance_code, 32, :integer
|
24
|
+
field :balance_amount, 33..46, :integer
|
25
|
+
field :currency_code, 47..49, :integer
|
26
|
+
field :information_mode_code, 50, :integer
|
27
|
+
field :abbreviated_name, 51..76
|
28
|
+
end
|
29
|
+
|
30
|
+
class AccountEnd < LineParser
|
31
|
+
field :bank_code, 2..5, :integer
|
32
|
+
field :branch_code, 6..9, :integer
|
33
|
+
field :account_number, 10..19, :integer
|
34
|
+
field :debit_entries, 20..24, :integer
|
35
|
+
field :debit_amount, 25..38, :integer
|
36
|
+
field :credit_entries, 39..43, :integer
|
37
|
+
field :credit_amount, 44..57, :integer
|
38
|
+
field :balance_code, 58, :integer
|
39
|
+
field :balance_amount, 59..72, :integer
|
40
|
+
field :currency_code, 73..75, :integer
|
41
|
+
end
|
42
|
+
|
43
|
+
class Transaction < LineParser
|
44
|
+
field :origin_branch_code, 6..9, :integer
|
45
|
+
field :transaction_date, 10..15, :date
|
46
|
+
field :value_date, 16..21, :date
|
47
|
+
field :shared_item, 22..23, :integer
|
48
|
+
field :own_item, 24..26, :integer
|
49
|
+
field :amount_code, 27, :integer
|
50
|
+
field :amount, 28..41, :integer
|
51
|
+
field :document_number, 42..51, :integer
|
52
|
+
field :reference_1, 52..63, :integer
|
53
|
+
field :reference_2, 64..79
|
54
|
+
end
|
55
|
+
|
56
|
+
class AdditionalItem < LineParser
|
57
|
+
field :data_code, 2..3, :integer
|
58
|
+
field :item_1, 4..41
|
59
|
+
field :item_2, 42..79
|
60
|
+
end
|
61
|
+
|
62
|
+
class AdditionalCurrency < LineParser
|
63
|
+
field :data_code, 2..3, :integer
|
64
|
+
field :currency_code, 4..6, :integer
|
65
|
+
field :amount, 7..20, :integer
|
66
|
+
field :free, 21..79
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "norma43/models"
|
2
|
+
module Norma43
|
3
|
+
module LineProcessors
|
4
|
+
DocumentStart = ->(line, contexts) {
|
5
|
+
document = Models::Document.new line.attributes
|
6
|
+
|
7
|
+
contexts.add document
|
8
|
+
|
9
|
+
contexts
|
10
|
+
}
|
11
|
+
|
12
|
+
DocumentEnd = ->(line, contexts) {
|
13
|
+
contexts.move_to Models::Document
|
14
|
+
contexts.current.number_of_lines = line.record_number
|
15
|
+
contexts
|
16
|
+
}
|
17
|
+
|
18
|
+
AccountStart = ->(line, contexts) {
|
19
|
+
contexts.move_to Models::Document
|
20
|
+
account = Models::Account.new line.attributes
|
21
|
+
contexts.current.accounts << account
|
22
|
+
contexts.add account
|
23
|
+
|
24
|
+
contexts
|
25
|
+
}
|
26
|
+
|
27
|
+
AccountEnd = ->(line, contexts) {
|
28
|
+
contexts.move_to Models::Account
|
29
|
+
contexts.current.attributes = line.attributes
|
30
|
+
contexts
|
31
|
+
}
|
32
|
+
|
33
|
+
Transaction = ->(line, contexts) {
|
34
|
+
contexts.move_to Models::Account
|
35
|
+
|
36
|
+
transaction = Models::Transaction.new line.attributes
|
37
|
+
|
38
|
+
contexts.current.transactions << transaction
|
39
|
+
|
40
|
+
contexts.add transaction
|
41
|
+
|
42
|
+
contexts
|
43
|
+
}
|
44
|
+
|
45
|
+
AdditionalItem = ->(line, contexts) {
|
46
|
+
contexts.move_to Models::Transaction
|
47
|
+
additional_item = Models::AdditionalItem.new line.attributes
|
48
|
+
contexts.current.additional_items << additional_item
|
49
|
+
contexts
|
50
|
+
}
|
51
|
+
|
52
|
+
AdditionalCurrency = ->(line, contexts) {
|
53
|
+
contexts.move_to Models::Transaction
|
54
|
+
additional_currency = Models::AdditionalCurrency.new line.attributes
|
55
|
+
contexts.current.additional_currency = additional_currency
|
56
|
+
contexts
|
57
|
+
}
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "norma43/utils/string_helpers"
|
2
|
+
require 'virtus'
|
3
|
+
|
4
|
+
module Norma43
|
5
|
+
module Models
|
6
|
+
#forward declarations
|
7
|
+
class Account; end
|
8
|
+
class Transaction; end
|
9
|
+
class AdditionalItem; end
|
10
|
+
class AdditionalCurrency; end
|
11
|
+
DEBIT_CODE = 1
|
12
|
+
CREDIT_CODE = 2
|
13
|
+
|
14
|
+
class Document
|
15
|
+
include Virtus.model
|
16
|
+
|
17
|
+
attribute :id
|
18
|
+
attribute :created_at
|
19
|
+
attribute :delivery_number
|
20
|
+
attribute :file_type
|
21
|
+
attribute :name
|
22
|
+
attribute :number_of_lines
|
23
|
+
attribute :accounts, Array[Account]
|
24
|
+
|
25
|
+
def transaction_date
|
26
|
+
accounts.map(&:date).compact.first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Account
|
31
|
+
include Virtus.model
|
32
|
+
|
33
|
+
attribute :bank_code
|
34
|
+
attribute :branch_code
|
35
|
+
attribute :account_number
|
36
|
+
attribute :start_date
|
37
|
+
attribute :end_date
|
38
|
+
attribute :balance_code
|
39
|
+
attribute :balance_amount
|
40
|
+
attribute :currency_code
|
41
|
+
attribute :information_mode_code
|
42
|
+
attribute :abbreviated_name
|
43
|
+
attribute :debit_entries
|
44
|
+
attribute :debit_amount
|
45
|
+
attribute :credit_entries
|
46
|
+
attribute :credit_amount
|
47
|
+
attribute :transactions, Array[Transaction]
|
48
|
+
end
|
49
|
+
|
50
|
+
class Transaction
|
51
|
+
include Virtus.model
|
52
|
+
|
53
|
+
attribute :origin_branch_code
|
54
|
+
attribute :transaction_date
|
55
|
+
attribute :value_date
|
56
|
+
attribute :shared_item
|
57
|
+
attribute :own_item
|
58
|
+
attribute :amount_code
|
59
|
+
attribute :amount
|
60
|
+
attribute :document_number
|
61
|
+
attribute :reference_1
|
62
|
+
attribute :reference_2
|
63
|
+
attribute :additional_items, Array[AdditionalItem]
|
64
|
+
attribute :additional_currency, AdditionalCurrency
|
65
|
+
def debit?; self.amount_code==DEBIT_CODE end
|
66
|
+
end
|
67
|
+
|
68
|
+
class AdditionalItem
|
69
|
+
include Virtus.model
|
70
|
+
|
71
|
+
attribute :data_code
|
72
|
+
attribute :item_1
|
73
|
+
attribute :item_2
|
74
|
+
end
|
75
|
+
|
76
|
+
class AdditionalCurrency
|
77
|
+
include Virtus.model
|
78
|
+
|
79
|
+
attribute :data_code
|
80
|
+
attribute :currency_code
|
81
|
+
attribute :amount
|
82
|
+
attribute :free
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "norma43/line_parsers/file_format_validator"
|
2
|
+
require "norma43/line_handlers"
|
3
|
+
require "norma43/utils/contexts"
|
4
|
+
|
5
|
+
module Norma43
|
6
|
+
class InvalidFileFormatError < ArgumentError; end;
|
7
|
+
|
8
|
+
class Parser
|
9
|
+
attr_reader :file
|
10
|
+
|
11
|
+
# Parser.new accepts a File instance or a String
|
12
|
+
# A InvalidFileFormatError will be raised if file isn't in the Norma43 format
|
13
|
+
def initialize file
|
14
|
+
@file = file
|
15
|
+
validator = validate_file_format
|
16
|
+
@contexts = if validator.has_document?
|
17
|
+
Contexts.new
|
18
|
+
else
|
19
|
+
# in theory Norma43 says that files should start with DocumentStart but
|
20
|
+
# practically doesn't happen, so that we create one artificially
|
21
|
+
# to avoid corner cases in the processors
|
22
|
+
Contexts.new().tap { |ctx| ctx.add Models::Document.new }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def result
|
27
|
+
parse_lines(@contexts).result
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def lines
|
33
|
+
@lines ||= file.each_line
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def validate_file_format
|
39
|
+
validator = FileFormatValidator.new first_line
|
40
|
+
raise InvalidFileFormatError.new(validator.errors.join(", ")) unless validator.valid?
|
41
|
+
validator
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_lines contexts
|
45
|
+
parse_lines parse_line(self.lines.next, contexts)
|
46
|
+
|
47
|
+
rescue StopIteration# because lines is an enumerator raises StopIteration on end
|
48
|
+
self.lines.rewind # Ensure we do not bomb out when calling result multiple times
|
49
|
+
contexts
|
50
|
+
end
|
51
|
+
|
52
|
+
# Look up a matching handler for the line and process it
|
53
|
+
# The process method on a handler always returns a Contexts object
|
54
|
+
def parse_line line, contexts
|
55
|
+
line = line.encode Encoding::UTF_8 if encode_lines?
|
56
|
+
|
57
|
+
handler = handler_for_line line
|
58
|
+
|
59
|
+
handler.process line, contexts
|
60
|
+
end
|
61
|
+
|
62
|
+
def handler_for_line line
|
63
|
+
LineHandlers.mapping.fetch line[0..1]
|
64
|
+
end
|
65
|
+
|
66
|
+
def encode_lines?
|
67
|
+
first_line.encoding != Encoding::UTF_8
|
68
|
+
end
|
69
|
+
|
70
|
+
def first_line
|
71
|
+
@first_line ||= begin
|
72
|
+
line = self.lines.peek
|
73
|
+
self.lines.rewind # peek seems to move the pointer when file is an actual File object
|
74
|
+
|
75
|
+
line
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Norma43
|
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) or current.nil?
|
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,19 @@
|
|
1
|
+
require "time"
|
2
|
+
|
3
|
+
module Norma43
|
4
|
+
module Typecaster
|
5
|
+
def self.cast value, type
|
6
|
+
casters.fetch(type).call(value) unless value == ""
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.casters
|
10
|
+
{
|
11
|
+
integer: ->(value) { value.to_i },
|
12
|
+
time: ->(value) { Time.strptime(value, "%Y%m%d%H%M%S%N") },
|
13
|
+
date: ->(value) { Date.strptime(value, "%y%m%d") },
|
14
|
+
string: ->(value) { value unless value.match(/\A0+\Z/) },
|
15
|
+
raw: ->(value) { value }
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/norma43.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "norma43/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "norma43_parser"
|
8
|
+
spec.version = Norma43::VERSION
|
9
|
+
spec.authors = ["Sequra engineering"]
|
10
|
+
spec.email = ["dev@sequra.es"]
|
11
|
+
spec.summary = %q{Parses banks transactions files specified in rule 43}
|
12
|
+
spec.homepage = "https://github.com/sequra/norma43_parser"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.required_ruby_version = "~> 2.0"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "byebug"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_runtime_dependency "virtus"
|
27
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "norma43"
|
2
|
+
|
3
|
+
RSpec.describe Norma43 do
|
4
|
+
describe "parse" do
|
5
|
+
|
6
|
+
let(:document) do
|
7
|
+
file = File.open( File.join(__dir__, "fixtures/example1.n43"),
|
8
|
+
encoding: "iso-8859-1")
|
9
|
+
Norma43.parse file
|
10
|
+
end
|
11
|
+
|
12
|
+
it "finds one account" do
|
13
|
+
expect(document.accounts.size).to eq 1
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "first account" do
|
17
|
+
let(:account) { document.accounts.first }
|
18
|
+
|
19
|
+
it "stores expected attributes from AccountStart parser" do
|
20
|
+
expect(account).to have_attributes({
|
21
|
+
"bank_code" => 9999,
|
22
|
+
"branch_code" => 1111,
|
23
|
+
"account_number" => 123456789,
|
24
|
+
"start_date" => Date.parse("2004-08-04"),
|
25
|
+
"end_date" => Date.parse("2004-09-05"),
|
26
|
+
"currency_code" => 1,
|
27
|
+
"information_mode_code" => 3,
|
28
|
+
"abbreviated_name" => "MY ACCOUNT"
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
it "stores expected attributes from AccountEnd parser" do
|
33
|
+
expect(account).to have_attributes({
|
34
|
+
"balance_code" => 2,
|
35
|
+
"balance_amount" => 78889999999999,
|
36
|
+
"debit_entries" => 4,
|
37
|
+
"debit_amount" => 4936,
|
38
|
+
"credit_entries" => 2,
|
39
|
+
"credit_amount" => 999999,
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "transactions" do
|
44
|
+
it "finds all transactions" do
|
45
|
+
expect(account.transactions.size).to eq 4
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "first transaction" do
|
49
|
+
let(:transaction) { account.transactions[0] }
|
50
|
+
it "stores expected attributes" do
|
51
|
+
expect(transaction).to have_attributes({
|
52
|
+
"origin_branch_code" => 6700,
|
53
|
+
"transaction_date" => Date.parse("2004-04-08"),
|
54
|
+
"value_date" => Date.parse("2004-04-08"),
|
55
|
+
"shared_item" => 4,
|
56
|
+
"own_item" => 7,
|
57
|
+
"amount_code" => 2,
|
58
|
+
"amount" => 1234,
|
59
|
+
"document_number" => 0,
|
60
|
+
"reference_1" => 0,
|
61
|
+
"reference_2" => nil,
|
62
|
+
})
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "each transaction has 5 additional_items as a maximum" do
|
67
|
+
account.transactions.each do |transaction|
|
68
|
+
expect(transaction.additional_items.size).to be <= 5
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "first additional item" do
|
73
|
+
let(:additional_item) { account.transactions[0].additional_items[0]}
|
74
|
+
it "stores expected attributes" do
|
75
|
+
expect(additional_item).to have_attributes({
|
76
|
+
"data_code" => 1,
|
77
|
+
"item_1" => "XXXXXXXXX",
|
78
|
+
"item_2" => nil
|
79
|
+
})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "first additional currency" do
|
84
|
+
xit "stores expected attributes" do
|
85
|
+
# We don't have exaples to write test write when have
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
119999111101234567890408040409052000000001234569783MY ACCOUNT
|
2
|
+
2212346700040408040408040072000000000012340000000000000000000000
|
3
|
+
2301XXXXXXXXX
|
4
|
+
2212346700040408040408040072000000000012340000000000000000000000
|
5
|
+
2301A28152585
|
6
|
+
2256781128040405040405040072000000000012340000000000000000000000
|
7
|
+
2301XXXXXXXXX
|
8
|
+
2256781127040805040805020092000000000012340000000000000000000000
|
9
|
+
2301REF XXXXXXXXX
|
10
|
+
3399991111012345678900004000000000049360000200000000999999278889999999999001
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "norma43/line_parsers/line_parsers"
|
2
|
+
|
3
|
+
module Norma43
|
4
|
+
module LineParsers
|
5
|
+
RSpec.describe AccountEnd do
|
6
|
+
let :account_end do
|
7
|
+
AccountEnd.new "3399991111012345678900004000000000049360000200000000999999278889999999999001 "
|
8
|
+
end
|
9
|
+
|
10
|
+
it "parses the bank code" do
|
11
|
+
expect(account_end.bank_code).to eq 9999
|
12
|
+
end
|
13
|
+
|
14
|
+
it "parses the branch code" do
|
15
|
+
expect(account_end.branch_code).to eq 1111
|
16
|
+
end
|
17
|
+
|
18
|
+
it "parses the account number" do
|
19
|
+
expect(account_end.account_number).to eq 123456789
|
20
|
+
end
|
21
|
+
|
22
|
+
it "parses the number of debit entries" do
|
23
|
+
expect(account_end.debit_entries).to eq 4
|
24
|
+
end
|
25
|
+
|
26
|
+
it "parses the total of debit amounts" do
|
27
|
+
expect(account_end.debit_amount).to eq 4936
|
28
|
+
end
|
29
|
+
|
30
|
+
it "parses the number of credit entries" do
|
31
|
+
expect(account_end.credit_entries).to eq 2
|
32
|
+
end
|
33
|
+
|
34
|
+
it "parses the total of credit amounts" do
|
35
|
+
expect(account_end.credit_amount).to eq 999999
|
36
|
+
end
|
37
|
+
|
38
|
+
it "parses the final balance code" do
|
39
|
+
expect(account_end.balance_code).to eq 2
|
40
|
+
end
|
41
|
+
|
42
|
+
it "parses the final balance amount" do
|
43
|
+
expect(account_end.balance_amount).to eq 78889999999999
|
44
|
+
end
|
45
|
+
|
46
|
+
it "parses the currency code" do
|
47
|
+
expect(account_end.currency_code).to eq 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|