my_data 0.1.0 → 0.9.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +37 -0
  3. data/.rubocop.yml +12 -2
  4. data/Gemfile +9 -4
  5. data/Guardfile +7 -0
  6. data/README.md +55 -8
  7. data/lib/my_data.rb +9 -10
  8. data/lib/my_data/client.rb +34 -11
  9. data/lib/my_data/resource.rb +43 -29
  10. data/lib/my_data/resources/continuation_token_type.rb +7 -0
  11. data/lib/my_data/resources/ecls/expenses_classification.rb +7 -0
  12. data/lib/my_data/resources/ecls/expenses_classification_type.rb +1 -1
  13. data/lib/my_data/resources/ecls/invoice_expenses_classification_type.rb +1 -1
  14. data/lib/my_data/resources/ecls/invoices_expenses_classification_detail_type.rb +1 -1
  15. data/lib/my_data/resources/error_type.rb +1 -2
  16. data/lib/my_data/resources/icls/income_classification.rb +7 -0
  17. data/lib/my_data/resources/icls/income_classification_type.rb +1 -1
  18. data/lib/my_data/resources/icls/invoice_income_classification_type.rb +1 -1
  19. data/lib/my_data/resources/icls/invoices_income_classification_detail_type.rb +1 -1
  20. data/lib/my_data/resources/inv/aade_book_invoice_type.rb +1 -1
  21. data/lib/my_data/resources/inv/address_type.rb +1 -1
  22. data/lib/my_data/resources/inv/cancelled_invoice_type.rb +7 -0
  23. data/lib/my_data/resources/inv/continuation_token_type.rb +7 -0
  24. data/lib/my_data/resources/inv/invoice_header_type.rb +1 -1
  25. data/lib/my_data/resources/inv/invoice_row_type.rb +1 -1
  26. data/lib/my_data/resources/inv/invoice_summary_type.rb +1 -1
  27. data/lib/my_data/resources/inv/invoices_doc.rb +1 -11
  28. data/lib/my_data/resources/inv/party_type.rb +1 -1
  29. data/lib/my_data/resources/inv/payment_method_detail_type.rb +1 -1
  30. data/lib/my_data/resources/inv/request_doc.rb +7 -0
  31. data/lib/my_data/resources/inv/requested_invoices_doc.rb +7 -0
  32. data/lib/my_data/resources/inv/ship_type.rb +1 -1
  33. data/lib/my_data/resources/inv/tax_totals_type.rb +1 -1
  34. data/lib/my_data/resources/invoice_provider_type.rb +7 -0
  35. data/lib/my_data/resources/requested_provider_doc.rb +7 -0
  36. data/lib/my_data/resources/response.rb +7 -0
  37. data/lib/my_data/resources/response_type.rb +1 -13
  38. data/lib/my_data/response_parser.rb +42 -0
  39. data/lib/my_data/type_caster.rb +5 -4
  40. data/lib/my_data/version.rb +1 -1
  41. data/lib/my_data/xml_generator.rb +29 -17
  42. data/lib/my_data/xml_parser.rb +37 -76
  43. data/lib/my_data/xsd/complex_type.rb +11 -3
  44. data/lib/my_data/xsd/doc.rb +77 -0
  45. data/lib/my_data/xsd/element.rb +20 -8
  46. data/lib/my_data/xsd/resource_generator.rb +26 -13
  47. data/lib/my_data/xsd/structure.rb +41 -35
  48. data/my_data.gemspec +4 -3
  49. metadata +41 -19
  50. data/lib/my_data/resources.rb +0 -10
  51. data/lib/my_data/resources/ecls.rb +0 -7
  52. data/lib/my_data/resources/icls.rb +0 -7
  53. data/lib/my_data/resources/inv.rb +0 -14
  54. data/lib/my_data/resources/responses_doc.rb +0 -8
  55. data/lib/my_data/xsd.rb +0 -7
@@ -3,17 +3,17 @@
3
3
  class MyData::Xsd::ComplexType
4
4
  attr_reader :doc, :namespace
5
5
 
6
- def initialize(doc, namespace:)
6
+ def initialize(doc, namespace: nil)
7
7
  @doc = doc
8
8
  @namespace = namespace
9
9
  end
10
10
 
11
11
  def name
