cremul-parser 0.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/.gitignore +18 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +34 -0
- data/Rakefile +12 -0
- data/cremul-parser.gemspec +23 -0
- data/lib/cremul/cremul_header.rb +27 -0
- data/lib/cremul/cremul_line.rb +33 -0
- data/lib/cremul/cremul_message.rb +23 -0
- data/lib/cremul/cremul_money.rb +22 -0
- data/lib/cremul/cremul_name_and_address.rb +20 -0
- data/lib/cremul/cremul_payment_tx.rb +79 -0
- data/lib/cremul/cremul_reference.rb +28 -0
- data/lib/cremul/parser_helper.rb +207 -0
- data/lib/cremul/version.rb +3 -0
- data/lib/cremul_parser.rb +24 -0
- data/test/test_helper.rb +2 -0
- data/test/unit/files/CREMUL0001-utf-8.txt +8 -0
- data/test/unit/files/CREMUL0001.DAT +8 -0
- data/test/unit/files/CREMUL0002-utf-8.txt +6 -0
- data/test/unit/files/CREMUL0002.DAT +6 -0
- data/test/unit/files/CREMUL0003-utf-8.txt +77 -0
- data/test/unit/files/CREMUL0003.DAT +77 -0
- data/test/unit/files/README.md +4 -0
- data/test/unit/files/convert_files_to_utf8.sh +10 -0
- data/test/unit/files/cremul_multi_lines.txt +55 -0
- data/test/unit/parser_test.rb +154 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8c49cb69e363b32f6967ef41f5caa5084a242337
|
4
|
+
data.tar.gz: 076bd033930f02c267935e93a4f72e2a1262eece
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8f648ff6cfd20bf0094adcebd51e32e9dfed926164fa0ba48e6d1fc0d5dd64a634eeed12e9b463cbbee1e2a124bddc3ccd28c76c83524cc473008b9f535a7e77
|
7
|
+
data.tar.gz: 1557e5ac8d18b8fc1c65e106534b9dcdf61ff03209264f9af020eb1401e5a5fca4feeec8e18c464c5d878b621bd1a903dc9148fa78b46bc42b5e00fc00899121
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Per Spilling
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# cremul-parser gem
|
2
|
+
|
3
|
+
This is a simple parser for CREMUL payment transaction files written in Ruby. It parses
|
4
|
+
the CREMUL file (which should be in UTF-8 encoding) and creates a Ruby object structure
|
5
|
+
corresponding to the elements in the file.
|
6
|
+
|
7
|
+
## References
|
8
|
+
|
9
|
+
Here are som useful references regarding the CREMUL file format:
|
10
|
+
|
11
|
+
1. [CREMUL documentation from bsk.no](http://bsk.no/hovedmeny/gjeldende-standarder.aspx)
|
12
|
+
2. [CREMUL documentation from truugo.com](http://www.truugo.com/edifact/d12b/cremul/)
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'cremul-parser'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle install
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install cremul-parser
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
See the `parser_test.rb` file.
|
31
|
+
|
32
|
+
## Copyright
|
33
|
+
|
34
|
+
Copyright (c) 2014 Per Spilling (per@kodemaker.no). See LICENSE.txt for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cremul/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "cremul-parser"
|
8
|
+
gem.version = Cremul::VERSION
|
9
|
+
gem.authors = ["Per Spilling"]
|
10
|
+
gem.email = ["per@kodemaker.no"]
|
11
|
+
gem.summary = %q{A Ruby parser for CREMUL payment transaction files.}
|
12
|
+
gem.description = %q{Based on the format specification from BSK: http://bsk.no/media/18244/CREMUL_BSK_v2_13_d96A-201112.pdf}
|
13
|
+
gem.homepage = "https://github.com/perspilling/cremul-parser"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files -z`.split("\x0")
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_development_dependency 'bundler', '~> 1.5'
|
22
|
+
gem.add_development_dependency 'rake', '~> 10'
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'parser_helper'
|
2
|
+
|
3
|
+
class CremulHeader
|
4
|
+
include Cremul::ParserHelper
|
5
|
+
|
6
|
+
# bf_id : Beneficiary ID. When the beneficiary is an organization this will be the organzation-number,
|
7
|
+
# and when the beneficiary is a person this will be the SSN, aka personnummer (NO).
|
8
|
+
|
9
|
+
#attr_reader :header_segments, :msg_id, :created_date, :bf_id
|
10
|
+
attr_reader :msg_id, :created_date, :bf_id
|
11
|
+
|
12
|
+
# Expects an array with all segments in the CREMUL file
|
13
|
+
def initialize(segments)
|
14
|
+
#i = next_line_segment_index(segments, 0)
|
15
|
+
#@header_segments = {}
|
16
|
+
#segments[0,i].each {|s| @header_segments[s[0,3]] = s[3,s.size] }
|
17
|
+
|
18
|
+
@msg_id = segments[msg_id_segment_index(segments)]
|
19
|
+
|
20
|
+
d = segments[next_date_segment_index(segments, 0)].split(':')
|
21
|
+
@created_date = Date.parse(d[1])
|
22
|
+
|
23
|
+
nad = segments[next_nad_segment_index(segments, 0)]
|
24
|
+
@bf_id = nad.split('+')[2].to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'parser_helper'
|
2
|
+
require_relative 'cremul_reference'
|
3
|
+
require_relative 'cremul_money'
|
4
|
+
require_relative 'cremul_payment_tx'
|
5
|
+
|
6
|
+
# Represents a line item in a CREMUL payment transaction message. A line item may have
|
7
|
+
# 1-* child-elements with the individual payments. A line item will have an amount field
|
8
|
+
# which will be the sum of the amounts of the child payment items.
|
9
|
+
class CremulLine
|
10
|
+
include Cremul::ParserHelper
|
11
|
+
|
12
|
+
attr_reader :posting_date, :money, :reference, :bf_account_number, :transactions
|
13
|
+
|
14
|
+
def initialize(segments, line_segment_pos)
|
15
|
+
d = segments[next_date_segment_index(segments, line_segment_pos)].split(':')
|
16
|
+
@posting_date = Date.parse(d[1])
|
17
|
+
|
18
|
+
@reference = CremulReference.new(segments[next_ref_segment_index(segments, line_segment_pos)])
|
19
|
+
@money = CremulMoney.new(segments[next_amount_segment_index(segments, line_segment_pos)])
|
20
|
+
bf = segments[next_fii_bf_segment_index(segments, line_segment_pos)].split('+')
|
21
|
+
@bf_account_number = bf[2]
|
22
|
+
|
23
|
+
@transactions = []
|
24
|
+
n = number_of_transactions_in_line(segments, line_segment_pos)
|
25
|
+
tx_index = next_tx_sequence_segment_index(segments, line_segment_pos)
|
26
|
+
n.times do
|
27
|
+
@transactions << CremulPaymentTx.new(segments, tx_index)
|
28
|
+
tx_index = next_tx_sequence_segment_index(segments, tx_index+1)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'cremul_header'
|
2
|
+
require_relative 'cremul_line'
|
3
|
+
require_relative 'parser_helper'
|
4
|
+
|
5
|
+
class CremulMessage
|
6
|
+
include Cremul::ParserHelper
|
7
|
+
|
8
|
+
attr_reader :header, :number_of_lines, :lines
|
9
|
+
|
10
|
+
def initialize(segments)
|
11
|
+
@header = CremulHeader.new(segments)
|
12
|
+
@lines = []
|
13
|
+
@number_of_lines = number_of_lines_in_message(segments)
|
14
|
+
|
15
|
+
# instantiate the line items
|
16
|
+
line_segment_pos = next_line_segment_index(segments, 0)
|
17
|
+
@number_of_lines.times do
|
18
|
+
@lines << CremulLine.new(segments, line_segment_pos)
|
19
|
+
line_segment_pos = next_line_segment_index(segments, line_segment_pos+1)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'parser_helper'
|
2
|
+
|
3
|
+
class CremulMoney
|
4
|
+
include Cremul::ParserHelper
|
5
|
+
|
6
|
+
DEFAULT_CURRENCY = :NOK
|
7
|
+
|
8
|
+
attr_reader :amount, :currency
|
9
|
+
|
10
|
+
def initialize(money_segment)
|
11
|
+
m = money_segment.split(':')
|
12
|
+
|
13
|
+
@amount = m[1].to_f
|
14
|
+
if m.size == 3
|
15
|
+
@currency = m[2].to_sym
|
16
|
+
else
|
17
|
+
@currency = DEFAULT_CURRENCY
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'parser_helper'
|
2
|
+
|
3
|
+
class CremulNameAndAddress
|
4
|
+
include Cremul::ParserHelper
|
5
|
+
|
6
|
+
# NAD+party-id+code+code+nad-line1+nad-line2+nad-line3+nad-line4+nad-line5
|
7
|
+
|
8
|
+
attr_reader :type, :nad_lines
|
9
|
+
|
10
|
+
def initialize(nad_segment)
|
11
|
+
s = nad_segment.split('+')
|
12
|
+
@type = s[1].to_sym
|
13
|
+
|
14
|
+
@nad_lines = []
|
15
|
+
5.times do |i|
|
16
|
+
@nad_lines << s[i+4]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative 'parser_helper'
|
2
|
+
require_relative 'cremul_reference'
|
3
|
+
require_relative 'cremul_name_and_address'
|
4
|
+
|
5
|
+
# Represents an individual payment transaction (SEQ segment) i a CREMUL message
|
6
|
+
class CremulPaymentTx
|
7
|
+
include Cremul::ParserHelper
|
8
|
+
|
9
|
+
REF_TYPE_KID = 999 # Norwegian customer invoice reference
|
10
|
+
REF_TYPE_INVOICE_NUMBER = 380
|
11
|
+
|
12
|
+
attr_reader :posting_date, :money, :references, :invoice_ref_type, :invoice_ref, :free_text
|
13
|
+
attr_reader :payer_account_number, :payer_nad, :beneficiary_nad
|
14
|
+
|
15
|
+
|
16
|
+
def initialize(segments, tx_segment_pos)
|
17
|
+
s = segments[next_date_segment_index(segments, tx_segment_pos)].split(':')
|
18
|
+
@posting_date = Date.parse(s[1])
|
19
|
+
|
20
|
+
s = segments[next_fii_or_segment_index(segments, tx_segment_pos)].split('+')
|
21
|
+
@payer_account_number = s[2]
|
22
|
+
|
23
|
+
init_invoice_ref(segments, tx_segment_pos)
|
24
|
+
init_free_text(segments, tx_segment_pos)
|
25
|
+
|
26
|
+
@money = CremulMoney.new(segments[next_amount_segment_index(segments, tx_segment_pos)])
|
27
|
+
|
28
|
+
init_refs(segments, tx_segment_pos)
|
29
|
+
init_name_and_addresses(segments, tx_segment_pos)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def init_free_text(segments, tx_segment_pos)
|
35
|
+
i = payment_details_segment_index(segments, tx_segment_pos)
|
36
|
+
unless i.nil?
|
37
|
+
s = segments[i].split('+')
|
38
|
+
@free_text = s[s.size-1]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def init_invoice_ref(segments, tx_segment_pos)
|
43
|
+
i = doc_segment_index(segments, tx_segment_pos)
|
44
|
+
unless i.nil?
|
45
|
+
s = segments[doc_segment_index(segments, tx_segment_pos)].split('+')
|
46
|
+
@invoice_ref_type = ref_type(s[1])
|
47
|
+
@invoice_ref = s[2]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def init_name_and_addresses(segments, tx_segment_pos)
|
52
|
+
n = last_segment_index_in_tx(segments, tx_segment_pos)
|
53
|
+
nad_index = next_nad_segment_index(segments, tx_segment_pos)
|
54
|
+
while nad_index.nil? == false && nad_index <= n
|
55
|
+
nad = CremulNameAndAddress.new(segments[nad_index])
|
56
|
+
assign_nad(nad)
|
57
|
+
nad_index = next_nad_segment_index(segments, nad_index+1)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def init_refs(segments, tx_segment_pos)
|
62
|
+
@references = []
|
63
|
+
n = number_of_references_in_tx(segments, tx_segment_pos)
|
64
|
+
ref_segment_index = next_ref_segment_index(segments, tx_segment_pos)
|
65
|
+
n.times do
|
66
|
+
@references << CremulReference.new(segments[ref_segment_index])
|
67
|
+
ref_segment_index = next_ref_segment_index(segments, ref_segment_index+1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def assign_nad(nad)
|
72
|
+
if nad.type == :PL
|
73
|
+
@payer_nad = nad
|
74
|
+
elsif nad.type == :BE
|
75
|
+
@beneficiary_nad = nad
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'parser_helper'
|
2
|
+
|
3
|
+
|
4
|
+
# Represents a reference (RFF) segment in a CREMUL message.
|
5
|
+
# Type may be:
|
6
|
+
# - :ACK - Bank reference - KID in Norwegian
|
7
|
+
# - :AII - Bank’s reference number allocated by the bank to different underlaying individual transactions
|
8
|
+
# - :CT - AutoGiro agreement ID
|
9
|
+
# - :ABO - Originator´s reference – for excample SWIFT reference senders bank
|
10
|
+
# - :ACD - Bank reference = Archive reference
|
11
|
+
# - :AEK - Payment order number
|
12
|
+
# - :AFO - Beneficiary’s reference
|
13
|
+
# - :AGN - Payer’s reference, aka 'egenref' (NO)
|
14
|
+
# - :AHK - Payer’s reference number, aka 'debetref' (NO)
|
15
|
+
# - :RA - Remittance advice number
|
16
|
+
# - :TBR - Reference number pre-advice
|
17
|
+
class CremulReference
|
18
|
+
include Cremul::ParserHelper
|
19
|
+
|
20
|
+
attr_reader :number, :type
|
21
|
+
|
22
|
+
def initialize(ref_segment)
|
23
|
+
s = ref_segment.split(':')
|
24
|
+
@number = s[1]
|
25
|
+
s = s[0].split('+')
|
26
|
+
@type = s[1].to_sym
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
module Cremul
|
2
|
+
module ParserHelper
|
3
|
+
|
4
|
+
ELEMENT_SEPARATOR = '+'
|
5
|
+
DATA_SEPARATOR = ':'
|
6
|
+
REPETITION_SEPARATOR = '*'
|
7
|
+
SEGMENT_DELIMITER = "'"
|
8
|
+
|
9
|
+
MESSAGE_HEADER = 'UNH'
|
10
|
+
MESSAGE_BEGIN = 'BGM'
|
11
|
+
|
12
|
+
LINE_ITEM_SEGMENT = 'LIN'
|
13
|
+
DATE_SEGMENT = 'DTM'
|
14
|
+
BUSINESS_FUNCTION_SEGMENT = 'BUS'
|
15
|
+
|
16
|
+
REFERENCE_SEGMENT = 'RFF'
|
17
|
+
NAME_ADDRESS_SEGMENT = 'NAD'
|
18
|
+
SEQUENCE_SEGMENT = 'SEQ'
|
19
|
+
|
20
|
+
FINANCIAL_INSTITUTION_SEGMENT = 'FII'
|
21
|
+
BENEFICIARY = 'BF'
|
22
|
+
# Example: FII+BF+12345678901' (Beneficiary bank account number)
|
23
|
+
|
24
|
+
MONETARY_AMOUNT_SEGMENT = 'MOA'
|
25
|
+
CURRENCIES_SEGMENT = 'CUX'
|
26
|
+
|
27
|
+
PROCESS_TYPE_SEGMENT = 'PRC'
|
28
|
+
FREETEXT_SEGMENT = 'FTX'
|
29
|
+
|
30
|
+
CODES = {
|
31
|
+
BUSINESS_FUNCTION_SEGMENT => {
|
32
|
+
c230: 'Total amount valid KID',
|
33
|
+
c231: 'Total amount invalid KID',
|
34
|
+
c232: 'Total amount AutoGiro',
|
35
|
+
c233: 'Total amount electronic payments',
|
36
|
+
c234: 'Total amount Giro notes',
|
37
|
+
c240: 'Total amount structured information'
|
38
|
+
|
39
|
+
},
|
40
|
+
MONETARY_AMOUNT_SEGMENT => {
|
41
|
+
c60: 'Final posted amount',
|
42
|
+
c346: 'Total credit. Sum of final posted amounts on level C',
|
43
|
+
c349: 'Amount that will be posted/amount not confirmed by bank',
|
44
|
+
c362: 'Amount for information – can be changed'
|
45
|
+
},
|
46
|
+
REFERENCE_SEGMENT => {
|
47
|
+
ACK: 'Bank reference - KID in Norwegian',
|
48
|
+
AII: 'Bank’s reference number allocated by the bank to different underlaying individual transactions',
|
49
|
+
CT: 'AutoGiro agreement ID'
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
REF_TYPES = {
|
54
|
+
c380: :INVOICE_NUMBER,
|
55
|
+
c381: :CREDIT_NOTE,
|
56
|
+
c999: :KID,
|
57
|
+
c998: :INVOICE_NUMBER
|
58
|
+
}
|
59
|
+
|
60
|
+
# Assumes that the parameter is a string with the code
|
61
|
+
def ref_type(type_number)
|
62
|
+
type_symbol = ('c' << type_number).to_sym
|
63
|
+
REF_TYPES[type_symbol]
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def segment_codes
|
68
|
+
CODES
|
69
|
+
end
|
70
|
+
|
71
|
+
def msg_id_segment_index(segments)
|
72
|
+
segments.index { |x| /UNH.*/.match(x) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def next_date_segment_index(segments, start_pos)
|
76
|
+
index = segments[start_pos, segments.size].index { |x| /DTM.*/.match(x) }
|
77
|
+
index += start_pos unless index.nil?
|
78
|
+
index
|
79
|
+
end
|
80
|
+
|
81
|
+
def next_amount_segment_index(segments, start_pos)
|
82
|
+
index = segments[start_pos, segments.size].index { |x| /MOA.*/.match(x) }
|
83
|
+
index += start_pos unless index.nil?
|
84
|
+
index
|
85
|
+
end
|
86
|
+
|
87
|
+
def next_line_segment_index(segments, start_pos)
|
88
|
+
index = segments[start_pos, segments.size].index { |x| /LIN\+\d/.match(x) }
|
89
|
+
index += start_pos unless index.nil?
|
90
|
+
index
|
91
|
+
end
|
92
|
+
|
93
|
+
def next_tx_sequence_segment_index(segments, start_pos)
|
94
|
+
index = segments[start_pos, segments.size].index { |x| /SEQ\+\+\d/.match(x) }
|
95
|
+
index += start_pos unless index.nil?
|
96
|
+
index
|
97
|
+
end
|
98
|
+
|
99
|
+
def doc_segment_index(segments, start_pos)
|
100
|
+
index = segments[start_pos, segments.size].index { |x| /DOC.*/.match(x) }
|
101
|
+
index += start_pos unless index.nil?
|
102
|
+
index
|
103
|
+
end
|
104
|
+
|
105
|
+
def payment_details_segment_index(segments, start_pos)
|
106
|
+
index = segments[start_pos, segments.size].index { |x| /FTX\+PMD.*/.match(x) }
|
107
|
+
index += start_pos unless index.nil?
|
108
|
+
index
|
109
|
+
end
|
110
|
+
|
111
|
+
# Optional segment with free text info regarding the payment
|
112
|
+
def payment_advice_segment_index(segments, start_pos)
|
113
|
+
index = segments[start_pos, segments.size].index { |x| /FTX\+AAG.*/.match(x) }
|
114
|
+
index += start_pos unless index.nil?
|
115
|
+
index
|
116
|
+
end
|
117
|
+
|
118
|
+
def next_ref_segment_index(segments, start_pos)
|
119
|
+
index = segments[start_pos, segments.size].index { |x| /RFF.*/.match(x) }
|
120
|
+
index += start_pos unless index.nil?
|
121
|
+
index
|
122
|
+
end
|
123
|
+
|
124
|
+
def next_fii_bf_segment_index(segments, start_pos)
|
125
|
+
index = segments[start_pos, segments.size].index { |x| /FII\+BF.*/.match(x) }
|
126
|
+
index += start_pos unless index.nil?
|
127
|
+
index
|
128
|
+
end
|
129
|
+
|
130
|
+
def next_fii_or_segment_index(segments, start_pos)
|
131
|
+
index = segments[start_pos, segments.size].index { |x| /FII\+OR.*/.match(x) }
|
132
|
+
index += start_pos unless index.nil?
|
133
|
+
index
|
134
|
+
end
|
135
|
+
|
136
|
+
def next_nad_segment_index(segments, start_pos)
|
137
|
+
index = segments[start_pos, segments.size].index { |x| /NAD.*/.match(x) }
|
138
|
+
index += start_pos unless index.nil?
|
139
|
+
index
|
140
|
+
end
|
141
|
+
|
142
|
+
def line_count_segment_index(segments)
|
143
|
+
segments.index { |x| /CNT\+LI:\d/.match(x) }
|
144
|
+
end
|
145
|
+
|
146
|
+
def number_of_lines_in_message(segments)
|
147
|
+
s = segments[line_count_segment_index(segments)]
|
148
|
+
s[s.index(':')+1, s.size].to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
# Return the number of individual payments transactions in the line item. Expects 'line_segment_pos'
|
152
|
+
# to be the index of the current line item.
|
153
|
+
def number_of_transactions_in_line(segments, line_segment_pos)
|
154
|
+
n = 1 # there must be at least 1 payment tx
|
155
|
+
tx_pos = next_tx_sequence_segment_index(segments, line_segment_pos+1)
|
156
|
+
# search for payment tx items until next line item or end of message
|
157
|
+
next_line_index = next_line_segment_index(segments, line_segment_pos+1)
|
158
|
+
loop do
|
159
|
+
tx_pos = next_tx_sequence_segment_index(segments, tx_pos+1)
|
160
|
+
if tx_pos.nil?
|
161
|
+
break
|
162
|
+
elsif !next_line_index.nil? && tx_pos > next_line_index
|
163
|
+
break
|
164
|
+
else
|
165
|
+
n += 1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
n
|
169
|
+
end
|
170
|
+
|
171
|
+
def number_of_references_in_tx(segments, tx_segment_pos)
|
172
|
+
n = 0
|
173
|
+
ref_index = next_ref_segment_index(segments, tx_segment_pos)
|
174
|
+
next_tx_index = next_tx_sequence_segment_index(segments, tx_segment_pos+1)
|
175
|
+
next_line_index = next_line_segment_index(segments, tx_segment_pos)
|
176
|
+
loop do
|
177
|
+
if ref_index.nil?
|
178
|
+
break
|
179
|
+
elsif !next_tx_index.nil? && ref_index > next_tx_index
|
180
|
+
break
|
181
|
+
elsif !next_line_index.nil? && ref_index > next_line_index
|
182
|
+
break
|
183
|
+
else
|
184
|
+
n += 1
|
185
|
+
end
|
186
|
+
ref_index = next_ref_segment_index(segments, ref_index+1)
|
187
|
+
end
|
188
|
+
n
|
189
|
+
end
|
190
|
+
|
191
|
+
def last_segment_index_in_tx(segments, tx_segment_pos)
|
192
|
+
next_tx_index = next_tx_sequence_segment_index(segments, tx_segment_pos+1)
|
193
|
+
next_line_index = next_line_segment_index(segments, tx_segment_pos)
|
194
|
+
cnt_index = line_count_segment_index(segments)
|
195
|
+
|
196
|
+
if next_tx_index
|
197
|
+
next_tx_index - 1
|
198
|
+
elsif next_line_index
|
199
|
+
next_line_index - 1
|
200
|
+
else
|
201
|
+
cnt_index - 1
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require_relative 'cremul/parser_helper'
|
4
|
+
require_relative 'cremul/cremul_message'
|
5
|
+
|
6
|
+
class CremulParser
|
7
|
+
include Cremul::ParserHelper
|
8
|
+
|
9
|
+
attr_reader :segments, :msg
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse(file)
|
15
|
+
file_as_a_string = ''
|
16
|
+
file.each do |line|
|
17
|
+
line.encode(Encoding::UTF_8)
|
18
|
+
file_as_a_string += line.chop
|
19
|
+
end
|
20
|
+
@segments = file_as_a_string.split("'")
|
21
|
+
@msg = CremulMessage.new(@segments)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
UNA:+,? 'UNB+UNOC:3+00810506482+00975945065+140312:1546+01001386'UNH+1+CREMUL:D:
|
2
|
+
96A:UN'BGM+435+2014031215350976'DTM+137:20140312:102'NAD+MR+00975945065'LIN+1'DT
|
3
|
+
M+209:20140312:102'BUS++DO++233:25:124'MOA+349:1394:NOK'RFF+ACK:08012992096'DTM+
|
4
|
+
171:20140312:102'FII+BF+12121212121'SEQ++1'DTM+203:20140312:102'FII+OR+123123123
|
5
|
+
12'RFF+AEK:12072200001'RFF+ACD:180229451'MOA+143:1394'NAD+PL+++Tømrer Morten Rog
|
6
|
+
nebær AS+Skjerpåkeren 17+STANGE++2335'NAD+BE+++FOND.FOR REGIONALE VERNEOMBUD++++
|
7
|
+
0000'PRC+11'FTX+PMD+++Tømrer Morten Rognebær AS'CNT+LI:1'UNT+23+1'UNZ+1+01001386
|
8
|
+
'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
UNA:+,? 'UNB+UNOC:3+00810506482+00975945065+140312:1546+01001386'UNH+1+CREMUL:D:
|
2
|
+
96A:UN'BGM+435+2014031215350976'DTM+137:20140312:102'NAD+MR+00975945065'LIN+1'DT
|
3
|
+
M+209:20140312:102'BUS++DO++233:25:124'MOA+349:1394:NOK'RFF+ACK:08012992096'DTM+
|
4
|
+
171:20140312:102'FII+BF+12121212121'SEQ++1'DTM+203:20140312:102'FII+OR+123123123
|
5
|
+
12'RFF+AEK:12072200001'RFF+ACD:180229451'MOA+143:1394'NAD+PL+++T�mrer Morten Rog
|
6
|
+
neb�r AS+Skjerp�keren 17+STANGE++2335'NAD+BE+++THE BENEFICIARY COMPANY++++
|
7
|
+
0000'PRC+11'FTX+PMD+++T�mrer Morten Rogneb�r AS'CNT+LI:1'UNT+23+1'UNZ+1+01001386
|
8
|
+
'
|
@@ -0,0 +1,6 @@
|
|
1
|
+
UNA:+,? 'UNB+UNOC:3+00810506482+00975945065+130402:1812+01001057'UNH+1+CREMUL:D:
|
2
|
+
96A:UN'BGM+435+2013040217241217'DTM+137:20130402:102'NAD+MR+00975945065'LIN+1'DT
|
3
|
+
M+209:20130402:102'BUS++DO++230:25:124'MOA+349:250:NOK'RFF+ACK:08002130826'DTM+1
|
4
|
+
71:20130402:102'FII+BF+12121212121'SEQ++1'DTM+203:20130331:102'FII+OR+1231231231
|
5
|
+
2'RFF+AEK:3900263127'RFF+ACD:303019152'MOA+143:250'NAD+PL+++Haugene Nils Pe'PRC+
|
6
|
+
8'DOC+999+20122124330'MOA+12:250'GIS+37'CNT+LI:1'UNT+24+1'UNZ+1+01001057'
|
@@ -0,0 +1,6 @@
|
|
1
|
+
UNA:+,? 'UNB+UNOC:3+00810506482+00975945065+130402:1812+01001057'UNH+1+CREMUL:D:
|
2
|
+
96A:UN'BGM+435+2013040217241217'DTM+137:20130402:102'NAD+MR+00975945065'LIN+1'DT
|
3
|
+
M+209:20130402:102'BUS++DO++230:25:124'MOA+349:250:NOK'RFF+ACK:08002130826'DTM+1
|
4
|
+
71:20130402:102'FII+BF+12121212121'SEQ++1'DTM+203:20130331:102'FII+OR+1231231231
|
5
|
+
2'RFF+AEK:3900263127'RFF+ACD:303019152'MOA+143:250'NAD+PL+++Haugene Nils Pe'PRC+
|
6
|
+
8'DOC+999+20122124330'MOA+12:250'GIS+37'CNT+LI:1'UNT+24+1'UNZ+1+01001057'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
UNA:+,? 'UNB+UNOC:3+00810506482+00975945065+130411:1547+01001066'UNH+1+CREMUL:D:
|
2
|
+
96A:UN'BGM+435+2013041115380742'DTM+137:20130411:102'NAD+MR+00975945065'LIN+1'DT
|
3
|
+
M+209:20130411:102'BUS++DO++230:25:124'MOA+349:3000:NOK'RFF+ACK:08011116222'DTM+
|
4
|
+
171:20130411:102'FII+BF+70380518552'SEQ++1'DTM+203:20130410:102'FII+OR+123456789
|
5
|
+
01'RFF+ACD:*85290467'MOA+143:250'NAD+PL+++RUNAR NORDLI+KVENNBERGGT 30+KRISTIANSU
|
6
|
+
ND N++6515'NAD+BE+++THE BENEFICIARY COMPANY'PRC+8'DOC+999+20132065978'MOA+
|
7
|
+
12:250'GIS+37'SEQ++2'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000164149
|
8
|
+
'RFF+ACD:362509152'MOA+143:250'NAD+PL+++R S Bygg'PRC+8'DOC+999+20132148105'MOA+1
|
9
|
+
2:250'GIS+37'SEQ++3'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000257918'
|
10
|
+
RFF+ACD:890209152'MOA+143:250'NAD+PL+++B Bolle AS'PRC+8'DOC+999+20132161140'MOA+
|
11
|
+
12:250'GIS+37'SEQ++4'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000270111
|
12
|
+
'RFF+ACD:890209152'MOA+143:250'NAD+PL+++Jakobsen Kriste'PRC+8'DOC+999+2013053828
|
13
|
+
1'MOA+12:250'GIS+37'SEQ++5'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000
|
14
|
+
998400'RFF+ACD:936509152'MOA+143:250'NAD+PL+++Kjetil Vestad E'PRC+8'DOC+999+2013
|
15
|
+
0133695'MOA+12:250'GIS+37'SEQ++6'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK
|
16
|
+
:31000352894'RFF+ACD:470109152'MOA+143:250'NAD+PL+++Brunes Service'PRC+8'DOC+999
|
17
|
+
+20131095927'MOA+12:250'GIS+37'SEQ++7'DTM+203:20130410:102'FII+OR+12345678901'RF
|
18
|
+
F+AEK:31000302531'RFF+ACD:470109151'MOA+143:250'NAD+PL+++STRØM HILMAR JO'PRC+8'D
|
19
|
+
OC+999+20130204637'MOA+12:250'GIS+37'SEQ++8'DTM+203:20130410:102'FII+OR+12345678
|
20
|
+
901:INGE KJELL MEEK'RFF+ACD:860185489'MOA+143:250'NAD+PL+++INGE KJELL MEEK+BREMS
|
21
|
+
NES+AVERØY++6530+NO'PRC+8'DOC+999+20132050046'MOA+12:250'GIS+37'SEQ++9'DTM+203:2
|
22
|
+
0130410:102'FII+OR+12345678901'RFF+AEK:933920002'RFF+ACD:393019451'MOA+143:250'N
|
23
|
+
AD+PL+++We-Bo Graving A'PRC+8'DOC+999+20130982836'MOA+12:250'GIS+37'SEQ++10'DTM+
|
24
|
+
203:20130410:102'FII+OR+12345678901'RFF+AEK:975030000'RFF+ACD:470119451'MOA+143:
|
25
|
+
250'NAD+PL+++2 Snekkers AS'PRC+8'DOC+999+20130888439'MOA+12:250'GIS+37'SEQ++11'D
|
26
|
+
TM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000424164'RFF+ACD:420109152'MOA
|
27
|
+
+143:250'NAD+PL+++BRATBERG RUNE'PRC+8'DOC+999+20131099606'MOA+12:250'GIS+37'SEQ+
|
28
|
+
+12'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:936050001'RFF+ACD:420119451'
|
29
|
+
MOA+143:250'NAD+PL+++Murmester Langn'PRC+8'DOC+999+20131268482'MOA+12:250'GIS+37
|
30
|
+
'LIN+2'DTM+209:20130411:102'BUS++DO++230:25:124'MOA+349:1000:NOK'RFF+ACK:0801197
|
31
|
+
9782'DTM+171:20130411:102'FII+BF+70380518552'SEQ++1'DTM+203:20130411:102'FII+OR+
|
32
|
+
12345678901:UAB NORSTATA'RFF+ACD:860195251'MOA+143:250'NAD+PL+++UAB NORSTATA++OP
|
33
|
+
PDAL++7341+NO'PRC+8'DOC+999+20131316414'MOA+12:250'GIS+37'SEQ++2'DTM+203:2013041
|
34
|
+
1:102'FII+OR+12345678901'RFF+AEK:31010464264'RFF+ACD:470119152'MOA+143:250'NAD+P
|
35
|
+
L+++Røstgård Birger'PRC+8'DOC+999+20130492877'MOA+12:250'GIS+37'SEQ++3'DTM+203:2
|
36
|
+
0130411:102'FII+OR+12345678901'RFF+AEK:31010478197'RFF+ACD:222019152'MOA+143:250
|
37
|
+
'NAD+PL+++LUVENT AS'PRC+8'DOC+999+20130542564'MOA+12:250'GIS+37'SEQ++4'DTM+203:2
|
38
|
+
0130411:102'FII+OR+12345678901'RFF+AEK:3713048'RFF+ACD:797410302'MOA+143:250'NAD
|
39
|
+
+PL+++OPGÅRD MASKIN AS+REISTADHAUGEN 8+ALTA++9513'NAD+BE+++THE BENEFICIARY COMPA
|
40
|
+
NY+Postboks 22 Sentrum+OSLO++0101'INP+BF+2:SI'FTX+AAG+++OPGÅRD MASKIN AS'PR
|
41
|
+
C+8'DOC+999+20130139262'MOA+12:250'GIS+37'LIN+3'DTM+209:20130411:102'BUS++DO++23
|
42
|
+
0:25:124'MOA+349:1894:NOK'RFF+ACK:08011994246'DTM+171:20130411:102'FII+BF+703805
|
43
|
+
18552'SEQ++1'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:31010681540'RFF+ACD
|
44
|
+
:393019152'MOA+143:250'NAD+PL+++Gocakov Michail'PRC+8'DOC+999+20131256453'MOA+12
|
45
|
+
:250'GIS+37'SEQ++2'DTM+203:20130411:102'FII+OR+12345678901'RFF+ACD:265538979'RFF
|
46
|
+
+ABO:9357538979'MOA+143:250'NAD+PL++Jon Adler Torp:Jøransberg 24:3770 Kragerø'PR
|
47
|
+
C+8'DOC+999+20132137371'MOA+12:250'GIS+37'SEQ++3'DTM+203:20130411:102'FII+OR+123
|
48
|
+
45678901'RFF+AEK:1113010006'RFF+ACD:890219451'MOA+143:1394'NAD+PL+++Fauske Elekt
|
49
|
+
ro'PRC+8'DOC+999+20130142076'MOA+12:1394'GIS+37'LIN+4'DTM+209:20130411:102'BUS++
|
50
|
+
DO++230:25:124'MOA+349:3095,61:NOK'RFF+ACK:08011909226'DTM+171:20130411:102'FII+
|
51
|
+
BF+70380518552'SEQ++1'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:1195720000
|
52
|
+
'RFF+ACD:470119451'MOA+143:250'NAD+PL+++Jessen Rør AS'PRC+8'DOC+999+20130080284'
|
53
|
+
MOA+12:250'GIS+37'SEQ++2'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:227'RFF
|
54
|
+
+ACD:797614172'MOA+143:250'NAD+PL++Laurynas Lukosius:Bruveien 9 B::3055 KROKSTAD
|
55
|
+
ELVA'NAD+BE++THE BENEFICIARY COMPANY'INP+BF+2:SI'FTX+AAG+++Laurynas Lukosi
|
56
|
+
us 20131371971'PRC+8'DOC+999+20131371971'MOA+12:250'GIS+37'SEQ+
|
57
|
+
+3'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:31010773517'RFF+ACD:261019152
|
58
|
+
'MOA+143:250'NAD+PL+++NILSEN TORE'PRC+8'DOC+999+20131337626'MOA+12:250'GIS+37'SE
|
59
|
+
Q++4'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:10007596'RFF+ACD:393211000'
|
60
|
+
MOA+143:250'NAD+PL+++Inge Langnes'PRC+8'DOC+999+20132006675'MOA+12:250'GIS+37'SE
|
61
|
+
Q++5'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:34229470001'RFF+ACD:9055194
|
62
|
+
51'MOA+143:250'NAD+PL+++Bravida Norge AS'PRC+8'DOC+999+20132008606'MOA+12:250'GI
|
63
|
+
S+37'SEQ++6'DTM+203:20130411:102'FII+OR+12345678901'RFF+ACD:233340798'RFF+ABO:93
|
64
|
+
67540798'MOA+143:250'NAD+PL++Gunvald Haugeplass:Bardølavegen 142:3580 Geilo'PRC+
|
65
|
+
8'DOC+999+20130598905'MOA+12:250'GIS+37'SEQ++7'DTM+203:20130411:102'FII+OR+12345
|
66
|
+
678901'RFF+AEK:3774669'RFF+ACD:797410819'MOA+143:250'NAD+PL+++OLE ROGNDALEN+HAGA
|
67
|
+
STUVEIEN 54+HAFSLUNDSØY++1734'NAD+BE+++THE BENEFICIARY COMPANY+Postboks 22
|
68
|
+
Sentrum+OSLO++0101'INP+BF+2:SI'FTX+AAG+++OLE ROGNDALEN'PRC+8'DOC+999+20131226563
|
69
|
+
'MOA+12:250'GIS+37'SEQ++8'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:378560
|
70
|
+
1'RFF+ACD:797410452'MOA+143:250'NAD+PL+++HYTTE OG BOLIG PARTNER AS+HO 405:SJØGAT
|
71
|
+
A 6+BODØ++8006'NAD+BE+++ +Postboks 22 Sentrum+OSLO++0
|
72
|
+
101'INP+BF+2:SI'FTX+AAG+++HYTTE OG BOLIG PARTNER AS'PRC+8'DOC+999+20132188044'MO
|
73
|
+
A+12:250'GIS+37'SEQ++9'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:118454000
|
74
|
+
3'RFF+ACD:108019451'MOA+143:845,61'NAD+PL+++Bris AS'PRC+8'DOC+999+20131223909'MO
|
75
|
+
A+12:845,61'GIS+37'SEQ++10'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:11888
|
76
|
+
10001'RFF+ACD:261019451'MOA+143:250'NAD+PL+++Herøya Elektro'PRC+8'DOC+999+201301
|
77
|
+
41516'MOA+12:250'GIS+37'CNT+LI:4'UNT+363+1'UNZ+1+01001066'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
UNA:+,? 'UNB+UNOC:3+00810506482+00975945065+130411:1547+01001066'UNH+1+CREMUL:D:
|
2
|
+
96A:UN'BGM+435+2013041115380742'DTM+137:20130411:102'NAD+MR+00975945065'LIN+1'DT
|
3
|
+
M+209:20130411:102'BUS++DO++230:25:124'MOA+349:3000:NOK'RFF+ACK:08011116222'DTM+
|
4
|
+
171:20130411:102'FII+BF+70380518552'SEQ++1'DTM+203:20130410:102'FII+OR+123456789
|
5
|
+
01'RFF+ACD:*85290467'MOA+143:250'NAD+PL+++RUNAR NORDLI+KVENNBERGGT 30+KRISTIANSU
|
6
|
+
ND N++6515'NAD+BE+++THE BENEFICIARY COMPANY'PRC+8'DOC+999+20132065978'MOA+
|
7
|
+
12:250'GIS+37'SEQ++2'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000164149
|
8
|
+
'RFF+ACD:362509152'MOA+143:250'NAD+PL+++R S Bygg'PRC+8'DOC+999+20132148105'MOA+1
|
9
|
+
2:250'GIS+37'SEQ++3'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000257918'
|
10
|
+
RFF+ACD:890209152'MOA+143:250'NAD+PL+++B Bolle AS'PRC+8'DOC+999+20132161140'MOA+
|
11
|
+
12:250'GIS+37'SEQ++4'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000270111
|
12
|
+
'RFF+ACD:890209152'MOA+143:250'NAD+PL+++Jakobsen Kriste'PRC+8'DOC+999+2013053828
|
13
|
+
1'MOA+12:250'GIS+37'SEQ++5'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000
|
14
|
+
998400'RFF+ACD:936509152'MOA+143:250'NAD+PL+++Kjetil Vestad E'PRC+8'DOC+999+2013
|
15
|
+
0133695'MOA+12:250'GIS+37'SEQ++6'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK
|
16
|
+
:31000352894'RFF+ACD:470109152'MOA+143:250'NAD+PL+++Brunes Service'PRC+8'DOC+999
|
17
|
+
+20131095927'MOA+12:250'GIS+37'SEQ++7'DTM+203:20130410:102'FII+OR+12345678901'RF
|
18
|
+
F+AEK:31000302531'RFF+ACD:470109151'MOA+143:250'NAD+PL+++STR�M HILMAR JO'PRC+8'D
|
19
|
+
OC+999+20130204637'MOA+12:250'GIS+37'SEQ++8'DTM+203:20130410:102'FII+OR+12345678
|
20
|
+
901:INGE KJELL MEEK'RFF+ACD:860185489'MOA+143:250'NAD+PL+++INGE KJELL MEEK+BREMS
|
21
|
+
NES+AVER�Y++6530+NO'PRC+8'DOC+999+20132050046'MOA+12:250'GIS+37'SEQ++9'DTM+203:2
|
22
|
+
0130410:102'FII+OR+12345678901'RFF+AEK:933920002'RFF+ACD:393019451'MOA+143:250'N
|
23
|
+
AD+PL+++We-Bo Graving A'PRC+8'DOC+999+20130982836'MOA+12:250'GIS+37'SEQ++10'DTM+
|
24
|
+
203:20130410:102'FII+OR+12345678901'RFF+AEK:975030000'RFF+ACD:470119451'MOA+143:
|
25
|
+
250'NAD+PL+++2 Snekkers AS'PRC+8'DOC+999+20130888439'MOA+12:250'GIS+37'SEQ++11'D
|
26
|
+
TM+203:20130410:102'FII+OR+12345678901'RFF+AEK:31000424164'RFF+ACD:420109152'MOA
|
27
|
+
+143:250'NAD+PL+++BRATBERG RUNE'PRC+8'DOC+999+20131099606'MOA+12:250'GIS+37'SEQ+
|
28
|
+
+12'DTM+203:20130410:102'FII+OR+12345678901'RFF+AEK:936050001'RFF+ACD:420119451'
|
29
|
+
MOA+143:250'NAD+PL+++Murmester Langn'PRC+8'DOC+999+20131268482'MOA+12:250'GIS+37
|
30
|
+
'LIN+2'DTM+209:20130411:102'BUS++DO++230:25:124'MOA+349:1000:NOK'RFF+ACK:0801197
|
31
|
+
9782'DTM+171:20130411:102'FII+BF+70380518552'SEQ++1'DTM+203:20130411:102'FII+OR+
|
32
|
+
12345678901:UAB NORSTATA'RFF+ACD:860195251'MOA+143:250'NAD+PL+++UAB NORSTATA++OP
|
33
|
+
PDAL++7341+NO'PRC+8'DOC+999+20131316414'MOA+12:250'GIS+37'SEQ++2'DTM+203:2013041
|
34
|
+
1:102'FII+OR+12345678901'RFF+AEK:31010464264'RFF+ACD:470119152'MOA+143:250'NAD+P
|
35
|
+
L+++R�stg�rd Birger'PRC+8'DOC+999+20130492877'MOA+12:250'GIS+37'SEQ++3'DTM+203:2
|
36
|
+
0130411:102'FII+OR+12345678901'RFF+AEK:31010478197'RFF+ACD:222019152'MOA+143:250
|
37
|
+
'NAD+PL+++LUVENT AS'PRC+8'DOC+999+20130542564'MOA+12:250'GIS+37'SEQ++4'DTM+203:2
|
38
|
+
0130411:102'FII+OR+12345678901'RFF+AEK:3713048'RFF+ACD:797410302'MOA+143:250'NAD
|
39
|
+
+PL+++OPG�RD MASKIN AS+REISTADHAUGEN 8+ALTA++9513'NAD+BE+++THE BENEFICIARY COMPA
|
40
|
+
NY+Postboks 22 Sentrum+OSLO++0101'INP+BF+2:SI'FTX+AAG+++OPG�RD MASKIN AS'PR
|
41
|
+
C+8'DOC+999+20130139262'MOA+12:250'GIS+37'LIN+3'DTM+209:20130411:102'BUS++DO++23
|
42
|
+
0:25:124'MOA+349:1894:NOK'RFF+ACK:08011994246'DTM+171:20130411:102'FII+BF+703805
|
43
|
+
18552'SEQ++1'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:31010681540'RFF+ACD
|
44
|
+
:393019152'MOA+143:250'NAD+PL+++Gocakov Michail'PRC+8'DOC+999+20131256453'MOA+12
|
45
|
+
:250'GIS+37'SEQ++2'DTM+203:20130411:102'FII+OR+12345678901'RFF+ACD:265538979'RFF
|
46
|
+
+ABO:9357538979'MOA+143:250'NAD+PL++Jon Adler Torp:J�ransberg 24:3770 Krager�'PR
|
47
|
+
C+8'DOC+999+20132137371'MOA+12:250'GIS+37'SEQ++3'DTM+203:20130411:102'FII+OR+123
|
48
|
+
45678901'RFF+AEK:1113010006'RFF+ACD:890219451'MOA+143:1394'NAD+PL+++Fauske Elekt
|
49
|
+
ro'PRC+8'DOC+999+20130142076'MOA+12:1394'GIS+37'LIN+4'DTM+209:20130411:102'BUS++
|
50
|
+
DO++230:25:124'MOA+349:3095,61:NOK'RFF+ACK:08011909226'DTM+171:20130411:102'FII+
|
51
|
+
BF+70380518552'SEQ++1'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:1195720000
|
52
|
+
'RFF+ACD:470119451'MOA+143:250'NAD+PL+++Jessen R�r AS'PRC+8'DOC+999+20130080284'
|
53
|
+
MOA+12:250'GIS+37'SEQ++2'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:227'RFF
|
54
|
+
+ACD:797614172'MOA+143:250'NAD+PL++Laurynas Lukosius:Bruveien 9 B::3055 KROKSTAD
|
55
|
+
ELVA'NAD+BE++THE BENEFICIARY COMPANY'INP+BF+2:SI'FTX+AAG+++Laurynas Lukosi
|
56
|
+
us 20131371971'PRC+8'DOC+999+20131371971'MOA+12:250'GIS+37'SEQ+
|
57
|
+
+3'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:31010773517'RFF+ACD:261019152
|
58
|
+
'MOA+143:250'NAD+PL+++NILSEN TORE'PRC+8'DOC+999+20131337626'MOA+12:250'GIS+37'SE
|
59
|
+
Q++4'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:10007596'RFF+ACD:393211000'
|
60
|
+
MOA+143:250'NAD+PL+++Inge Langnes'PRC+8'DOC+999+20132006675'MOA+12:250'GIS+37'SE
|
61
|
+
Q++5'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:34229470001'RFF+ACD:9055194
|
62
|
+
51'MOA+143:250'NAD+PL+++Bravida Norge AS'PRC+8'DOC+999+20132008606'MOA+12:250'GI
|
63
|
+
S+37'SEQ++6'DTM+203:20130411:102'FII+OR+12345678901'RFF+ACD:233340798'RFF+ABO:93
|
64
|
+
67540798'MOA+143:250'NAD+PL++Gunvald Haugeplass:Bard�lavegen 142:3580 Geilo'PRC+
|
65
|
+
8'DOC+999+20130598905'MOA+12:250'GIS+37'SEQ++7'DTM+203:20130411:102'FII+OR+12345
|
66
|
+
678901'RFF+AEK:3774669'RFF+ACD:797410819'MOA+143:250'NAD+PL+++OLE ROGNDALEN+HAGA
|
67
|
+
STUVEIEN 54+HAFSLUNDS�Y++1734'NAD+BE+++THE BENEFICIARY COMPANY+Postboks 22
|
68
|
+
Sentrum+OSLO++0101'INP+BF+2:SI'FTX+AAG+++OLE ROGNDALEN'PRC+8'DOC+999+20131226563
|
69
|
+
'MOA+12:250'GIS+37'SEQ++8'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:378560
|
70
|
+
1'RFF+ACD:797410452'MOA+143:250'NAD+PL+++HYTTE OG BOLIG PARTNER AS+HO 405:SJ�GAT
|
71
|
+
A 6+BOD�++8006'NAD+BE+++ +Postboks 22 Sentrum+OSLO++0
|
72
|
+
101'INP+BF+2:SI'FTX+AAG+++HYTTE OG BOLIG PARTNER AS'PRC+8'DOC+999+20132188044'MO
|
73
|
+
A+12:250'GIS+37'SEQ++9'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:118454000
|
74
|
+
3'RFF+ACD:108019451'MOA+143:845,61'NAD+PL+++Bris AS'PRC+8'DOC+999+20131223909'MO
|
75
|
+
A+12:845,61'GIS+37'SEQ++10'DTM+203:20130411:102'FII+OR+12345678901'RFF+AEK:11888
|
76
|
+
10001'RFF+ACD:261019451'MOA+143:250'NAD+PL+++Her�ya Elektro'PRC+8'DOC+999+201301
|
77
|
+
41516'MOA+12:250'GIS+37'CNT+LI:4'UNT+363+1'UNZ+1+01001066'
|
@@ -0,0 +1,55 @@
|
|
1
|
+
UNA:+.? '
|
2
|
+
UNB+UNOC:1+00810506482+00900831941+990512:1423+1293++++0'
|
3
|
+
UNH+1294+CREMUL:D:96A:UN:BSK'
|
4
|
+
BGM+455+245'
|
5
|
+
DTM+137:20110111:102'
|
6
|
+
NAD+MR+00900831941'
|
7
|
+
LIN+1'
|
8
|
+
DTM+202:20110111:102'
|
9
|
+
BUS++DO'
|
10
|
+
MOA+60:14637:NOK'
|
11
|
+
RFF+ACK:00412107263'
|
12
|
+
FII+BF+70580500043'
|
13
|
+
SEQ++1'
|
14
|
+
FII+OR+82001234567'
|
15
|
+
RFF+AEK:8803609752'
|
16
|
+
RFF+ACD:*90000000'
|
17
|
+
MOA+143:14637:NOK'
|
18
|
+
NAD+PL+++NSB BA PERSONTRAFIKK ØST+ØKONOMIKONTORET 5 ETG+OSLO++0048'
|
19
|
+
PRC+11'
|
20
|
+
FTX+PMD+++VÅR REF DERES REF BELØP 42224 170:14.637,00'
|
21
|
+
LIN+2'
|
22
|
+
DTM+202:20110111:102'
|
23
|
+
BUS++DO'
|
24
|
+
MOA+60:15000:NOK'
|
25
|
+
RFF+ACK:00412108142'
|
26
|
+
FII+BF+70580500043'
|
27
|
+
SEQ++1'FII+OR+15502345678'
|
28
|
+
RFF+AEK:8803609752'
|
29
|
+
RFF+ACD:*90000000'
|
30
|
+
MOA+143:15000:NOK'
|
31
|
+
NAD+PL+++ARA DAMPSKIPSSELSKAP POSTBOKS 1235+HALDEN++1750'
|
32
|
+
PRC+8'
|
33
|
+
DOC+380+6128793'
|
34
|
+
GIS+37'
|
35
|
+
LIN+3'
|
36
|
+
DTM+202:20110111:102'
|
37
|
+
BUS++DO++234'
|
38
|
+
MOA+346:6740,40:NOK'
|
39
|
+
RFF+ACK:00412511745'
|
40
|
+
FII+BF+70580500043'
|
41
|
+
SEQ++1'
|
42
|
+
DTM+193:20110110:102'
|
43
|
+
FII+OR+24403456789'
|
44
|
+
RFF+AEK:6206632921'
|
45
|
+
RFF+ACD:*93139354'
|
46
|
+
MOA+143:4126,65:NOK'
|
47
|
+
SEQ++2'
|
48
|
+
DTM+193:20110110:102'
|
49
|
+
FII+OR+60397654321'
|
50
|
+
RFF+AEK:6206632595'
|
51
|
+
RFF+ACD:*97454800'
|
52
|
+
MOA+143:2613,75'
|
53
|
+
CNT+LI:3'
|
54
|
+
UNT+55+1294'
|
55
|
+
UNZ+1+1293'
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe CremulParser do
|
4
|
+
|
5
|
+
describe 'parsing valid cremul files' do
|
6
|
+
before do
|
7
|
+
@parser = CremulParser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should parse a valid cremul file with 1 line item' do
|
11
|
+
@parser.parse(File.open('files/CREMUL0001-utf-8.txt'))
|
12
|
+
@parser.segments.must_be_instance_of Array
|
13
|
+
@parser.msg.must_be_instance_of CremulMessage
|
14
|
+
|
15
|
+
d2014_03_12 = Date.new(2014,3,12)
|
16
|
+
|
17
|
+
msg = @parser.msg
|
18
|
+
msg.header.must_be_instance_of CremulHeader
|
19
|
+
msg.header.msg_id.must_include 'CREMUL'
|
20
|
+
msg.header.created_date.must_equal d2014_03_12
|
21
|
+
msg.header.bf_id.must_equal 975945065
|
22
|
+
|
23
|
+
msg.number_of_lines.must_equal 1
|
24
|
+
|
25
|
+
line = msg.lines[0]
|
26
|
+
line.must_be_instance_of CremulLine
|
27
|
+
line.posting_date.must_equal d2014_03_12
|
28
|
+
line.bf_account_number.must_equal '12121212121'
|
29
|
+
line.money.must_be_instance_of CremulMoney
|
30
|
+
line.money.amount.must_equal 1394.to_f
|
31
|
+
line.money.currency.must_equal :NOK
|
32
|
+
|
33
|
+
ref = line.reference
|
34
|
+
ref.must_be_instance_of CremulReference
|
35
|
+
ref.type.must_equal :ACK
|
36
|
+
ref.number.must_equal '08012992096'
|
37
|
+
|
38
|
+
line.transactions.size.must_equal 1
|
39
|
+
tx = line.transactions[0]
|
40
|
+
tx.must_be_instance_of CremulPaymentTx
|
41
|
+
tx.posting_date.must_equal d2014_03_12
|
42
|
+
tx.money.amount.must_equal 1394.to_f
|
43
|
+
tx.money.currency.must_equal :NOK
|
44
|
+
tx.references.size.must_equal 2
|
45
|
+
tx.free_text.must_equal 'Tømrer Morten Rognebær AS'
|
46
|
+
|
47
|
+
ref = tx.references[0]
|
48
|
+
ref.must_be_instance_of CremulReference
|
49
|
+
ref.type.must_equal :AEK
|
50
|
+
ref.number.must_equal '12072200001'
|
51
|
+
|
52
|
+
ref = tx.references[1]
|
53
|
+
ref.type.must_equal :ACD
|
54
|
+
ref.number.must_equal '180229451'
|
55
|
+
|
56
|
+
tx_payer = tx.payer_nad
|
57
|
+
tx_payer.must_be_instance_of CremulNameAndAddress
|
58
|
+
tx_payer.type.must_equal :PL
|
59
|
+
tx_payer.nad_lines[1].must_equal 'Skjerpåkeren 17'
|
60
|
+
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should parse a valid cremul file with multiple line items' do
|
65
|
+
@parser.parse(File.open('files/cremul_multi_lines.txt'))
|
66
|
+
@parser.segments.must_be_instance_of Array
|
67
|
+
@parser.msg.must_be_instance_of CremulMessage
|
68
|
+
|
69
|
+
d2011_01_11 = Date.new(2011,1,11)
|
70
|
+
|
71
|
+
msg = @parser.msg
|
72
|
+
msg.header.must_be_instance_of CremulHeader
|
73
|
+
msg.header.msg_id.must_include 'CREMUL'
|
74
|
+
msg.header.created_date.must_equal d2011_01_11
|
75
|
+
|
76
|
+
msg.number_of_lines.must_equal 3
|
77
|
+
|
78
|
+
line1 = msg.lines[0]
|
79
|
+
line1.must_be_instance_of CremulLine
|
80
|
+
line1.posting_date.must_equal d2011_01_11
|
81
|
+
line1.money.must_be_instance_of CremulMoney
|
82
|
+
line1.money.amount.must_equal 14637.to_f
|
83
|
+
line1.money.currency.must_equal :NOK
|
84
|
+
|
85
|
+
line1.transactions.size.must_equal 1
|
86
|
+
tx = line1.transactions[0]
|
87
|
+
tx.must_be_instance_of CremulPaymentTx
|
88
|
+
tx.posting_date.must_equal d2011_01_11
|
89
|
+
tx.money.amount.must_equal 14637.to_f
|
90
|
+
tx.money.currency.must_equal :NOK
|
91
|
+
tx.references.size.must_equal 2
|
92
|
+
|
93
|
+
tx.payer_nad.must_be_instance_of CremulNameAndAddress
|
94
|
+
tx.payer_nad.type.must_equal :PL
|
95
|
+
tx.payer_nad.nad_lines[1].must_equal 'ØKONOMIKONTORET 5 ETG'
|
96
|
+
|
97
|
+
|
98
|
+
line2 = msg.lines[1]
|
99
|
+
line2.must_be_instance_of CremulLine
|
100
|
+
line2.posting_date.must_equal d2011_01_11
|
101
|
+
line2.money.must_be_instance_of CremulMoney
|
102
|
+
line2.money.amount.must_equal 15000.to_f
|
103
|
+
line2.money.currency.must_equal :NOK
|
104
|
+
line2.transactions.size.must_equal 1
|
105
|
+
|
106
|
+
line3 = msg.lines[2]
|
107
|
+
line3.must_be_instance_of CremulLine
|
108
|
+
line3.posting_date.must_equal d2011_01_11
|
109
|
+
line3.money.must_be_instance_of CremulMoney
|
110
|
+
line3.money.amount.must_equal '6740,40'.to_f
|
111
|
+
line3.money.currency.must_equal :NOK
|
112
|
+
line3.transactions.size.must_equal 2
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should parse a valid long cremul file' do
|
117
|
+
@parser.parse(File.open('files/CREMUL0003-utf-8.txt'))
|
118
|
+
@parser.segments.must_be_instance_of Array
|
119
|
+
@parser.msg.must_be_instance_of CremulMessage
|
120
|
+
|
121
|
+
d2013_04_11 = Date.new(2013,4,11)
|
122
|
+
|
123
|
+
msg = @parser.msg
|
124
|
+
msg.header.must_be_instance_of CremulHeader
|
125
|
+
msg.header.msg_id.must_include 'CREMUL'
|
126
|
+
msg.header.created_date.must_equal d2013_04_11
|
127
|
+
|
128
|
+
msg.number_of_lines.must_equal 4
|
129
|
+
|
130
|
+
|
131
|
+
line1 = msg.lines[0]
|
132
|
+
line1.must_be_instance_of CremulLine
|
133
|
+
line1.posting_date.must_equal d2013_04_11
|
134
|
+
line1.money.must_be_instance_of CremulMoney
|
135
|
+
line1.money.amount.must_equal 3000.to_f
|
136
|
+
line1.money.currency.must_equal :NOK
|
137
|
+
|
138
|
+
line1.transactions.size.must_equal 12
|
139
|
+
|
140
|
+
tx = line1.transactions[0]
|
141
|
+
tx.must_be_instance_of CremulPaymentTx
|
142
|
+
tx.posting_date.must_equal Date.new(2013,4,10)
|
143
|
+
tx.money.amount.must_equal 250.to_f
|
144
|
+
tx.money.currency.must_equal :NOK
|
145
|
+
tx.payer_account_number.must_equal '12345678901'
|
146
|
+
tx.invoice_ref.must_equal '20132065978'
|
147
|
+
tx.invoice_ref_type.must_equal :KID
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cremul-parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Per Spilling
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10'
|
41
|
+
description: 'Based on the format specification from BSK: http://bsk.no/media/18244/CREMUL_BSK_v2_13_d96A-201112.pdf'
|
42
|
+
email:
|
43
|
+
- per@kodemaker.no
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- cremul-parser.gemspec
|
54
|
+
- lib/cremul/cremul_header.rb
|
55
|
+
- lib/cremul/cremul_line.rb
|
56
|
+
- lib/cremul/cremul_message.rb
|
57
|
+
- lib/cremul/cremul_money.rb
|
58
|
+
- lib/cremul/cremul_name_and_address.rb
|
59
|
+
- lib/cremul/cremul_payment_tx.rb
|
60
|
+
- lib/cremul/cremul_reference.rb
|
61
|
+
- lib/cremul/parser_helper.rb
|
62
|
+
- lib/cremul/version.rb
|
63
|
+
- lib/cremul_parser.rb
|
64
|
+
- test/test_helper.rb
|
65
|
+
- test/unit/files/CREMUL0001-utf-8.txt
|
66
|
+
- test/unit/files/CREMUL0001.DAT
|
67
|
+
- test/unit/files/CREMUL0002-utf-8.txt
|
68
|
+
- test/unit/files/CREMUL0002.DAT
|
69
|
+
- test/unit/files/CREMUL0003-utf-8.txt
|
70
|
+
- test/unit/files/CREMUL0003.DAT
|
71
|
+
- test/unit/files/README.md
|
72
|
+
- test/unit/files/convert_files_to_utf8.sh
|
73
|
+
- test/unit/files/cremul_multi_lines.txt
|
74
|
+
- test/unit/parser_test.rb
|
75
|
+
homepage: https://github.com/perspilling/cremul-parser
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.2.1
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: A Ruby parser for CREMUL payment transaction files.
|
99
|
+
test_files:
|
100
|
+
- test/test_helper.rb
|
101
|
+
- test/unit/files/CREMUL0001-utf-8.txt
|
102
|
+
- test/unit/files/CREMUL0001.DAT
|
103
|
+
- test/unit/files/CREMUL0002-utf-8.txt
|
104
|
+
- test/unit/files/CREMUL0002.DAT
|
105
|
+
- test/unit/files/CREMUL0003-utf-8.txt
|
106
|
+
- test/unit/files/CREMUL0003.DAT
|
107
|
+
- test/unit/files/README.md
|
108
|
+
- test/unit/files/convert_files_to_utf8.sh
|
109
|
+
- test/unit/files/cremul_multi_lines.txt
|
110
|
+
- test/unit/parser_test.rb
|