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 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