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,21 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Date
6
+ def self.ruby_type
7
+ ::Date
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add("cbc:#{as}", obj.to_date.iso8601)
12
+ end
13
+
14
+ def self.parse(r)
15
+ ruby_type.parse(r.text)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,55 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class DocumentReference
6
+ DREF_SUFFIX = "DocumentReference"
7
+
8
+ # Element names are based on the document type.
9
+ # Map based on our internal document type IDs.
10
+ TYPE_MAP = {
11
+ commercial_invoice: "Invoice",
12
+ credit_note: "CreditNote",
13
+ debit_note: "DebitNote"
14
+ }
15
+
16
+ private_constant :DREF_SUFFIX, :TYPE_MAP
17
+
18
+ def self.ruby_type
19
+ Model::DocumentReference
20
+ end
21
+
22
+ def self.dump(w, obj, as:)
23
+ element_name_root = TYPE_MAP.fetch(obj.type.id)
24
+
25
+ w.add(as) do
26
+ w.add("cac:#{element_name_root}#{DREF_SUFFIX}") do
27
+ w.add("cbc:ID", obj.id)
28
+ w.add("cbc:UUID", obj.uuid)
29
+ w.render(obj.issue_date, as: "IssueDate")
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.parse(r)
35
+ # The type of the document reference is embedded in the node name, so we
36
+ # have to match that manually to derive the type and pick the right child node.
37
+ dr_node = r.node.children.detect { it.node_name.end_with?(DREF_SUFFIX) }
38
+
39
+ return if dr_node.nil?
40
+
41
+ ruby_type.new.tap do |dr|
42
+ dr.type = TYPE_MAP.key(dr_node.node_name.delete_suffix(DREF_SUFFIX))
43
+
44
+ r.with_node(dr_node) do
45
+ r.parse("cbc:ID", :String) { dr.id = it }
46
+ r.parse("cbc:UUID", :String) { dr.uuid = it }
47
+ r.parse("cbc:IssueDate", :Date) { dr.issue_date = it }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,33 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class ExchangeRate
6
+ def self.ruby_type
7
+ Model::ExchangeRate
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:ExchangeRate")
11
+ w.add(as) do
12
+ w.render(obj.source_currency_code, as: "cbc:SourceCurrencyCode")
13
+ w.render(obj.target_currency_code, as: "cbc:TargetCurrencyCode")
14
+ w.render(obj.market_id, as: "cbc:ExchangeMarketID")
15
+ w.render(obj.rate, as: "cbc:CalculationRate")
16
+ w.render(obj.date, as: "Date")
17
+ end
18
+ end
19
+
20
+ def self.parse(r)
21
+ ruby_type.new.tap do |xr|
22
+ r.parse("cbc:SourceCurrencyCode", :String) { xr.source_currency_code = it }
23
+ r.parse("cbc:TargetCurrencyCode", :String) { xr.target_currency_code = it }
24
+ r.parse("cbc:CalculationRate", :BigDecimal) { xr.rate = it }
25
+ r.parse("cbc:ExchangeMarketID", :String) { xr.market_id = it }
26
+ r.parse("cbc:Date", :Date) { xr.date = it }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class FinancialAccount
6
+ def self.ruby_type
7
+ Model::FinancialAccount
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add(as) do
12
+ w.add("cbc:ID", obj.account_number, schemeName: obj.scheme_name)
13
+ w.render(obj.financial_institution)
14
+ end
15
+ end
16
+
17
+ def self.parse(r)
18
+ ruby_type.new.tap do |obj|
19
+ r.with_node("cbc:ID") do
20
+ r.parse("@schemeName", :String) { obj.scheme_name = it }
21
+ r.parse("text()", :String) { obj.account_number = it }
22
+ end
23
+ r.parse("cac:FinancialInstitutionBranch", :FinancialInstitution) do
24
+ obj.financial_institution = it
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class FinancialInstitution
6
+ def self.ruby_type
7
+ Model::FinancialInstitution
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:FinancialInstitutionBranch")
11
+ w.add(as) do
12
+ w.add("cac:FinancialInstitution") do
13
+ # If there's no NCS, then this is a SWIFT code
14
+ scheme_name = if (ncs = obj.national_clearing_system)
15
+ ncs.iso_code
16
+ else
17
+ "SWIFTBIC"
18
+ end
19
+
20
+ w.add("cbc:ID", obj.id, schemeName: scheme_name)
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.parse(r)
26
+ r.with_node("cac:FinancialInstitution") do
27
+ ruby_type.new.tap do |obj|
28
+ r.with_node("cbc:ID") do
29
+ obj.id = r.text
30
+
31
+ # Won't be present for SWIFT/BIC, and that's what we want
32
+ obj.national_clearing_system =
33
+ Tradedoc::Code::NationalClearingSystem.find_by_iso_code(r.attribute("schemeName"))
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,92 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Invoice
6
+ NS = {
7
+ "xmlns:inv" => "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
8
+ "xmlns:cac" => "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2",
9
+ "xmlns:cbc" => "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",
10
+ "xmlns:ext" => "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
11
+ }.freeze
12
+
13
+ private_constant :NS
14
+
15
+ def self.namespaces
16
+ NS
17
+ end
18
+
19
+ # @param xmldoc [Nokogiri::XML::Document]
20
+ def self.can_parse?(xmldoc)
21
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns:inv")
22
+ end
23
+
24
+ def self.ruby_type
25
+ Model::Invoice
26
+ end
27
+
28
+ def self.dump(w, obj)
29
+ w.add("inv:Invoice", NS) do
30
+ w.render(obj.specification_id, as: "cbc:CustomizationID")
31
+ w.render(obj.invoice_number, as: "cbc:ID")
32
+ w.render(obj.issue_date, as: "IssueDate")
33
+ w.render(obj.due_date, as: "DueDate")
34
+ w.render(obj.invoice_type_code, as: "cbc:InvoiceTypeCode", listAgencyID: Code::Agency::CEFACT)
35
+ w.render(obj.note, as: "cbc:Note")
36
+ w.render(obj.currency_code, as: "cbc:DocumentCurrencyCode", listAgencyID: Code::Agency::CEFACT)
37
+ w.render(obj.invoice_period, as: "InvoicePeriod")
38
+ if (po_number = obj.purchase_order_number)
39
+ w.add("cac:OrderReference") do
40
+ w.render(po_number, as: "cbc:ID")
41
+ end
42
+ end
43
+ if (supplier = obj.supplier)
44
+ w.add("cac:AccountingSupplierParty") do
45
+ w.render(supplier, as: "cac:Party")
46
+ end
47
+ end
48
+ if (buyer = obj.buyer)
49
+ w.add("cac:AccountingCustomerParty") do
50
+ w.render(buyer, as: "cac:Party")
51
+ end
52
+ end
53
+ w.render(obj.monetary_total&.tax_breakdown)
54
+ w.render(obj.monetary_total)
55
+ w.render_list(obj.lines)
56
+ end
57
+ end
58
+
59
+ def self.parse(r)
60
+ ruby_type.new.tap do |inv|
61
+ r.with_node("inv:Invoice") do
62
+ r.parse("cbc:ID", :String) { inv.invoice_number = it }
63
+ r.parse("cbc:IssueDate", :Date) { inv.issue_date = it }
64
+ r.parse("cbc:DueDate", :Date) { inv.due_date = it }
65
+ r.parse("cbc:InvoiceTypeCode", :String) { inv.invoice_type_code = it }
66
+ r.parse("cbc:Note", :String) { inv.note = it }
67
+ r.parse("cbc:DocumentCurrencyCode", :String) { inv.currency_code = it }
68
+ r.parse("cac:InvoicePeriod", :Period) { inv.invoice_period = it }
69
+ r.parse("cac:AccountingSupplierParty", :TradeParty) { inv.supplier = it }
70
+ r.parse("cac:AccountingCustomerParty", :TradeParty) { inv.buyer = it }
71
+ r.parse_list("cac:PaymentMeans", :PaymentMeans) { inv.payment_means = it }
72
+ r.parse("cac:LegalMonetaryTotal", :MonetaryTotal) { inv.monetary_total = it }
73
+ r.parse("cac:TaxTotal", :TaxBreakdown) { inv.monetary_total.tax_breakdown = it }
74
+ r.parse_list("cac:InvoiceLine", :InvoiceLine) { inv.lines = it }
75
+
76
+ r.with_node("cac:OrderReference") do
77
+ r.parse("cbc:ID", :String) { inv.purchase_order_number = it }
78
+ end
79
+
80
+ # The due date may have been put into payment means
81
+ # This is allowed per the Peppol docs
82
+ if inv.due_date.nil?
83
+ r.parse("cac:PaymentMeans/cbc:PaymentDueDate", :Date) { inv.due_date = it }
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,53 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class InvoiceLine
6
+ def self.ruby_type
7
+ Model::InvoiceLine
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:InvoiceLine")
11
+ w.add(as) do
12
+ w.render(obj.id, as: "cbc:ID")
13
+ w.render(obj.invoiced_quantity, as: "cbc:InvoicedQuantity")
14
+ w.render(obj.total_excluding_tax, as: "LineExtensionAmount")
15
+ if (total_tax = obj.total_tax)
16
+ w.add("cac:TaxTotal") do
17
+ w.render(total_tax, as: "TotalTax")
18
+ end
19
+ end
20
+
21
+ w.render(obj.product)
22
+
23
+ if (price = obj.price)
24
+ w.add("cac:Price") do
25
+ w.render(price.net, as: "PriceAmount")
26
+ w.render(price.base_quantity, as: "cbc:BaseQuantity")
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.parse(r)
33
+ ruby_type.new.tap do |line|
34
+ r.parse("cbc:ID", :String) { line.id = it }
35
+ r.parse("cbc:InvoicedQuantity", :BigDecimal) { line.invoiced_quantity = it }
36
+ r.parse("cbc:LineExtensionAmount", :Money) { line.total_excluding_tax = it }
37
+ r.with_node("cac:TaxTotal") do
38
+ r.parse("cbc:TotalTax", :Money) { line.total_tax = it }
39
+ end
40
+ r.parse("cac:Item", :Product) { line.product = it }
41
+ r.with_node("cac:Price") do
42
+ line.price = Model::Price.new.tap do |price|
43
+ r.parse("cbc:PriceAmount", :Money) { price.net = it }
44
+ r.parse("cbc:BaseQuantity", :BigDecimal) { price.base_quantity = it }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,39 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class MonetaryTotal
6
+ def self.ruby_type
7
+ Model::MonetaryTotal
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:LegalMonetaryTotal")
11
+ w.add(as) do
12
+ w.render(obj.line_items_tax_exclusive, as: "LineExtensionAmount")
13
+ w.render(obj.tax_exclusive, as: "TaxExclusiveAmount")
14
+ w.render(obj.tax_inclusive, as: "TaxInclusiveAmount")
15
+ w.render(obj.discounts, as: "AllowanceTotalAmount")
16
+ w.render(obj.charges, as: "ChargeTotalAmount")
17
+ w.render(obj.prepaid, as: "PrepaidAmount")
18
+ w.render(obj.rounding, as: "PayableRoundingAmount")
19
+ w.render(obj.payable, as: "PayableAmount")
20
+ end
21
+ end
22
+
23
+ def self.parse(r)
24
+ ruby_type.new.tap do |mt|
25
+ r.parse("cbc:LineExtensionAmount", :Money) { mt.line_items_tax_exclusive = it }
26
+ r.parse("cbc:TaxExclusiveAmount", :Money) { mt.tax_exclusive = it }
27
+ r.parse("cbc:TaxInclusiveAmount", :Money) { mt.tax_inclusive = it }
28
+ r.parse("cbc:AllowanceTotalAmount", :Money) { mt.discounts = it }
29
+ r.parse("cbc:ChargeTotalAmount", :Money) { mt.charges = it }
30
+ r.parse("cbc:PrepaidAmount", :Money) { mt.prepaid = it }
31
+ r.parse("cbc:PayableRoundingAmount", :Money) { mt.rounding = it }
32
+ r.parse("cbc:PayableAmount", :Money) { mt.payable = it }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Money
6
+ def self.ruby_type
7
+ ::Money
8
+ end
9
+
10
+ def self.dump(w, obj, as:, decimals: 2)
11
+ as_string = obj.to_d.round(decimals).to_s("F")
12
+ w.add("cbc:#{as}", as_string, currencyID: obj.currency.iso_code)
13
+ end
14
+
15
+ def self.parse(r)
16
+ ruby_type.from_amount(BigDecimal(r.text), r.attribute!("currencyID"))
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class PaymentMeans
6
+ def self.ruby_type
7
+ Model::PaymentMeans
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:PaymentMeans")
11
+ w.add(as) do
12
+ w.add("cbc:PaymentMeansCode", obj.type_code.code, listID: "UN/CE 4461", listAgencyID: Code::Agency::CEFACT)
13
+ w.render(obj.instruction_id, as: "cbc:InstructionID")
14
+ obj.messages.each do |msg|
15
+ w.add("cbc:InstructionNote", msg)
16
+ end
17
+ w.render(obj.payment_id, as: "cbc:PaymentID")
18
+ w.render(obj.sending_account, as: "cac:PayerFinancialAccount")
19
+ w.render(obj.receiving_account, as: "cac:PayeeFinancialAccount")
20
+ end
21
+ end
22
+
23
+ def self.parse(r)
24
+ ruby_type.new.tap do |obj|
25
+ r.parse("cbc:PaymentMeansCode", :String) { obj.type_code = it }
26
+ r.parse("cbc:PaymentID", :String) { obj.payment_id = it }
27
+ r.parse("cbc:InstructionID", :String) { obj.instruction_id = it }
28
+ r.with_nodes("cbc:InstructionNote") do
29
+ obj.messages.push(r.text)
30
+ end
31
+ r.parse("cac:PayerFinancialAccount", :FinancialAccount) { obj.sending_account = it }
32
+ r.parse("cac:PayeeFinancialAccount", :FinancialAccount) { obj.receiving_account = it }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Period
6
+ def self.ruby_type
7
+ Model::Period
8
+ end
9
+
10
+ def self.dump(w, obj, as:)
11
+ w.add("cac:#{as}") do
12
+ w.render(obj.start_date, as: "StartDate")
13
+ w.render(obj.end_date, as: "EndDate")
14
+ end
15
+ end
16
+
17
+ def self.parse(r)
18
+ ruby_type.new.tap do |obj|
19
+ r.parse("cbc:StartDate", :Date) { obj.start_date = it }
20
+ r.parse("cbc:EndDate", :Date) { obj.end_date = it }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class Product
6
+ def self.ruby_type
7
+ Model::Product
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:Item")
11
+ w.add(as) do
12
+ w.render(obj.description, as: "cbc:Description")
13
+ w.render(obj.name, as: "cbc:Name")
14
+ if (id = obj.seller_assigned_id)
15
+ w.add("cac:SellersItemIdentification") do
16
+ w.render(id, as: "cbc:ID")
17
+ end
18
+ end
19
+ w.render(obj.tax_category, as: "cac:ClassifiedTaxCategory")
20
+ end
21
+ end
22
+
23
+ def self.parse(r)
24
+ ruby_type.new.tap do |prod|
25
+ r.parse("cbc:Description", :String) { prod.description = it }
26
+ r.parse("cbc:Name", :String) { prod.name = it }
27
+ r.with_node("cac:SellersItemIdentification") do
28
+ r.parse("cbc:ID", :String) { prod.seller_assigned_id = it }
29
+ end
30
+ r.parse("cac:ClassifiedTaxCategory", :TaxCategory) { prod.tax_category = it }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,91 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class RemittanceAdvice
6
+ NS = {
7
+ "xmlns:rad" => "urn:oasis:names:specification:ubl:schema:xsd:RemittanceAdvice-2",
8
+ "xmlns:cac" => "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2",
9
+ "xmlns:cbc" => "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
10
+ }.freeze
11
+
12
+ private_constant :NS
13
+
14
+ def self.namespaces
15
+ NS
16
+ end
17
+
18
+ # @param xmldoc [Nokogiri::XML::Document]
19
+ def self.can_parse?(xmldoc)
20
+ xmldoc.root.namespace&.href == namespaces.fetch("xmlns:rad")
21
+ end
22
+
23
+ def self.ruby_type
24
+ Model::RemittanceAdvice
25
+ end
26
+
27
+ def self.dump(w, obj)
28
+ w.add("rad:RemittanceAdvice", NS) do
29
+ w.add("cbc:ID", obj.id)
30
+ w.render(obj.uuid, as: "cbc:UUID")
31
+ w.render(obj.issue_date, as: "IssueDate")
32
+ w.render(obj.note, as: "cbc:Note")
33
+
34
+ w.render(obj.total_payment_amount, as: "TotalPaymentAmount")
35
+ w.render(obj.invoice_period, as: "InvoicePeriod")
36
+
37
+ w.add("cac:AccountingCustomerParty") do
38
+ w.render(obj.buyer)
39
+ end
40
+
41
+ w.add("cac:AccountingSupplierParty") do
42
+ w.render(obj.supplier)
43
+ end
44
+
45
+ w.render(obj.payment_means)
46
+
47
+ obj.lines.each do |line|
48
+ w.add("cac:RemittanceAdviceLine") do
49
+ w.add("cbc:ID", line.id)
50
+ w.render(line.note, as: "cbc:Note")
51
+ w.render(line.balance_amount, as: "BalanceAmount")
52
+ w.render(line.document_reference, as: "cac:BillingReference")
53
+ w.render(line.exchange_rate, as: "cac:ExchangeRate")
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ def self.parse(r)
60
+ obj = ruby_type.new
61
+
62
+ r.with_node("rad:RemittanceAdvice") do
63
+ r.parse("cbc:ID", :String) { obj.id = it }
64
+ r.parse("cbc:UUID", :String) { obj.uuid = it }
65
+ r.parse("cbc:IssueDate", :Date) { obj.issue_date = it }
66
+ r.parse("cbc:Note", :String) { obj.note = it }
67
+ r.parse("cbc:TotalPaymentAmount", :Money) { obj.total_payment_amount = it }
68
+ r.parse("cac:AccountingCustomerParty", :TradeParty) { obj.buyer = it }
69
+ r.parse("cac:AccountingSupplierParty", :TradeParty) { obj.supplier = it }
70
+ r.parse("cac:PaymentMeans", :PaymentMeans) { obj.payment_means = it }
71
+ r.parse("cac:InvoicePeriod", :Period) { obj.invoice_period = it }
72
+
73
+ r.with_nodes("cac:RemittanceAdviceLine") do
74
+ line = Model::RemittanceAdviceLine.new
75
+ r.parse("cbc:ID", :String) { line.id = it }
76
+ r.parse("cbc:Note", :String) { line.note = it }
77
+ r.parse("cbc:BalanceAmount", :Money) { line.balance_amount = it }
78
+ r.parse("cac:BillingReference", :DocumentReference) { line.document_reference = it }
79
+ r.parse("cac:ExchangeRate", :ExchangeRate) { line.exchange_rate = it }
80
+
81
+ obj.lines.push(line)
82
+ end
83
+ end
84
+
85
+ obj
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,21 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class String
6
+ def self.ruby_type
7
+ ::String
8
+ end
9
+
10
+ def self.dump(w, obj, as:, **opts)
11
+ w.add(as, obj, **opts)
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,27 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class TaxBreakdown
6
+ def self.ruby_type
7
+ Model::TaxBreakdown
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:TaxTotal")
11
+ w.add(as) do
12
+ w.render(obj.total_tax, as: "TaxAmount")
13
+ w.render_list(obj.subtotals, as: "cac:TaxSubtotal")
14
+ end
15
+ end
16
+
17
+ def self.parse(r)
18
+ ruby_type.new.tap do |tax|
19
+ r.parse("cbc:TaxAmount", :Money) { tax.total_tax = it }
20
+ r.parse_list("cac:TaxSubtotal", :TaxSubtotal) { tax.subtotals = it }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module Tradedoc
2
+ module Format
3
+ module UBL
4
+ module Coder
5
+ class TaxCategory
6
+ def self.ruby_type
7
+ Model::TaxCategory
8
+ end
9
+
10
+ def self.dump(w, obj, as: "cac:TaxCategory")
11
+ w.add(as) do
12
+ w.render(obj.code.edifact_id, as: "cbc:ID")
13
+ w.render(obj.rate_percent, as: "cbc:Percent")
14
+ w.render(obj.exemption_reason_code, as: "cbc:TaxExemptionReasonCode")
15
+ w.render(obj.exemption_reason, as: "cbc:TaxExemptionReason")
16
+ if (tax_scheme = obj.tax_scheme)
17
+ w.add("cac:TaxScheme") do
18
+ w.render(tax_scheme, as: "cbc:ID")
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def self.parse(r)
25
+ ruby_type.new.tap do |cat|
26
+ r.parse("cbc:ID", :String) { cat.code = it }
27
+ r.parse("cbc:Percent", :BigDecimal) { cat.rate_percent = it }
28
+ r.parse("cbc:TaxExemptionReason", :String) { cat.exemption_reason = it }
29
+ r.parse("cbc:TaxExemptionReasonCode", :String) { cat.exemption_reason_code = it }
30
+ r.parse("cac:TaxScheme/cbc:ID", :String) { cat.tax_scheme = it }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end