12
- @name ||= doc.attributes["name"].value
12
+ @name ||= doc.attributes["name"].value.camelize
13
13
  end
14
14
 
15
15
  def elements
16
- @elements ||= doc.xpath("xs:sequence/xs:element").map do |element|
16
+ @elements ||= extract_elements(doc).flatten.map do |element|
17
17
  MyData::Xsd::Element.new(element)
18
18
  end
19
19
  end
@@ -21,4 +21,12 @@ class MyData::Xsd::ComplexType
21
21
  def inspect
22
22
  "ComplexType: { name: #{name.to_json}, elements: #{elements} }"
23
23
  end
24
+
25
+ private
26
+
27
+ def extract_elements(node)
28
+ return node if node.name == "element"
29
+
30
+ node.element_children.map { |child| extract_elements(child) }
31
+ end
24
32
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MyData::Xsd::Doc
4
+ attr_reader :doc
5
+
6
+ DEFAULT_ATTRS = {
7
+ "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance"
8
+ }.freeze
9
+
10
+ def initialize(doc)
11
+ @doc = doc
12
+ end
13
+
14
+ def target_namespace
15
+ return @target_namespace if defined? @target_namespace
16
+
17
+ @target_namespace =
18
+ (doc.namespaces.find { |_k, v| v == target_namespace_value }.first.split(":").last if target_namespace_value)
19
+ end
20
+
21
+ def attributes
22
+ @attributes ||= DEFAULT_ATTRS
23
+ .merge(target_namespace_attributes)
24
+ .merge(namespace_attributes)
25
+ end
26
+
27
+ def elements
28
+ @elements ||=
29
+ begin
30
+ sequence = doc.child.xpath("xs:element/xs:complexType/xs:sequence").first
31
+ elements = sequence.xpath("xs:element")
32
+ collection = elements.count == 1 && sequence.attributes["maxOccurs"].present?
33
+
34
+ sequence.xpath("xs:element").map do |element|
35
+ MyData::Xsd::Element.new(element, force_collection: collection)
36
+ end
37
+ end
38
+ end
39
+
40
+ def complex_types
41
+ @complex_types ||= doc.xpath("//xs:schema/xs:complexType").map do |node|
42
+ MyData::Xsd::ComplexType.new(node, namespace: target_namespace)
43
+ end
44
+ end
45
+
46
+ def simple_types
47
+ @simple_types ||= doc.xpath("//xs:schema/xs:simpleType").map do |node|
48
+ MyData::Xsd::Element.new(node, namespace: target_namespace)
49
+ end
50
+ end
51
+
52
+ def inspect
53
+ "<Schema target_namespace: #{target_namespace.to_json}, attributes: #{attributes}>"
54
+ end
55
+
56
+ private
57
+
58
+ def target_namespace_value
59
+ doc.child.attributes["targetNamespace"]&.value
60
+ end
61
+
62
+ def target_namespace_attributes
63
+ return {} unless target_namespace_value
64
+
65
+ {
66
+ "xmlns" => target_namespace_value,
67
+ "xmlns:schema" => "#{target_namespace_value} schemaLocation.xsd"
68
+ }
69
+ end
70
+
71
+ def namespace_attributes
72
+ @namespace_attributes ||= doc
73
+ .namespaces
74
+ .reject { |k, _| k == "xmlns:xs" }
75
+ .reject { |_, v| v == target_namespace }
76
+ end
77
+ end
@@ -3,9 +3,10 @@
3
3
  class MyData::Xsd::Element
4
4
  attr_reader :element, :namespace
5
5
 
6
- def initialize(element, namespace: nil)
6
+ def initialize(element, namespace: nil, force_collection: nil)
7
7
  @element = element
8
8
  @namespace = namespace
9
+ force_collection && @collection = force_collection
9
10
  end
10
11
 
11
12
  def name
@@ -14,13 +15,14 @@ class MyData::Xsd::Element
14
15
 
15
16
  def type
16
17
  @type =
