ubl 0.0.4 → 0.1.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -5
  3. data/lib/ubl/builder.rb +2 -5
  4. data/lib/ubl/constants.rb +6 -0
  5. data/lib/ubl/validate.rb +78 -0
  6. data/lib/ubl/version.rb +1 -1
  7. data/lib/ubl.rb +31 -2
  8. data/xsd/common/CCTS_CCT_SchemaModule-2.1.xsd +731 -0
  9. data/xsd/common/UBL-CommonAggregateComponents-2.1.xsd +39799 -0
  10. data/xsd/common/UBL-CommonBasicComponents-2.1.xsd +5389 -0
  11. data/xsd/common/UBL-CommonExtensionComponents-2.1.xsd +223 -0
  12. data/xsd/common/UBL-CommonSignatureComponents-2.1.xsd +101 -0
  13. data/xsd/common/UBL-CoreComponentParameters-2.1.xsd +63 -0
  14. data/xsd/common/UBL-ExtensionContentDataType-2.1.xsd +89 -0
  15. data/xsd/common/UBL-QualifiedDataTypes-2.1.xsd +69 -0
  16. data/xsd/common/UBL-SignatureAggregateComponents-2.1.xsd +138 -0
  17. data/xsd/common/UBL-SignatureBasicComponents-2.1.xsd +78 -0
  18. data/xsd/common/UBL-UnqualifiedDataTypes-2.1.xsd +553 -0
  19. data/xsd/common/UBL-XAdESv132-2.1.xsd +476 -0
  20. data/xsd/common/UBL-XAdESv141-2.1.xsd +25 -0
  21. data/xsd/common/UBL-xmldsig-core-schema-2.1.xsd +330 -0
  22. data/xsd/maindoc/UBL-ApplicationResponse-2.1.xsd +362 -0
  23. data/xsd/maindoc/UBL-AttachedDocument-2.1.xsd +416 -0
  24. data/xsd/maindoc/UBL-AwardedNotification-2.1.xsd +418 -0
  25. data/xsd/maindoc/UBL-BillOfLading-2.1.xsd +540 -0
  26. data/xsd/maindoc/UBL-CallForTenders-2.1.xsd +513 -0
  27. data/xsd/maindoc/UBL-Catalogue-2.1.xsd +565 -0
  28. data/xsd/maindoc/UBL-CatalogueDeletion-2.1.xsd +465 -0
  29. data/xsd/maindoc/UBL-CatalogueItemSpecificationUpdate-2.1.xsd +533 -0
  30. data/xsd/maindoc/UBL-CataloguePricingUpdate-2.1.xsd +532 -0
  31. data/xsd/maindoc/UBL-CatalogueRequest-2.1.xsd +571 -0
  32. data/xsd/maindoc/UBL-CertificateOfOrigin-2.1.xsd +417 -0
  33. data/xsd/maindoc/UBL-ContractAwardNotice-2.1.xsd +493 -0
  34. data/xsd/maindoc/UBL-ContractNotice-2.1.xsd +459 -0
  35. data/xsd/maindoc/UBL-CreditNote-2.1.xsd +951 -0
  36. data/xsd/maindoc/UBL-DebitNote-2.1.xsd +916 -0
  37. data/xsd/maindoc/UBL-DespatchAdvice-2.1.xsd +482 -0
  38. data/xsd/maindoc/UBL-DocumentStatus-2.1.xsd +350 -0
  39. data/xsd/maindoc/UBL-DocumentStatusRequest-2.1.xsd +348 -0
  40. data/xsd/maindoc/UBL-ExceptionCriteria-2.1.xsd +417 -0
  41. data/xsd/maindoc/UBL-ExceptionNotification-2.1.xsd +403 -0
  42. data/xsd/maindoc/UBL-Forecast-2.1.xsd +454 -0
  43. data/xsd/maindoc/UBL-ForecastRevision-2.1.xsd +453 -0
  44. data/xsd/maindoc/UBL-ForwardingInstructions-2.1.xsd +517 -0
  45. data/xsd/maindoc/UBL-FreightInvoice-2.1.xsd +867 -0
  46. data/xsd/maindoc/UBL-FulfilmentCancellation-2.1.xsd +471 -0
  47. data/xsd/maindoc/UBL-GoodsItemItinerary-2.1.xsd +431 -0
  48. data/xsd/maindoc/UBL-GuaranteeCertificate-2.1.xsd +481 -0
  49. data/xsd/maindoc/UBL-InstructionForReturns-2.1.xsd +383 -0
  50. data/xsd/maindoc/UBL-InventoryReport-2.1.xsd +401 -0
  51. data/xsd/maindoc/UBL-Invoice-2.1.xsd +1002 -0
  52. data/xsd/maindoc/UBL-ItemInformationRequest-2.1.xsd +402 -0
  53. data/xsd/maindoc/UBL-Order-2.1.xsd +891 -0
  54. data/xsd/maindoc/UBL-OrderCancellation-2.1.xsd +416 -0
  55. data/xsd/maindoc/UBL-OrderChange-2.1.xsd +869 -0
  56. data/xsd/maindoc/UBL-OrderResponse-2.1.xsd +956 -0
  57. data/xsd/maindoc/UBL-OrderResponseSimple-2.1.xsd +486 -0
  58. data/xsd/maindoc/UBL-PackingList-2.1.xsd +432 -0
  59. data/xsd/maindoc/UBL-PriorInformationNotice-2.1.xsd +441 -0
  60. data/xsd/maindoc/UBL-ProductActivity-2.1.xsd +387 -0
  61. data/xsd/maindoc/UBL-Quotation-2.1.xsd +583 -0
  62. data/xsd/maindoc/UBL-ReceiptAdvice-2.1.xsd +485 -0
  63. data/xsd/maindoc/UBL-Reminder-2.1.xsd +759 -0
  64. data/xsd/maindoc/UBL-RemittanceAdvice-2.1.xsd +567 -0
  65. data/xsd/maindoc/UBL-RequestForQuotation-2.1.xsd +519 -0
  66. data/xsd/maindoc/UBL-RetailEvent-2.1.xsd +515 -0
  67. data/xsd/maindoc/UBL-SelfBilledCreditNote-2.1.xsd +918 -0
  68. data/xsd/maindoc/UBL-SelfBilledInvoice-2.1.xsd +933 -0
  69. data/xsd/maindoc/UBL-Statement-2.1.xsd +600 -0
  70. data/xsd/maindoc/UBL-StockAvailabilityReport-2.1.xsd +403 -0
  71. data/xsd/maindoc/UBL-Tender-2.1.xsd +464 -0
  72. data/xsd/maindoc/UBL-TenderReceipt-2.1.xsd +398 -0
  73. data/xsd/maindoc/UBL-TendererQualification-2.1.xsd +401 -0
  74. data/xsd/maindoc/UBL-TendererQualificationResponse-2.1.xsd +399 -0
  75. data/xsd/maindoc/UBL-TradeItemLocationProfile-2.1.xsd +415 -0
  76. data/xsd/maindoc/UBL-TransportExecutionPlan-2.1.xsd +769 -0
  77. data/xsd/maindoc/UBL-TransportExecutionPlanRequest-2.1.xsd +696 -0
  78. data/xsd/maindoc/UBL-TransportProgressStatus-2.1.xsd +396 -0
  79. data/xsd/maindoc/UBL-TransportProgressStatusRequest-2.1.xsd +345 -0
  80. data/xsd/maindoc/UBL-TransportServiceDescription-2.1.xsd +430 -0
  81. data/xsd/maindoc/UBL-TransportServiceDescriptionRequest-2.1.xsd +363 -0
  82. data/xsd/maindoc/UBL-TransportationStatus-2.1.xsd +566 -0
  83. data/xsd/maindoc/UBL-TransportationStatusRequest-2.1.xsd +484 -0
  84. data/xsd/maindoc/UBL-UnawardedNotification-2.1.xsd +415 -0
  85. data/xsd/maindoc/UBL-UtilityStatement-2.1.xsd +490 -0
  86. data/xsd/maindoc/UBL-Waybill-2.1.xsd +501 -0
  87. metadata +99 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f257c1e68bac4286b082be4900f49a27fc736a69dc7cafa7de79cca2219e9035
