my_data 0.1.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4eb6195b397b23da4c0756c94382ac9a245ea48ff07c7bcff7ce75d318750f55
4
- data.tar.gz: 2443d4836cecf9d08657e998a39ca73cdcdc58d131463b805be2c84a4429ed53
3
+ metadata.gz: 21734192525f3cdc66a24be64cfc3f147647f8decb6f71a6cd17094f5fc79bcb
4
+ data.tar.gz: ce56b3d0ec170898a593cbfab881e843c1a89a3e3de6a055dce39f0d302f6a67
5
5
  SHA512:
6
- metadata.gz: e3922efa99513f4222db05df50762d502252a99c0159ec11ae0ea35c2ceb5bd89612a54dac86d22e5ccaeca33f573aa58b7f011a00f7da09e65482bdd7e6693d
7
- data.tar.gz: 0135fb723a5e2f759bd5cab73c91c31ef1ef3a47303e111a02593d9589403dc07756e9353e3f3de11becbe84c08ccad4031e06ed61fd9a03ded8c666c2b994aa
6
+ metadata.gz: e18093c80a0108ee8fe815ab50ca359cc019e2346a297b62e45d7c27f83652cab79461c5549bf6e69cad6752a546ae536bf84a10ecf23e320b2bdbb426cb932b
7
+ data.tar.gz: 9d64a6162fbb18bb511159e8c43d2117c795e91e222ce7e5ca10523b6cc7aea72b6bf9412245185537dadd7a512ade270f46672278b982f8377e86a68d5e3ca1
@@ -0,0 +1,37 @@
1
+ name: Lint
2
+
3
+ on: push
4
+
5
+ jobs:
6
+ run-test-lint:
7
+ name: Run tests and linter
8
+ runs-on: ubuntu-latest
9
+
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ ruby: ['2.5', '2.6', '2.7', '3.0']
14
+ gemfile: ['Gemfile']
15
+
16
+ env:
17
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
18
+
19
+ steps:
20
+ - name: Check out Git repository
21
+ uses: actions/checkout@v2
22
+
23
+ - name: Set up Ruby
24
+ uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby }}
27
+ bundler-cache: true
28
+
29
+ - name: Run Rubocop
30
+ uses: wearerequired/lint-action@v1
31
+ with:
32
+ rubocop: true
33
+ rubocop_command_prefix: bundle exec
34
+
35
+ - name: Run specs
36
+ run: bundle exec rake spec
37
+
data/.rubocop.yml CHANGED
@@ -1,11 +1,17 @@
1
+ require:
2
+ - rubocop-rake
3
+
4
+ AllCops:
5
+ NewCops: enable
6
+
1
7
  Metrics/ModuleLength:
2
8
  Max: 200
3
9
 
4
10
  Metrics/MethodLength:
5
- Max: 15
11
+ Max: 15
6
12
 
7
13
  Metrics/BlockLength:
8
- ExcludedMethods:
14
+ IgnoredMethods:
9
15
  - class_methods
10
16
 
11
17
  Style/Documentation:
@@ -30,3 +36,7 @@ Style/StringLiteralsInInterpolation:
30
36
 
31
37
  Layout/LineLength:
32
38
  Max: 120
39
+
40
+ Lint/UselessAccessModifier:
41
+ ContextCreatingMethods:
42
+ - class_methods
data/Gemfile CHANGED
@@ -7,9 +7,14 @@ gemspec
7
7
 
8
8
  gem "rake", "~> 13.0"
9
9
 
10
- gem "rspec", "~> 3.0"
11
-
12
- group :development do
10
+ group :development, :test do
11
+ gem "factory_bot"
12
+ gem "guard-rspec", require: false
13
13
  gem "pry"
14
- gem "rubocop", "~> 0.80"
14
+ gem "rspec", "~> 3.0"
15
+ gem "rubocop", "~> 1.0"
16
+ gem "rubocop-rake", "~> 0.5"
17
+ gem "rubocop-rspec", "~> 2.0"
18
+ gem "vcr"
19
+ gem "webmock"
15
20
  end