17
- if element.attributes["type"].present?
18
- element.attributes["type"]
19
- elsif element.xpath(".//xs:restriction[@base]").any?
20
- element.xpath(".//xs:restriction[@base]").first.attributes["base"]
21
- elsif element.xpath(".//xs:element[@type]").any?
22
- element.xpath(".//xs:element[@type]").first.attributes["type"]
23
- end.value
18
+ begin
19
+ extracted_type =
20
+ element.attributes["type"] ||
21
+ element.at_xpath(".//xs:element[@type]")&.attributes.try(:[], "type") ||
22
+ element.at_xpath(".//xs:restriction[@base]")&.attributes.try(:[], "base")
23
+
24
+ camelize_type(extracted_type.value)
25
+ end
24
26
  end
25
27
 
26
28
  def collection?
@@ -46,4 +48,14 @@ class MyData::Xsd::Element
46
48
  def inspect
47
49
  "Element: { name: #{name.to_json}, type: #{type.to_json}, collection: #{collection?} }"
48
50
  end
51
+
52
+ private
53
+
54
+ def camelize_type(extracted_type)
55
+ return extracted_type if extracted_type.starts_with?("xs:")
56
+
57
+ ns, name = extracted_type.include?(":") ? extracted_type.split(":") : [nil, extracted_type]
58
+
59
+ [ns, name.camelize].compact.join(":")
60
+ end
49
61
  end
@@ -4,32 +4,45 @@ require "fileutils"
4
4
 
5
5
  # This class is for development reason only, to generate resources
6
6
  module MyData::Xsd::ResourceGenerator
7
- module_function
7
+ extend self
8
8
 
9
- def generate
10
- MyData::Xsd::Structure.complex_types.each do |_, type|
11
- folder_name = File.join(MyData.root, "lib/my_data/resources", type.namespace.to_s)
12
- FileUtils.mkdir_p(folder_name)
13
-
14
- class_name = "#{type.namespace.capitalize}::#{type.name}"
9
+ def generate_docs
10
+ MyData::Xsd::Structure.docs.each do |name, doc|
11
+ generate_file(name: name, namespace: doc.target_namespace, xsd_mode: "xsd_doc")
12
+ end
15
13
 
16
- puts "Create file: #{folder_name} #{type.name}"
14
+ "done"
15
+ end
17
16
 
18
- file = File.new(File.join(folder_name, "#{type.name.underscore}.rb"), "w")
19
- file.write(class_string(class_name))
20
- file.close
17
+ def generate_types
18
+ MyData::Xsd::Structure.complex_types.each do |_, type|
19
+ generate_file(name: type.name, namespace: type.namespace, xsd_mode: "xsd_complex_type")
21
20
  end
22
21
 
23
22
  "done"
24
23
  end
25
24
 
26
- def class_string(class_name)
25
+ private
26
+
27
+ def generate_file(name:, namespace:, xsd_mode:)
28
+ folder_name = File.join(MyData.root, "lib/my_data/resources", namespace.to_s)
29
+ FileUtils.mkdir_p(folder_name)
30
+
31
+ class_name = [namespace&.camelize, name.camelize].compact.join("::")
32
+ puts "Create file: #{folder_name}, #{name}"
33
+
34
+ file = File.new(File.join(folder_name, "#{name.underscore}.rb"), "w")
35
+ file.write(class_string(class_name, xsd_mode))
36
+ file.close
37
+ end
38
+
39
+ def class_string(class_name, xsd_mode)
27
40
  string = "# frozen_string_literal: true\n"
28
41
  string += "\n"
29
42
  string += "class MyData::Resources::#{class_name}\n"
30
43
  string += " include MyData::Resource\n"
31
44
  string += "\n"
32
- string += " xsd_structure\n"
45
+ string += " #{xsd_mode}\n"
33
46
  string += "end\n"
34
47
 
35
48
  string
@@ -5,51 +5,65 @@ module MyData::Xsd::Structure
5
5
 
6
6
  PATH = File.join(MyData.root, "lib/my_data/xsd/docs")
7
7
 
8
- def resource_attributes(class_name)
8
+ def doc(class_name)
9
+ name = class_name.split("::").last
10
+ [name, docs[name]]
11
+ end
12
+
13
+ def resource_attributes(class_name, type)
9
14
  namespace, name = class_name.split("::").last(2)
15
+ key = namespace == "Resources" ? name : [namespace.downcase, name].join(":")
10
16
 
