norma43_parser 1.0.1
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/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
|