secretariat 3.1.0 → 3.3.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 +4 -4
- data/README.md +6 -2
- data/lib/secretariat/attachment.rb +83 -0
- data/lib/secretariat/constants.rb +17 -3
- data/lib/secretariat/helpers.rb +15 -0
- data/lib/secretariat/invoice.rb +64 -22
- data/lib/secretariat/line_item.rb +22 -5
- data/lib/secretariat/tax.rb +34 -0
- data/lib/secretariat/trade_party.rb +1 -1
- data/lib/secretariat/validation_error.rb +1 -1
- data/lib/secretariat/validator.rb +4 -4
- data/lib/secretariat/version.rb +2 -2
- data/lib/secretariat/versioner.rb +15 -0
- data/lib/secretariat.rb +3 -1
- data/schemas/{factur-x_1.0.0.7/Factur-X_1.0.07_EN16931.sch → factur-x_1/Factur-X_1.07.2_EN16931.sch} +70 -66
- data/schemas/{factur-x_1.0.0.7/Factur-X_1.0.07_EN16931.xsd → factur-x_1/Factur-X_1.07.2_EN16931.xsd} +3 -3
- data/schemas/{factur-x_1.0.0.7/Factur-X_1.0.07_EN16931_codedb.xml → factur-x_1/Factur-X_1.07.2_EN16931_codedb.xml} +35 -3
- data/schemas/{factur-x_1.0.0.7/Factur-X_1.0.07_EN16931_urn_un_unece_uncefact_data_standard_RABIE_100.xsd → factur-x_1/Factur-X_1.07.2_EN16931_urn_un_unece_uncefact_data_standard_RABIE_100.xsd} +2 -2
- metadata +38 -11
- /data/schemas/{factur-x_1.0.0.7/Factur-X_1.0.07_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd → factur-x_1/Factur-X_1.07.2_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd} +0 -0
- /data/schemas/{factur-x_1.0.0.7/Factur-X_1.0.07_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd → factur-x_1/Factur-X_1.07.2_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4aede1e2eafc1189446e824cb5977b9c3844f71fa4c505214aa4d9b9f79e1101
|
4
|
+
data.tar.gz: 533c4f81ae8b50977df60f6c2bc31565cbbfd93066c52d8cf1961215971319fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3358bd3eec524b4e76fc8f32945dca7cb665d683a256e69350fa31c340db2a75f77f3f64883978da387a52edd9beb4810ffe362d67341c81abe28579a979e1f
|
7
|
+
data.tar.gz: 5f347f7253bc8f814a0e1524c968506679d7bb1108c9a4cf03d9716830829ae393e5cde2df2b9d83210a237b075354863ef06af10df2e3d984a699a9c1d758c3
|
data/README.md
CHANGED
@@ -2,14 +2,18 @@
|
|
2
2
|
|
3
3
|
See tests for examples.
|
4
4
|
|
5
|
-
|
5
|
+
## Some words of caution
|
6
6
|
|
7
7
|
1. This is an opinionated library optimised for my very specific usecase
|
8
8
|
2. While I did start to add some validations to make sure you can't input absolute garbage into this, I cannot guarantee factual (as in taxation law) correctness of the resulting XML.
|
9
9
|
1. The library, for ZUGFeRD 2.x, currently only supports the EN16931 variant. This is probably what you want as well. PRs welcome.
|
10
10
|
3. This does not contain any code to attach the XML to a PDF file, mainly because I have yet to find a ruby library to do that. For software that does this, take a look at [this python library](https://github.com/akretion/factur-x).
|
11
11
|
|
12
|
-
|
12
|
+
## Contributors
|
13
|
+
|
14
|
+
See [CONTRIBUTORS.md](CONTRIBUTORS.md).
|
15
|
+
|
16
|
+
## LICENSE
|
13
17
|
|
14
18
|
See [LICENSE](LICENSE).
|
15
19
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright Jan Krutisch
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
|
16
|
+
=end
|
17
|
+
|
18
|
+
|
19
|
+
require 'mime/types'
|
20
|
+
|
21
|
+
module Secretariat
|
22
|
+
Attachment = Struct.new('Attachment',
|
23
|
+
:filename,
|
24
|
+
:type_code,
|
25
|
+
:base64,
|
26
|
+
|
27
|
+
keyword_init: true
|
28
|
+
) do
|
29
|
+
include Versioner
|
30
|
+
|
31
|
+
def errors
|
32
|
+
@errors
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid?
|
36
|
+
@errors = []
|
37
|
+
|
38
|
+
@errors << "the attribute filename needs to be present" if filename.nil? || filename == ''
|
39
|
+
@errors << "the attribute type_code needs to be present" if type_code.nil? || type_code == ''
|
40
|
+
@errors << "the attribute base64 needs to be present" if base64.nil? || base64 == ''
|
41
|
+
|
42
|
+
if type_code.to_i != 916
|
43
|
+
@errors << "we only support type_code 916"
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
if mime_code.nil?
|
48
|
+
@errors << "cannot determine content type for filename: #{filename}"
|
49
|
+
return false
|
50
|
+
end
|
51
|
+
|
52
|
+
if !ALLOWED_MIME_TYPES.include?(mime_code)
|
53
|
+
@errors << "the mime_code '#{mime_code}' is not allowed"
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
return true
|
58
|
+
end
|
59
|
+
|
60
|
+
def mime_code
|
61
|
+
type_for = MIME::Types.type_for(filename).first
|
62
|
+
return if type_for.nil?
|
63
|
+
|
64
|
+
type_for.content_type
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_xml(xml, attachment_index, version: 2, validate: true)
|
68
|
+
if validate && !valid?
|
69
|
+
pp errors
|
70
|
+
raise ValidationError.new("Attachment #{attachment_index} is invalid", errors)
|
71
|
+
end
|
72
|
+
|
73
|
+
xml['ram'].AdditionalReferencedDocument do
|
74
|
+
xml['ram'].IssuerAssignedID filename
|
75
|
+
xml['ram'].TypeCode type_code
|
76
|
+
xml['ram'].Name filename
|
77
|
+
xml['ram'].AttachmentBinaryObject(mimeCode: mime_code, filename: filename) do
|
78
|
+
xml.text(base64)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright Jan Krutisch
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
3
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
you may not use this file except in compliance with the License.
|
@@ -15,6 +15,14 @@ limitations under the License.
|
|
15
15
|
=end
|
16
16
|
|
17
17
|
module Secretariat
|
18
|
+
ALLOWED_MIME_TYPES = [
|
19
|
+
"application/pdf",
|
20
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
21
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
22
|
+
"image/jpeg",
|
23
|
+
"image/png",
|
24
|
+
"text/csv"
|
25
|
+
]
|
18
26
|
|
19
27
|
TAX_CATEGORY_CODES = {
|
20
28
|
:STANDARDRATE => "S",
|
@@ -45,15 +53,21 @@ module Secretariat
|
|
45
53
|
:DEBITADVICE => "31",
|
46
54
|
:CREDITCARD => "48",
|
47
55
|
:DEBIT => "49",
|
48
|
-
:COMPENSATION => "97"
|
56
|
+
:COMPENSATION => "97"
|
49
57
|
}
|
50
58
|
|
51
59
|
TAX_EXEMPTION_REASONS = {
|
52
60
|
:REVERSECHARGE => 'Reverse Charge',
|
53
61
|
:INTRACOMMUNITY => 'Intra-community transaction',
|
54
|
-
:EXPORT => 'Export outside the EU'
|
62
|
+
:EXPORT => 'Export outside the EU',
|
63
|
+
:TAXEXEMPT => 'VAT exempt',
|
64
|
+
:UNTAXEDSERVICE => 'Not subject to VAT'
|
55
65
|
}
|
56
66
|
|
67
|
+
# For the background of vertical and horizontal tax calculation see https://hilfe.pacemo.de/de-form/articles/3489851-rundungsfehler-bei-rechnungen
|
68
|
+
# The idea of introducing an unknown value is that this could be inferred from the given invoice total and line items by probing both variants and selecting the matching one - or reporting a taxation error if neither matches.
|
69
|
+
TAX_CALCULATION_METHODS = %i[HORIZONTAL VERTICAL UNKNOWN].freeze
|
70
|
+
|
57
71
|
UNIT_CODES = {
|
58
72
|
:PIECE => "C62",
|
59
73
|
:DAY => "DAY",
|
data/lib/secretariat/helpers.rb
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
1
16
|
module Secretariat
|
2
17
|
module Helpers
|
3
18
|
def self.format(something, round: nil, digits:2)
|
data/lib/secretariat/invoice.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright Jan Krutisch
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
3
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
you may not use this file except in compliance with the License.
|
@@ -28,6 +28,7 @@ module Secretariat
|
|
28
28
|
:line_items,
|
29
29
|
:currency_code,
|
30
30
|
:payment_type,
|
31
|
+
:payment_reference,
|
31
32
|
:payment_text,
|
32
33
|
:payment_terms_text,
|
33
34
|
:payment_due_date,
|
@@ -40,7 +41,8 @@ module Secretariat
|
|
40
41
|
:grand_total_amount,
|
41
42
|
:due_amount,
|
42
43
|
:paid_amount,
|
43
|
-
|
44
|
+
:tax_calculation_method,
|
45
|
+
:attachments,
|
44
46
|
keyword_init: true
|
45
47
|
) do
|
46
48
|
|
@@ -54,11 +56,28 @@ module Secretariat
|
|
54
56
|
tax_reason || TAX_EXEMPTION_REASONS[tax_category]
|
55
57
|
end
|
56
58
|
|
57
|
-
def tax_category_code(version: 2)
|
59
|
+
def tax_category_code(tax, version: 2)
|
58
60
|
if version == 1
|
59
|
-
return TAX_CATEGORY_CODES_1[tax_category] || 'S'
|
61
|
+
return TAX_CATEGORY_CODES_1[tax.tax_category || tax_category] || 'S'
|
62
|
+
end
|
63
|
+
TAX_CATEGORY_CODES[tax.tax_category || tax_category] || 'S'
|
64
|
+
end
|
65
|
+
|
66
|
+
def taxes
|
67
|
+
taxes = {}
|
68
|
+
line_items.each do |line_item|
|
69
|
+
taxes[line_item.tax_percent] = Tax.new(tax_percent: BigDecimal(line_item.tax_percent), tax_category: line_item.tax_category) if taxes[line_item.tax_percent].nil?
|
70
|
+
taxes[line_item.tax_percent].tax_amount += BigDecimal(line_item.tax_amount)
|
71
|
+
taxes[line_item.tax_percent].base_amount += BigDecimal(line_item.net_amount) * line_item.quantity
|
72
|
+
end
|
73
|
+
if tax_calculation_method == :VERTICAL
|
74
|
+
taxes.values.map do |tax|
|
75
|
+
tax.tax_amount = (tax.base_amount * tax.tax_percent / 100).round(2)
|
76
|
+
tax
|
77
|
+
end
|
78
|
+
else
|
79
|
+
taxes.values
|
60
80
|
end
|
61
|
-
TAX_CATEGORY_CODES[tax_category] || 'S'
|
62
81
|
end
|
63
82
|
|
64
83
|
def payment_code
|
@@ -69,12 +88,24 @@ module Secretariat
|
|
69
88
|
@errors = []
|
70
89
|
tax = BigDecimal(tax_amount)
|
71
90
|
basis = BigDecimal(basis_amount)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
91
|
+
summed_tax_amount = taxes.sum(&:tax_amount)
|
92
|
+
if tax != summed_tax_amount
|
93
|
+
@errors << "Tax amount and summed tax amounts deviate: #{tax_amount} / #{summed_tax_amount}"
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
summed_tax_base_amount = taxes.sum(&:base_amount)
|
97
|
+
if basis != summed_tax_base_amount
|
98
|
+
@errors << "Base amount and summed tax base amount deviate: #{basis} / #{summed_tax_base_amount}"
|
76
99
|
return false
|
77
100
|
end
|
101
|
+
taxes.each do |tax|
|
102
|
+
calc_tax = tax.base_amount * BigDecimal(tax.tax_percent) / BigDecimal(100)
|
103
|
+
calc_tax = calc_tax.round(2)
|
104
|
+
if tax.tax_amount != calc_tax
|
105
|
+
@errors << "Tax amount and calculated tax amount deviate for rate #{tax.tax_percent}: #{tax.tax_amount} / #{calc_tax}"
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
end
|
78
109
|
grand_total = BigDecimal(grand_total_amount)
|
79
110
|
calc_grand_total = basis + tax
|
80
111
|
if grand_total != calc_grand_total
|
@@ -82,7 +113,7 @@ module Secretariat
|
|
82
113
|
return false
|
83
114
|
end
|
84
115
|
line_item_sum = line_items.inject(BigDecimal(0)) do |m, item|
|
85
|
-
m + BigDecimal(item.charge_amount)
|
116
|
+
m + BigDecimal(item.quantity.negative? ? -item.charge_amount : item.charge_amount)
|
86
117
|
end
|
87
118
|
if line_item_sum != basis
|
88
119
|
@errors << "Line items do not add up to basis amount #{line_item_sum} / #{basis}"
|
@@ -147,7 +178,7 @@ module Secretariat
|
|
147
178
|
xml.text(issue_date.strftime("%Y%m%d"))
|
148
179
|
end
|
149
180
|
end
|
150
|
-
|
181
|
+
|
151
182
|
end
|
152
183
|
transaction = by_version(version, 'SpecifiedSupplyChainTradeTransaction', 'SupplyChainTradeTransaction')
|
153
184
|
xml['rsm'].send(transaction) do
|
@@ -170,6 +201,13 @@ module Secretariat
|
|
170
201
|
xml['ram'].BuyerTradeParty do
|
171
202
|
buyer.to_xml(xml, version: version)
|
172
203
|
end
|
204
|
+
if version == 2
|
205
|
+
if Array(attachments).size > 0
|
206
|
+
attachments.each_with_index do |attachment, index|
|
207
|
+
attachment.to_xml(xml, index, version: version, validate: validate)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
173
211
|
end
|
174
212
|
|
175
213
|
delivery = by_version(version, 'ApplicableSupplyChainTradeDelivery', 'ApplicableHeaderTradeDelivery')
|
@@ -190,6 +228,9 @@ module Secretariat
|
|
190
228
|
end
|
191
229
|
trade_settlement = by_version(version, 'ApplicableSupplyChainTradeSettlement', 'ApplicableHeaderTradeSettlement')
|
192
230
|
xml['ram'].send(trade_settlement) do
|
231
|
+
if payment_reference && payment_reference != ''
|
232
|
+
xml['ram'].PaymentReference payment_reference
|
233
|
+
end
|
193
234
|
xml['ram'].InvoiceCurrencyCode currency_code
|
194
235
|
xml['ram'].SpecifiedTradeSettlementPaymentMeans do
|
195
236
|
xml['ram'].TypeCode payment_code
|
@@ -200,18 +241,19 @@ module Secretariat
|
|
200
241
|
end
|
201
242
|
end
|
202
243
|
end
|
203
|
-
|
244
|
+
taxes.each do |tax|
|
245
|
+
xml['ram'].ApplicableTradeTax do
|
246
|
+
Helpers.currency_element(xml, 'ram', 'CalculatedAmount', tax.tax_amount, currency_code, add_currency: version == 1)
|
247
|
+
xml['ram'].TypeCode 'VAT'
|
248
|
+
if tax_reason_text && tax_reason_text != ''
|
249
|
+
xml['ram'].ExemptionReason tax_reason_text
|
250
|
+
end
|
251
|
+
Helpers.currency_element(xml, 'ram', 'BasisAmount', tax.base_amount, currency_code, add_currency: version == 1)
|
252
|
+
xml['ram'].CategoryCode tax_category_code(tax, version: version)
|
204
253
|
|
205
|
-
|
206
|
-
|
207
|
-
if tax_reason_text && tax_reason_text != ''
|
208
|
-
xml['ram'].ExemptionReason tax_reason_text
|
254
|
+
percent = by_version(version, 'ApplicablePercent', 'RateApplicablePercent')
|
255
|
+
xml['ram'].send(percent, Helpers.format(tax.tax_percent))
|
209
256
|
end
|
210
|
-
Helpers.currency_element(xml, 'ram', 'BasisAmount', basis_amount, currency_code, add_currency: version == 1)
|
211
|
-
xml['ram'].CategoryCode tax_category_code(version: version)
|
212
|
-
|
213
|
-
percent = by_version(version, 'ApplicablePercent', 'RateApplicablePercent')
|
214
|
-
xml['ram'].send(percent, Helpers.format(tax_percent))
|
215
257
|
end
|
216
258
|
if version == 2 && service_period_start && service_period_end
|
217
259
|
xml['ram'].BillingSpecifiedPeriod do
|
@@ -248,7 +290,7 @@ module Secretariat
|
|
248
290
|
end
|
249
291
|
if version == 1
|
250
292
|
line_items.each_with_index do |item, i|
|
251
|
-
item.to_xml(xml, i + 1, version: version) # one indexed
|
293
|
+
item.to_xml(xml, i + 1, version: version, validate: validate) # one indexed
|
252
294
|
end
|
253
295
|
end
|
254
296
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright Jan Krutisch
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
3
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
you may not use this file except in compliance with the License.
|
@@ -12,7 +12,6 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
13
|
See the License for the specific language governing permissions and
|
14
14
|
limitations under the License.
|
15
|
-
|
16
15
|
=end
|
17
16
|
|
18
17
|
|
@@ -50,7 +49,7 @@ module Secretariat
|
|
50
49
|
gross_price = BigDecimal(gross_amount)
|
51
50
|
charge_price = BigDecimal(charge_amount)
|
52
51
|
tax = BigDecimal(tax_amount)
|
53
|
-
unit_price = net_price * BigDecimal(quantity)
|
52
|
+
unit_price = net_price * BigDecimal(quantity.abs)
|
54
53
|
|
55
54
|
if charge_price != unit_price
|
56
55
|
@errors << "charge price and gross price times quantity deviate: #{charge_price} / #{unit_price}"
|
@@ -66,6 +65,8 @@ module Secretariat
|
|
66
65
|
end
|
67
66
|
|
68
67
|
calculated_tax = charge_price * BigDecimal(tax_percent) / BigDecimal(100)
|
68
|
+
calculated_tax = calculated_tax.round(2)
|
69
|
+
calculated_tax = -calculated_tax if quantity.negative?
|
69
70
|
if calculated_tax != tax
|
70
71
|
@errors << "Tax and calculated tax deviate: #{tax} / #{calculated_tax}"
|
71
72
|
return false
|
@@ -85,8 +86,24 @@ module Secretariat
|
|
85
86
|
end
|
86
87
|
|
87
88
|
def to_xml(xml, line_item_index, version: 2, validate: true)
|
89
|
+
net_price = net_amount && BigDecimal(net_amount)
|
90
|
+
gross_price = gross_amount && BigDecimal(gross_amount)
|
91
|
+
charge_price = charge_amount && BigDecimal(charge_amount)
|
92
|
+
|
93
|
+
if net_price&.zero?
|
94
|
+
self.tax_percent = 0
|
95
|
+
end
|
96
|
+
|
97
|
+
if net_price&.negative?
|
98
|
+
# Zugferd doesn't allow negative amounts at the item level.
|
99
|
+
# Instead, a negative quantity is used.
|
100
|
+
self.quantity = -quantity
|
101
|
+
self.gross_amount = gross_price&.abs
|
102
|
+
self.net_amount = net_price&.abs
|
103
|
+
self.charge_amount = charge_price&.abs
|
104
|
+
end
|
105
|
+
|
88
106
|
if validate && !valid?
|
89
|
-
pp errors
|
90
107
|
raise ValidationError.new("LineItem #{line_item_index} is invalid", errors)
|
91
108
|
end
|
92
109
|
|
@@ -160,7 +177,7 @@ module Secretariat
|
|
160
177
|
end
|
161
178
|
monetary_summation = by_version(version, 'SpecifiedTradeSettlementMonetarySummation', 'SpecifiedTradeSettlementLineMonetarySummation')
|
162
179
|
xml['ram'].send(monetary_summation) do
|
163
|
-
Helpers.currency_element(xml, 'ram', 'LineTotalAmount', charge_amount, currency_code, add_currency: version == 1)
|
180
|
+
Helpers.currency_element(xml, 'ram', 'LineTotalAmount', (quantity.negative? ? -charge_amount : charge_amount), currency_code, add_currency: version == 1)
|
164
181
|
end
|
165
182
|
end
|
166
183
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
require 'bigdecimal'
|
18
|
+
|
19
|
+
module Secretariat
|
20
|
+
Tax = Struct.new('Tax',
|
21
|
+
:tax_percent,
|
22
|
+
:tax_amount,
|
23
|
+
:tax_category,
|
24
|
+
:base_amount,
|
25
|
+
keyword_init: true
|
26
|
+
) do
|
27
|
+
|
28
|
+
def initialize(*)
|
29
|
+
super
|
30
|
+
self.tax_amount = 0
|
31
|
+
self.base_amount = 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright Jan Krutisch
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
3
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
you may not use this file except in compliance with the License.
|
@@ -25,17 +25,17 @@ module Secretariat
|
|
25
25
|
class Validator
|
26
26
|
SCHEMATRON = [
|
27
27
|
'../../schemas/zugferd_1/ZUGFeRD1p0.sch',
|
28
|
-
'../../schemas/factur-x_1
|
28
|
+
'../../schemas/factur-x_1/Factur-X_1.07.2_EN16931.sch'
|
29
29
|
]
|
30
30
|
|
31
31
|
SCHEMA = [
|
32
32
|
'../../schemas/zugferd_1/ZUGFeRD1p0.xsd',
|
33
|
-
'../../schemas/factur-x_1
|
33
|
+
'../../schemas/factur-x_1/Factur-X_1.07.2_EN16931.xsd'
|
34
34
|
]
|
35
35
|
|
36
36
|
SCHEMA_DIR = [
|
37
37
|
'../../schemas/zugferd_1',
|
38
|
-
'../../schemas/factur-x_1
|
38
|
+
'../../schemas/factur-x_1/'
|
39
39
|
]
|
40
40
|
|
41
41
|
attr_accessor :doc, :version
|
data/lib/secretariat/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright Jan Krutisch
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
3
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
you may not use this file except in compliance with the License.
|
@@ -15,5 +15,5 @@ limitations under the License.
|
|
15
15
|
=end
|
16
16
|
|
17
17
|
module Secretariat
|
18
|
-
VERSION = '3.
|
18
|
+
VERSION = '3.3.0'
|
19
19
|
end
|
@@ -1,3 +1,18 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
1
16
|
module Secretariat
|
2
17
|
module Versioner
|
3
18
|
def by_version(version, v1, v2)
|
data/lib/secretariat.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright Jan Krutisch
|
2
|
+
Copyright Jan Krutisch and contributors (see CONTRIBUTORS.md)
|
3
3
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
you may not use this file except in compliance with the License.
|
@@ -23,3 +23,5 @@ require_relative 'secretariat/invoice'
|
|
23
23
|
require_relative 'secretariat/trade_party'
|
24
24
|
require_relative 'secretariat/line_item'
|
25
25
|
require_relative 'secretariat/validator'
|
26
|
+
require_relative 'secretariat/tax'
|
27
|
+
require_relative 'secretariat/attachment'
|