sie 4.1.0 → 4.1.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 +4 -4
- data/README.md +4 -3
- data/lib/sie/document/renderer.rb +2 -2
- data/lib/sie/parser/build_entry.rb +4 -3
- data/lib/sie/parser/entry_types.rb +35 -35
- data/lib/sie/parser/tokenizer/token.rb +1 -1
- data/lib/sie/version.rb +1 -1
- metadata +8 -40
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/Gemfile +0 -4
- data/Gemfile.pre_2.2.2 +0 -8
- data/Rakefile +0 -15
- data/script/bootstrap +0 -3
- data/script/refresh +0 -25
- data/script/test +0 -1
- data/script/turbux_rspec +0 -6
- data/sie.gemspec +0 -27
- data/spec/fixtures/sie_file.se +0 -28
- data/spec/fixtures/sie_file_with_unknown_entries.se +0 -32
- data/spec/integration/parser_spec.rb +0 -56
- data/spec/spec_helper.rb +0 -5
- data/spec/unit/build_entry_spec.rb +0 -17
- data/spec/unit/document/renderer_spec.rb +0 -13
- data/spec/unit/document/voucher_series_spec.rb +0 -41
- data/spec/unit/document_spec.rb +0 -317
- data/spec/unit/parser/line_parser_spec.rb +0 -37
- data/spec/unit/parser/tokenizer_spec.rb +0 -98
- data/spec/unit/parser_spec.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26526531e52a08b42e851ecb48e7139284c0d123497e0690b96e034568d80260
|
4
|
+
data.tar.gz: 66f9a81079464969de19e6fdd5a5b35c2eda75376ec6495b7afe31d3bf3e9b45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a00336cae71fa202912e83f523fd3229600f6712f12531425e841cb328c2a45fd3f2203e009266b467ca9e544fcb3abbfceef8b5dc6254f324f88213957f217
|
7
|
+
data.tar.gz: 3fa86473dd8b9ade5ba84fd227fca41be16bb7c6e4cfc15ae27cb9cb1a4d2a1d3a765b7bd6134b3d6765a2446b74e6a209d3e355756d62d2c2de165a21a54749
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Sie
|
2
2
|
|
3
|
-
[](https://github.com/barsoom/sie/actions/workflows/ci.yml)
|
4
|
+
[](https://codeclimate.com/github/barsoom/sie)
|
5
5
|
|
6
|
+
SIE parser and generator supporting the [format "SIE typ 1-4 – Klassisk SIE"](https://sie.se/format/).
|
6
7
|
|
7
8
|
## Installation
|
8
9
|
|
@@ -161,7 +162,7 @@ Getting the latest code and gems:
|
|
161
162
|
|
162
163
|
## Resources
|
163
164
|
|
164
|
-
[SIE format specification rev 4B (
|
165
|
+
[SIE format specification rev 4B (Swedish)](https://sie.se/wp-content/uploads/2020/05/SIE_filformat_ver_4B_080930.pdf)
|
165
166
|
|
166
167
|
## See also
|
167
168
|
|
@@ -9,7 +9,7 @@ class Sie::Document::Renderer
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def add_line(label, *values)
|
12
|
-
append ["##{
|
12
|
+
append [ "##{label}", *format_values(values) ].join(" ")
|
13
13
|
end
|
14
14
|
|
15
15
|
def add_array
|
@@ -36,7 +36,7 @@ class Sie::Document::Renderer
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def encoded(text)
|
39
|
-
text.encode(ENCODING, :
|
39
|
+
text.encode(ENCODING, invalid: :replace, undef: :replace, replace: "?")
|
40
40
|
end
|
41
41
|
|
42
42
|
def format_value(value)
|
@@ -27,9 +27,9 @@ module Sie
|
|
27
27
|
entry.attributes[label] = attr_tokens.first
|
28
28
|
else
|
29
29
|
type = attr.fetch(:type)
|
30
|
-
values = attr_tokens
|
31
|
-
each_slice(type.size)
|
32
|
-
map { |slice| Hash[type.zip(slice)] }
|
30
|
+
values = attr_tokens
|
31
|
+
.each_slice(type.size)
|
32
|
+
.map { |slice| Hash[type.zip(slice)] }
|
33
33
|
|
34
34
|
entry.attributes[label] = values
|
35
35
|
end
|
@@ -53,6 +53,7 @@ module Sie
|
|
53
53
|
hash_tokens = []
|
54
54
|
while token = tokens.shift
|
55
55
|
break if token.is_a?(Tokenizer::EndArrayToken)
|
56
|
+
|
56
57
|
hash_tokens << token.value
|
57
58
|
end
|
58
59
|
|
@@ -1,41 +1,41 @@
|
|
1
1
|
module Sie
|
2
2
|
class Parser
|
3
3
|
ENTRY_TYPES = {
|
4
|
-
"adress" => [
|
5
|
-
"bkod" => [
|
6
|
-
"dim" => [
|
7
|
-
"enhet" => [
|
8
|
-
"flagga" => [
|
9
|
-
"fnamn" => [
|
10
|
-
"fnr" => [
|
11
|
-
"format" => [
|
12
|
-
"ftyp" => [
|
13
|
-
"gen" => [
|
14
|
-
"ib" => [
|
15
|
-
"konto" => [
|
16
|
-
"kptyp" => [
|
17
|
-
"ktyp" => [
|
18
|
-
"objekt" => [
|
19
|
-
"oib" => [
|
20
|
-
"omfattn" => [
|
21
|
-
"orgnr" => [
|
22
|
-
"oub" => [
|
23
|
-
"pbudget" => [
|
24
|
-
"program" => [
|
25
|
-
"prosa" => [
|
26
|
-
"psaldo" => [
|
27
|
-
"rar" => [
|
28
|
-
"res" => [
|
29
|
-
"sietyp" => [
|
30
|
-
"sru" => [
|
31
|
-
"taxar" => [
|
32
|
-
"trans" => [
|
33
|
-
"rtrans" => [
|
34
|
-
"btrans" => [
|
35
|
-
"ub" => [
|
36
|
-
"underdim" => [
|
37
|
-
"valuta" => [
|
38
|
-
"ver" => [
|
4
|
+
"adress" => [ "kontakt", "utdelningsadr", "postadr", "tel" ],
|
5
|
+
"bkod" => [ "SNI-kod" ],
|
6
|
+
"dim" => [ "dimensionsnr", "namn" ],
|
7
|
+
"enhet" => [ "kontonr", "enhet" ],
|
8
|
+
"flagga" => [ "x" ],
|
9
|
+
"fnamn" => [ "foretagsnamn" ],
|
10
|
+
"fnr" => [ "foretagsid" ],
|
11
|
+
"format" => [ "PC8" ],
|
12
|
+
"ftyp" => [ "foretagstyp" ],
|
13
|
+
"gen" => [ "datum", "sign" ],
|
14
|
+
"ib" => [ "arsnr", "konto", "saldo", "kvantitet" ],
|
15
|
+
"konto" => [ "kontonr", "kontonamn" ],
|
16
|
+
"kptyp" => [ "typ" ],
|
17
|
+
"ktyp" => [ "kontonr", "kontotyp" ],
|
18
|
+
"objekt" => [ "dimensionsnr", "objektnr", "objektnamn" ],
|
19
|
+
"oib" => [ "arsnr", "konto", { name: "objekt", type: [ "dimensionsnr", "objektnr" ] }, "saldo", "kvantitet" ],
|
20
|
+
"omfattn" => [ "datum" ],
|
21
|
+
"orgnr" => [ "orgnr", "forvnr", "verknr" ],
|
22
|
+
"oub" => [ "arsnr", "konto", { name: "objekt", type: [ "dimensionsnr", "objektnr" ] }, "saldo", "kvantitet" ],
|
23
|
+
"pbudget" => [ "arsnr", "period", "konto", { name: "objekt", type: [ "dimensionsnr", "objektnr" ] }, "saldo", "kvantitet" ],
|
24
|
+
"program" => [ "programnamn", "version" ],
|
25
|
+
"prosa" => [ "text" ],
|
26
|
+
"psaldo" => [ "arsnr", "period", "konto", { name: "objekt", type: [ "dimensionsnr", "objektnr" ] }, "saldo", "kvantitet" ],
|
27
|
+
"rar" => [ "arsnr", "start", "slut" ],
|
28
|
+
"res" => [ "ars", "konto", "saldo", "kvantitet" ],
|
29
|
+
"sietyp" => [ "typnr" ],
|
30
|
+
"sru" => [ "konto", "SRU-kod" ],
|
31
|
+
"taxar" => [ "ar" ],
|
32
|
+
"trans" => [ "kontonr", { name: "objektlista", type: [ "dimensionsnr", "objektnr" ], many: true }, "belopp", "transdat", "transtext", "kvantitet", "sign" ],
|
33
|
+
"rtrans" => [ "kontonr", { name: "objektlista", type: [ "dimensionsnr", "objektnr" ], many: true }, "belopp", "transdat", "transtext", "kvantitet", "sign" ],
|
34
|
+
"btrans" => [ "kontonr", { name: "objektlista", type: [ "dimensionsnr", "objektnr" ], many: true }, "belopp", "transdat", "transtext", "kvantitet", "sign" ],
|
35
|
+
"ub" => [ "arsnr", "konto", "saldo", "kvantitet" ],
|
36
|
+
"underdim" => [ "dimensionsnr", "namn", "superdimension" ],
|
37
|
+
"valuta" => [ "valutakod" ],
|
38
|
+
"ver" => [ "serie", "vernr", "verdatum", "vertext", "regdatum", "sign" ],
|
39
39
|
}
|
40
40
|
end
|
41
41
|
end
|
data/lib/sie/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Barsoom AB
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: attr_extras
|
@@ -42,14 +42,14 @@ dependencies:
|
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -87,13 +87,7 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- ".gitignore"
|
91
|
-
- ".rspec"
|
92
|
-
- ".travis.yml"
|
93
|
-
- Gemfile
|
94
|
-
- Gemfile.pre_2.2.2
|
95
90
|
- README.md
|
96
|
-
- Rakefile
|
97
91
|
- lib/sie.rb
|
98
92
|
- lib/sie/document.rb
|
99
93
|
- lib/sie/document/renderer.rb
|
@@ -107,26 +101,11 @@ files:
|
|
107
101
|
- lib/sie/parser/tokenizer.rb
|
108
102
|
- lib/sie/parser/tokenizer/token.rb
|
109
103
|
- lib/sie/version.rb
|
110
|
-
- script/bootstrap
|
111
|
-
- script/refresh
|
112
|
-
- script/test
|
113
|
-
- script/turbux_rspec
|
114
|
-
- sie.gemspec
|
115
|
-
- spec/fixtures/sie_file.se
|
116
|
-
- spec/fixtures/sie_file_with_unknown_entries.se
|
117
|
-
- spec/integration/parser_spec.rb
|
118
|
-
- spec/spec_helper.rb
|
119
|
-
- spec/unit/build_entry_spec.rb
|
120
|
-
- spec/unit/document/renderer_spec.rb
|
121
|
-
- spec/unit/document/voucher_series_spec.rb
|
122
|
-
- spec/unit/document_spec.rb
|
123
|
-
- spec/unit/parser/line_parser_spec.rb
|
124
|
-
- spec/unit/parser/tokenizer_spec.rb
|
125
|
-
- spec/unit/parser_spec.rb
|
126
104
|
homepage: ''
|
127
105
|
licenses:
|
128
106
|
- MIT
|
129
|
-
metadata:
|
107
|
+
metadata:
|
108
|
+
rubygems_mfa_required: 'true'
|
130
109
|
post_install_message:
|
131
110
|
rdoc_options: []
|
132
111
|
require_paths:
|
@@ -142,19 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
121
|
- !ruby/object:Gem::Version
|
143
122
|
version: '0'
|
144
123
|
requirements: []
|
145
|
-
rubygems_version: 3.
|
124
|
+
rubygems_version: 3.2.31
|
146
125
|
signing_key:
|
147
126
|
specification_version: 4
|
148
127
|
summary: Parses and generates SIE files (http://sie.se/)
|
149
|
-
test_files:
|
150
|
-
- spec/fixtures/sie_file.se
|
151
|
-
- spec/fixtures/sie_file_with_unknown_entries.se
|
152
|
-
- spec/integration/parser_spec.rb
|
153
|
-
- spec/spec_helper.rb
|
154
|
-
- spec/unit/build_entry_spec.rb
|
155
|
-
- spec/unit/document/renderer_spec.rb
|
156
|
-
- spec/unit/document/voucher_series_spec.rb
|
157
|
-
- spec/unit/document_spec.rb
|
158
|
-
- spec/unit/parser/line_parser_spec.rb
|
159
|
-
- spec/unit/parser/tokenizer_spec.rb
|
160
|
-
- spec/unit/parser_spec.rb
|
128
|
+
test_files: []
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/Gemfile
DELETED
data/Gemfile.pre_2.2.2
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in sie.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
# Ruby <2.2.2 can't use Active Support 5.
|
7
|
-
# https://apotonick.wordpress.com/2012/08/14/different-gemfiles-for-ruby-1-8-and-1-9-on-travis-ci/
|
8
|
-
gem "activesupport", "< 5"
|
data/Rakefile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
|
3
|
-
namespace :spec do
|
4
|
-
task :unit do
|
5
|
-
puts "Running unit tests:"
|
6
|
-
system("rspec spec/unit/**_spec.rb") || exit(1)
|
7
|
-
end
|
8
|
-
|
9
|
-
task :integration do
|
10
|
-
puts "Running integrated tests:"
|
11
|
-
system("rspec spec/integration/**_spec.rb") || exit(1)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
task :default => [ :"spec:unit", :"spec:integration" ]
|
data/script/bootstrap
DELETED
data/script/refresh
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
|
3
|
-
printf "\e[00;34mGetting the latest version\e[00m... "
|
4
|
-
|
5
|
-
(git status|grep 'nothing to commit' 1> /dev/null)
|
6
|
-
|
7
|
-
if [ ! $? -eq 0 ]
|
8
|
-
then
|
9
|
-
set -e
|
10
|
-
git stash 1> /dev/null
|
11
|
-
git pull --rebase 1> /dev/null
|
12
|
-
git stash pop 1> /dev/null
|
13
|
-
else
|
14
|
-
set -e
|
15
|
-
git pull --rebase 1> /dev/null
|
16
|
-
fi
|
17
|
-
|
18
|
-
echo "done"
|
19
|
-
|
20
|
-
printf "\e[00;34mBundling\e[00m... "
|
21
|
-
bundle 1> /dev/null
|
22
|
-
echo "done"
|
23
|
-
echo
|
24
|
-
|
25
|
-
rake
|
data/script/test
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
script/turbux_rspec
|
data/script/turbux_rspec
DELETED
data/sie.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'sie/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "sie"
|
8
|
-
spec.version = Sie::VERSION
|
9
|
-
spec.authors = ["Barsoom AB"]
|
10
|
-
spec.email = ["all@barsoom.se"]
|
11
|
-
spec.description = %q{SIE parser and generator}
|
12
|
-
spec.summary = %q{Parses and generates SIE files (http://sie.se/)}
|
13
|
-
spec.homepage = ""
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_dependency "attr_extras"
|
22
|
-
spec.add_dependency "activesupport"
|
23
|
-
|
24
|
-
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
-
spec.add_development_dependency "rake"
|
26
|
-
spec.add_development_dependency "rspec"
|
27
|
-
end
|
data/spec/fixtures/sie_file.se
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
#FLAGGA 0
|
2
|
-
#PROGRAM "fooconomic" "1.0"
|
3
|
-
#FORMAT PC8
|
4
|
-
#GEN 20130101
|
5
|
-
#SIETYP 4
|
6
|
-
#ORGNR 555555-5555
|
7
|
-
#FNAMN "Foocorp"
|
8
|
-
#ADRESS "Foocorp" "" "12345 City" "555-12345"
|
9
|
-
#KONTO 1510 "Accounts receivable"
|
10
|
-
#KTYP 1510 T
|
11
|
-
#SRU 1510 204
|
12
|
-
#KONTO 1930 "Bank account"
|
13
|
-
#KTYP 1930 T
|
14
|
-
#SRU 1930 200
|
15
|
-
#KONTO 2440 Supplier
|
16
|
-
#KTYP 2440 S
|
17
|
-
#SRU 2440 300
|
18
|
-
#VER A 1 20130101 "Invoice" 20120105
|
19
|
-
{
|
20
|
-
#TRANS 1510 {} -200 20130101 "Coffee machine"
|
21
|
-
#TRANS 4100 {} 180 20130101 "Coffee machine"
|
22
|
-
#TRANS 2611 {} -20 20130101 "VAT"
|
23
|
-
}
|
24
|
-
#VER A 2 20130102 "Payment" 20120105
|
25
|
-
{
|
26
|
-
#TRANS 1510 {} -200 20130101 "Payment: Coffee machine"
|
27
|
-
#TRANS 1970 {} 200 20130101 "Payment: Coffee machine"
|
28
|
-
}
|
@@ -1,32 +0,0 @@
|
|
1
|
-
#FLAGGA 0
|
2
|
-
#PROGRAM "fooconomic" "1.0"
|
3
|
-
#FORMAT PC8
|
4
|
-
#GEN 20130101
|
5
|
-
#SIETYP 4
|
6
|
-
#ORGNR 555555-5555
|
7
|
-
#FNAMN "Foocorp"
|
8
|
-
#ADRESS "Foocorp" "" "12345 City" "555-12345"
|
9
|
-
#KONTO 1510 "Accounts receivable"
|
10
|
-
#KTYP 1510 T
|
11
|
-
#SRU 1510 204
|
12
|
-
#KONTO 1930 "Bank account"
|
13
|
-
#KTYP 1930 T
|
14
|
-
#SRU 1930 200
|
15
|
-
#KONTO 2440 Supplier
|
16
|
-
#KTYP 2440 S
|
17
|
-
#SRU 2440 300
|
18
|
-
#KONTO 2610 "Utgaende moms, oreducerad "
|
19
|
-
#KTYP 2610 S
|
20
|
-
#SRU 2610 7369
|
21
|
-
#MOMSKOD 2610 10
|
22
|
-
#VER A 1 20130101 "Invoice" 20120105
|
23
|
-
{
|
24
|
-
#TRANS 1510 {} -200 20130101 "Coffee machine"
|
25
|
-
#TRANS 4100 {} 180 20130101 "Coffee machine"
|
26
|
-
#TRANS 2611 {} -20 20130101 "VAT"
|
27
|
-
}
|
28
|
-
#VER A 2 20130102 "Payment" 20120105
|
29
|
-
{
|
30
|
-
#TRANS 1510 {} -200 20130101 "Payment: Coffee machine"
|
31
|
-
#TRANS 1970 {} 200 20130101 "Payment: Coffee machine"
|
32
|
-
}
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
describe Sie::Parser do
|
6
|
-
it "parses a file" do
|
7
|
-
parser = Sie::Parser.new
|
8
|
-
|
9
|
-
open_file("fixtures/sie_file.se") do |f|
|
10
|
-
sie_file = parser.parse(f)
|
11
|
-
|
12
|
-
expect(sie_file.entries_with_label("fnamn").first.attributes["foretagsnamn"]).to eq("Foocorp")
|
13
|
-
|
14
|
-
account = sie_file.entries_with_label("konto").first
|
15
|
-
expect(account.attributes["kontonr"]).to eq("1510")
|
16
|
-
expect(account.attributes["kontonamn"]).to eq("Accounts receivable")
|
17
|
-
expect(sie_file.entries_with_label("ver").size).to eq(2)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context "with unknown entries" do
|
22
|
-
let(:file_with_unknown_entries) { "fixtures/sie_file_with_unknown_entries.se" }
|
23
|
-
|
24
|
-
context "using a lenient parser" do
|
25
|
-
let(:parser) { Sie::Parser.new(lenient: true) }
|
26
|
-
|
27
|
-
it "handles unknown entries without raising error" do
|
28
|
-
open_file(file_with_unknown_entries) do |f|
|
29
|
-
expect { parser.parse(f) }.not_to raise_error
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it "continues to parse the complete file after unknown entries" do
|
34
|
-
open_file(file_with_unknown_entries) do |f|
|
35
|
-
sie_file = parser.parse(f)
|
36
|
-
|
37
|
-
expect(sie_file.entries_with_label("ver").size).to eq(2)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context "with strict parser" do
|
43
|
-
let(:parser) { Sie::Parser.new }
|
44
|
-
|
45
|
-
it "raises error when encountering unknown entries" do
|
46
|
-
open_file(file_with_unknown_entries) do |f|
|
47
|
-
expect { parser.parse(f) }.to raise_error(/Unknown entry type: momskod.+Pass 'lenient: true'/)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def open_file(fixture_file, &block)
|
54
|
-
File.open(File.join(File.dirname(__FILE__), "../#{fixture_file}"), &block)
|
55
|
-
end
|
56
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "sie/parser/build_entry"
|
3
|
-
require "sie/parser/tokenizer"
|
4
|
-
|
5
|
-
describe Sie::Parser::BuildEntry, ".call" do
|
6
|
-
context "with an unexpected token at start of array" do
|
7
|
-
it "raises InvalidEntryError" do
|
8
|
-
line = '#TRANS 2400 [] -200 20130101 "Foocorp expense"'
|
9
|
-
tokens = Sie::Parser::Tokenizer.new(line).tokenize
|
10
|
-
first_token = tokens.shift
|
11
|
-
|
12
|
-
expect {
|
13
|
-
Sie::Parser::BuildEntry.call(line, first_token, tokens, false)
|
14
|
-
}.to raise_error(Sie::Parser::BuildEntry::InvalidEntryError)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
describe Sie::Document::Renderer, "#add_line" do
|
6
|
-
it "replaces input of the wrong encoding with '?'" do
|
7
|
-
renderer = Sie::Document::Renderer.new
|
8
|
-
renderer.add_line "Hello ☃", 1
|
9
|
-
output = renderer.render
|
10
|
-
|
11
|
-
expect(output).to eq "#Hello ? 1\n"
|
12
|
-
end
|
13
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Sie::Document::VoucherSeries, ".for" do
|
4
|
-
subject(:series) { Sie::Document::VoucherSeries.for(creditor, type) }
|
5
|
-
|
6
|
-
let(:type) { :invoice }
|
7
|
-
|
8
|
-
context "when on the creditor side" do
|
9
|
-
let(:creditor) { true }
|
10
|
-
|
11
|
-
context "with an invoice" do
|
12
|
-
let(:type) { :invoice }
|
13
|
-
it { should == "LF" }
|
14
|
-
end
|
15
|
-
|
16
|
-
context "with a payment" do
|
17
|
-
let(:type) { :payment }
|
18
|
-
it { should == "KB" }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "when on the debtor side" do
|
23
|
-
let(:creditor) { false }
|
24
|
-
|
25
|
-
context "with an invoice" do
|
26
|
-
let(:type) { :invoice }
|
27
|
-
it { should == "KF" }
|
28
|
-
end
|
29
|
-
|
30
|
-
context "with a payment" do
|
31
|
-
let(:type) { :payment }
|
32
|
-
it { should == "KI" }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context "when neither a payment or invoice" do
|
37
|
-
let(:creditor) { false }
|
38
|
-
let(:type) { :manual_bookable }
|
39
|
-
it { should == "LV" }
|
40
|
-
end
|
41
|
-
end
|
data/spec/unit/document_spec.rb
DELETED
@@ -1,317 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "spec_helper"
|
3
|
-
require "sie"
|
4
|
-
require "active_support/core_ext/date/calculations"
|
5
|
-
|
6
|
-
describe Sie::Document, "#render" do
|
7
|
-
let(:financial_years) {
|
8
|
-
[
|
9
|
-
Date.new(2011, 1, 1)..Date.new(2011, 12, 31),
|
10
|
-
Date.new(2012, 1, 1)..Date.new(2012, 12, 31),
|
11
|
-
Date.new(2013, 1, 1)..Date.new(2013, 12, 31),
|
12
|
-
]
|
13
|
-
}
|
14
|
-
let(:generated_on) { Date.yesterday }
|
15
|
-
let(:accounts) {
|
16
|
-
[
|
17
|
-
number: 1500, description: "Customer ledger",
|
18
|
-
]
|
19
|
-
}
|
20
|
-
let(:vouchers) {
|
21
|
-
[
|
22
|
-
{
|
23
|
-
creditor: false, type: :invoice, number: 1, booked_on: Date.new(2011, 9, 3), description: "Invoice 1",
|
24
|
-
voucher_lines: [
|
25
|
-
{
|
26
|
-
account_number: 1500, amount: 512.0, booked_on: Date.new(2011, 9, 3), description: "Item 1",
|
27
|
-
dimensions: { 6 => 1 }
|
28
|
-
},
|
29
|
-
{
|
30
|
-
account_number: 3100, amount: -512.0, booked_on: Date.new(2011, 9, 3), description: "Item 1",
|
31
|
-
dimensions: { 6 => 1 }
|
32
|
-
},
|
33
|
-
]
|
34
|
-
},
|
35
|
-
{
|
36
|
-
creditor: true, type: :payment, number: 2, booked_on: Date.new(2012, 8, 31), description: "Payout 1",
|
37
|
-
voucher_lines: [
|
38
|
-
{
|
39
|
-
account_number: 2400, amount: 256.0, booked_on: Date.new(2012, 8, 31), description: "Payout line 1"
|
40
|
-
},
|
41
|
-
{
|
42
|
-
account_number: 1970, amount: -256.0, booked_on: Date.new(2012, 8, 31), description: "Payout line 2"
|
43
|
-
},
|
44
|
-
]
|
45
|
-
}
|
46
|
-
]
|
47
|
-
}
|
48
|
-
let(:dimensions) {
|
49
|
-
[
|
50
|
-
{
|
51
|
-
number: 6, description: "Project",
|
52
|
-
objects: [
|
53
|
-
{ number: 1, description: "Education" }
|
54
|
-
]
|
55
|
-
}
|
56
|
-
]
|
57
|
-
}
|
58
|
-
|
59
|
-
class TestDataSource
|
60
|
-
attr_accessor :program, :program_version, :generated_on, :company_name,
|
61
|
-
:accounts, :balance_account_numbers, :closing_account_numbers,
|
62
|
-
:vouchers, :financial_years, :dimensions
|
63
|
-
|
64
|
-
# vouchers is not part of the expected interface so making it private.
|
65
|
-
#
|
66
|
-
# Sie::Document uses #each_voucher so that you can build documents for huge sets of vouchers
|
67
|
-
# by loading them in batches.
|
68
|
-
private :vouchers
|
69
|
-
|
70
|
-
def initialize(hash)
|
71
|
-
hash.each do |k, v|
|
72
|
-
public_send("#{k}=", v)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def each_voucher(&block)
|
77
|
-
vouchers.each(&block)
|
78
|
-
end
|
79
|
-
|
80
|
-
def balance_before(account_number, date)
|
81
|
-
if account_number == 9999
|
82
|
-
# So we can test empty balances.
|
83
|
-
nil
|
84
|
-
else
|
85
|
-
# Faking a fetch based on date and number.
|
86
|
-
account_number.to_i + (date.mday * 100).to_f
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
let(:data_source) {
|
92
|
-
TestDataSource.new(
|
93
|
-
accounts: accounts,
|
94
|
-
vouchers: vouchers,
|
95
|
-
program: "Foonomic",
|
96
|
-
program_version: "3.11",
|
97
|
-
generated_on: generated_on,
|
98
|
-
company_name: "Foocorp",
|
99
|
-
financial_years: financial_years,
|
100
|
-
balance_account_numbers: [ 1500, 2400, 9999 ],
|
101
|
-
closing_account_numbers: [ 3100, 9999 ],
|
102
|
-
dimensions: dimensions
|
103
|
-
)
|
104
|
-
}
|
105
|
-
|
106
|
-
let(:doc) {
|
107
|
-
Sie::Document.new(data_source)
|
108
|
-
}
|
109
|
-
|
110
|
-
let(:sie_file) { Sie::Parser.new.parse(doc.render) }
|
111
|
-
|
112
|
-
it "adds a header" do
|
113
|
-
expect(entry_attribute("flagga", "x")).to eq("0")
|
114
|
-
expect(entry_attribute("program", "programnamn")).to eq("Foonomic")
|
115
|
-
expect(entry_attribute("program", "version")).to eq("3.11")
|
116
|
-
expect(entry_attribute("format", "PC8")).to eq("PC8")
|
117
|
-
expect(entry_attribute("gen", "datum")).to eq(generated_on.strftime("%Y%m%d"))
|
118
|
-
expect(entry_attribute("sietyp", "typnr")).to eq("4")
|
119
|
-
expect(entry_attribute("fnamn", "foretagsnamn")).to eq("Foocorp")
|
120
|
-
end
|
121
|
-
|
122
|
-
it "has accounting years" do
|
123
|
-
expect(indexed_entry_attribute("rar", 0, "arsnr")).to eq("0")
|
124
|
-
expect(indexed_entry_attribute("rar", 0, "start")).to eq("20130101")
|
125
|
-
expect(indexed_entry_attribute("rar", 0, "slut")).to eq("20131231")
|
126
|
-
expect(indexed_entry_attribute("rar", 1, "arsnr")).to eq("-1")
|
127
|
-
expect(indexed_entry_attribute("rar", 1, "start")).to eq("20120101")
|
128
|
-
expect(indexed_entry_attribute("rar", 1, "slut")).to eq("20121231")
|
129
|
-
expect(indexed_entry_attribute("rar", 2, "arsnr")).to eq("-2")
|
130
|
-
expect(indexed_entry_attribute("rar", 2, "start")).to eq("20110101")
|
131
|
-
expect(indexed_entry_attribute("rar", 2, "slut")).to eq("20111231")
|
132
|
-
end
|
133
|
-
|
134
|
-
it "has accounts" do
|
135
|
-
expect(indexed_entry_attributes("konto", 0)).to eq("kontonr" => "1500", "kontonamn" => "Customer ledger")
|
136
|
-
end
|
137
|
-
|
138
|
-
it "has dimensions" do
|
139
|
-
expect(indexed_entry_attributes("dim", 0)).to eq("dimensionsnr" => "6", "namn" => "Project")
|
140
|
-
end
|
141
|
-
|
142
|
-
it "has objects" do
|
143
|
-
expect(indexed_entry_attributes("objekt", 0)).to eq("dimensionsnr" => "6", "objektnr" => "1", "objektnamn" => "Education")
|
144
|
-
end
|
145
|
-
|
146
|
-
it "has balances brought forward (ingående balans)" do
|
147
|
-
expect(indexed_entry_attributes("ib", 0)).not_to eq("arsnr" => "0", "konto" => "9999", "saldo" => "")
|
148
|
-
expect(indexed_entry_attributes("ib", 0)).to eq("arsnr" => "0", "konto" => "1500", "saldo" => "1600.0")
|
149
|
-
expect(indexed_entry_attributes("ib", 1)).to eq("arsnr" => "0", "konto" => "2400", "saldo" => "2500.0")
|
150
|
-
expect(indexed_entry_attributes("ib", 2)).to eq("arsnr" => "-1", "konto" => "1500", "saldo" => "1600.0")
|
151
|
-
expect(indexed_entry_attributes("ib", 3)).to eq("arsnr" => "-1", "konto" => "2400", "saldo" => "2500.0")
|
152
|
-
expect(indexed_entry_attributes("ib", 4)).to eq("arsnr" => "-2", "konto" => "1500", "saldo" => "1600.0")
|
153
|
-
expect(indexed_entry_attributes("ib", 5)).to eq("arsnr" => "-2", "konto" => "2400", "saldo" => "2500.0")
|
154
|
-
end
|
155
|
-
|
156
|
-
it "has balances carried forward (utgående balans)" do
|
157
|
-
expect(indexed_entry_attributes("ub", 0)).not_to eq("arsnr" => "0", "konto" => "9999", "saldo" => "")
|
158
|
-
expect(indexed_entry_attributes("ub", 0)).to eq("arsnr" => "0", "konto" => "1500", "saldo" => "4600.0")
|
159
|
-
expect(indexed_entry_attributes("ub", 1)).to eq("arsnr" => "0", "konto" => "2400", "saldo" => "5500.0")
|
160
|
-
expect(indexed_entry_attributes("ub", 2)).to eq("arsnr" => "-1", "konto" => "1500", "saldo" => "4600.0")
|
161
|
-
expect(indexed_entry_attributes("ub", 3)).to eq("arsnr" => "-1", "konto" => "2400", "saldo" => "5500.0")
|
162
|
-
expect(indexed_entry_attributes("ub", 4)).to eq("arsnr" => "-2", "konto" => "1500", "saldo" => "4600.0")
|
163
|
-
expect(indexed_entry_attributes("ub", 5)).to eq("arsnr" => "-2", "konto" => "2400", "saldo" => "5500.0")
|
164
|
-
end
|
165
|
-
|
166
|
-
it "has closing account balances (saldo för resultatkonto)" do
|
167
|
-
expect(indexed_entry_attributes("res", 0)).not_to eq("ars" => "0", "konto" => "9999", "saldo" => "")
|
168
|
-
expect(indexed_entry_attributes("res", 0)).to eq("ars" => "0", "konto" => "3100", "saldo" => "6200.0")
|
169
|
-
expect(indexed_entry_attributes("res", 1)).to eq("ars" => "-1", "konto" => "3100", "saldo" => "6200.0")
|
170
|
-
expect(indexed_entry_attributes("res", 2)).to eq("ars" => "-2", "konto" => "3100", "saldo" => "6200.0")
|
171
|
-
end
|
172
|
-
|
173
|
-
it "has vouchers" do
|
174
|
-
expect(indexed_entry("ver", 0).attributes).to eq(
|
175
|
-
"serie" => "KF", "vernr" => "1",
|
176
|
-
"verdatum" => "20110903", "vertext" => "Invoice 1"
|
177
|
-
)
|
178
|
-
expect(indexed_voucher_entries(0)[0].attributes).to eq(
|
179
|
-
"kontonr" => "1500", "belopp" => "512.0",
|
180
|
-
"transdat" => "20110903", "transtext" => "Item 1",
|
181
|
-
"objektlista" => [{"dimensionsnr" => "6", "objektnr" => "1"}]
|
182
|
-
)
|
183
|
-
expect(indexed_voucher_entries(0)[1].attributes).to eq(
|
184
|
-
"kontonr" => "3100", "belopp" => "-512.0",
|
185
|
-
"transdat" => "20110903", "transtext" => "Item 1",
|
186
|
-
"objektlista" => [{"dimensionsnr" => "6", "objektnr" => "1"}]
|
187
|
-
)
|
188
|
-
|
189
|
-
expect(indexed_entry("ver", 1).attributes).to eq(
|
190
|
-
"serie" => "KB", "vernr" => "2",
|
191
|
-
"verdatum" => "20120831", "vertext" => "Payout 1"
|
192
|
-
)
|
193
|
-
expect(indexed_voucher_entries(1)[0].attributes).to eq(
|
194
|
-
"kontonr" => "2400", "belopp" => "256.0",
|
195
|
-
"transdat" => "20120831", "transtext" => "Payout line 1",
|
196
|
-
"objektlista" => []
|
197
|
-
)
|
198
|
-
expect(indexed_voucher_entries(1)[1].attributes).to eq(
|
199
|
-
"kontonr" => "1970", "belopp" => "-256.0",
|
200
|
-
"transdat" => "20120831", "transtext" => "Payout line 2",
|
201
|
-
"objektlista" => []
|
202
|
-
)
|
203
|
-
end
|
204
|
-
|
205
|
-
it "excludes balance rows if given the option 'exclude_balance_rows'" do
|
206
|
-
document_without_balance_rows = Sie::Document.new(data_source, exclude_balance_rows: true)
|
207
|
-
sie_file = Sie::Parser.new.parse(document_without_balance_rows.render)
|
208
|
-
expect(sie_file.entries_with_label("ib")).to be_empty
|
209
|
-
expect(sie_file.entries_with_label("ub")).to be_empty
|
210
|
-
expect(sie_file.entries_with_label("res")).to be_empty
|
211
|
-
|
212
|
-
document_with_balance_rows = Sie::Document.new(data_source, exclude_balance_rows: false)
|
213
|
-
sie_file = Sie::Parser.new.parse(document_with_balance_rows.render)
|
214
|
-
expect(sie_file.entries_with_label("ib")).not_to be_empty
|
215
|
-
expect(sie_file.entries_with_label("ub")).not_to be_empty
|
216
|
-
expect(sie_file.entries_with_label("res")).not_to be_empty
|
217
|
-
|
218
|
-
document_will_default_with_balance_rows = Sie::Document.new(data_source)
|
219
|
-
sie_file = Sie::Parser.new.parse(document_will_default_with_balance_rows.render)
|
220
|
-
expect(sie_file.entries_with_label("ib")).not_to be_empty
|
221
|
-
expect(sie_file.entries_with_label("ub")).not_to be_empty
|
222
|
-
expect(sie_file.entries_with_label("res")).not_to be_empty
|
223
|
-
end
|
224
|
-
|
225
|
-
context "with really long descriptions" do
|
226
|
-
let(:accounts) {
|
227
|
-
[
|
228
|
-
number: 1500, description: "k" * 101 # Make sure that the description exceeds the limit (100 chars).
|
229
|
-
]
|
230
|
-
}
|
231
|
-
let(:vouchers) {
|
232
|
-
[
|
233
|
-
build_voucher(
|
234
|
-
description: "d" * 101,
|
235
|
-
voucher_lines: [
|
236
|
-
build_voucher_line(description: "v" * 101),
|
237
|
-
build_voucher_line(description: "Payout line 2"),
|
238
|
-
]
|
239
|
-
)
|
240
|
-
]
|
241
|
-
}
|
242
|
-
|
243
|
-
it "truncates the descriptions" do
|
244
|
-
expect(indexed_entry_attributes("konto", 0)).to eq("kontonr" => "1500", "kontonamn" => "k" * 100)
|
245
|
-
expect(indexed_entry("ver", 0).attributes["vertext"]).to eq("d" * 100)
|
246
|
-
expect(indexed_voucher_entries(0)[0].attributes["transtext"]).to eq("v" * 100)
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
context "with a zeroed single voucher line" do
|
251
|
-
let(:vouchers) {
|
252
|
-
[
|
253
|
-
build_voucher(voucher_lines: [ build_voucher_line(amount: 0) ])
|
254
|
-
]
|
255
|
-
}
|
256
|
-
|
257
|
-
it "ensures there are at least two lines" do
|
258
|
-
expect(indexed_voucher_entries(0).size).to eq(2)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
context "with a series defined" do
|
263
|
-
let(:vouchers) {
|
264
|
-
[
|
265
|
-
build_voucher(series: "X"),
|
266
|
-
]
|
267
|
-
}
|
268
|
-
|
269
|
-
it "reads the series from the voucher" do
|
270
|
-
expect(indexed_entry("ver", 0).attributes["serie"]).to eq("X")
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
private
|
275
|
-
|
276
|
-
def build_voucher(attributes)
|
277
|
-
defaults = {
|
278
|
-
creditor: true,
|
279
|
-
type: :payment,
|
280
|
-
number: 1,
|
281
|
-
booked_on: Date.today,
|
282
|
-
description: "A voucher",
|
283
|
-
voucher_lines: [
|
284
|
-
build_voucher_line,
|
285
|
-
build_voucher_line,
|
286
|
-
],
|
287
|
-
}
|
288
|
-
defaults.merge(attributes)
|
289
|
-
end
|
290
|
-
|
291
|
-
def build_voucher_line(attributes = {})
|
292
|
-
defaults = { account_number: 1234, amount: 1, booked_on: Date.today, description: "A voucher line" }
|
293
|
-
defaults.merge(attributes)
|
294
|
-
end
|
295
|
-
|
296
|
-
def entry_attribute(label, attribute)
|
297
|
-
indexed_entry_attribute(label, 0, attribute)
|
298
|
-
end
|
299
|
-
|
300
|
-
def indexed_entry_attribute(label, index, attribute)
|
301
|
-
indexed_entry_attributes(label, index).fetch(attribute) do
|
302
|
-
raise "Unknown attribute #{ attribute } in #{ entry.attributes.keys.inspect }"
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
def indexed_entry_attributes(label, index)
|
307
|
-
indexed_entry(label, index).attributes
|
308
|
-
end
|
309
|
-
|
310
|
-
def indexed_voucher_entries(index)
|
311
|
-
indexed_entry("ver", index).entries
|
312
|
-
end
|
313
|
-
|
314
|
-
def indexed_entry(label, index)
|
315
|
-
sie_file.entries_with_label(label)[index] or raise "No entry with label #{ label.inspect } found!"
|
316
|
-
end
|
317
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "sie/parser/line_parser"
|
3
|
-
|
4
|
-
describe Sie::Parser::LineParser, "parse" do
|
5
|
-
it "parses lines from a sie file" do
|
6
|
-
parser = Sie::Parser::LineParser.new('#TRANS 2400 {"3" "5"} -200 20130101 "Foocorp expense"')
|
7
|
-
entry = parser.parse
|
8
|
-
expect(entry.label).to eq("trans")
|
9
|
-
expect(entry.attributes).to eq({
|
10
|
-
"kontonr" => "2400",
|
11
|
-
"belopp" => "-200",
|
12
|
-
"transdat" => "20130101",
|
13
|
-
"transtext" => "Foocorp expense",
|
14
|
-
"objektlista" => [{"dimensionsnr" => "3", "objektnr" => "5"}],
|
15
|
-
})
|
16
|
-
end
|
17
|
-
|
18
|
-
context "with unknown entry" do
|
19
|
-
let(:line) { "#MOMSKOD 2611 10"}
|
20
|
-
|
21
|
-
context "using a lenient parser" do
|
22
|
-
let(:parser) { Sie::Parser::LineParser.new(line, lenient: true) }
|
23
|
-
|
24
|
-
it "raises no error when encountering unknown entries" do
|
25
|
-
expect { parser.parse }.not_to raise_error
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "using a strict parser" do
|
30
|
-
let(:parser) { Sie::Parser::LineParser.new(line) }
|
31
|
-
|
32
|
-
it "raises error when encountering unknown entries" do
|
33
|
-
expect { parser.parse }.to raise_error(/Unknown entry type/)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "sie/parser/tokenizer"
|
3
|
-
|
4
|
-
describe Sie::Parser::Tokenizer do
|
5
|
-
it "tokenizes the given line" do
|
6
|
-
tokenizer = Sie::Parser::Tokenizer.new('#TRANS 2400 {} -200 20130101 "Foocorp expense"')
|
7
|
-
tokens = tokenizer.tokenize
|
8
|
-
|
9
|
-
expect(token_table_for(tokens)).to eq([
|
10
|
-
[ "EntryToken", "TRANS" ],
|
11
|
-
[ "StringToken", "2400" ],
|
12
|
-
[ "BeginArrayToken", "" ],
|
13
|
-
[ "EndArrayToken", "" ],
|
14
|
-
[ "StringToken", "-200" ],
|
15
|
-
[ "StringToken", "20130101" ],
|
16
|
-
[ "StringToken", "Foocorp expense" ]
|
17
|
-
])
|
18
|
-
end
|
19
|
-
|
20
|
-
it "can parse metadata arrays" do
|
21
|
-
tokenizer = Sie::Parser::Tokenizer.new('#TRANS 2400 { 1 "2" } -200 20130101 "Foocorp expense"')
|
22
|
-
tokens = tokenizer.tokenize
|
23
|
-
|
24
|
-
expect(token_table_for(tokens)).to eq([
|
25
|
-
[ "EntryToken", "TRANS" ],
|
26
|
-
[ "StringToken", "2400" ],
|
27
|
-
[ "BeginArrayToken", "" ],
|
28
|
-
[ "StringToken", "1" ],
|
29
|
-
[ "StringToken", "2" ],
|
30
|
-
[ "EndArrayToken", "" ],
|
31
|
-
[ "StringToken", "-200" ],
|
32
|
-
[ "StringToken", "20130101" ],
|
33
|
-
[ "StringToken", "Foocorp expense" ]
|
34
|
-
])
|
35
|
-
end
|
36
|
-
|
37
|
-
it "handles escaped quotes in quoted strings" do
|
38
|
-
tokenizer = Sie::Parser::Tokenizer.new('"String with \\" quote"')
|
39
|
-
tokens = tokenizer.tokenize
|
40
|
-
|
41
|
-
expect(token_table_for(tokens)).to eq([
|
42
|
-
[ "StringToken", 'String with " quote']
|
43
|
-
])
|
44
|
-
end
|
45
|
-
|
46
|
-
it "handles escaped quotes in non-quoted strings" do
|
47
|
-
tokenizer = Sie::Parser::Tokenizer.new('String_with_\\"_quote')
|
48
|
-
tokens = tokenizer.tokenize
|
49
|
-
|
50
|
-
expect(token_table_for(tokens)).to eq([
|
51
|
-
[ "StringToken", 'String_with_"_quote']
|
52
|
-
])
|
53
|
-
end
|
54
|
-
|
55
|
-
it "handles escaped backslash in strings" do
|
56
|
-
tokenizer = Sie::Parser::Tokenizer.new('"String with \\\\ backslash"')
|
57
|
-
tokens = tokenizer.tokenize
|
58
|
-
|
59
|
-
expect(token_table_for(tokens)).to eq([
|
60
|
-
[ "StringToken", 'String with \\ backslash']
|
61
|
-
])
|
62
|
-
end
|
63
|
-
|
64
|
-
it "has reasonable behavior for consecutive escape characters" do
|
65
|
-
tokenizer = Sie::Parser::Tokenizer.new('"\\\\\\"\\\\"')
|
66
|
-
tokens = tokenizer.tokenize
|
67
|
-
|
68
|
-
expect(token_table_for(tokens)).to eq([
|
69
|
-
[ "StringToken", '\\"\\']
|
70
|
-
])
|
71
|
-
end
|
72
|
-
|
73
|
-
it "handles tab character as field separator" do
|
74
|
-
tokenizer = Sie::Parser::Tokenizer.new("#TRANS\t2400")
|
75
|
-
tokens = tokenizer.tokenize
|
76
|
-
|
77
|
-
expect(token_table_for(tokens)).to eq([
|
78
|
-
[ "EntryToken", "TRANS"],
|
79
|
-
[ "StringToken", "2400"]
|
80
|
-
])
|
81
|
-
end
|
82
|
-
|
83
|
-
it "rejects control characters" do
|
84
|
-
codes_not_allowed = (0..8).to_a + (10..31).to_a + [127]
|
85
|
-
codes_not_allowed.each do |x|
|
86
|
-
tokenizer = Sie::Parser::Tokenizer.new([x].pack("C"))
|
87
|
-
expect{tokenizer.tokenize}.to raise_error /Unhandled character/
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def token_table_for(tokens)
|
94
|
-
tokens.map { |token|
|
95
|
-
[ token.class.name.split("::").last, token.value ]
|
96
|
-
}
|
97
|
-
end
|
98
|
-
end
|
data/spec/unit/parser_spec.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "sie/parser"
|
3
|
-
|
4
|
-
describe Sie::Parser, "parse" do
|
5
|
-
it "parses sie data that includes arrays" do
|
6
|
-
data = <<-DATA
|
7
|
-
#VER "LF" 2222 20130101 "Foocorp expense"
|
8
|
-
{
|
9
|
-
#TRANS 2400 {} -200 20130101 "Foocorp expense"
|
10
|
-
#TRANS 4100 {} 180 20130101 "Widgets from foocorp"
|
11
|
-
#TRANS 2611 {} -20 20130101 "VAT"
|
12
|
-
}
|
13
|
-
DATA
|
14
|
-
|
15
|
-
parser = Sie::Parser.new
|
16
|
-
sie_file = parser.parse(data)
|
17
|
-
|
18
|
-
voucher_entry = sie_file.entries.first
|
19
|
-
expect(sie_file.entries.size).to eq(1)
|
20
|
-
expect(voucher_entry.attributes["verdatum"]).to eq("20130101")
|
21
|
-
expect(voucher_entry.entries.size).to eq(3)
|
22
|
-
expect(voucher_entry.entries.first.attributes["kontonr"]).to eq("2400")
|
23
|
-
end
|
24
|
-
|
25
|
-
it "handles leading whitespace" do
|
26
|
-
data = <<-DATA
|
27
|
-
#VER "LF" 2222 20130101 "Foocorp expense"
|
28
|
-
{
|
29
|
-
#TRANS 2400 {} -200 20130101 "Foocorp expense"
|
30
|
-
#TRANS 4100 {} 180 20130101 "Widgets from foocorp"
|
31
|
-
#TRANS 2611 {} -20 20130101 "VAT"
|
32
|
-
}
|
33
|
-
DATA
|
34
|
-
|
35
|
-
parser = Sie::Parser.new
|
36
|
-
sie_file = parser.parse(data)
|
37
|
-
|
38
|
-
voucher_entry = sie_file.entries.first
|
39
|
-
expect(sie_file.entries.size).to eq(1)
|
40
|
-
expect(voucher_entry.entries.size).to eq(3)
|
41
|
-
end
|
42
|
-
end
|