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.
Files changed (21) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/lib/secretariat/attachment.rb +83 -0
  4. data/lib/secretariat/constants.rb +17 -3
  5. data/lib/secretariat/helpers.rb +15 -0
  6. data/lib/secretariat/invoice.rb +64 -22
  7. data/lib/secretariat/line_item.rb +22 -5
  8. data/lib/secretariat/tax.rb +34 -0
  9. data/lib/secretariat/trade_party.rb +1 -1
  10. data/lib/secretariat/validation_error.rb +1 -1
  11. data/lib/secretariat/validator.rb +4 -4
  12. data/lib/secretariat/version.rb +2 -2
  13. data/lib/secretariat/versioner.rb +15 -0
  14. data/lib/secretariat.rb +3 -1
  15. 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
  16. 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
  17. 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
  18. 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
  19. metadata +38 -11
  20. /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
  21. /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: 78a5b530fb987800431c180f91436cd9d538ed364f478aa17ddee805e85fc2f3
4
- data.tar.gz: c4d569c8923b971e91eb5d1862f1e8484ddaf402cb62b6e405c4bee24ba2518f
3
+ metadata.gz: 4aede1e2eafc1189446e824cb5977b9c3844f71fa4c505214aa4d9b9f79e1101
4
+ data.tar.gz: 533c4f81ae8b50977df60f6c2bc31565cbbfd93066c52d8cf1961215971319fd
5
5
  SHA512:
6
- metadata.gz: 7dbdd370a0790c03b4f2fdbbefa16c3653e5554236e97b25eb7ff778ec1253a57e1323166ada9e8010fd5b47266ceee0bfc5e3c4e0f4d31a98f8ffd2d417f5d1
7
- data.tar.gz: 61c934e0e8994226b61ad2780695c610d86000265cb0e95478d994f3740143f5849c3662be0fe2e8754cc5ef02aff1176f2e7753a5036437cb087a39d833fb56
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
- # Some words of caution
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
- # LICENSE
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",
@@ -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)
@@ -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
- calc_tax = basis * BigDecimal(tax_percent) / BigDecimal(100)
73
- calc_tax = calc_tax.round(2, :down)
74
- if tax != calc_tax
75
- @errors << "Tax amount and calculated tax amount deviate: #{tax} / #{calc_tax}"
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
- xml['ram'].ApplicableTradeTax do
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
- Helpers.currency_element(xml, 'ram', 'CalculatedAmount', tax_amount, currency_code, add_currency: version == 1)
206
- xml['ram'].TypeCode 'VAT'
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.
@@ -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.
@@ -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.0.0.7/Factur-X_1.0.07_EN16931.sch'
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.0.0.7/Factur-X_1.0.07_EN16931.xsd'
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.0.0.7/'
38
+ '../../schemas/factur-x_1/'
39
39
  ]
40
40
 
41
41
  attr_accessor :doc, :version
@@ -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.1.0'
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'