4
- data.tar.gz: 15be033154369701934e55ddc4ae34a2270032f129e8f9409927a4b06174f00e
3
+ metadata.gz: 5c951c7c837dfd7a900976e605a78832e0bf2bfd15733c4877f045df4bf0214e
4
+ data.tar.gz: bceb1d66414fe51ae67db3c15ad0e60f6e127834dfc7f587781f9464a430364c
5
5
  SHA512:
6
- metadata.gz: 63d7d62032fc619e8756655f2e737cc17bb5f54b9452478bdf15aadb3c040430f54a1db90e647fe5696182c719f33f2d22ff3649d5ade31c38ed8f8758f8f99d
7
- data.tar.gz: 8e9ef76a121e0288be720acd30d14bb38747c0ed5e19f22abed25ec5768ba57ca4640d17dd547ce0b9f7be988d139cac7a667a4e3085ee4dac871c39b82c37fd
6
+ metadata.gz: f94eccdd50a880d39a67ab3fcfa102ff6115792fc06f94c6fc0c9702797902e3975e75c532d0512ee4ea9c58f05042b07cb2419703a5955be3cf19dabd30ffb3
7
+ data.tar.gz: 3ced736e13ab314f47aea124fdea03188512b659e8f1579500d60a4ddf3d11a1f32f2b52573e54bc526c9494d50e9ca692818f1d8c1afbc0bc8570e2fc2a7d09
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Ubl
4
4
 
