zugpferd 0.6.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb023a7256c9cf26f6688283b6204bbccc0f46f2a6c8f0bb8082c2b1db277151
4
- data.tar.gz: 00d5dc92b2d38a3744af4388017629d83b74b28241014448c75b684fb8de7c5c
3
+ metadata.gz: 05fc84848e61ccfc901d5a22ab7d35ff8032531d543dcd85883073a7d0bd2c43
4
+ data.tar.gz: cd37bf998f94dd2be0f9adac19761976145b49f7aace4d22d5af2812df173e1a
5
5
  SHA512:
6
- metadata.gz: 0b6313dfce9be63204e9c7317be9abfbd38c0a53c97e5a7960c4b4fab98421f7f5ec892af59457c4babcdc0ec811de4159f926ae8f443df5f1d417055eb3847f
7
- data.tar.gz: 449b38ee768cea1a0a5167f498c5b80a6bc3604bfe92967cabed4e51d230fe56b307dd88c5313886cb2b67d6b053932bf5f8e575b18385b781fd323f74d10fdf
6
+ metadata.gz: 245cb66ea6b7b151145130747873780113acd36790a66420e23b210ddd1920082e22bd50661cadde218bf15bc1713687ddbc0b5a802bfd0245aa6b72b569fe7c
7
+ data.tar.gz: 72af5d37db91aaa59deee1cc9b9ec7aa70347d1dce1f87decc6f5347f5714a077d869533f4bcb23d9bb42b4b52b6db73157904c987c98144c5a888616d7f5f24
@@ -26,6 +26,8 @@ module Zugpferd
26
26
  # Delivery (BG-13)
27
27
  DELIVERY = "#{TRANSACTION}/ram:ApplicableHeaderTradeDelivery"
28
28
  DELIVERY_DATE = "ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString"
29
+ # Deliver to address (BG-15), fields as in ADDRESS
30
+ DELIVER_TO_ADDRESS = "ram:ShipToTradeParty/ram:PostalTradeAddress"
29
31
 
30
32
  # Settlement (contains currency, payment, tax, totals)
31
33
  SETTLEMENT = "#{TRANSACTION}/ram:ApplicableHeaderTradeSettlement"
@@ -64,6 +66,7 @@ module Zugpferd
64
66
  legal_registration_id: "ram:SpecifiedLegalOrganization/ram:ID",
65
67
  legal_form: "ram:Description",
66
68
  vat_identifier: "ram:SpecifiedTaxRegistration/ram:ID[@schemeID='VA']",
69
+ tax_registration_identifier: "ram:SpecifiedTaxRegistration/ram:ID[@schemeID='FC']",
67
70
  electronic_address: "ram:URIUniversalCommunication/ram:URIID",
68
71
  }.freeze
69
72
 
@@ -49,6 +49,7 @@ module Zugpferd
49
49
  issue_date: parse_cii_date(text(root, INVOICE[:issue_date])),
50
50
  due_date: parse_cii_date(settlement ? text(settlement, PAYMENT_TERMS_DUE_DATE) : nil),
51
51
  delivery_date: parse_cii_date(delivery ? text(delivery, DELIVERY_DATE) : nil),
52
+ deliver_to_address: build_deliver_to_address(delivery),
52
53
  invoicing_period_start_date: parse_cii_date(period ? text(period, BILLING_PERIOD_FIELDS[:start_date]) : nil),
53
54
  invoicing_period_end_date: parse_cii_date(period ? text(period, BILLING_PERIOD_FIELDS[:end_date]) : nil),
54
55
  type_code: text(root, INVOICE[:type_code]),
@@ -58,7 +59,7 @@ module Zugpferd
58
59
  customization_id: text(root, INVOICE[:customization_id]),
59
60
  profile_id: text(root, INVOICE[:profile_id]),
60
61
  note: text(root, INVOICE[:note]),
61
- seller: build_party(root.at_xpath(SELLER, NS)),
62
+ seller: build_party(root.at_xpath(SELLER, NS), seller: true),
62
63
  buyer: build_party(root.at_xpath(BUYER, NS)),
