tradedoc 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.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +13 -0
  3. data/CHANGELOG.md +5 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +53 -0
  6. data/Rakefile +10 -0
  7. data/lib/tradedoc/code/agency.rb +8 -0
  8. data/lib/tradedoc/code/document_type.rb +95 -0
  9. data/lib/tradedoc/code/national_clearing_system.rb +97 -0
  10. data/lib/tradedoc/code/payment_means_type.rb +107 -0
  11. data/lib/tradedoc/code/tax_category.rb +97 -0
  12. data/lib/tradedoc/code.rb +12 -0
  13. data/lib/tradedoc/format/apeh.rb +36 -0
  14. data/lib/tradedoc/format/cii/coder/address.rb +55 -0
  15. data/lib/tradedoc/format/cii/coder/big_decimal.rb +21 -0
  16. data/lib/tradedoc/format/cii/coder/contact.rb +43 -0
  17. data/lib/tradedoc/format/cii/coder/date.rb +87 -0
  18. data/lib/tradedoc/format/cii/coder/document_reference.rb +33 -0
  19. data/lib/tradedoc/format/cii/coder/exchange_rate.rb +33 -0
  20. data/lib/tradedoc/format/cii/coder/financial_account.rb +45 -0
  21. data/lib/tradedoc/format/cii/coder/financial_institution.rb +39 -0
  22. data/lib/tradedoc/format/cii/coder/invoice.rb +127 -0
  23. data/lib/tradedoc/format/cii/coder/invoice_line.rb +88 -0
  24. data/lib/tradedoc/format/cii/coder/monetary_total.rb +36 -0
  25. data/lib/tradedoc/format/cii/coder/money.rb +27 -0
  26. data/lib/tradedoc/format/cii/coder/payment_means.rb +49 -0
  27. data/lib/tradedoc/format/cii/coder/period.rb +27 -0
  28. data/lib/tradedoc/format/cii/coder/remittance_advice.rb +130 -0
  29. data/lib/tradedoc/format/cii/coder/string.rb +21 -0
  30. data/lib/tradedoc/format/cii/coder/tax_subtotal.rb +35 -0
  31. data/lib/tradedoc/format/cii/coder/trade_party.rb +29 -0
  32. data/lib/tradedoc/format/cii/coder.rb +27 -0
  33. data/lib/tradedoc/format/cii.rb +12 -0
  34. data/lib/tradedoc/format/facturae.rb +51 -0
  35. data/lib/tradedoc/format/fatturapa/coder/invoice.rb +31 -0
  36. data/lib/tradedoc/format/fatturapa/coder.rb +8 -0
  37. data/lib/tradedoc/format/fatturapa.rb +13 -0
  38. data/lib/tradedoc/format/isdoc.rb +40 -0
  39. data/lib/tradedoc/format/ksef/coder/invoice.rb +32 -0
  40. data/lib/tradedoc/format/ksef/coder.rb +10 -0
  41. data/lib/tradedoc/format/ksef.rb +17 -0
  42. data/lib/tradedoc/format/mydata.rb +42 -0
  43. data/lib/tradedoc/format/nav.rb +38 -0
  44. data/lib/tradedoc/format/ubl/coder/address.rb +48 -0
  45. data/lib/tradedoc/format/ubl/coder/big_decimal.rb +21 -0
  46. data/lib/tradedoc/format/ubl/coder/contact.rb +29 -0
  47. data/lib/tradedoc/format/ubl/coder/country.rb +27 -0
  48. data/lib/tradedoc/format/ubl/coder/date.rb +21 -0
  49. data/lib/tradedoc/format/ubl/coder/document_reference.rb +55 -0
  50. data/lib/tradedoc/format/ubl/coder/exchange_rate.rb +33 -0
  51. data/lib/tradedoc/format/ubl/coder/financial_account.rb +32 -0
  52. data/lib/tradedoc/format/ubl/coder/financial_institution.rb +42 -0
  53. data/lib/tradedoc/format/ubl/coder/invoice.rb +92 -0
  54. data/lib/tradedoc/format/ubl/coder/invoice_line.rb +53 -0
  55. data/lib/tradedoc/format/ubl/coder/monetary_total.rb +39 -0
  56. data/lib/tradedoc/format/ubl/coder/money.rb +22 -0
  57. data/lib/tradedoc/format/ubl/coder/payment_means.rb +39 -0
  58. data/lib/tradedoc/format/ubl/coder/period.rb +27 -0
  59. data/lib/tradedoc/format/ubl/coder/product.rb +37 -0
  60. data/lib/tradedoc/format/ubl/coder/remittance_advice.rb +91 -0
  61. data/lib/tradedoc/format/ubl/coder/string.rb +21 -0
  62. data/lib/tradedoc/format/ubl/coder/tax_breakdown.rb +27 -0
  63. data/lib/tradedoc/format/ubl/coder/tax_category.rb +37 -0
  64. data/lib/tradedoc/format/ubl/coder/tax_subtotal.rb +29 -0
  65. data/lib/tradedoc/format/ubl/coder/trade_party.rb +37 -0
  66. data/lib/tradedoc/format/ubl/coder.rb +29 -0
  67. data/lib/tradedoc/format/ubl.rb +13 -0
  68. data/lib/tradedoc/format/zugferdv1/coder/invoice.rb +33 -0
  69. data/lib/tradedoc/format/zugferdv1/coder.rb +8 -0
  70. data/lib/tradedoc/format/zugferdv1.rb +21 -0
  71. data/lib/tradedoc/format.rb +110 -0
  72. data/lib/tradedoc/model/address.rb +21 -0
  73. data/lib/tradedoc/model/base.rb +153 -0
  74. data/lib/tradedoc/model/contact.rb +9 -0
  75. data/lib/tradedoc/model/country.rb +8 -0
  76. data/lib/tradedoc/model/country_subdivision.rb +8 -0
  77. data/lib/tradedoc/model/document.rb +9 -0
  78. data/lib/tradedoc/model/document_reference.rb +11 -0
  79. data/lib/tradedoc/model/exchange_rate.rb +17 -0
  80. data/lib/tradedoc/model/financial_account.rb +19 -0
  81. data/lib/tradedoc/model/financial_institution.rb +11 -0
  82. data/lib/tradedoc/model/invoice.rb +57 -0
  83. data/lib/tradedoc/model/invoice_line.rb +46 -0
  84. data/lib/tradedoc/model/monetary_total.rb +34 -0
  85. data/lib/tradedoc/model/payment_means.rb +27 -0
  86. data/lib/tradedoc/model/period.rb +8 -0
  87. data/lib/tradedoc/model/price.rb +21 -0
  88. data/lib/tradedoc/model/product.rb +18 -0
  89. data/lib/tradedoc/model/remittance_advice.rb +20 -0
  90. data/lib/tradedoc/model/remittance_advice_line.rb +24 -0
  91. data/lib/tradedoc/model/tax_breakdown.rb +11 -0
  92. data/lib/tradedoc/model/tax_category.rb +26 -0
  93. data/lib/tradedoc/model/tax_subtotal.rb +13 -0
  94. data/lib/tradedoc/model/trade_party.rb +9 -0
  95. data/lib/tradedoc/model.rb +33 -0
  96. data/lib/tradedoc/version.rb +5 -0
  97. data/lib/tradedoc/xml/reader.rb +163 -0
  98. data/lib/tradedoc/xml/writer.rb +56 -0
  99. data/lib/tradedoc/xml.rb +8 -0
  100. data/lib/tradedoc.rb +98 -0
  101. data/sig/tradedoc.rbs +4 -0
  102. metadata +187 -0
