sie 2.2.0 → 3.0.0
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 +8 -8
- data/.travis.yml +1 -1
- data/README.md +14 -1
- data/lib/sie/document.rb +19 -3
- data/lib/sie/document/renderer.rb +3 -3
- data/lib/sie/parser/build_entry.rb +37 -17
- data/lib/sie/parser/tokenizer.rb +1 -0
- data/lib/sie/version.rb +1 -1
- data/spec/unit/build_entry_spec.rb +16 -0
- data/spec/unit/document_spec.rb +44 -11
- data/spec/unit/parser/line_parser_spec.rb +3 -7
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTQzMmU0NGU3NmVhMDY1OWM0OWJmZWMxY2I3M2IyZDJjZTVmMDRiYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWNlN2E5OWE3ZGRmZmZkNmRiZmI0MGVkNGZmMThlMDI3M2EwZjE3Yw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NGY1ZTViZWQyNGUwMzVkNjhlMDI3ZTk4NDYyODg2MjZjYTY2M2Y5YzI0NzI1
|
10
|
+
NTNhODYzZmEwMWQ1ZjExYmU3YTVlMzNmMzAxNDNkNTkzOWQzMThjNGY1OTE2
|
11
|
+
YzQxM2Y1ZGJhZWQ5ZDhiMzljZDk4OWQ0MmVjYjliM2RjYWE0ZGQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTUyMjk5NmMwYzZkZTEyZmU5YTM3MGMwYWQ5YzQ5YzQ1OGFmODU5MmY2ODI5
|
14
|
+
NmVkNTE4ZjcwNDU4YjRjZmVkNTk3MDA3ZWYyOTY0NmEyMmE0OWI1NWQxMTMz
|
15
|
+
NWU3YjhlNWEwMDY5OTNlNzQzYWU3ODYzZjdlN2NhNzY1YzVhOGQ=
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -64,6 +64,18 @@ class YourDataSource
|
|
64
64
|
[ 3100 ]
|
65
65
|
end
|
66
66
|
|
67
|
+
def dimensions
|
68
|
+
[
|
69
|
+
{
|
70
|
+
number: 6,
|
71
|
+
description: "Projekt",
|
72
|
+
objects: [
|
73
|
+
{ number: 1, description: "Education" }
|
74
|
+
]
|
75
|
+
}
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
67
79
|
# Used to calculate balance before (and on) the given date for an account.
|
68
80
|
def balance_before(account_number, date)
|
69
81
|
# ActiveRecord example:
|
@@ -90,7 +102,8 @@ class YourDataSource
|
|
90
102
|
},
|
91
103
|
{
|
92
104
|
account_number: 3100, amount: -512.0,
|
93
|
-
booked_on: Date.today, description: "Item 1"
|
105
|
+
booked_on: Date.today, description: "Item 1",
|
106
|
+
dimensions: { 6 => 1 }
|
94
107
|
},
|
95
108
|
]
|
96
109
|
}
|
data/lib/sie/document.rb
CHANGED
@@ -14,6 +14,7 @@ module Sie
|
|
14
14
|
add_header
|
15
15
|
add_financial_years
|
16
16
|
add_accounts
|
17
|
+
add_dimensions
|
17
18
|
add_balances
|
18
19
|
add_vouchers
|
19
20
|
|
@@ -24,7 +25,7 @@ module Sie
|
|
24
25
|
|
25
26
|
delegate :program, :program_version, :generated_on, :company_name,
|
26
27
|
:accounts, :balance_account_numbers, :closing_account_numbers,
|
27
|
-
:balance_before, :each_voucher,
|
28
|
+
:balance_before, :each_voucher, :dimensions,
|
28
29
|
to: :data_source
|
29
30
|
|
30
31
|
def add_header
|
@@ -66,6 +67,20 @@ module Sie
|
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
70
|
+
def add_dimensions
|
71
|
+
dimensions.each do |dimension|
|
72
|
+
dimension_number = dimension.fetch(:number)
|
73
|
+
dimension_description = dimension.fetch(:description)
|
74
|
+
add_line("DIM", dimension_number, dimension_description)
|
75
|
+
|
76
|
+
dimension.fetch(:objects).each do |object|
|
77
|
+
object_number = object.fetch(:number)
|
78
|
+
object_description = object.fetch(:description)
|
79
|
+
add_line("OBJEKT", dimension_number, object_number, object_description)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
69
84
|
def add_vouchers
|
70
85
|
each_voucher do |voucher|
|
71
86
|
add_voucher(voucher)
|
@@ -90,17 +105,18 @@ module Sie
|
|
90
105
|
account_number = line.fetch(:account_number)
|
91
106
|
amount = line.fetch(:amount)
|
92
107
|
booked_on = line.fetch(:booked_on)
|
108
|
+
dimensions = line.fetch(:dimensions, {}).flatten
|
93
109
|
# Some SIE-importers (fortnox) cannot handle descriptions longer than 30 characters,
|
94
110
|
# but the specification has no limit.
|
95
111
|
description = line.fetch(:description).slice(0, DESCRIPTION_LENGTH_MAX)
|
96
112
|
|
97
|
-
add_line("TRANS", account_number,
|
113
|
+
add_line("TRANS", account_number, dimensions, amount, booked_on, description)
|
98
114
|
|
99
115
|
# Some consumers of SIE cannot handle single voucher lines (fortnox), so add another empty one to make
|
100
116
|
# it balance. The spec just requires the sum of lines to be 0, so single lines with zero amount would conform,
|
101
117
|
# but break for these implementations.
|
102
118
|
if voucher_lines.size < 2 && amount.zero?
|
103
|
-
add_line("TRANS", account_number,
|
119
|
+
add_line("TRANS", account_number, dimensions, amount, booked_on, description)
|
104
120
|
end
|
105
121
|
end
|
106
122
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require "stringio"
|
2
2
|
|
3
3
|
class Sie::Document::Renderer
|
4
|
-
EMPTY_ARRAY = :empty_array
|
5
4
|
ENCODING = Encoding::CP437
|
6
5
|
|
7
6
|
def initialize
|
@@ -44,8 +43,9 @@ class Sie::Document::Renderer
|
|
44
43
|
case value
|
45
44
|
when Date
|
46
45
|
value.strftime("%Y%m%d")
|
47
|
-
when
|
48
|
-
|
46
|
+
when Array
|
47
|
+
subvalues = value.map { |subvalue| format_value(subvalue.to_s) }
|
48
|
+
"{#{subvalues.join(' ')}}"
|
49
49
|
when Numeric
|
50
50
|
value.to_s
|
51
51
|
else
|
@@ -19,38 +19,58 @@ module Sie
|
|
19
19
|
|
20
20
|
def build_complete_entry
|
21
21
|
entry = build_empty_entry
|
22
|
-
entry_type = first_token.entry_type
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
attributes_with_tokens.each do |attr, *attr_tokens|
|
24
|
+
label = attr.is_a?(Hash) ? attr.fetch(:name) : attr
|
26
25
|
|
27
|
-
if
|
28
|
-
|
29
|
-
next
|
26
|
+
if attr_tokens.size == 1
|
27
|
+
entry.attributes[label] = attr_tokens.first
|
30
28
|
else
|
31
|
-
|
32
|
-
|
29
|
+
type = attr.fetch(:type)
|
30
|
+
values = attr_tokens.
|
31
|
+
each_slice(type.size).
|
32
|
+
map { |slice| Hash[type.zip(slice)] }
|
33
|
+
|
34
|
+
entry.attributes[label] = values
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
36
38
|
entry
|
37
39
|
end
|
38
40
|
|
41
|
+
def attributes_with_tokens
|
42
|
+
line_entry_type.map { |attr_entry_type|
|
43
|
+
token = tokens.shift
|
44
|
+
next unless token
|
45
|
+
|
46
|
+
if attr_entry_type.is_a?(String)
|
47
|
+
[ attr_entry_type, token.value ]
|
48
|
+
else
|
49
|
+
unless token.is_a?(Tokenizer::BeginArrayToken)
|
50
|
+
raise InvalidEntryError, "Unexpected token: #{token.inspect}"
|
51
|
+
end
|
52
|
+
|
53
|
+
hash_tokens = []
|
54
|
+
while token = tokens.shift
|
55
|
+
break if token.is_a?(Tokenizer::EndArrayToken)
|
56
|
+
hash_tokens << token.value
|
57
|
+
end
|
58
|
+
|
59
|
+
[ attr_entry_type, *hash_tokens ]
|
60
|
+
end
|
61
|
+
}.compact
|
62
|
+
end
|
63
|
+
|
39
64
|
def build_empty_entry
|
40
65
|
Entry.new(first_token.label)
|
41
66
|
end
|
42
67
|
|
43
|
-
def
|
44
|
-
|
68
|
+
def line_entry_type
|
69
|
+
first_token.entry_type
|
45
70
|
end
|
46
71
|
|
47
|
-
def
|
48
|
-
|
49
|
-
!tokens[i+1].is_a?(Tokenizer::EndArrayToken)
|
50
|
-
raise "We currently don't support metadata within entries as we haven't had a need for it yet (the data between {} in #{line})."
|
51
|
-
end
|
52
|
-
|
53
|
-
tokens.reject! { |token| token.is_a?(Tokenizer::EndArrayToken) }
|
72
|
+
def raise_invalid_entry_error
|
73
|
+
raise InvalidEntryError, "Unknown entry type: #{first_token.label}"
|
54
74
|
end
|
55
75
|
end
|
56
76
|
end
|
data/lib/sie/parser/tokenizer.rb
CHANGED
data/lib/sie/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
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
|
+
build_entry = Sie::Parser::BuildEntry.new(line, first_token, tokens, false)
|
12
|
+
|
13
|
+
expect { build_entry.call }.to raise_error(Sie::Parser::BuildEntry::InvalidEntryError)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/unit/document_spec.rb
CHANGED
@@ -22,15 +22,35 @@ describe Sie::Document, "#render" do
|
|
22
22
|
{
|
23
23
|
creditor: false, type: :invoice, number: 1, booked_on: Date.new(2011, 9, 3), description: "Invoice 1",
|
24
24
|
voucher_lines: [
|
25
|
-
{
|
26
|
-
|
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
|
+
},
|
27
33
|
]
|
28
34
|
},
|
29
35
|
{
|
30
36
|
creditor: true, type: :payment, number: 2, booked_on: Date.new(2012, 8, 31), description: "Payout 1",
|
31
37
|
voucher_lines: [
|
32
|
-
{
|
33
|
-
|
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" }
|
34
54
|
]
|
35
55
|
}
|
36
56
|
]
|
@@ -39,7 +59,7 @@ describe Sie::Document, "#render" do
|
|
39
59
|
class TestDataSource
|
40
60
|
attr_accessor :program, :program_version, :generated_on, :company_name,
|
41
61
|
:accounts, :balance_account_numbers, :closing_account_numbers,
|
42
|
-
:vouchers, :financial_years
|
62
|
+
:vouchers, :financial_years, :dimensions
|
43
63
|
|
44
64
|
# vouchers is not part of the expected interface so making it private.
|
45
65
|
#
|
@@ -73,9 +93,10 @@ describe Sie::Document, "#render" do
|
|
73
93
|
company_name: "Foocorp",
|
74
94
|
financial_years: financial_years,
|
75
95
|
balance_account_numbers: [ 1500, 2400 ],
|
76
|
-
closing_account_numbers: [ 3100 ]
|
96
|
+
closing_account_numbers: [ 3100 ],
|
97
|
+
dimensions: dimensions
|
77
98
|
)
|
78
|
-
|
99
|
+
Sie::Document.new(data_source)
|
79
100
|
}
|
80
101
|
|
81
102
|
let(:sie_file) { Sie::Parser.new.parse(doc.render) }
|
@@ -106,6 +127,14 @@ describe Sie::Document, "#render" do
|
|
106
127
|
expect(indexed_entry_attributes("konto", 0)).to eq("kontonr" => "1500", "kontonamn" => "Customer ledger")
|
107
128
|
end
|
108
129
|
|
130
|
+
it "has dimensions" do
|
131
|
+
expect(indexed_entry_attributes("dim", 0)).to eq("dimensionsnr" => "6", "namn" => "Project")
|
132
|
+
end
|
133
|
+
|
134
|
+
it "has objects" do
|
135
|
+
expect(indexed_entry_attributes("objekt", 0)).to eq("dimensionsnr" => "6", "objektnr" => "1", "objektnamn" => "Education")
|
136
|
+
end
|
137
|
+
|
109
138
|
it "has balances brought forward (ingående balans)" do
|
110
139
|
expect(indexed_entry_attributes("ib", 0)).to eq("arsnr" => "0", "konto" => "1500", "saldo" => "1600.0")
|
111
140
|
expect(indexed_entry_attributes("ib", 1)).to eq("arsnr" => "0", "konto" => "2400", "saldo" => "2500.0")
|
@@ -137,11 +166,13 @@ describe Sie::Document, "#render" do
|
|
137
166
|
)
|
138
167
|
expect(indexed_voucher_entries(0)[0].attributes).to eq(
|
139
168
|
"kontonr" => "1500", "belopp" => "512.0",
|
140
|
-
"transdat" => "20110903", "transtext" => "Item 1"
|
169
|
+
"transdat" => "20110903", "transtext" => "Item 1",
|
170
|
+
"objektlista" => [{"dimensionsnr" => "6", "objektnr" => "1"}]
|
141
171
|
)
|
142
172
|
expect(indexed_voucher_entries(0)[1].attributes).to eq(
|
143
173
|
"kontonr" => "3100", "belopp" => "-512.0",
|
144
|
-
"transdat" => "20110903", "transtext" => "Item 1"
|
174
|
+
"transdat" => "20110903", "transtext" => "Item 1",
|
175
|
+
"objektlista" => [{"dimensionsnr" => "6", "objektnr" => "1"}]
|
145
176
|
)
|
146
177
|
|
147
178
|
expect(indexed_entry("ver", 1).attributes).to eq(
|
@@ -150,11 +181,13 @@ describe Sie::Document, "#render" do
|
|
150
181
|
)
|
151
182
|
expect(indexed_voucher_entries(1)[0].attributes).to eq(
|
152
183
|
"kontonr" => "2400", "belopp" => "256.0",
|
153
|
-
"transdat" => "20120831", "transtext" => "Payout line 1"
|
184
|
+
"transdat" => "20120831", "transtext" => "Payout line 1",
|
185
|
+
"objektlista" => []
|
154
186
|
)
|
155
187
|
expect(indexed_voucher_entries(1)[1].attributes).to eq(
|
156
188
|
"kontonr" => "1970", "belopp" => "-256.0",
|
157
|
-
"transdat" => "20120831", "transtext" => "Payout line 2"
|
189
|
+
"transdat" => "20120831", "transtext" => "Payout line 2",
|
190
|
+
"objektlista" => []
|
158
191
|
)
|
159
192
|
end
|
160
193
|
|
@@ -3,14 +3,15 @@ require "sie/parser/line_parser"
|
|
3
3
|
|
4
4
|
describe Sie::Parser::LineParser, "parse" do
|
5
5
|
it "parses lines from a sie file" do
|
6
|
-
parser = Sie::Parser::LineParser.new('#TRANS 2400 {} -200 20130101 "Foocorp expense"')
|
6
|
+
parser = Sie::Parser::LineParser.new('#TRANS 2400 {"3" "5"} -200 20130101 "Foocorp expense"')
|
7
7
|
entry = parser.parse
|
8
8
|
expect(entry.label).to eq("trans")
|
9
9
|
expect(entry.attributes).to eq({
|
10
10
|
"kontonr" => "2400",
|
11
11
|
"belopp" => "-200",
|
12
12
|
"transdat" => "20130101",
|
13
|
-
"transtext" => "Foocorp expense"
|
13
|
+
"transtext" => "Foocorp expense",
|
14
|
+
"objektlista" => [{"dimensionsnr" => "3", "objektnr" => "5"}],
|
14
15
|
})
|
15
16
|
end
|
16
17
|
|
@@ -33,9 +34,4 @@ describe Sie::Parser::LineParser, "parse" do
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
36
|
-
|
37
|
-
it "fails if you have non empty metadata arrays until there is a need to support that" do
|
38
|
-
parser = Sie::Parser::LineParser.new('#TRANS 2400 { 1 "2" } -200 20130101 "Foocorp expense"')
|
39
|
-
expect(-> { parser.parse }).to raise_error(/don't support metadata/)
|
40
|
-
end
|
41
37
|
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
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Barsoom AB
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: attr_extras
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- spec/fixtures/sie_file_with_unknown_entries.se
|
118
118
|
- spec/integration/parser_spec.rb
|
119
119
|
- spec/spec_helper.rb
|
120
|
+
- spec/unit/build_entry_spec.rb
|
120
121
|
- spec/unit/document/renderer_spec.rb
|
121
122
|
- spec/unit/document/voucher_series_spec.rb
|
122
123
|
- spec/unit/document_spec.rb
|
@@ -152,6 +153,7 @@ test_files:
|
|
152
153
|
- spec/fixtures/sie_file_with_unknown_entries.se
|
153
154
|
- spec/integration/parser_spec.rb
|
154
155
|
- spec/spec_helper.rb
|
156
|
+
- spec/unit/build_entry_spec.rb
|
155
157
|
- spec/unit/document/renderer_spec.rb
|
156
158
|
- spec/unit/document/voucher_series_spec.rb
|
157
159
|
- spec/unit/document_spec.rb
|