63
64
  line_items: root.xpath(INVOICE_LINE, NS).map { |n| build_line_item(n) },
64
65
  allowance_charges: settlement ? build_allowance_charges(settlement) : [],
@@ -69,7 +70,8 @@ module Zugpferd
69
70
  )
70
71
  end
71
72
 
72
- def build_party(node)
73
+ # Seller-only terms are read only for the seller
74
+ def build_party(node, seller: false)
73
75
  return nil unless node
74
76
 
75
77
  party = Model::TradeParty.new(
@@ -77,8 +79,9 @@ module Zugpferd
77
79
  trading_name: text(node, PARTY[:trading_name]),
78
80
  identifier: text(node, PARTY[:identifier]),
79
81
  legal_registration_id: text(node, PARTY[:legal_registration_id]),
80
- legal_form: text(node, PARTY[:legal_form]),
82
+ legal_form: (text(node, PARTY[:legal_form]) if seller),
81
83
  vat_identifier: text(node, PARTY[:vat_identifier]),
84
+ tax_registration_identifier: (text(node, PARTY[:tax_registration_identifier]) if seller),
82
85
  electronic_address: text(node, PARTY[:electronic_address]),
83
86
  )
84
87
 
@@ -103,6 +106,11 @@ module Zugpferd
103
106
  )
104
107
  end
105
108
 
109
+ def build_deliver_to_address(delivery_node)
110
+ addr_node = delivery_node&.at_xpath(DELIVER_TO_ADDRESS, NS)
111
+ build_postal_address(addr_node) if addr_node
112
+ end
113
+
106
114
  def build_contact(node)