data/Guardfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard :rspec, cmd: "rspec" do
4
+ watch(%r{^spec/.+_spec\.rb$})
5
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
6
+ watch("spec/spec_helper.rb") { "spec" }
7
+ end
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
- # MyData
1
+ # AADE MyData ruby client
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/my_data`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ A Ruby client for [AADE myDATA](https://www.aade.gr/mydata) API
6
4
 
7
5
  ## Installation
8
6
 
@@ -20,15 +18,64 @@ Or install it yourself as:
20
18
 
21
19
  $ gem install my_data
22
20
 
21
+ ## Resources
22
+ There are all the [resources](https://github.com/mikezaby/my_data/tree/master/lib/my_data/resources)
23
+ that are specified by the given
24
+ [xsd files](https://www.aade.gr/sites/default/files/2020-11/version%20v1.0.2%20XSDs.zip) from AADE.
25
+
26
+ e.x.
27
+ ```irb
28
+ irb> MyData::Resources::Inv::PartyType
29
+ => MyData::Resources::Inv::PartyType vat_number: string, country: string, branch: integer, name: string, address: MyData::Resources::Inv::AddressType
30
+ ```
31
+
23
32
  ## Usage
24
33
 
25
- TODO: Write usage instructions here
34
+ ##### Initialize client
35
+ ```ruby
36
+ client = MyData::Client.new(user_id: "johndoe", subscription_key: "c9b79ff1841fb5cfecc66e1ea5a29b4d")
37
+ ```
26
38
 
27
- ## Development
39
+ ##### Send invoices
40
+ ```ruby
41
+ # send invoices
42
+ invoice_data = {
43
+ issuer: { vat_number: "111111111", country: "GR", branch: 0 },
44
+ invoice_header: { series: "A", aa: "1", issue_date: "2021-02-21", invoice_type: "11.2", currency: "EUR" },
45
+ invoice_details: [{
46
+ line_number: "1",
47
+ net_value: 100.00,
48
+ vat_category: 1,
49
+ vat_amount: 24.00,
50
+ income_classification: [{ classification_type: "E3_561_003", classification_category: "category1_3", amount: 100.00 }]
51
+ }],
52
+ invoice_summary: {
53
+ total_net_value: 100.00,
54
+ total_vat_amount: 24.00,
55
+ total_withheld_amount: 0.0,
56
+ total_fees_amount: 0.0,
57
+ total_stamp_duty_amount: 0.0,
58
+ total_other_taxes_amount: 0.0,
59
+ total_deductions_amount: 0.0,
60
+ total_gross_value: 124.00,
61
+ income_classification: [{ classification_type: "E3_561_003", classification_category: "category1_3", amount: 100.00 }]
62
+ },
63
+ payment_methods: [{ type: 3, amount: 124.00 }]
64
+ }
65
+
66
+ invoices_doc = MyData::Resources::Inv::InvoicesDoc.new(invoice: [invoice_data])
67
+ client.send_invoices(doc: invoices_doc.to_xml)
68
+ ```
28
69
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
70
+ ##### Request transmitted docs
71
+ ```ruby
72
+ client.request_transmitted_docs(mark: 1)
73
+ ```
30
74
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
75
+ ##### Cancel Invoice
76
+ ```ruby
77
+ client.cancel_invoice(mark: 400001831924171)
78
+ ```
32
79
 
33
80
  ## Contributing
34
81
 
data/lib/my_data.rb CHANGED
@@ -4,21 +4,20 @@ require "active_model"
4
4
  require "active_support/all"
5
5
  require "faraday"
6
6
  require "nokogiri"
7
-
8
- require_relative "my_data/version"
7
+ require "zeitwerk"
9
8
 
10
9
  module MyData
10
+ LOADER = Zeitwerk::Loader.for_gem
11
+ LOADER.enable_reloading
12
+ LOADER.setup
13
+
11
14
  class Error < StandardError; end
12
15
 
13
16
  def self.root
14
- File.expand_path '../..', __FILE__
17
+ File.expand_path "..", __dir__
15
18
  end
16
19
 
17
- autoload :Client, "my_data/client"
18
- autoload :Resource, "my_data/resource"
19
- autoload :Resources, "my_data/resources"
20
- autoload :TypeCaster, "my_data/type_caster"
21
- autoload :XmlGenerator, "my_data/xml_generator"
22
- autoload :XmlParser, "my_data/xml_parser"
23
- autoload :Xsd, "my_data/xsd"
20
+ def self.reload!
21
+ MyData::LOADER.reload
22
+ end
24
23
  end
@@ -9,25 +9,48 @@ module MyData
9
9
  @subscription_key = subscription_key
10
10
  end
11
11
 
12
- def connection
13
- @connection ||= Faraday.new(BASE_URL) do |conn|
14
- conn.headers = headers
15
- end
12
+ def send_invoices(doc:)
13
+ response = connection.post("SendInvoices", doc)
14
+
15
+ parse_response(
16
+ response,
17
+ resource: MyData::Resources::Response,
18
+ root: "response_doc"
19
+ )
20
+ end
21
+
22
+ def request_transmitted_docs(mark:)
23
+ response = connection.get("RequestTransmittedDocs", mark: mark)
24
+
25
+ parse_response(
26
+ response,
27
+ resource: MyData::Resources::Inv::RequestDoc,
28
+ root: "requested_doc"
29
+ )
16
30
  end
17
31
 
18
- def send_invoice(invoice_doc)
19
- response = connection.post("SendInvoices", invoice_doc)
32
+ def cancel_invoice(mark:)
33
+ response = connection.post("CancelInvoice") do |req|
34
+ req.params["mark"] = mark
35
+ end
20
36
 
21
- response_parser(response.body)
37
+ parse_response(
38
+ response,
39
+ resource: MyData::Resources::Response,
40
+ root: "response_doc"
41
+ )
22
42
  end
23
43
 
24
44
  private
25
45
 
26
- def response_parser(response)
27
- fixed_xml = response.sub(/^.+/, "").sub("</string>", "").strip
28
- .gsub("&lt;", "<").gsub("&gt;", ">")
46
+ def connection
47
+ @connection ||= Faraday.new(BASE_URL) do |conn|
48
+ conn.headers = headers
49
+ end
50
+ end
29
51
 
30
- Hash.from_xml(fixed_xml)
52
+ def parse_response(response, resource:, root:)
53
+ MyData::ResponseParser.new(response, resource: resource, root: root)
31
54
  end
32
55
 
33
56
  def headers
@@ -29,15 +29,15 @@ module MyData
29
29
  @container[:attributes] = opts
30
30
  end
31
31
 
32
- def xsd_structure
33
- MyData::Xsd::Structure.resource_attributes(name).each do |attrs|
34
- e_name, type, opts = attrs
35
- required = opts.delete :required
32
+ def xsd_doc
33
+ doc_name, doc = MyData::Xsd::Structure.doc(name)
34
+ container_tag(doc_name, doc.attributes)
36
35
 
37
- attribute(e_name, type, opts)
36
+ xsd_resource_attributes(name, :doc)
37
+ end
38
38
 
39
- validates_presence_of e_name if required
40
- end
39
+ def xsd_complex_type
40
+ xsd_resource_attributes(name, :complex_type)
41
41
  end
42
42
 
43
43
  # @param name [String] the name of the attribute
@@ -59,9 +59,8 @@ module MyData
59
59
  @attributes.push(name)
60
60
  attr_mappings(name, type, opts)
61
61
 
62
- attr_reader name
63
-
64
- define_attr_setter name, collection: !!opts[:collection]
62
+ define_attr_getter name, collection: opts[:collection]
63
+ define_attr_setter name, collection: opts[:collection]
65
64
  end
66
65
 
67
66
  def inspect
@@ -76,13 +75,19 @@ module MyData
76
75
  "#{name} #{format_attrs.join(", ")}"
77
76
  end
78
77
 
79
- def from_xml(doc_or_string)
80
- doc = doc_or_string.is_a?(String) ? Nokogiri::XML(doc_or_string).child : doc_or_string
81
- new(parse_xml(doc))
82
- end
83
-
84
78
  private
85
79
 
80
+ def xsd_resource_attributes(name, type)
81
+ MyData::Xsd::Structure.resource_attributes(name, type).each do |attrs|
82
+ e_name, type, opts = attrs
83
+ required = opts.delete :required
84
+
85
+ attribute(e_name, type, opts)
86
+
87
+ validates_presence_of e_name if required
88
+ end
89
+ end
90
+
86
91
  def attr_mappings(name, type, opts)
87
92
  resource =
88
93
  if type == :resource
@@ -98,6 +103,14 @@ module MyData
98
103
  }
99
104
  end
100
105
 
106
+ def define_attr_getter(name, collection: false)
107
+ define_method name do
108
+ value = instance_variable_get("@#{name}")
109
+
110
+ collection && value.nil? ? [] : value
111
+ end
112
+ end
113
+
101
114
  def define_attr_setter(name, collection: false)
102
115
  define_method "#{name}=" do |value|
103
116
  type, resource = self.class.mappings[name].values_at(:type, :resource)
@@ -112,11 +125,6 @@ module MyData
112
125
  instance_variable_set("@#{name}", type_casted_value)
113
126
  end
114
127
  end
115
-
116
- def parse_xml(doc)
117
- parser = MyData::XmlParser.new(doc, mappings, name)
118
- parser.parse_xml
119
- end
120
128
  end
121
129
 
122
130
  def initialize(attrs = {})
@@ -134,6 +142,8 @@ module MyData
134
142
  end
135
143
 
136
144
  def attributes=(attrs)
145
+ attrs = attrs.respond_to?(:attributes) ? attrs.attributes : attrs
146
+
137
147
  attrs.each do |key, value|
138
148
  next unless attribute_names.include?(key.to_s)
139
149
 
@@ -152,15 +162,7 @@ module MyData
152
162
 
153
163
  return true if is_valid
154
164
 
155
- resources.compact.each do |k, resource|
156
- rs = resource.is_a?(Array) ? resource : [resource]
157
-
158
- next if rs.all?(&:valid?)
159
-
160
- rs.each do |r|
161
- errors.add(k, :invalid_resource, message: r.errors.full_messages.join(", "))
162
- end
163
- end
165
+ add_nested_errors
164
166
 
165
167
  false
166
168
  end
@@ -187,5 +189,17 @@ module MyData
187
189
  generator = MyData::XmlGenerator.new(self)
188
190
  generator.to_xml
189
191
  end
192
+
193
+ private
194
+
195
+ def add_nested_errors
196
+ resources.compact.each do |k, resource|
197
+ rs = resource.is_a?(Array) ? resource : [resource]
198
+
199
+ rs.reject(&:valid?).each do |r|
200
+ errors.add(k, :invalid_resource, message: r.errors.full_messages.join(", "))
201
+ end
202
+ end
203
+ end
190
204
  end
191
205
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MyData::Resources::ContinuationTokenType
4
+ include MyData::Resource
5
+
6
+ xsd_complex_type
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MyData::Resources::Ecls::ExpensesClassification
4
+ include MyData::Resource
5
+
6
+ xsd_doc
7
+ end
@@ -3,5 +3,5 @@
3
3
  class MyData::Resources::Ecls::ExpensesClassificationType
4
4
  include MyData::Resource
5
5
 
6
- xsd_structure
6
+ xsd_complex_type
7
7
  end
@@ -3,5 +3,5 @@
3
3
  class MyData::Resources::Ecls::InvoiceExpensesClassificationType
4
4
  include MyData::Resource
5
5
 
6
- xsd_structure
6
+ xsd_complex_type
7
7
  end
@@ -3,5 +3,5 @@
3
3
  class MyData::Resources::Ecls::InvoicesExpensesClassificationDetailType
4
4
  include MyData::Resource
5
5
 
6
- xsd_structure
6
+ xsd_complex_type
7
7
  end