11
- complex_types["#{namespace.downcase}:#{name}"].elements.map do |element|
12
- type = type_mapping(element.type)
13
-
14
- [
15
- element.name.underscore,
16
- type,
17
- {
18
- collection: element.collection?,
19
- collection_element_name: element.collection_element_name,
20
- class_name: type == :resource ? classify(element.type) : nil,
21
- required: element.required?
22
- }
23
- ]
24
- end
17
+ current_doc = type == :complex_type ? complex_types[key] : docs[name]
18
+
19
+ current_doc.elements.map { |element| element_attributes(element) }
25
20
  end
26
21
 
27
- def complex_types
28
- @complex_types ||= docs.each_with_object({}) do |(namespace, doc), types|
29
- doc.xpath("//xs:schema/xs:complexType").each do |node|
30
- type = MyData::Xsd::ComplexType.new(node, namespace: namespace)
22
+ def docs
23
+ @docs ||= Dir.glob("*.xsd", base: PATH).map do |file_name|
24
+ [file_name.sub(/-.+$/, "").camelize, MyData::Xsd::Doc.new(read_xsd(file_name))]
25
+ end.to_h
26
+ end
31
27
 
32
- types["#{type.namespace}:#{type.name}"] = type
28
+ def complex_types
29
+ @complex_types ||= docs.values.each_with_object({}) do |document, types|
30
+ document.complex_types.each do |type|
31
+ name = [type.namespace, type.name].compact.join(":")
32
+ types[name] = type
33
33
  end
34
34
  end
35
35
  end
36
36
 
37
37
  def simple_types
38
- @simple_types ||= docs.each_with_object({}) do |(namespace, doc), types|
39
- doc.xpath("//xs:schema/xs:simpleType").each do |node|
40
- type = MyData::Xsd::Element.new(node, namespace: namespace)
41
-
42
- types["#{type.namespace}:#{type.name}"] = type
38
+ @simple_types ||= docs.values.each_with_object({}) do |document, types|
39
+ document.simple_types.each do |type|
40
+ name = [type.namespace, type.name].compact.join(":")
41
+ types[name] = type
43
42
  end
44
43
  end
45
44
  end
46
45
 
47
46
  private
48
47
 
48
+ def element_attributes(element)
49
+ type = type_mapping(element.type)
50
+
51
+ [
52
+ element.name.underscore,
53
+ type,
54
+ {
55
+ collection: element.collection?,
56
+ collection_element_name: element.collection_element_name,
57
+ class_name: type == :resource ? classify(element.type) : nil,
58
+ required: element.required?
59
+ }
60
+ ]
61
+ end
62
+
49
63
  def classify(type)
50
- namespace, name = type.split(":")
64
+ namespace, name = type.split(":").map(&:camelize)
51
65
 
52
- "#{namespace.capitalize}::#{name}"
66
+ "#{namespace}::#{name}"
53
67
  end
54
68
 
55
69
  def type_mapping(type)
@@ -66,14 +80,6 @@ module MyData::Xsd::Structure
66
80
  end
67
81
  end
68
82
 
69
- def docs
70
- @docs ||= {
71
- inv: read_xsd("InvoicesDoc-v1.0.2.xsd"),
72
- icls: read_xsd("incomeClassification-v1.0.2.xsd"),
73
- ecls: read_xsd("expensesClassification-v1.0.2.xsd")
74
- }
75
- end
76
-
77
83
  def read_xsd(name)
78
84
  Nokogiri::XML(File.read(File.join(PATH, name)))
79
85
  end
data/my_data.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Api client for AADE myData"
13
13
  spec.homepage = "https://github.com/mikezaby/my_data"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = spec.homepage
@@ -26,10 +26,11 @@ Gem::Specification.new do |spec|
26
26
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ["lib"]
28
28
 
29
- spec.add_dependency "faraday", "~> 1.0"
30
- spec.add_dependency "activesupport", ">= 3.2"
31
29
  spec.add_dependency "activemodel", ">= 3.2"
30
+ spec.add_dependency "activesupport", ">= 3.2"
31
+ spec.add_dependency "faraday", "~> 1.0"
32
32
  spec.add_dependency "nokogiri", ">= 1.10"
33
+ spec.add_dependency "zeitwerk", ">= 2.4"
33
34
 
34
35
  # For more information and examples about making a new gem, checkout our
