diff --git a/lib/secretariat/invoice.rb b/lib/secretariat/invoice.rb index 4e88664..fdab3e6 100644 --- a/lib/secretariat/invoice.rb +++ b/lib/secretariat/invoice.rb @@ -24,8 +24,9 @@ module Secretariat :issue_date, :service_period_start, :service_period_end, - :seller, - :buyer, + :seller, # TradeParty + :buyer, # TradeParty + :ship_to, # TradeParty or nil (buyer) or false (no ShipTo) :buyer_reference, :line_items, :currency_code, @@ -61,6 +62,14 @@ def tax_reason_text tax_reason || TAX_EXEMPTION_REASONS[tax_category] end + # ship_to: nil => use buyer (backwards compatibility) + # ship_to: false => ignore + def ship_to_or_buyer + return buyer if ship_to.nil? + + ship_to + end + def tax_category_code(tax, version: 2) if version == 1 return TAX_CATEGORY_CODES_1[tax.tax_category || tax_category] || 'S' @@ -245,9 +254,9 @@ def to_xml(version: 1, validate: true) delivery = by_version(version, 'ApplicableSupplyChainTradeDelivery', 'ApplicableHeaderTradeDelivery') xml['ram'].send(delivery) do - if version == 2 + if version == 2 && ship_to_or_buyer xml['ram'].ShipToTradeParty do - buyer.to_xml(xml, exclude_tax: true, version: version) + ship_to_or_buyer.to_xml(xml, exclude_tax: true, version: version) end end xml['ram'].ActualDeliverySupplyChainEvent do diff --git a/lib/secretariat/trade_party.rb b/lib/secretariat/trade_party.rb index ebd1afb..40b2a16 100644 --- a/lib/secretariat/trade_party.rb +++ b/lib/secretariat/trade_party.rb @@ -18,10 +18,14 @@ module Secretariat using ObjectExtensions TradeParty = Struct.new('TradeParty', + :id, :name, :street1, :street2, :city, :postal_code, :country_id, :vat_id, :global_id, :global_id_scheme_id, :tax_id, keyword_init: true, ) do def to_xml(xml, exclude_tax: false, version: 2) + if id && !exclude_tax + xml['ram'].ID id # BT-46 + end if global_id.present? && global_id_scheme_id.present? xml['ram'].GlobalID(schemeID: global_id_scheme_id) do xml.text(global_id) diff --git a/test/invoice_test.rb b/test/invoice_test.rb index cf7fbb7..d31eb35 100644 --- a/test/invoice_test.rb +++ b/test/invoice_test.rb @@ -5,7 +5,7 @@ module Secretariat class InvoiceTest < Minitest::Test - def make_eu_invoice(tax_category: :REVERSECHARGE) + def make_eu_invoice(tax_category: :REVERSECHARGE, ship_to: nil) seller = TradeParty.new( name: 'Depfu inc', street1: 'Quickbornstr. 46', @@ -15,6 +15,7 @@ def make_eu_invoice(tax_category: :REVERSECHARGE) vat_id: 'DE304755032' ) buyer = TradeParty.new( + id: 'Kunde 4711', name: 'Depfu inc', street1: 'Quickbornstr. 46', city: 'Hamburg', @@ -42,6 +43,7 @@ def make_eu_invoice(tax_category: :REVERSECHARGE) service_period_end: Date.today + 30, seller: seller, buyer: buyer, + ship_to: ship_to, line_items: [line_item], currency_code: 'USD', payment_type: :CREDITCARD, @@ -367,6 +369,29 @@ def test_simple_eu_invoice_v2 assert_match(/AE<\/ram:CategoryCode>/, xml) assert_match(/Reverse Charge<\/ram:ExemptionReason>/, xml) assert_match(//, xml) + assert_match(%r{\s*Kunde 4711}, xml) + + v = Validator.new(xml, version: 2) + errors = v.validate_against_schema + if !errors.empty? + puts xml + errors.each do |error| + puts error + end + end + assert_equal [], errors + rescue ValidationError => e + puts e.errors + end + + def test_simple_eu_invoice_v2_without_ship_to + begin + xml = make_eu_invoice(ship_to: false).to_xml(version: 2) + rescue ValidationError => e + pp e.errors + end + + refute_match(//, xml) v = Validator.new(xml, version: 2) errors = v.validate_against_schema