107
115
  Model::Contact.new(
108
116
  name: text(node, CONTACT_FIELDS[:name]),
@@ -74,7 +74,7 @@ module Zugpferd
74
74
  def build_agreement(xml, doc)
75
75
  xml["ram"].ApplicableHeaderTradeAgreement do
76
76
  xml["ram"].BuyerReference doc.buyer_reference if doc.buyer_reference
77
- build_party(xml, "SellerTradeParty", doc.seller) if doc.seller
77
+ build_party(xml, "SellerTradeParty", doc.seller, seller: true) if doc.seller
78
78
  build_party(xml, "BuyerTradeParty", doc.buyer) if doc.buyer
79
79
  build_buyer_order_reference(xml, doc) if doc.purchase_order_reference
80
80
  end
@@ -86,7 +86,8 @@ module Zugpferd
86
86
  end
87
87
  end
88
88
 
89
- def build_party(xml, element_name, party)
89
+ # Seller-only terms are written only for the seller
90
+ def build_party(xml, element_name, party, seller: false)
90
91
  xml["ram"].send(element_name) do
91
92
  if party.identifier
92
93
  xml["ram"].ID party.identifier
@@ -94,7 +95,7 @@ module Zugpferd
94
95
 
95
96
  xml["ram"].Name party.name
96
97
 
97
- xml["ram"].Description party.legal_form if party.legal_form
98
+ xml["ram"].Description party.legal_form if seller && party.legal_form
98
99
 
99
100
  if party.legal_registration_id || party.trading_name
100
101
  xml["ram"].SpecifiedLegalOrganization do
@@ -120,6 +121,12 @@ module Zugpferd
120
121
  xml["ram"].ID(party.vat_identifier, schemeID: "VA")
121
122
  end
122
123
  end
124
+
125
+ if seller && party.tax_registration_identifier
126
+ xml["ram"].SpecifiedTaxRegistration do
127
+ xml["ram"].ID(party.tax_registration_identifier, schemeID: "FC")
128
+ end
129
+ end
123
130
  end
124
131
  end
125
132
 
@@ -150,6 +157,11 @@ module Zugpferd
150
157
 
151
158
  def build_delivery(xml, doc)
152
159
  xml["ram"].ApplicableHeaderTradeDelivery do
160
+ if doc.deliver_to_address
161
+ xml["ram"].ShipToTradeParty do
162
+ build_postal_address(xml, doc.deliver_to_address)
163
+ end
164
+ end
153
165
  if doc.delivery_date
154
166
  xml["ram"].ActualDeliverySupplyChainEvent do
155
167
  xml["ram"].OccurrenceDateTime do
@@ -19,6 +19,7 @@ module Zugpferd
19
19
  # @return [String] BT-3 Invoice type code
20
20
  # @return [String] BT-5 Document currency code (default: "EUR")
21
21
  # @return [Date, nil] BT-72 Actual delivery date
22
+ # @return [PostalAddress, nil] BG-15 Deliver to address
22
23
  # @return [Array<PrecedingInvoice>] BG-3 Preceding invoice references
23
24
  # @return [Date, nil] BT-73 Invoicing period start date
24
25
  # @return [Date, nil] BT-74 Invoicing period end date
@@ -35,7 +36,7 @@ module Zugpferd
35
36
  # @return [PaymentInstructions, nil] BG-16 Payment information
36
37
  # @return [Array<AllowanceCharge>] BG-20/BG-21 Document-level allowances and charges
37
38
  attr_accessor :number, :issue_date, :due_date, :type_code,
38
- :currency_code, :delivery_date,
39
+ :currency_code, :delivery_date, :deliver_to_address,
39
40
  :invoicing_period_start_date, :invoicing_period_end_date,
40
41
  :buyer_reference, :purchase_order_reference,
41
42
  :customization_id, :profile_id, :note, :seller, :buyer,
@@ -1,14 +1,14 @@
1
1
  module Zugpferd
2
2
  module Model
3
- # Postal address (BG-5 / BG-8).
3
+ # Postal address (BG-5 / BG-8 / BG-15).
4
4
  class PostalAddress
5
- # @return [String, nil] BT-35/BT-50 Street name
6
- # @return [String, nil] BT-37/BT-52 City name
7
- # @return [String, nil] BT-38/BT-53 Postal zone
8
- # @return [String] BT-40/BT-55 Country code
5
+ # @return [String, nil] BT-35/BT-50/BT-75 Street name
6
+ # @return [String, nil] BT-37/BT-52/BT-77 City name
7
+ # @return [String, nil] BT-38/BT-53/BT-78 Postal zone
8
+ # @return [String] BT-40/BT-55/BT-80 Country code
9
9
  attr_accessor :street_name, :city_name, :postal_zone, :country_code
10
10
 
11
- # @param country_code [String] BT-40/BT-55 Country code (ISO 3166-1 alpha-2)
11
+ # @param country_code [String] BT-40/BT-55/BT-80 Country code (ISO 3166-1 alpha-2)
12
12
  # @param rest [Hash] additional attributes set via accessors
13
13
  def initialize(country_code:, **rest)
14
14
  @country_code = country_code
@@ -10,14 +10,16 @@ module Zugpferd
10
10
  # @return [String, nil] BT-28/BT-45 Trading name
11
11
  # @return [String, nil] BT-29/BT-46 Party identifier
12
12
  # @return [String, nil] BT-30/BT-47 Legal registration identifier
13
- # @return [String, nil] BT-33 Company legal form
13
+ # @return [String, nil] BT-33 Company legal form (seller only)
14
14
  # @return [String, nil] BT-31/BT-48 VAT identifier
15
+ # @return [String, nil] BT-32 Seller tax registration identifier (seller only)
15
16
  # @return [String, nil] BT-34/BT-49 Electronic address
16
17
  # @return [String, nil] BT-34-1/BT-49-1 Electronic address scheme
17
18
  # @return [PostalAddress, nil] BG-5/BG-8 Postal address
18
19
  # @return [Contact, nil] BG-6/BG-9 Contact information
19
20
  attr_accessor :name, :trading_name, :identifier,
20
21
  :legal_registration_id, :legal_form, :vat_identifier,
22
+ :tax_registration_identifier,
21
23
  :electronic_address, :electronic_address_scheme,
22
24
  :postal_address, :contact
23
25
 
@@ -32,6 +32,8 @@ module Zugpferd
32
32
  # Delivery (BG-13)
33
33
  DELIVERY = "cac:Delivery"
34
34
  DELIVERY_DATE = "cbc:ActualDeliveryDate"
35
+ # Deliver to address (BG-15), fields as in ADDRESS
36
+ DELIVER_TO_ADDRESS = "cac:DeliveryLocation/cac:Address"
35
37
 
36
38
  # Invoicing period (BG-14)
37
39
  INVOICE_PERIOD = "cac:InvoicePeriod"
@@ -63,6 +65,7 @@ module Zugpferd
63
65
  legal_registration_id: "cac:PartyLegalEntity/cbc:CompanyID",
64
66
  legal_form: "cac:PartyLegalEntity/cbc:CompanyLegalForm",
65
67
  vat_identifier: "cac:PartyTaxScheme[cac:TaxScheme/cbc:ID='VAT']/cbc:CompanyID",
68
+ tax_registration_identifier: "cac:PartyTaxScheme[cac:TaxScheme/cbc:ID!='VAT']/cbc:CompanyID",
66
69
  electronic_address: "cbc:EndpointID",
67
70
  }.freeze