@@ -0,0 +1,130 @@
1
+ module Tradedoc
2
+ module Format
3
+ module CII
4
+ module Coder
5
+ class RemittanceAdvice
6
+ NS = {
7
+ "xmlns:qdt" => "urn:un:unece:uncefact:data:standard:QualifiedDataType:100",
8
+ "xmlns:ram" => "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100",
9
+ "xmlns:rsm" => "urn:un:unece:uncefact:data:standard:CrossIndustryRemittanceAdvice:100",
10
+ "xmlns:udt" => "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100",
11
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema"
12
+ }.freeze
13
+
14
+ def self.namespaces
15
+ NS
16
+ end
17
+
18
+ def self.can_parse?(xmldoc)
19
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns:rsm")
20
+ end
21
+
22
+ def self.ruby_type
23
+ Model::RemittanceAdvice
24
+ end
25
+
26
+ def self.dump(w, obj)
27
+ w.add("rsm:CrossIndustryRemittanceAdvice", NS) do
28
+ w.add("ExchangedDocument") do
29
+ w.add("ram:ID", obj.id)
30
+ w.render(obj.issue_date, as: "ram:IssueDateTime")
31
+
32
+ if (note = obj.note)
33
+ w.add("ram:IncludedNote") do
34
+ w.add("ram:Content", note)
35
+ end
36
+ end
37
+
38
+ w.render(obj.invoice_period, as: "ram:EffectiveSpecifiedPeriod")
39
+ end
40
+
41
+ w.add("rsm:TradeSettlementPayment") do
42
+ w.render(obj.payment_means.payment_id, as: "ram:EndToEndID")
43
+ w.render(obj.payment_means.instruction_id, as: "ram:InstructionID")
44
+ w.add("ram:SpecifiedPaymentTradeSettlement") do
45
+ w.render(obj.supplier, as: "PayeeTradeParty")
46
+ w.render(obj.buyer, as: "PayerTradeParty")
47
+ w.add("ram:SpecifiedTradeSettlementPaymentMonetarySummation") do
48
+ w.render(obj.total_payment_amount, as: "PaymentTotalAmount")
49
+ end
50
+ w.render(obj.payment_means)
51
+ end
52
+ end
53
+
54
+ obj.lines.each do |line|
55
+ w.add("rsm:SupplyChainTradeTransaction") do
56
+ w.add("ram:AssociatedDocumentLineDocument") do
57
+ w.add("ram:LineID", line.id)
58
+ end
59
+
60
+ w.add("ram:ApplicableHeaderTradeSettlement") do
61
+ w.render(line.exchange_rate, as: "ram:PaymentApplicableTradeCurrencyExchange")
62
+
63
+ # The final amount *in the payout currency* for this line.
64
+ w.add("ram:SpecifiedTradeSettlementHeaderMonetarySummation") do
65
+ w.render(line.balance_amount, as: "PaymentTotalAmount")
66
+ end
67
+
68
+ w.render(line.document_reference, as: "ram:InvoiceReferencedDocument")
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def self.parse(r)
76
+ ruby_type.new.tap do |ra|
77
+ r.with_node("rsm:CrossIndustryRemittanceAdvice") do
78
+ r.with_node("rsm:ExchangedDocument") do
79
+ r.parse("ram:ID", :String) { ra.id = it }
80
+ r.with_node("ram:IncludedNote") do
81
+ r.parse("ram:Content", :String) { ra.note = it }
82
+ end
83
+ r.parse("ram:IssueDateTime", :Date) { ra.issue_date = it }
84
+ r.parse("ram:EffectiveSpecifiedPeriod", :Period) { ra.invoice_period = it }
85
+ end
86
+
87
+ r.with_node("rsm:TradeSettlementPayment") do
88
+ r.with_node("ram:SpecifiedPaymentTradeSettlement") do
89
+ r.parse("ram:PayeeTradeParty", :TradeParty) { ra.supplier = it }
90
+ r.parse("ram:PayerTradeParty", :TradeParty) { ra.buyer = it }
91
+ r.parse("ram:SpecifiedTradeSettlementPaymentMeans", :PaymentMeans) { ra.payment_means = it }
92
+
93
+ r.with_node("ram:SpecifiedTradeSettlementPaymentMonetarySummation") do
94
+ r.parse("ram:PaymentTotalAmount", :Money) { ra.total_payment_amount = it }
95
+ end
96
+ end
97
+
98
+ # Our `PaymentMeans` is spread across multiple different nodes, so we can't
99
+ # do a nice clean parse all at once. We have to add to the existing object.
100
+ r.parse("ram:EndToEndID", :String) { ra.payment_means.payment_id = it }
101
+ r.parse("ram:InstructionID", :String) { ra.payment_means.instruction_id = it }
102
+ end
103
+
104
+ r.with_nodes("rsm:SupplyChainTradeTransaction") do
105
+ line = Model::RemittanceAdviceLine.new
106
+
107
+ r.with_node("ram:AssociatedDocumentLineDocument") do
108
+ r.parse("ram:LineID", :String) { line.id = it }
109
+ end
110
+
111
+ r.with_node("ram:ApplicableHeaderTradeSettlement") do
112
+ r.parse("ram:PaymentApplicableTradeCurrencyExchange", :ExchangeRate) { line.exchange_rate = it }
113
+ r.with_node("ram:SpecifiedTradeSettlementHeaderMonetarySummation") do
114
+ r.parse("ram:GrandTotalAmount", :Money) { line.debit_amount = it }
115
+ r.parse("ram:TotalDiscountBasis", :Money) { line.credit_amount = it }
116
+ r.parse("ram:PaymentTotalAmount", :Money) { line.balance_amount = it }
117
+ end
118
+ r.parse("ram:InvoiceReferencedDocument", :DocumentReference) { line.document_reference = it }
119
+ end
120
+
121
+ ra.lines.push(line)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,21 @@
1
+ module Tradedoc
2
+ module Format
3
+ module CII
4
+ module Coder
5
+ class String
6
+ def self.ruby_type
7
+ ::String
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add(as, obj)
12
+ end
13
+
14
+ def self.parse(r, strip: true, nilify: true)
15
+ r.text(strip:, nilify:)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ module Tradedoc
2
+ module Format
3
+ module CII
4
+ module Coder
5
+ class TaxSubtotal
6
+ def self.ruby_type
7
+ Model::TaxSubtotal
8
+ end
9
+
10
+ def self.dump(w, obj, as: "ram:ApplicableTradeTax")
11
+ w.add(as) do
12
+ w.render(obj.tax_amount, as: "ram:CalculatedAmount")
13
+ w.render(obj.tax_category.tax_scheme, as: "ram:TypeCode")
14
+ w.render(obj.taxable_amount, as: "ram:BasisAmount")
15
+ w.render(obj.tax_category.code.edifact_id, as: "ram:CategoryCode")
16
+ w.render(obj.tax_category.rate_percent, as: "ram:RateApplicablePercent")
17
+ end
18
+ end
19
+
20
+ def self.parse(r, default_currency: nil)
21
+ ruby_type.new.tap do |obj|
22
+ obj.tax_category ||= Model::TaxCategory.new
23
+
24
+ r.parse("ram:CalculatedAmount", :Money, default_currency:) { obj.tax_amount = it }
25
+ r.parse("ram:TypeCode", :String) { obj.tax_category.tax_scheme = it }
26
+ r.parse("ram:BasisAmount", :Money, default_currency:) { obj.taxable_amount = it }
27
+ r.parse("ram:CategoryCode", :String) { obj.tax_category.code = it }
28
+ r.parse("ram:RateApplicablePercent", :BigDecimal) { obj.tax_category.rate_percent = it }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module Tradedoc
2
+ module Format
3
+ module CII
4
+ module Coder
5
+ class TradeParty
6
+ def self.ruby_type
7
+ Model::TradeParty
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add(as) do
12
+ w.render(obj.name, as: "Name")
13
+ w.render(obj.contact, as: "ram:DefinedTradeContact")
14
+ w.render(obj.address, as: "PostalTradeAddress")
15
+ end
16
+ end
17
+
18
+ def self.parse(r)
19
+ ruby_type.new.tap do |tp|
20
+ r.parse("ram:Name", :String) { tp.name = it }
21
+ r.parse("ram:DefinedTradeContact", :Contact) { tp.contact = it }
22
+ r.parse("ram:PostalTradeAddress", :Address) { tp.address = it }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module Tradedoc
2
+ module Format
3
+ module CII
4
+ module Coder
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require_relative "coder/address"
11
+ require_relative "coder/big_decimal"
12
+ require_relative "coder/contact"
13
+ require_relative "coder/date"
14
+ require_relative "coder/document_reference"
15
+ require_relative "coder/exchange_rate"
16
+ require_relative "coder/financial_account"
17
+ require_relative "coder/financial_institution"
18
+ require_relative "coder/invoice"
19
+ require_relative "coder/invoice_line"
20
+ require_relative "coder/monetary_total"
21
+ require_relative "coder/money"
22
+ require_relative "coder/payment_means"
23
+ require_relative "coder/period"
24
+ require_relative "coder/remittance_advice"
25
+ require_relative "coder/string"
26
+ require_relative "coder/tax_subtotal"
27
+ require_relative "coder/trade_party"
@@ -0,0 +1,12 @@
1
+ # CII, or Cross-Industry Invoice standard from UN/CEFACT
2
+ module Tradedoc
3
+ module Format
4
+ module CII
5
+ extend Accessors
6
+ extend Finders
7
+ extend XMLSerialization
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative "cii/coder"
@@ -0,0 +1,51 @@
1
+ module Tradedoc
2
+ module Format
3
+ # Spanish e-invoice format.
4
+ # No actual support implemented yet, just detection.
5
+ module FacturaE
6
+ extend Accessors
7
+ extend Finders
8
+ extend XMLSerialization
9
+
10
+ def self.file_extensions
11
+ Set[".xml", ".xsig"]
12
+ end
13
+
14
+ module Coder
15
+ class Invoice
16
+ # Each revision of the spec gets its own namespace.
17
+ # `NS` is for building current-spec documents.
18
+ # `OTHER_NS` is for detecting legacy versions that can still be parsed.
19
+ NS = {
20
+ "xmlns" => "http://www.facturae.gob.es/formato/Versiones/Facturaev3_2_2.xml"
21
+ }.freeze
22
+
23
+ OTHER_NS = Set[
24
+ "http://www.facturae.es/Facturae/2007/v3.0/Facturae",
25
+ "http://www.facturae.es/Facturae/2009/v3.2/Facturae",
26
+ "http://www.facturae.es/Facturae/2014/v3.2.1/Facturae"
27
+ ].freeze
28
+
29
+ private_constant :NS, :OTHER_NS
30
+
31
+ def self.namespaces
32
+ NS
33
+ end
34
+
35
+ def self.can_parse?(xmldoc)
36
+ root_ns = xmldoc.root.namespace&.href
37
+ namespaces.fetch("xmlns") == root_ns || OTHER_NS.include?(root_ns)
38
+ end
39
+
40
+ def self.dump(w, obj)
41
+ raise NotImplementedError
42
+ end
43
+
44
+ def self.parse(r)
45
+ raise NotImplementedError
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ module Tradedoc
2
+ module Format
3
+ module FatturaPA
4
+ module Coder
5
+ class Invoice
6
+ NS = {
7
+ "xmlns:p" => "http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"
8
+ }
9
+ private_constant :NS
10
+
11
+ def self.namespaces
12
+ NS
13
+ end
14
+
15
+ # @param xmldoc [Nokogiri::XML::Document]
16
+ def self.can_parse?(xmldoc)
17
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns:p")
18
+ end
19
+
20
+ def self.dump(w, obj)
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def self.parse(r)
25
+ raise NotImplementedError
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ module Tradedoc
2
+ module FatturaPA
3
+ module Coder
4
+ end
5
+ end
6
+ end
7
+
8
+ require_relative "coder/invoice"
@@ -0,0 +1,13 @@
1
+ module Tradedoc
2
+ module Format
3
+ # Italian e-invoice format. Not compliant with EN 16931.
4
+ # https://www.fatturapa.gov.it/en/norme-e-regole/documentazione-fattura-elettronica/formato-fatturapa/
5
+ module FatturaPA
6
+ extend Accessors
7
+ extend Finders
8
+ extend XMLSerialization
9
+ end
10
+ end
11
+ end
12
+
13
+ require_relative "fatturapa/coder"
@@ -0,0 +1,40 @@
1
+ module Tradedoc
2
+ module Format
3
+ # Czechia
4
+ module ISDOC
5
+ extend Accessors
6
+ extend Finders
7
+ extend XMLSerialization
8
+
9
+ def self.file_extensions
10
+ Set[".isdoc"]
11
+ end
12
+
13
+ module Coder
14
+ class Invoice
15
+ NS = {
16
+ "xmlns" => "http://isdoc.cz/namespace/2013"
17
+ }.freeze
18
+
19
+ private_constant :NS
20
+
21
+ def self.namespaces
22
+ NS
23
+ end
24
+
25
+ def self.can_parse?(xmldoc)
26
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns")
27
+ end
28
+
29
+ def self.dump(w, obj)
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def self.parse(r)
34
+ raise NotImplementedError
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ module Tradedoc
2
+ module Format
3
+ module KSEF
4
+ module Coder
5
+ class Invoice
6
+ NS = {
7
+ "xmlns" => "http://crd.gov.pl/wzor/2025/06/25/13775/",
8
+ "xmlns:etd" => "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2022/01/05/eD/DefinicjeTypy/"
9
+ }
10
+ private_constant :NS
11
+
12
+ def self.namespaces
13
+ NS
14
+ end
15
+
16
+ # @param xmldoc [Nokogiri::XML::Document]
17
+ def self.can_parse?(xmldoc)
18
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns")
19
+ end
20
+
21
+ def self.dump(w, obj)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def self.parse(r)
26
+ raise NotImplementedError
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,10 @@
1
+ module Tradedoc
2
+ module Format
3
+ module KSEF
4
+ module Coder
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require_relative "coder/invoice"
@@ -0,0 +1,17 @@
1
+ module Tradedoc
2
+ module Format
3
+ # Poland
4
+ # https://ksef.mf.gov.pl/
5
+ module KSEF
6
+ extend Accessors
7
+ extend Finders
8
+ extend XMLSerialization
9
+
10
+ def self.label
11
+ "KSeF"
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ require_relative "ksef/coder"
@@ -0,0 +1,42 @@
1
+ module Tradedoc
2
+ module Format
3
+ # Greece
4
+ module MyData
5
+ extend Accessors
6
+ extend Finders
7
+ extend XMLSerialization
8
+
9
+ def self.label
10
+ "myDATA"
11
+ end
12
+
13
+ module Coder
14
+ class Invoice
15
+ NS = {
16
+ "xmlns" => "http://www.aade.gr/myDATA/invoice/v1.0",
17
+ "xmlns:icls" => "https://www.aade.gr/myDATA/incomeClassificaton/v1.0",
18
+ "xmlns:ecls" => "https://www.aade.gr/myDATA/expensesClassificaton/v1.0"
19
+ }.freeze
20
+
21
+ private_constant :NS
22
+
23
+ def self.namespaces
24
+ NS
25
+ end
26
+
27
+ def self.can_parse?(xmldoc)
28
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns")
29
+ end
30
+
31
+ def self.dump(w, obj)
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def self.parse(r)
36
+ raise NotImplementedError
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ module Tradedoc
2
+ module Format
3
+ # Current Hungarian e-invoice format
4
+ module NAV
5
+ extend Accessors
6
+ extend Finders
7
+ extend XMLSerialization
8
+
9
+ module Coder
10
+ class Invoice
11
+ NS = {
12
+ "xmlns" => "http://schemas.nav.gov.hu/OSA/3.0/data",
13
+ "xmlns:base" => "http://schemas.nav.gov.hu/OSA/3.0/base",
14
+ "xmlns:common" => "http://schemas.nav.gov.hu/NTCA/1.0/common"
15
+ }.freeze
16
+
17
+ private_constant :NS
18
+
19
+ def self.namespaces
20
+ NS
21
+ end
22
+
23
+ def self.can_parse?(xmldoc)
24
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns")
25
+ end
26
+
27
+ def self.dump(w, obj)
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def self.parse(r)
32
+ raise NotImplementedError
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,48 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Address
6
+ def self.ruby_type
7
+ Model::Address
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add("cac:#{as}") do
12
+ w.render(obj.street_name, as: "cbc:StreetName")
13
+ w.render(obj.building_number, as: "cbc:BuildingNumber")
14
+ w.render(obj.city, as: "cbc:CityName")
15
+ w.render(obj.postal_code, as: "cbc:PostalZone")
16
+ w.render(obj.subdivision&.name, as: "cbc:CountrySubentity")
17
+ w.render(obj.subdivision&.code, as: "cbc:CountrySubentityCode")
18
+ obj.lines.each do |line|
19
+ w.add("cac:AddressLine") do
20
+ w.add("cbc:Line", line)
21
+ end
22
+ end
23
+ w.render(obj.country)
24
+ end
25
+ end
26
+
27
+ def self.parse(r)
28
+ ruby_type.new.tap do |obj|
29
+ obj.subdivision = {}
30
+ r.parse("cbc:StreetName", :String) { obj.street_name = it }
31
+ r.parse("cbc:BuildingNumber", :String) { obj.building_number = it }
32
+ r.parse("cbc:CityName", :String) { obj.city = it }
33
+ r.parse("cbc:PostalZone", :String) { obj.postal_code = it }
34
+ r.parse("cbc:CountrySubentity", :String) { obj.subdivision.name = it }
35
+ r.parse("cbc:CountrySubentityCode", :String) { obj.subdivision.code = it }
36
+ r.parse("cac:Country", :Country) { obj.country = it }
37
+ r.with_nodes("cac:AddressLine") do
38
+ r.with_node("cbc:Line") do
39
+ obj.lines.push(r.text)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class BigDecimal
6
+ def self.ruby_type
7
+ ::BigDecimal
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add(as, obj.to_s("F"))
12
+ end
13
+
14
+ def self.parse(r)
15
+ ruby_type.interpret_loosely(r.text)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Contact
6
+ def self.ruby_type
7
+ Model::Contact
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:Contact")
11
+ w.add(as) do
12
+ w.render(obj.name, as: "cbc:Name")
13
+ w.render(obj.phone, as: "cbc:Telephone")
14
+ w.render(obj.email, as: "cbc:ElectronicMail")
15
+ end
16
+ end
17
+
18
+ def self.parse(r)
19
+ ruby_type.new.tap do |c|
20
+ r.parse("cbc:Name", :String) { c.name = it }
21
+ r.parse("cbc:Telephone", :String) { c.phone = it }
22
+ r.parse("cbc:ElectronicMail", :String) { c.email = it }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Country
6
+ def self.ruby_type
7
+ Model::Country
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:Country")
11
+ w.add(as) do
12
+ w.render(obj.iso_code, as: "cbc:IdentificationCode")
13
+ w.render(obj.name, as: "cbc:Name")
14
+ end
15
+ end
16
+
17
+ def self.parse(r)
18
+ ruby_type.new.tap do |c|
19
+ r.parse("cbc:IdentificationCode", :String) { c.iso_code = it }
20
+ r.parse("cbc:Name", :String) { c.name = it }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end