35
36
  # guide at: https://bundler.io/guides/creating_gem.html
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: my_data
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michalis Zamparas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-12 00:00:00.000000000 Z
11
+ date: 2021-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: faraday
14
+ name: activemodel
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: activemodel
42
+ name: faraday
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.2'
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.2'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: nokogiri
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: zeitwerk
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '2.4'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '2.4'
69
83
  description: Api client for AADE myData
70
84
  email:
71
85
  - mikezaby@gmail.com
@@ -73,10 +87,12 @@ executables: []
73
87
  extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
90
+ - ".github/workflows/lint.yml"
76
91
  - ".gitignore"
77
92
  - ".rspec"
78
93
  - ".rubocop.yml"
79
94
  - Gemfile
95
+ - Guardfile
80
96
  - LICENSE.txt
81
97
  - README.md
82
98
  - Rakefile
@@ -85,35 +101,41 @@ files:
85
101
  - lib/my_data.rb
86
102
  - lib/my_data/client.rb
87
103
  - lib/my_data/resource.rb
88
- - lib/my_data/resources.rb
89
- - lib/my_data/resources/ecls.rb
104
+ - lib/my_data/resources/continuation_token_type.rb
105
+ - lib/my_data/resources/ecls/expenses_classification.rb
90
106
  - lib/my_data/resources/ecls/expenses_classification_type.rb
91
107
  - lib/my_data/resources/ecls/invoice_expenses_classification_type.rb
92
108
  - lib/my_data/resources/ecls/invoices_expenses_classification_detail_type.rb
93
109
  - lib/my_data/resources/error_type.rb
94
- - lib/my_data/resources/icls.rb
110
+ - lib/my_data/resources/icls/income_classification.rb
95
111
  - lib/my_data/resources/icls/income_classification_type.rb
96
112
  - lib/my_data/resources/icls/invoice_income_classification_type.rb
97
113
  - lib/my_data/resources/icls/invoices_income_classification_detail_type.rb
98
- - lib/my_data/resources/inv.rb
99
114
  - lib/my_data/resources/inv/aade_book_invoice_type.rb
100
115
  - lib/my_data/resources/inv/address_type.rb
116
+ - lib/my_data/resources/inv/cancelled_invoice_type.rb
117
+ - lib/my_data/resources/inv/continuation_token_type.rb
101
118
  - lib/my_data/resources/inv/invoice_header_type.rb
102
119
  - lib/my_data/resources/inv/invoice_row_type.rb
103
120
  - lib/my_data/resources/inv/invoice_summary_type.rb
104
121
  - lib/my_data/resources/inv/invoices_doc.rb
105
122
  - lib/my_data/resources/inv/party_type.rb
106
123
  - lib/my_data/resources/inv/payment_method_detail_type.rb
124
+ - lib/my_data/resources/inv/request_doc.rb
125
+ - lib/my_data/resources/inv/requested_invoices_doc.rb
107
126
  - lib/my_data/resources/inv/ship_type.rb
108
127
  - lib/my_data/resources/inv/tax_totals_type.rb
128
+ - lib/my_data/resources/invoice_provider_type.rb
129
+ - lib/my_data/resources/requested_provider_doc.rb
130
+ - lib/my_data/resources/response.rb
109
131
  - lib/my_data/resources/response_type.rb
110
- - lib/my_data/resources/responses_doc.rb
132
+ - lib/my_data/response_parser.rb
111
133
  - lib/my_data/type_caster.rb
112
134
  - lib/my_data/version.rb
113
135
  - lib/my_data/xml_generator.rb
114
136
  - lib/my_data/xml_parser.rb
115
- - lib/my_data/xsd.rb
116
137
  - lib/my_data/xsd/complex_type.rb
138
+ - lib/my_data/xsd/doc.rb
117
139
  - lib/my_data/xsd/docs/InvoicesDoc-v1.0.2.xsd
118
140
  - lib/my_data/xsd/docs/RequestedProviderDoc-v1.0.2.xsd
119
141
  - lib/my_data/xsd/docs/expensesClassification-v1.0.2.xsd
@@ -139,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
161
  requirements:
140
162
  - - ">="
141
163
  - !ruby/object:Gem::Version
142
- version: 2.3.0
164
+ version: 2.4.0
143
165
  required_rubygems_version: !ruby/object:Gem::Requirement
144
166
  requirements:
145
167
  - - ">="