68
71
 
@@ -42,6 +42,7 @@ module Zugpferd
42
42
  issue_date: parse_date(text(root, INVOICE[:issue_date])),
43
43
  due_date: parse_date(text(root, due_date_element)),
44
44
  delivery_date: delivery_node ? parse_date(text(delivery_node, DELIVERY_DATE)) : nil,
45
+ deliver_to_address: build_deliver_to_address(delivery_node),
45
46
  invoicing_period_start_date: period_node ? parse_date(text(period_node, INVOICE_PERIOD_FIELDS[:start_date])) : nil,
46
47
  invoicing_period_end_date: period_node ? parse_date(text(period_node, INVOICE_PERIOD_FIELDS[:end_date])) : nil,
47
48
  type_code: text(root, type_code_element),
@@ -51,7 +52,7 @@ module Zugpferd
51
52
  customization_id: text(root, INVOICE[:customization_id]),
52
53
  profile_id: text(root, INVOICE[:profile_id]),
53
54
  note: text(root, INVOICE[:note]),
54
- seller: build_party(root.at_xpath(SELLER, @ns)),
55
+ seller: build_party(root.at_xpath(SELLER, @ns), seller: true),
55
56
  buyer: build_party(root.at_xpath(BUYER, @ns)),
56
57
  line_items: root.xpath(line_element, @ns).map { |n| build_line_item(n) },
57
58
  allowance_charges: root.xpath(ALLOWANCE_CHARGE, @ns).map { |n| build_allowance_charge(n) },
@@ -62,7 +63,8 @@ module Zugpferd
62
63
  )
63
64
  end
64
65
 
65
- def build_party(node)
66
+ # Seller-only terms are read only for the seller
67
+ def build_party(node, seller: false)
66
68
  return nil unless node
67
69
 
68
70
  party = Model::TradeParty.new(
@@ -70,8 +72,9 @@ module Zugpferd
70
72
  trading_name: text(node, PARTY[:trading_name]),
71
73
  identifier: text(node, PARTY[:identifier]),
72
74
  legal_registration_id: text(node, PARTY[:legal_registration_id]),
73
- legal_form: text(node, PARTY[:legal_form]),
75
+ legal_form: (text(node, PARTY[:legal_form]) if seller),
74
76
  vat_identifier: text(node, PARTY[:vat_identifier]),
77
+ tax_registration_identifier: (text(node, PARTY[:tax_registration_identifier]) if seller),
75
78
  electronic_address: text(node, PARTY[:electronic_address]),
76
79
  )
77
80
 
@@ -96,6 +99,11 @@ module Zugpferd
96
99
  )
97
100
  end
98
101
 
102
+ def build_deliver_to_address(delivery_node)
103
+ addr_node = delivery_node&.at_xpath(DELIVER_TO_ADDRESS, @ns)
104
+ build_postal_address(addr_node) if addr_node
105
+ end
106
+
99
107
  def build_contact(node)
