en16931 0.1.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 +7 -0
- data/CHANGELOG.md +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +144 -0
- data/Rakefile +42 -0
- data/fonts/DejaVuSans-Bold.ttf +0 -0
- data/fonts/DejaVuSans.ttf +0 -0
- data/fonts/LICENSE-DejaVu.txt +187 -0
- data/icc/LICENSE-Compact-ICC-Profiles.txt +537 -0
- data/icc/sRGB-v2-micro.icc +0 -0
- data/lib/en16931/branding.rb +75 -0
- data/lib/en16931/de.rb +46 -0
- data/lib/en16931/invoice.rb +60 -0
- data/lib/en16931/line.rb +27 -0
- data/lib/en16931/party.rb +27 -0
- data/lib/en16931/payment.rb +12 -0
- data/lib/en16931/pdf/a3.rb +92 -0
- data/lib/en16931/pdf/giro_code.rb +74 -0
- data/lib/en16931/pdf/renderer.rb +266 -0
- data/lib/en16931/pdf/xmp.rb +85 -0
- data/lib/en16931/pdf.rb +27 -0
- data/lib/en16931/tax.rb +35 -0
- data/lib/en16931/totals.rb +38 -0
- data/lib/en16931/validation/kosit.rb +100 -0
- data/lib/en16931/validation/report.rb +20 -0
- data/lib/en16931/validation/vera_pdf.rb +66 -0
- data/lib/en16931/validation.rb +13 -0
- data/lib/en16931/version.rb +5 -0
- data/lib/en16931/xml.rb +219 -0
- data/lib/en16931.rb +37 -0
- metadata +148 -0
data/lib/en16931/xml.rb
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "nokogiri"
|
|
4
|
+
|
|
5
|
+
module EN16931
|
|
6
|
+
# The invoice as UN/CEFACT CII XML, by default in the XRechnung profile
|
|
7
|
+
# (the German CIUS of EN 16931, which every German business must be able
|
|
8
|
+
# to receive and which a ZUGFeRD "XRECHNUNG" hybrid carries unchanged).
|
|
9
|
+
#
|
|
10
|
+
# The element tree comes from zugpferd; the few things its writer does not
|
|
11
|
+
# cover yet (tax number with scheme FC, BIC and account name, the invoicing
|
|
12
|
+
# period, the preceding invoice of a correction) are added here.
|
|
13
|
+
module XML
|
|
14
|
+
NS = {
|
|
15
|
+
"rsm" => "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100",
|
|
16
|
+
"ram" => "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100",
|
|
17
|
+
"udt" => "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
module_function
|
|
21
|
+
|
|
22
|
+
# @param profile [:xrechnung, :en16931] the guideline the XML claims (BT-24)
|
|
23
|
+
# @return [String] UTF-8 XML
|
|
24
|
+
def cii(invoice, profile: :xrechnung)
|
|
25
|
+
document = to_zugpferd(invoice, profile:)
|
|
26
|
+
xml = Zugpferd::CII::Writer.new.write(document)
|
|
27
|
+
Extensions.apply(xml, invoice)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def guideline(profile)
|
|
31
|
+
case profile
|
|
32
|
+
when :xrechnung then XRECHNUNG_GUIDELINE
|
|
33
|
+
when :en16931 then EN16931_GUIDELINE
|
|
34
|
+
else raise ArgumentError, "unknown profile #{profile.inspect}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Maps the invoice onto zugpferd's EN 16931 model.
|
|
39
|
+
def to_zugpferd(invoice, profile: :xrechnung)
|
|
40
|
+
totals = invoice.totals
|
|
41
|
+
klass = { "380" => Zugpferd::Model::Invoice, "381" => Zugpferd::Model::CreditNote,
|
|
42
|
+
"384" => Zugpferd::Model::CorrectedInvoice, "389" => Zugpferd::Model::SelfBilledInvoice,
|
|
43
|
+
"326" => Zugpferd::Model::PartialInvoice, "386" => Zugpferd::Model::PrepaymentInvoice }.fetch(invoice.type_code)
|
|
44
|
+
doc = klass.new(number: invoice.number, issue_date: invoice.issue_date, currency_code: invoice.currency)
|
|
45
|
+
doc.customization_id = guideline(profile)
|
|
46
|
+
doc.profile_id = PEPPOL_BILLING_PROCESS
|
|
47
|
+
doc.due_date = invoice.due_date
|
|
48
|
+
doc.delivery_date = invoice.delivery_date
|
|
49
|
+
doc.buyer_reference = invoice.buyer_reference
|
|
50
|
+
doc.note = invoice.notes.join("\n") unless invoice.notes.empty?
|
|
51
|
+
hide_vat_ids = invoice.taxes.any?(&:forbids_vat_identifiers?)
|
|
52
|
+
doc.seller = party(invoice.seller, vat_identifier: !hide_vat_ids, seller: true)
|
|
53
|
+
doc.buyer = party(invoice.buyer, vat_identifier: !hide_vat_ids)
|
|
54
|
+
doc.line_items = invoice.lines.each_with_index.map { |line, i| line_item(invoice, line, i + 1) }
|
|
55
|
+
doc.allowance_charges = (invoice.allowances + invoice.charges).map { |ac| allowance_charge(invoice, ac) }
|
|
56
|
+
doc.tax_breakdown = tax_breakdown(invoice, totals)
|
|
57
|
+
doc.monetary_totals = Zugpferd::Model::MonetaryTotals.new(
|
|
58
|
+
line_extension_amount: totals.line_total, tax_exclusive_amount: totals.net,
|
|
59
|
+
tax_inclusive_amount: totals.gross, payable_amount: totals.payable,
|
|
60
|
+
allowance_total_amount: (totals.allowance_total if totals.allowance_total.positive?),
|
|
61
|
+
charge_total_amount: (totals.charge_total if totals.charge_total.positive?),
|
|
62
|
+
prepaid_amount: (totals.prepaid if totals.prepaid.positive?)
|
|
63
|
+
)
|
|
64
|
+
doc.payment_instructions = payment_instructions(invoice)
|
|
65
|
+
doc
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# A seller without a VAT id on the invoice (Kleinunternehmer, category O)
|
|
69
|
+
# still has to be identifiable (BR-CO-26): the tax number serves as the
|
|
70
|
+
# seller identifier (BT-29) unless the party carries its own.
|
|
71
|
+
def party(party, vat_identifier: true, seller: false)
|
|
72
|
+
vat_id = (party.vat_id if vat_identifier)
|
|
73
|
+
identifier = party.identifier || (party.tax_number if seller && vat_id.nil?)
|
|
74
|
+
Zugpferd::Model::TradeParty.new(
|
|
75
|
+
name: party.name,
|
|
76
|
+
identifier: identifier,
|
|
77
|
+
legal_registration_id: party.registration_id,
|
|
78
|
+
trading_name: party.trading_name,
|
|
79
|
+
legal_form: party.legal_form,
|
|
80
|
+
vat_identifier: vat_id,
|
|
81
|
+
electronic_address: party.electronic_address_value,
|
|
82
|
+
electronic_address_scheme: party.electronic_address_scheme_value,
|
|
83
|
+
postal_address: Zugpferd::Model::PostalAddress.new(
|
|
84
|
+
country_code: party.country, street_name: party.street, city_name: party.city, postal_zone: party.postal_code
|
|
85
|
+
),
|
|
86
|
+
contact: contact(party)
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def contact(party)
|
|
91
|
+
return nil if party.contact_name.nil? && party.phone.nil? && party.email.nil?
|
|
92
|
+
|
|
93
|
+
Zugpferd::Model::Contact.new(name: party.contact_name || party.name, telephone: party.phone, email: party.email)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def line_item(invoice, line, position)
|
|
97
|
+
tax = invoice.tax_for(line)
|
|
98
|
+
Zugpferd::Model::LineItem.new(
|
|
99
|
+
id: position.to_s, invoiced_quantity: line.quantity, unit_code: line.unit, line_extension_amount: line.net,
|
|
100
|
+
note: line.note,
|
|
101
|
+
item: Zugpferd::Model::Item.new(name: line.description, sellers_identifier: line.sellers_id,
|
|
102
|
+
tax_category: tax.category, tax_percent: tax.rate_for_xml),
|
|
103
|
+
price: Zugpferd::Model::Price.new(amount: line.unit_price)
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def allowance_charge(invoice, ac)
|
|
108
|
+
tax = ac.tax || invoice.tax
|
|
109
|
+
Zugpferd::Model::AllowanceCharge.new(
|
|
110
|
+
charge_indicator: ac.charge?, amount: ac.amount, reason: ac.reason, reason_code: ac.reason_code,
|
|
111
|
+
tax_category_code: tax.category, tax_percent: tax.rate_for_xml, currency_code: invoice.currency
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def tax_breakdown(invoice, totals)
|
|
116
|
+
breakdown = Zugpferd::Model::TaxBreakdown.new(tax_amount: totals.vat, currency_code: invoice.currency)
|
|
117
|
+
breakdown.subtotals = totals.subtotals.map do |sub|
|
|
118
|
+
Zugpferd::Model::TaxSubtotal.new(
|
|
119
|
+
taxable_amount: sub.taxable, tax_amount: sub.amount, category_code: sub.tax.category,
|
|
120
|
+
percent: sub.tax.rate, currency_code: invoice.currency, # BT-119 always (BR-DE-14), also for O
|
|
121
|
+
exemption_reason: sub.tax.exemption_reason, exemption_reason_code: sub.tax.exemption_code
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
breakdown
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def payment_instructions(invoice)
|
|
128
|
+
payment = invoice.payment
|
|
129
|
+
return nil if payment.nil?
|
|
130
|
+
|
|
131
|
+
Zugpferd::Model::PaymentInstructions.new(
|
|
132
|
+
payment_means_code: payment.means_code, account_id: payment.iban, payment_id: payment.reference, note: payment.terms
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Elements zugpferd's writer leaves out, inserted at their schema position.
|
|
137
|
+
module Extensions
|
|
138
|
+
module_function
|
|
139
|
+
|
|
140
|
+
def apply(xml, invoice)
|
|
141
|
+
doc = Nokogiri::XML(xml, &:noblanks)
|
|
142
|
+
add_seller_tax_number(doc, invoice)
|
|
143
|
+
add_bank_details(doc, invoice)
|
|
144
|
+
add_billing_period(doc, invoice)
|
|
145
|
+
add_preceding_invoice(doc, invoice)
|
|
146
|
+
doc.to_xml(indent: 2, encoding: "UTF-8")
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# BT-32 seller tax registration (scheme FC). XRechnung wants a VAT id
|
|
150
|
+
# or a tax number; category O forbids the VAT id, so the number is the
|
|
151
|
+
# only way to identify a Kleinunternehmer or a seller invoicing abroad.
|
|
152
|
+
def add_seller_tax_number(doc, invoice)
|
|
153
|
+
number = invoice.seller.tax_number
|
|
154
|
+
return if number.nil?
|
|
155
|
+
|
|
156
|
+
seller = doc.at_xpath("//ram:SellerTradeParty", NS)
|
|
157
|
+
reg = Nokogiri::XML::Node.new("ram:SpecifiedTaxRegistration", doc)
|
|
158
|
+
id = Nokogiri::XML::Node.new("ram:ID", doc)
|
|
159
|
+
id["schemeID"] = "FC"
|
|
160
|
+
id.content = number
|
|
161
|
+
reg.add_child(id)
|
|
162
|
+
seller.add_child(reg)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# BT-85 account name, BT-86 BIC: after the IBAN.
|
|
166
|
+
def add_bank_details(doc, invoice)
|
|
167
|
+
payment = invoice.payment
|
|
168
|
+
return if payment.nil? || payment.iban.nil?
|
|
169
|
+
|
|
170
|
+
account = doc.at_xpath("//ram:PayeePartyCreditorFinancialAccount", NS)
|
|
171
|
+
if payment.holder
|
|
172
|
+
name = Nokogiri::XML::Node.new("ram:AccountName", doc)
|
|
173
|
+
name.content = payment.holder
|
|
174
|
+
account.add_child(name)
|
|
175
|
+
end
|
|
176
|
+
return if payment.bic.nil?
|
|
177
|
+
|
|
178
|
+
inst = Nokogiri::XML::Node.new("ram:PayeeSpecifiedCreditorFinancialInstitution", doc)
|
|
179
|
+
bic = Nokogiri::XML::Node.new("ram:BICID", doc)
|
|
180
|
+
bic.content = payment.bic
|
|
181
|
+
inst.add_child(bic)
|
|
182
|
+
account.add_next_sibling(inst)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# BG-14 invoicing period: after the last ApplicableTradeTax.
|
|
186
|
+
def add_billing_period(doc, invoice)
|
|
187
|
+
period = invoice.period
|
|
188
|
+
return if period.nil?
|
|
189
|
+
|
|
190
|
+
node = Nokogiri::XML::Node.new("ram:BillingSpecifiedPeriod", doc)
|
|
191
|
+
node.add_child(date_time(doc, "ram:StartDateTime", period.begin))
|
|
192
|
+
node.add_child(date_time(doc, "ram:EndDateTime", period.end))
|
|
193
|
+
doc.xpath("//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax", NS).last.add_next_sibling(node)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# BG-3 preceding invoice reference: after the monetary summation.
|
|
197
|
+
def add_preceding_invoice(doc, invoice)
|
|
198
|
+
preceding = invoice.preceding
|
|
199
|
+
return if preceding.nil?
|
|
200
|
+
|
|
201
|
+
node = Nokogiri::XML::Node.new("ram:InvoiceReferencedDocument", doc)
|
|
202
|
+
id = Nokogiri::XML::Node.new("ram:IssuerAssignedID", doc)
|
|
203
|
+
id.content = preceding.fetch(:number)
|
|
204
|
+
node.add_child(id)
|
|
205
|
+
node.add_child(date_time(doc, "ram:FormattedIssueDateTime", preceding[:issue_date], qualified: true)) if preceding[:issue_date]
|
|
206
|
+
doc.at_xpath("//ram:SpecifiedTradeSettlementHeaderMonetarySummation", NS).add_next_sibling(node)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def date_time(doc, name, date, qualified: false)
|
|
210
|
+
wrapper = Nokogiri::XML::Node.new(name, doc)
|
|
211
|
+
inner = Nokogiri::XML::Node.new(qualified ? "qdt:DateTimeString" : "udt:DateTimeString", doc)
|
|
212
|
+
inner["format"] = "102"
|
|
213
|
+
inner.content = date.strftime("%Y%m%d")
|
|
214
|
+
wrapper.add_child(inner)
|
|
215
|
+
wrapper
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
data/lib/en16931.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bigdecimal"
|
|
4
|
+
require "bigdecimal/util"
|
|
5
|
+
require "date"
|
|
6
|
+
require "zugpferd"
|
|
7
|
+
|
|
8
|
+
# EN 16931 e-invoices for Ruby: a small invoice model, CII XML in the
|
|
9
|
+
# XRechnung profile (through zugpferd), a PDF/A-3 hybrid with the XML
|
|
10
|
+
# embedded (through Prawn, pure Ruby), German tax presets, and wrappers for
|
|
11
|
+
# the official validators (KoSIT, veraPDF).
|
|
12
|
+
module EN16931
|
|
13
|
+
class Error < StandardError; end
|
|
14
|
+
class ValidationError < Error; end
|
|
15
|
+
|
|
16
|
+
# Guideline identifiers (BT-24) and business process (BT-23).
|
|
17
|
+
XRECHNUNG_GUIDELINE = "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0"
|
|
18
|
+
EN16931_GUIDELINE = "urn:cen.eu:en16931:2017"
|
|
19
|
+
PEPPOL_BILLING_PROCESS = "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
|
|
20
|
+
|
|
21
|
+
ROOT = File.expand_path("..", __dir__)
|
|
22
|
+
|
|
23
|
+
def self.font_path(name) = File.join(ROOT, "fonts", name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
require_relative "en16931/version"
|
|
27
|
+
require_relative "en16931/tax"
|
|
28
|
+
require_relative "en16931/de"
|
|
29
|
+
require_relative "en16931/party"
|
|
30
|
+
require_relative "en16931/line"
|
|
31
|
+
require_relative "en16931/payment"
|
|
32
|
+
require_relative "en16931/invoice"
|
|
33
|
+
require_relative "en16931/totals"
|
|
34
|
+
require_relative "en16931/branding"
|
|
35
|
+
require_relative "en16931/xml"
|
|
36
|
+
require_relative "en16931/pdf"
|
|
37
|
+
require_relative "en16931/validation"
|
metadata
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: en16931
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Markus Schwed
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: nokogiri
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.16'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.16'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: prawn
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.5'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.5'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: prawn-table
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.2'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.2'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rqrcode_core
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '2.0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '2.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: zugpferd
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0.3'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0.3'
|
|
82
|
+
description: Build EN 16931 invoices from a small Ruby model, write them as XRechnung
|
|
83
|
+
(CII) and as a ZUGFeRD/Factur-X hybrid PDF/A-3 with Prawn, with German VAT presets
|
|
84
|
+
(Regelbesteuerung, Kleinunternehmer, Reverse Charge, Drittland) and wrappers for
|
|
85
|
+
the official validators.
|
|
86
|
+
email:
|
|
87
|
+
- ma.schwed@googlemail.com
|
|
88
|
+
executables: []
|
|
89
|
+
extensions: []
|
|
90
|
+
extra_rdoc_files: []
|
|
91
|
+
files:
|
|
92
|
+
- CHANGELOG.md
|
|
93
|
+
- LICENSE.txt
|
|
94
|
+
- README.md
|
|
95
|
+
- Rakefile
|
|
96
|
+
- fonts/DejaVuSans-Bold.ttf
|
|
97
|
+
- fonts/DejaVuSans.ttf
|
|
98
|
+
- fonts/LICENSE-DejaVu.txt
|
|
99
|
+
- icc/LICENSE-Compact-ICC-Profiles.txt
|
|
100
|
+
- icc/sRGB-v2-micro.icc
|
|
101
|
+
- lib/en16931.rb
|
|
102
|
+
- lib/en16931/branding.rb
|
|
103
|
+
- lib/en16931/de.rb
|
|
104
|
+
- lib/en16931/invoice.rb
|
|
105
|
+
- lib/en16931/line.rb
|
|
106
|
+
- lib/en16931/party.rb
|
|
107
|
+
- lib/en16931/payment.rb
|
|
108
|
+
- lib/en16931/pdf.rb
|
|
109
|
+
- lib/en16931/pdf/a3.rb
|
|
110
|
+
- lib/en16931/pdf/giro_code.rb
|
|
111
|
+
- lib/en16931/pdf/renderer.rb
|
|
112
|
+
- lib/en16931/pdf/xmp.rb
|
|
113
|
+
- lib/en16931/tax.rb
|
|
114
|
+
- lib/en16931/totals.rb
|
|
115
|
+
- lib/en16931/validation.rb
|
|
116
|
+
- lib/en16931/validation/kosit.rb
|
|
117
|
+
- lib/en16931/validation/report.rb
|
|
118
|
+
- lib/en16931/validation/vera_pdf.rb
|
|
119
|
+
- lib/en16931/version.rb
|
|
120
|
+
- lib/en16931/xml.rb
|
|
121
|
+
homepage: https://github.com/Affliq/en16931
|
|
122
|
+
licenses:
|
|
123
|
+
- MIT
|
|
124
|
+
metadata:
|
|
125
|
+
homepage_uri: https://github.com/Affliq/en16931
|
|
126
|
+
source_code_uri: https://github.com/Affliq/en16931
|
|
127
|
+
changelog_uri: https://github.com/Affliq/en16931/blob/main/CHANGELOG.md
|
|
128
|
+
bug_tracker_uri: https://github.com/Affliq/en16931/issues
|
|
129
|
+
rubygems_mfa_required: 'true'
|
|
130
|
+
rdoc_options: []
|
|
131
|
+
require_paths:
|
|
132
|
+
- lib
|
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: 3.2.0
|
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
|
+
requirements:
|
|
140
|
+
- - ">="
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: '0'
|
|
143
|
+
requirements: []
|
|
144
|
+
rubygems_version: 3.6.9
|
|
145
|
+
specification_version: 4
|
|
146
|
+
summary: 'EN 16931 e-invoices for Ruby: XRechnung XML and ZUGFeRD hybrid PDF/A-3,
|
|
147
|
+
in pure Ruby.'
|
|
148
|
+
test_files: []
|