5
- Generate UBL invoices and credit notes for Peppol
5
+ Generate UBL (Universal Business Language) documents, such as invoices and credit notes, compliant with the Peppol network.
6
6
 
7
7
  ## installation
8
8
 
@@ -25,10 +25,7 @@ require "ubl"
25
25
 
26
26
  invoice = Ubl::Invoice.new
27
27
  invoice.invoice_nr = "INV-2025-001"
28
- invoice.issue_date = Date.new(2025, 6, 28)
29
- invoice.due_date = Date.new(2025, 7, 28)
30
- invoice.currency = "EUR"
31
- invoice.pdffile = __dir__ + "/invoice_test.pdf"
28
+ invoice.pdffile = "./invoice.pdf"
32
29
 
33
30
  invoice.add_supplier(
34
31
  name: "ACME Corp",
@@ -54,6 +51,20 @@ invoice.add_line(name: "Software License", quantity: 1, unit_price: 500.0, tax_r
54
51
  invoice.build
55
52
  ```
56
53
 
54
+ If you need the UBL.BE version:
55
+ ```ruby
56
+ invoice = Ubl::Invoice.new("UBL_BE")
57
+ ```
58
+
59
+ You can also validate the result.
60
+ You need Docker for the schematron validation.
61
+ With `schematron: false` you can disable this and only the xsd validation will run.
62
+ ```ruby
63
+ Tempfile.create("invoice.xml") do |invoice_file|
64
+ File.write(invoice_file, content)
65
+ p Ubl.validate_invoice(invoice_file.path, extension: "UBL_BE", schematron: true)
66
+ end
67
+ ```
57
68
 
58
69
  ## development
59
70
 
data/lib/ubl/builder.rb CHANGED
@@ -3,18 +3,15 @@
3
3
  require "nokogiri"
4
4
  require "date"
5
5
  require "base64"
6
+ require_relative "constants"
6
7
 
7
8
  module Ubl
8
9
  class UblBuilder
9
10
  attr_accessor :invoice_nr, :issue_date, :due_date, :currency, :supplier,
10
11
  :customer, :invoice_lines, :tax_total, :legal_monetary_total, :pdffile
11
12
 
12
- CUSTOMIZATION_ID = "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0"
13
- CUSTOMIZATION_UBL_BE = "urn:cen.eu:en16931:2017#conformant#urn:UBL.BE:1.0.0.20180214"
14
- PROFILE_ID = "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
15
-
16
13
  def initialize(extension = nil)
17
- @ubl_be = extension == "UBL_BE"
14
+ @ubl_be = extension == UBL_BE
18
15
  @issue_date = Date.today
19
16
  @due_date = @issue_date + 30
20
17
  @currency = "EUR"
@@ -0,0 +1,6 @@
1
+ module Ubl
2
+ CUSTOMIZATION_ID = "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0"
3
+ CUSTOMIZATION_UBL_BE = "urn:cen.eu:en16931:2017#conformant#urn:UBL.BE:1.0.0.20180214"
4
+ PROFILE_ID = "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
5
+ UBL_BE = "UBL_BE"
6
+ end
@@ -0,0 +1,78 @@
1
+ require "nokogiri"
2
+ require "date"
3
+ require "fileutils"
4
+ require "colorize"
5
+ require_relative "constants"
6
+
7
+ module Ubl
8
+ class Validator
9
+ def initialize(extension: nil, schematron: true)
10
+ @ubl_be = extension == UBL_BE
11
+ @schematron = schematron
12
+ end
13
+
14
+ def validate_invoice(path)
15
+ xsd = File.join(__dir__, "../../xsd/maindoc/UBL-Invoice-2.1.xsd")
16
+ validate(path, xsd)
17
+ end
18
+
19
+ def validate_credit_note(path)
20
+ xsd = File.join(__dir__, "../../xsd/maindoc/UBL-CreditNote-2.1.xsd")
21
+ validate(path, xsd)
22
+ end
23
+
24
+ private
25
+
26
+ def validate(path, xsd)
27
+ ubl_content = File.read(path)
28
+ errors = validate_xsd(ubl_content, xsd)
29
+ return errors if errors.any?
30
+
31
+ errors = validate_schematron(path) if @schematron
32
+
33
+ errors
34
+ end
35
+
36
+ def validate_xsd(xml_content, xsd)
37
+ return ["XSD not found: #{xsd}"] unless File.exist?(xsd)
38
+
39
+ begin
40
+ xml_doc = Nokogiri::XML(xml_content)
41
+ xsd_doc = Nokogiri::XML::Schema(File.open(xsd))
42
+ errors = xsd_doc.validate(xml_doc)
43
+ errors.map(&:message)
44
+ rescue => e
45
+ ["XSD validation error: #{e.message}"]
46
+ end
47
+ end
48
+
49
+ def validate_schematron(invoice_file)
50
+ env = @ubl_be ? "-e UBL_BE=true" : ""
51
+ cmd = "docker run --rm #{env} -v #{invoice_file}:/app/invoice.xml:ro ghcr.io/roel4d/peppol_schematron:latest 2>/dev/null"
52
+ # puts cmd
53
+ svrl_content = `#{cmd}`
54
+ parse_svrl_errors(svrl_content)
55
+ end
56
+
57
+ def get_svrl_errors(svrl_doc, flag, color)
58
+ errors = []
59
+ svrl_doc.xpath("//failed-assert[@flag=\"#{flag}\"]").each do |node|
60
+ test = node["test"].squeeze(" ")
61
+ # location = node['location']
62
+ text = node.xpath("text").map(&:content).join(" ").tr("\n", " ").squeeze(" ").strip
63
+ errors << flag.colorize(color) + ": #{text}\n #{test.colorize(:grey)}"
64
+ end
65
+ errors
66
+ end
67
+
68
+ # Parse SVRL (Schematron Validation Report Language) output for errors
69
+ def parse_svrl_errors(svrl_content)
70
+ svrl_doc = Nokogiri::XML(svrl_content)
71
+ svrl_doc.remove_namespaces!
72
+ errors = []
73
+ errors << get_svrl_errors(svrl_doc, "fatal", :red)
74
+ errors << get_svrl_errors(svrl_doc, "warning", :light_red)
75
+ errors.flatten
76
+ end
77
+ end
78
+ end
data/lib/ubl/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ubl
4
- VERSION = "0.0.4"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/ubl.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require_relative "ubl/builder"
2
+ require_relative "ubl/validate"
2
3
 
3
4
  ##
4
- # The Invoice and CreditNote class generates UBL (Universal Business Language) compliant XML
5
- # documents following PEPPOL standards.
5
+ # Generate UBL (Universal Business Language) documents,
6
+ # such as invoices and credit notes, compliant with the Peppol network.
6
7
  module Ubl
7
8
  class Invoice < UblBuilder
8
9
  ##
@@ -69,4 +70,32 @@ module Ubl
69
70
  builder.to_xml
70
71
  end
71
72
  end
73
+
74
+ ##
75
+ # Validate an invoice
76
+ #
77
+ # == Parameters
78
+ # * +path+ - The path to the XML invoice that needs validation.
79
+ # * +extension+ - Set to +"UBL_BE"+ to generate UBL.BE compliant documents.
80
+ # Defaults to +nil+ for standard PEPPOL format.
81
+ # * +schematron+ - If +true+, run a Schematron validation using Docker.
82
+ # Requires Docker to be installed and running. Defaults to +true+.
83
+ def self.validate_invoice(path, extension: nil, schematron: true)
84
+ validator = Validator.new(extension:, schematron:)
85
+ validator.validate_invoice(path)
86
+ end
87
+
88
+ ##
89
+ # Validate a credit note
90
+ #
91
+ # == Parameters
92
+ # * +path+ - The path to the XML credit note that needs validation.
93
+ # * +extension+ - Set to +"UBL_BE"+ to generate UBL.BE compliant documents.
94
+ # Defaults to +nil+ for standard PEPPOL format.
95
+ # * +schematron+ - If +true+, run a Schematron validation using Docker.
96
+ # Requires Docker to be installed and running. Defaults to +true+.
97
+ def self.validate_credit_note(path, extension: nil, schematron: true)
98
+ validator = Validator.new(extension:, schematron:)
99
+ validator.validate_credit_note(path)
100
+ end
72
101
  end