100
108
  Model::Contact.new(
101
109
  name: text(node, CONTACT_FIELDS[:name]),
@@ -56,7 +56,7 @@ module Zugpferd
56
56
 
57
57
  build_supplier(xml, doc.seller, doc.payment_instructions) if doc.seller
58
58
  build_customer(xml, doc.buyer) if doc.buyer
59
- build_delivery(xml, doc) if doc.delivery_date
59
+ build_delivery(xml, doc) if doc.delivery_date || doc.deliver_to_address
60
60
  build_payment_means(xml, doc.payment_instructions, doc.due_date) if doc.payment_instructions
61
61
  build_payment_terms(xml, doc.payment_instructions) if doc.payment_instructions&.note
62
62
  doc.allowance_charges.each { |ac| build_allowance_charge(xml, ac, doc.currency_code) }
@@ -68,7 +68,7 @@ module Zugpferd
68
68
  def build_supplier(xml, party, payment_instructions = nil)
69
69
  xml["cac"].AccountingSupplierParty do
70
70
  build_party(xml, party,
71
- creditor_reference_id: payment_instructions&.creditor_reference_id)
71
+ creditor_reference_id: payment_instructions&.creditor_reference_id, seller: true)
72
72
  end
73
73
  end
74
74
 
@@ -78,7 +78,8 @@ module Zugpferd
78
78
  end
79
79
  end
80
80
 
81
- def build_party(xml, party, creditor_reference_id: nil)
81
+ # Seller-only terms are written only for the seller
82
+ def build_party(xml, party, creditor_reference_id: nil, seller: false)
82
83
  xml["cac"].Party do
83
84
  if party.electronic_address
84
85
  attrs = {}
@@ -115,10 +116,19 @@ module Zugpferd
115
116
  end
116
117
  end
117
118
 
119
+ if seller && party.tax_registration_identifier
120
+ xml["cac"].PartyTaxScheme do
121
+ xml["cbc"].CompanyID party.tax_registration_identifier
122
+ xml["cac"].TaxScheme do
123
+ xml["cbc"].ID "FC"
124
+ end
125
+ end
126
+ end
127
+
118
128
  xml["cac"].PartyLegalEntity do
119
129
  xml["cbc"].RegistrationName party.name
120
130
  xml["cbc"].CompanyID party.legal_registration_id if party.legal_registration_id
121
- xml["cbc"].CompanyLegalForm party.legal_form if party.legal_form
131
+ xml["cbc"].CompanyLegalForm party.legal_form if seller && party.legal_form
122
132
  end
123
133
 
124
134
  build_contact(xml, party.contact) if party.contact
@@ -127,12 +137,16 @@ module Zugpferd
127
137
 
128
138
  def build_postal_address(xml, addr)
129
139
  xml["cac"].PostalAddress do
130
- xml["cbc"].StreetName addr.street_name if addr.street_name
131
- xml["cbc"].CityName addr.city_name if addr.city_name
132
- xml["cbc"].PostalZone addr.postal_zone if addr.postal_zone
133
- xml["cac"].Country do
134
- xml["cbc"].IdentificationCode addr.country_code
135
- end
140
+ build_address_fields(xml, addr)
141
+ end
142
+ end
143
+
144
+ def build_address_fields(xml, addr)
145
+ xml["cbc"].StreetName addr.street_name if addr.street_name
146
+ xml["cbc"].CityName addr.city_name if addr.city_name
147
+ xml["cbc"].PostalZone addr.postal_zone if addr.postal_zone
148
+ xml["cac"].Country do
149
+ xml["cbc"].IdentificationCode addr.country_code
136
150
  end
137
151
  end
138
152
 
@@ -168,7 +182,14 @@ module Zugpferd
168
182
 
169
183
  def build_delivery(xml, doc)
170
184
  xml["cac"].Delivery do
171
- xml["cbc"].ActualDeliveryDate doc.delivery_date.to_s
185
+ xml["cbc"].ActualDeliveryDate doc.delivery_date.to_s if doc.delivery_date
186
+ if doc.deliver_to_address
187
+ xml["cac"].DeliveryLocation do
188
+ xml["cac"].Address do
189
+ build_address_fields(xml, doc.deliver_to_address)
190
+ end
191
+ end
192
+ end
172
193
  end
173
194
  end
174
195
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zugpferd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Zeitler