sie 4.1.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13f115a1741394b88505486a4cc41995e93e0c4e00065c1c2aa1bd428a7b9dd1
4
- data.tar.gz: f9a4828e5c6acf66b4021b186ee2ec8009ff4eb7ae360195663015e2a92eca0f
3
+ metadata.gz: 26526531e52a08b42e851ecb48e7139284c0d123497e0690b96e034568d80260
4
+ data.tar.gz: 66f9a81079464969de19e6fdd5a5b35c2eda75376ec6495b7afe31d3bf3e9b45
5
5
  SHA512:
6
- metadata.gz: 8cc67c2a17bdf79f50d8b26c333e2e486e54685c3478f2034f93ba9137100da650fc8f503cc6905f085abf892999a00f8f799e00fdb98614299209d42b9ce48c
7
- data.tar.gz: c260f73d18c737c32449c8e9f44cae2d784c77333a9013f86603ee9c9c31e544cbc764d810a30c0e6fecfcb5c8062935cbc726aabdd756dd17451a2cf3cd76e1
6
+ metadata.gz: 1a00336cae71fa202912e83f523fd3229600f6712f12531425e841cb328c2a45fd3f2203e009266b467ca9e544fcb3abbfceef8b5dc6254f324f88213957f217
7
+ data.tar.gz: 3fa86473dd8b9ade5ba84fd227fca41be16bb7c6e4cfc15ae27cb9cb1a4d2a1d3a765b7bd6134b3d6765a2446b74e6a209d3e355756d62d2c2de165a21a54749
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Sie
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/barsoom/sie.png)](http://travis-ci.org/barsoom/sie)
4
- [![Code Climate](https://codeclimate.com/github/barsoom/sie.png)](https://codeclimate.com/github/barsoom/sie)
3
+ [![Build status](https://github.com/barsoom/sie/actions/workflows/ci.yml/badge.svg)](https://github.com/barsoom/sie/actions/workflows/ci.yml)
4
+ [![Code Climate](https://codeclimate.com/github/barsoom/sie.svg)](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 (swedish)](http://www.sie.se/wp-content/uploads/2014/01/SIE_filformat_ver_4B_080930.pdf)
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 ["##{ label }", *format_values(values)].join(" ")
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, :invalid => :replace, :undef => :replace, :replace => "?")
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" => [ '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' ]
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
@@ -19,7 +19,7 @@ module Sie
19
19
  end
20
20
 
21
21
  def label
22
- value.sub(/^#/, '').downcase
22
+ value.sub(/^#/, "").downcase
23
23
  end
24
24
  end
25
25
 
data/lib/sie/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sie
2
2
  # For versioning see: http://semver.org/
3
- VERSION = "4.1.0"
3
+ VERSION = "4.1.1"
4
4
  end
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.0
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: 2019-06-18 00:00:00.000000000 Z
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.0.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
@@ -1,18 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- .idea
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --format progress
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.6
4
- - 2.5
5
- - 2.4
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in sie.gemspec
4
- gemspec
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
@@ -1,3 +0,0 @@
1
- gem install bundler --no-ri --no-rdoc &&
2
- bundle &&
3
- rake
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
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Command to run the specs the correct way when triggered from the turbux vim plugin.
4
-
5
- command = "rspec #{ARGV.first}"
6
- exit(1) unless system(command)
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
@@ -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,5 +0,0 @@
1
- require "sie"
2
-
3
- RSpec.configure do |config|
4
- config.order = 'random'
5
- end
@@ -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
@@ -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
@@ -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