zugpferd 0.5.0 → 0.5.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 +4 -4
- data/lib/zugpferd/cii/mapping.rb +2 -0
- data/lib/zugpferd/cii/reader.rb +23 -7
- data/lib/zugpferd/cii/writer.rb +7 -0
- data/lib/zugpferd/model/billing_document.rb +3 -1
- data/lib/zugpferd/ubl/mapping.rb +3 -0
- data/lib/zugpferd/ubl/reader.rb +1 -0
- data/lib/zugpferd/ubl/writer.rb +7 -0
- data/lib/zugpferd.rb +4 -4
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 837410c3386f0fb24e0c903378bad0e4d797e24867b2a3b15b7fdc6d23f1edb3
|
|
4
|
+
data.tar.gz: e5a4808ba918693dcd393212064c3e6590038aa61406fcd0fccf37e3a91794d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f0fcf101222d3f841c8d1ea2601159509deafcc1c8344a04a70d4b63049d32dd78c180b4e9061f768f65b0675adfdc1393dbfbde9f40ef2efafdd37447e5478
|
|
7
|
+
data.tar.gz: 9bcf99a1530b14c1540551eab5534be30ffe6c6f1c1bf666f7875f2e7f442f0b929ebc08ff6351b477685520fe724dd7419292f2fce5f5a508a29b3b22cb162d
|
data/lib/zugpferd/cii/mapping.rb
CHANGED
|
@@ -41,6 +41,7 @@ module Zugpferd
|
|
|
41
41
|
INVOICE_SETTLEMENT = {
|
|
42
42
|
currency_code: "#{SETTLEMENT}/ram:InvoiceCurrencyCode",
|
|
43
43
|
buyer_reference: "#{AGREEMENT}/ram:BuyerReference",
|
|
44
|
+
purchase_order_reference: "#{AGREEMENT}/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID",
|
|
44
45
|
}.freeze
|
|
45
46
|
|
|
46
47
|
# Seller (BG-4)
|
|
@@ -93,6 +94,7 @@ module Zugpferd
|
|
|
93
94
|
|
|
94
95
|
# TaxTotal (BG-23)
|
|
95
96
|
TAX_SUBTOTAL = "ram:ApplicableTradeTax"
|
|
97
|
+
TAX_FALLBACK_CURRENCY = "ram:InvoiceCurrencyCode"
|
|
96
98
|
TAX = {
|
|
97
99
|
taxable_amount: "ram:BasisAmount",
|
|
98
100
|
tax_amount: "ram:CalculatedAmount",
|
data/lib/zugpferd/cii/reader.rb
CHANGED
|
@@ -12,6 +12,9 @@ module Zugpferd
|
|
|
12
12
|
class Reader
|
|
13
13
|
include Mapping
|
|
14
14
|
|
|
15
|
+
# Raised when BT-110 is missing and the VAT breakdown (BG-23) does not sum to 0.
|
|
16
|
+
class MissingTaxTotalError < Zugpferd::Error; end
|
|
17
|
+
|
|
15
18
|
TYPE_CODE_MAP = {
|
|
16
19
|
"381" => Model::CreditNote,
|
|
17
20
|
"384" => Model::CorrectedInvoice,
|
|
@@ -25,6 +28,7 @@ module Zugpferd
|
|
|
25
28
|
# @param xml_string [String] valid CII D16B XML
|
|
26
29
|
# @return [Model::BillingDocument]
|
|
27
30
|
# @raise [Nokogiri::XML::SyntaxError] if the XML is malformed
|
|
31
|
+
# @raise [MissingTaxTotalError] if BT-110 is missing and the VAT breakdown does not sum to 0
|
|
28
32
|
def read(xml_string)
|
|
29
33
|
doc = Nokogiri::XML(xml_string) { |config| config.strict }
|
|
30
34
|
root = doc.root
|
|
@@ -50,6 +54,7 @@ module Zugpferd
|
|
|
50
54
|
type_code: text(root, INVOICE[:type_code]),
|
|
51
55
|
currency_code: text(root, INVOICE_SETTLEMENT[:currency_code]),
|
|
52
56
|
buyer_reference: text(root, INVOICE_SETTLEMENT[:buyer_reference]),
|
|
57
|
+
purchase_order_reference: text(root, INVOICE_SETTLEMENT[:purchase_order_reference]),
|
|
53
58
|
customization_id: text(root, INVOICE[:customization_id]),
|
|
54
59
|
profile_id: text(root, INVOICE[:profile_id]),
|
|
55
60
|
note: text(root, INVOICE[:note]),
|
|
@@ -129,14 +134,9 @@ module Zugpferd
|
|
|
129
134
|
|
|
130
135
|
totals_node = settlement_node.at_xpath(MONETARY_TOTAL, NS)
|
|
131
136
|
tax_total_node = totals_node&.at_xpath(TOTALS[:tax_total_amount], NS)
|
|
132
|
-
currency = tax_total_node
|
|
133
|
-
|
|
134
|
-
breakdown = Model::TaxBreakdown.new(
|
|
135
|
-
tax_amount: tax_total_node&.text,
|
|
136
|
-
currency_code: currency,
|
|
137
|
-
)
|
|
137
|
+
currency = tax_total_node ? tax_total_node["currencyID"] : text(settlement_node, TAX_FALLBACK_CURRENCY)
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
subtotals = settlement_node.xpath(TAX_SUBTOTAL, NS).map do |sub|
|
|
140
140
|
Model::TaxSubtotal.new(
|
|
141
141
|
taxable_amount: text(sub, TAX[:taxable_amount]),
|
|
142
142
|
tax_amount: text(sub, TAX[:tax_amount]),
|
|
@@ -148,9 +148,25 @@ module Zugpferd
|
|
|
148
148
|
)
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
+
breakdown = Model::TaxBreakdown.new(
|
|
152
|
+
tax_amount: tax_total_node ? tax_total_node.text : zero_tax_total(subtotals),
|
|
153
|
+
currency_code: currency,
|
|
154
|
+
)
|
|
155
|
+
breakdown.subtotals = subtotals
|
|
151
156
|
breakdown
|
|
152
157
|
end
|
|
153
158
|
|
|
159
|
+
# BR-CO-15 lets CII omit BT-110 on invoices without VAT. A breakdown
|
|
160
|
+
# that shows VAT contradicts that, even where the Schematron passes it.
|
|
161
|
+
def zero_tax_total(subtotals)
|
|
162
|
+
sum = subtotals.sum(BigDecimal("0"), &:tax_amount)
|
|
163
|
+
return sum if subtotals.any? && sum.zero?
|
|
164
|
+
|
|
165
|
+
raise MissingTaxTotalError,
|
|
166
|
+
"Invoice total VAT amount (BT-110) is missing and the VAT breakdown (BG-23) " \
|
|
167
|
+
"#{subtotals.empty? ? "is empty" : "sums to #{sum.to_s("F")}"}"
|
|
168
|
+
end
|
|
169
|
+
|
|
154
170
|
def build_monetary_totals(node)
|
|
155
171
|
return nil unless node
|
|
156
172
|
|
data/lib/zugpferd/cii/writer.rb
CHANGED
|
@@ -76,6 +76,13 @@ module Zugpferd
|
|
|
76
76
|
xml["ram"].BuyerReference doc.buyer_reference if doc.buyer_reference
|
|
77
77
|
build_party(xml, "SellerTradeParty", doc.seller) if doc.seller
|
|
78
78
|
build_party(xml, "BuyerTradeParty", doc.buyer) if doc.buyer
|
|
79
|
+
build_buyer_order_reference(xml, doc) if doc.purchase_order_reference
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def build_buyer_order_reference(xml, doc)
|
|
84
|
+
xml["ram"].BuyerOrderReferencedDocument do
|
|
85
|
+
xml["ram"].IssuerAssignedID doc.purchase_order_reference
|
|
79
86
|
end
|
|
80
87
|
end
|
|
81
88
|
|
|
@@ -22,6 +22,7 @@ module Zugpferd
|
|
|
22
22
|
# @return [Date, nil] BT-73 Invoicing period start date
|
|
23
23
|
# @return [Date, nil] BT-74 Invoicing period end date
|
|
24
24
|
# @return [String, nil] BT-10 Buyer reference
|
|
25
|
+
# @return [String, nil] BT-13 Purchase order reference
|
|
25
26
|
# @return [String, nil] BT-24 Specification identifier
|
|
26
27
|
# @return [String, nil] BT-23 Business process type
|
|
27
28
|
# @return [String, nil] BT-22 Invoice note
|
|
@@ -35,7 +36,8 @@ module Zugpferd
|
|
|
35
36
|
attr_accessor :number, :issue_date, :due_date, :type_code,
|
|
36
37
|
:currency_code, :delivery_date,
|
|
37
38
|
:invoicing_period_start_date, :invoicing_period_end_date,
|
|
38
|
-
:buyer_reference, :
|
|
39
|
+
:buyer_reference, :purchase_order_reference,
|
|
40
|
+
:customization_id, :profile_id, :note, :seller, :buyer,
|
|
39
41
|
:line_items, :tax_breakdown, :monetary_totals,
|
|
40
42
|
:payment_instructions, :allowance_charges
|
|
41
43
|
|
data/lib/zugpferd/ubl/mapping.rb
CHANGED
data/lib/zugpferd/ubl/reader.rb
CHANGED
|
@@ -46,6 +46,7 @@ module Zugpferd
|
|
|
46
46
|
type_code: text(root, type_code_element),
|
|
47
47
|
currency_code: text(root, INVOICE[:currency_code]),
|
|
48
48
|
buyer_reference: text(root, INVOICE[:buyer_reference]),
|
|
49
|
+
purchase_order_reference: text(root, ORDER_REFERENCE),
|
|
49
50
|
customization_id: text(root, INVOICE[:customization_id]),
|
|
50
51
|
profile_id: text(root, INVOICE[:profile_id]),
|
|
51
52
|
note: text(root, INVOICE[:note]),
|
data/lib/zugpferd/ubl/writer.rb
CHANGED
|
@@ -51,6 +51,7 @@ module Zugpferd
|
|
|
51
51
|
xml["cbc"].DocumentCurrencyCode doc.currency_code
|
|
52
52
|
xml["cbc"].BuyerReference doc.buyer_reference if doc.buyer_reference
|
|
53
53
|
build_invoice_period(xml, doc) if doc.invoicing_period_start_date || doc.invoicing_period_end_date
|
|
54
|
+
build_order_reference(xml, doc) if doc.purchase_order_reference
|
|
54
55
|
|
|
55
56
|
build_supplier(xml, doc.seller, doc.payment_instructions) if doc.seller
|
|
56
57
|
build_customer(xml, doc.buyer) if doc.buyer
|
|
@@ -149,6 +150,12 @@ module Zugpferd
|
|
|
149
150
|
end
|
|
150
151
|
end
|
|
151
152
|
|
|
153
|
+
def build_order_reference(xml, doc)
|
|
154
|
+
xml["cac"].OrderReference do
|
|
155
|
+
xml["cbc"].ID doc.purchase_order_reference
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
152
159
|
def build_delivery(xml, doc)
|
|
153
160
|
xml["cac"].Delivery do
|
|
154
161
|
xml["cbc"].ActualDeliveryDate doc.delivery_date.to_s
|
data/lib/zugpferd.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
module Zugpferd
|
|
2
|
+
class Error < StandardError; end
|
|
3
|
+
end
|
|
4
|
+
|
|
1
5
|
require_relative "zugpferd/model/billing_document"
|
|
2
6
|
require_relative "zugpferd/model/invoice"
|
|
3
7
|
require_relative "zugpferd/model/credit_note"
|
|
@@ -20,7 +24,3 @@ require_relative "zugpferd/ubl/reader"
|
|
|
20
24
|
require_relative "zugpferd/ubl/writer"
|
|
21
25
|
require_relative "zugpferd/cii/reader"
|
|
22
26
|
require_relative "zugpferd/cii/writer"
|
|
23
|
-
|
|
24
|
-
module Zugpferd
|
|
25
|
-
class Error < StandardError; end
|
|
26
|
-
end
|