magento 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8bc5f8a39bdb839264e76b211f08b5ce3621340c64e866295456ec136180155
4
- data.tar.gz: 4711ecfd3c80b9f52dce500b8d832ebe9dd2f3ef981e9245eb4730bcfc1bc529
3
+ metadata.gz: 78965c7e294c387a88b86cf0af3a099f54729ca292050d1b0cc71046f6e5de6c
4
+ data.tar.gz: 7e714fbb399e0ed27946984437d2a4603481f33e98ffa551e5f83b0987518e9c
5
5
  SHA512:
6
- metadata.gz: c4eeca2012769013e626ffa61689d487ebcf92430cd9a0740254f16bffb2ec11f62b0b8c519446fe314a571a8def6c20e46ce80def22f1ea599ff4350d81c9c3
7
- data.tar.gz: df313171a3767e8bf326fbf6bb45aa53010f1a8b3f7469b4cb27cb44b82ea2e30fa19eeb7165fe3380e8c50c89760c38721cdeeb5d24b3236325da94411a1fb9
6
+ metadata.gz: 36cc52f478ee96696a451b1bf943db80128ca3f333391c628e026305d67d9f242fe699efc7dbbf624707945fdde47cf2f7f87391e24543e8cb4eefe3984d3bd1
7
+ data.tar.gz: 1f0ab0fd15b026b47ed6de9252e249bb084cd92fd60021beafc90e1341ea7439e2a9d75ad5046fce1cd89a6947626ae2f475fe4fa3c8dca5a88c457ba4502d00
data/.gitignore CHANGED
@@ -25,4 +25,4 @@ test/vcr_cassettes
25
25
 
26
26
  .vscode
27
27
  .byebug_history
28
- test.rb
28
+ /*test.rb
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  Add in your Gemfile
6
6
 
7
7
  ```rb
8
- gem 'magento', '~> 0.2.0'
8
+ gem 'magento', '~> 0.3.0'
9
9
  ```
10
10
 
11
11
  or run
@@ -22,67 +22,102 @@ Magento.token = 'MAGENTO_API_KEY'
22
22
  Magento.store = :default # optional, Default is :all
23
23
  ```
24
24
 
25
- ## Product
26
-
27
- ### Get product details by sku
28
-
25
+ ## Models
29
26
  ```rb
30
- Magento::Product.find_by_sku('sku-test')
27
+ Magento::Product
28
+ Magento::Order
29
+ Magento::Country
30
+ Magento::Category
31
31
  ```
32
32
 
33
- ## Customer
33
+ ## Get details
34
34
 
35
- ### Get customer by id
36
35
  ```rb
37
- Magento::Customer.find(id) # or
38
- Magento::Customer.find_by_id(id)
36
+ Magento::Product.find('sku-test')
37
+ Magento::Order.find(25)
38
+ Magento::Country.find('BR')
39
39
  ```
40
+ \* _same pattern to all models_
41
+
42
+ **Outside pattern**
43
+
44
+ Get customer by token
40
45
 
41
- ### Get customer by token
42
46
  ```rb
43
47
  Magento::Customer.find_by_token('user_token')
44
48
  ```
45
49
 
46
- ## Countries
47
-
48
- ### Get available regions for a country
50
+ ## Get List
49
51
 
50
52
  ```rb
51
- country = Magento::Country.find('BR')
53
+ Magento::Product.all
54
+ ```
52
55
 
53
- country.available_regions
56
+ #### Select fields:
57
+ ```rb
58
+ Magento::Product.select(:id, :sku, :name).all
59
+ Magento::Product.select(:id, :sku, :name, extension_attributes: :category_links }.all
60
+ Magento::Product.select(:id, :sku, :name, extension_attributes: [:category_links, :website_ids]).all
61
+ Magento::Product.select(:id, :sku, :name, extension_attributes: [:website_ids, { category_links: :category_id }]).all
54
62
  ```
55
63
 
56
- # TODO
57
- ### Get product list
64
+ #### Filters:
58
65
 
59
- Get all
60
66
  ```rb
61
- Magento::Product.all()
67
+ Magento::Product.where(name_like: 'IPhone%').all
68
+ Magento::Product.where(price_gt: 100).all
69
+ Magento::Product.where(price_gt: 100, price_lt: 200).all
62
70
  ```
63
71
 
64
- Set page and quantity per page
72
+ | Condition | Notes |
73
+ | ----------| ------|
74
+ |eq | Equals. |
75
+ |finset | A value within a set of values |
76
+ |from | The beginning of a range. Must be used with to |
77
+ |gt | Greater than |
78
+ |gteq | Greater than or equal |
79
+ |in | In. The value can contain a comma-separated list of values. |
80
+ |like | Like. The value can contain the SQL wildcard characters when like is |specified.
81
+ |lt | Less than |
82
+ |lteq | Less than or equal |
83
+ |moreq | More or equal |
84
+ |neq | Not equal |
85
+ |nfinset | A value that is not within a set of values |
86
+ |nin | Not in. The value can contain a comma-separated list of values. |
87
+ |notnull | Not null |
88
+ |null | Null |
89
+ |to | The end of a range. Must be used with from |
90
+
91
+
92
+ #### SortOrder:
93
+
65
94
  ```rb
66
- Magento::Product.all(page: 1, page_size: 25) # Default page size is 50
95
+ Magento::Product.order(:sku).all
96
+ Magento::Product.order(sku: :desc).all
97
+ Magento::Product.order(status: :desc, name: :asc).all
67
98
  ```
68
99
 
69
- Filter list by attribute
70
- ```rb
71
- Magento::Product.all(name_like: 'IPhone%')
100
+ #### Pagination:
72
101
 
73
- Magento::Product.all(price_gt: 100, page: 2)
102
+ ```rb
103
+ # Set page and quantity per page
104
+ Magento::Product.page(1).per(25) # Default per is 50
74
105
  ```
75
106
 
76
- ### Search products
107
+ #### Example of several options together:
77
108
  ```rb
78
- Magento::Product.search('tshort')
109
+ Magento::Product.select(:sku, :name, :price)
110
+ .where(name_like: 'Tshort%')
111
+ .order(price: :desc)
112
+ .per(10)
113
+ .all
79
114
  ```
80
115
 
81
- ## Order
116
+ \* _same pattern to all models_
117
+ ___
118
+ ## \######### TODO \##########
82
119
 
83
- ### Create Order as admin user
84
-
85
- See the [documentation](https://magento.redoc.ly/2.4-admin/#operation/salesOrderRepositoryV1SavePost) to all attributes
120
+ ## Create
86
121
 
87
122
  ```rb
88
123
  Magento::Order.create(
@@ -109,3 +144,33 @@ Magento::Order.create(
109
144
  }
110
145
  )
111
146
  ```
147
+
148
+ ### Update
149
+
150
+ ```rb
151
+ product = Magento::Product.find('sku-teste')
152
+
153
+ product.name = 'Updated name'
154
+ product.save
155
+
156
+ # or
157
+
158
+ product.update(name: 'Updated name')
159
+ ```
160
+
161
+ ### Delete
162
+
163
+ ```rb
164
+ product = Magento::Product.find('sku-teste')
165
+
166
+ product.delete
167
+
168
+ # or
169
+
170
+ Magento::Product.delete('sku-teste')
171
+ ```
172
+
173
+ ### Search products
174
+ ```rb
175
+ Magento::Product.search('tshort')
176
+ ```
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'time'
4
+ require 'dry/inflector'
4
5
 
5
6
  require_relative 'magento/errors'
6
7
  require_relative 'magento/request'
7
8
  require_relative 'magento/model'
9
+ require_relative 'magento/model_mapper'
10
+ require_relative 'magento/query'
8
11
  require_relative 'magento/product'
9
12
  require_relative 'magento/country'
10
13
  require_relative 'magento/customer'
14
+ require_relative 'magento/order'
11
15
 
12
16
  Dir[File.expand_path('magento/shared/*.rb', __dir__)].map { |f| require f }
13
17
 
@@ -0,0 +1,4 @@
1
+ module Magento
2
+ class Category < Model
3
+ end
4
+ end
@@ -1,10 +1,5 @@
1
1
  module Magento
2
2
  class Country < Model
3
- class << self
4
- def find(code)
5
- country_hash = request.get("directory/countries/#{code}").parse
6
- map_hash Country, country_hash
7
- end
8
- end
3
+ self.endpoint = 'directory/countries'
9
4
  end
10
5
  end
@@ -1,17 +1,12 @@
1
1
  module Magento
2
2
  class Customer < Model
3
3
  class << self
4
- def find_by_id(id)
5
- customer_hash = request.get("customers/#{id}").parse
6
- map_hash Customer, customer_hash
7
- end
8
-
9
- alias_method :find, :find_by_id
4
+ alias_method :find_by_id, :find
10
5
 
11
6
  def find_by_token(token)
12
7
  user_request = Request.new(token: token)
13
8
  customer_hash = user_request.get('customers/me').parse
14
- map_hash Customer, customer_hash
9
+ ModelMapper.from_hash(customer_hash).to_model(Customer)
15
10
  end
16
11
  end
17
12
  end
@@ -1,47 +1,79 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/inflector'
3
+ require 'forwardable'
4
4
 
5
5
  module Magento
6
6
  class Model
7
+ def save
8
+ body = ModelMapper.from_object(self).to_hash
9
+ self.class.update(send(self.class.primary_key), body)
10
+ end
11
+
12
+ def update(attrs)
13
+ raise "#{self.class.name} not saved" if send(self.class.primary_key).nil?
14
+
15
+ attrs.each { |key, value| send("#{key}=", value) }
16
+ save
17
+ end
18
+
19
+ def delete
20
+ self.class.delete(send(self.class.primary_key))
21
+ end
22
+
7
23
  class << self
8
- protected
24
+ extend Forwardable
25
+
26
+ def_delegators :query, :all, :page, :per, :order, :select
9
27
 
10
- def map_hash(klass, values)
11
- object = klass.new
12
- values.each do |key, value|
13
- object.singleton_class.instance_eval { attr_accessor key }
14
- if value.is_a?(Hash)
15
- class_name = inflector.camelize(inflector.singularize(key))
16
- value = map_hash(Object.const_get("Magento::#{class_name}"), value)
17
- elsif value.is_a?(Array)
18
- value = map_array(key, value)
19
- end
20
- object.send("#{key}=", value)
21
- end
22
- object
23
- end
24
-
25
- def map_array(key, values)
26
- result = []
27
- values.each do |value|
28
- if value.is_a?(Hash)
29
- class_name = inflector.camelize(inflector.singularize(key))
30
- result << map_hash(Object.const_get("Magento::#{class_name}"), value)
31
- else
32
- result << value
33
- end
34
- end
35
- result
28
+ def find(id)
29
+ hash = request.get("#{api_resource}/#{id}").parse
30
+ ModelMapper.from_hash(hash).to_model(self)
36
31
  end
37
32
 
38
- def inflector
39
- @inflector ||= Dry::Inflector.new
33
+ def create(attributes)
34
+ body = { entity_name => attributes }
35
+ hash = request.post(api_resource, body).parse
36
+ ModelMapper.from_hash(hash).to_model(self)
37
+ end
38
+
39
+ def delete(id)
40
+ request.delete("#{api_resource}/#{id}")
41
+ end
42
+
43
+ def update(id, attributes)
44
+ body = { entity_name => attributes }
45
+ hash = request.put("#{api_resource}/#{id}", body).parse
46
+ ModelMapper.from_hash(hash).to_model(self)
47
+ end
48
+
49
+ def api_resource
50
+ endpoint || inflector.pluralize(entity_name)
51
+ end
52
+
53
+ def entity_name
54
+ inflector.underscore(name).sub('magento/', '')
55
+ end
56
+
57
+ def primary_key
58
+ @primary_key || :id
59
+ end
60
+
61
+ protected
62
+
63
+ attr_writer :primary_key
64
+ attr_accessor :endpoint
65
+
66
+ def query
67
+ Query.new(self)
40
68
  end
41
69
 
42
70
  def request
43
71
  @request ||= Request.new
44
72
  end
73
+
74
+ def inflector
75
+ @inflector ||= Dry::Inflector.new
76
+ end
45
77
  end
46
78
  end
47
79
  end
@@ -0,0 +1,71 @@
1
+ class ModelMapper
2
+ def initialize(from)
3
+ @from = from
4
+ end
5
+
6
+ def to_model(model)
7
+ map_hash(model, @from)
8
+ end
9
+
10
+ def to_hash
11
+ self.class.to_hash(@from)
12
+ end
13
+
14
+ def self.from_object(object)
15
+ new(object)
16
+ end
17
+
18
+ def self.from_hash(values)
19
+ new(values)
20
+ end
21
+
22
+ def self.to_hash(object)
23
+ hash = {}
24
+ object.instance_variables.each do |attr|
25
+ key = attr.to_s.delete('@')
26
+ value = object.send(key)
27
+ value = to_hash(value) if value.class.name.include?('Magento::')
28
+ if value.is_a? Array
29
+ value = value.map do |item|
30
+ item.class.name.include?('Magento::') ? to_hash(item) : item
31
+ end
32
+ end
33
+ hash[key] = value
34
+ end
35
+ hash
36
+ end
37
+
38
+ private
39
+
40
+ def map_hash(model, values)
41
+ object = model.new
42
+ values.each do |key, value|
43
+ object.singleton_class.instance_eval { attr_accessor key }
44
+ if value.is_a?(Hash)
45
+ class_name = inflector.camelize(inflector.singularize(key))
46
+ value = map_hash(Object.const_get("Magento::#{class_name}"), value)
47
+ elsif value.is_a?(Array)
48
+ value = map_array(key, value)
49
+ end
50
+ object.send("#{key}=", value)
51
+ end
52
+ object
53
+ end
54
+
55
+ def map_array(key, values)
56
+ result = []
57
+ values.each do |value|
58
+ if value.is_a?(Hash)
59
+ class_name = inflector.camelize(inflector.singularize(key))
60
+ result << map_hash(Object.const_get("Magento::#{class_name}"), value)
61
+ else
62
+ result << value
63
+ end
64
+ end
65
+ result
66
+ end
67
+
68
+ def inflector
69
+ @inflector ||= Dry::Inflector.new
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ module Magento
2
+ class Order < Model
3
+ self.primary_key = :entity_id
4
+ end
5
+ end
@@ -1,10 +1,7 @@
1
1
  module Magento
2
2
  class Product < Model
3
3
  class << self
4
- def find_by_sku(sku)
5
- product_hash = request.get("products/#{sku}").parse
6
- map_hash Product, product_hash
7
- end
4
+ alias_method :find_by_sku, :find
8
5
  end
9
6
  end
10
7
  end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+
5
+ module Magento
6
+ class Query
7
+ ACCEPTED_CONDITIONS = [
8
+ 'eq', # Equals.
9
+ 'finset', # A value within a set of values
10
+ 'from', # The beginning of a range. Must be used with to
11
+ 'gt', # Greater than
12
+ 'gteq', # Greater than or equal
13
+ 'in', # In. The value can contain a comma-separated list of values.
14
+ 'like', # Like. The value can contain the SQL wildcard characters when like is specified.
15
+ 'lt', # Less than
16
+ 'lteq', # Less than or equal
17
+ 'moreq', # More or equal
18
+ 'neq', # Not equal
19
+ 'nfinset', # A value that is not within a set of values
20
+ 'nin', # Not in. The value can contain a comma-separated list of values.
21
+ 'notnull', # Not null
22
+ 'null', # Null
23
+ 'to' # The end of a range. Must be used with from
24
+ ].freeze
25
+
26
+ def initialize(model, request: Request.new)
27
+ @model = model
28
+ @request = request
29
+ @filter_groups = nil
30
+ @current_page = 1
31
+ @page_size = 50
32
+ @sort_orders = nil
33
+ @fields = nil
34
+ end
35
+
36
+ def where(attributes)
37
+ self.filter_groups = [] unless filter_groups
38
+ filters = []
39
+ attributes.each do |key, value|
40
+ field, condition = parse_filter(key)
41
+ filters << { field: field, conditionType: condition, value: value }
42
+ end
43
+ filter_groups << { filters: filters }
44
+ self
45
+ end
46
+
47
+ def page(current_page)
48
+ self.current_page = current_page
49
+ self
50
+ end
51
+
52
+ def per(page_size)
53
+ self.page_size = page_size
54
+ self
55
+ end
56
+
57
+ def select(*fields)
58
+ fields = fields.map { |field| parse_field(field) }
59
+ self.fields = "items[#{fields.join(',')}]"
60
+ self
61
+ end
62
+
63
+ def order(attributes)
64
+ if attributes.is_a?(String)
65
+ self.sort_orders = [{ field: verify_id(attributes), direction: :asc }]
66
+ elsif attributes.is_a?(Hash)
67
+ self.sort_orders = []
68
+ attributes.each do |field, direction|
69
+ raise "Invalid sort order direction '#{direction}'" unless %w[asc desc].include?(direction.to_s)
70
+
71
+ sort_orders << { field: verify_id(field), direction: direction }
72
+ end
73
+ end
74
+ self
75
+ end
76
+
77
+ def all
78
+ items = request.get("#{endpoint}?#{query_params}").parse['items']
79
+ items ? items.map { |i| ModelMapper.from_hash(i).to_model(model) } : []
80
+ end
81
+
82
+ private
83
+
84
+ attr_accessor :current_page, :filter_groups, :page_size, :request, :sort_orders, :model, :fields
85
+
86
+ def endpoint
87
+ model.api_resource
88
+ end
89
+
90
+ def verify_id(field)
91
+ return model.primary_key if (field.to_s == 'id') && (field.to_s != model.primary_key.to_s)
92
+
93
+ field
94
+ end
95
+
96
+ def query_params
97
+ query = {
98
+ searchCriteria: {
99
+ filterGroups: filter_groups,
100
+ currentPage: current_page,
101
+ sortOrders: sort_orders,
102
+ pageSize: page_size
103
+ }.compact,
104
+ fields: fields
105
+ }.compact
106
+
107
+ encode query
108
+ end
109
+
110
+ def parse_filter(key)
111
+ patter = /(.*)_([a-z]+)$/
112
+ raise 'Invalid format' unless key.match(patter)
113
+ raise 'Condition not accepted' unless ACCEPTED_CONDITIONS.include?(key.match(patter)[2])
114
+
115
+ key.match(patter).to_a[1..2]
116
+ end
117
+
118
+ def parse_field(value)
119
+ return verify_id(value) unless value.is_a? Hash
120
+
121
+ value.map do |k, v|
122
+ fields = v.is_a?(Array) ? v.map { |field| parse_field(field) } : [parse_field(v)]
123
+ "#{k}[#{fields.join(',')}]"
124
+ end.join(',')
125
+ end
126
+
127
+ def encode(value, key = nil)
128
+ case value
129
+ when Hash then value.map { |k, v| encode(v, append_key(key, k)) }.join('&')
130
+ when Array then value.each_with_index.map { |v, i| encode(v, "#{key}[#{i}]") }.join('&')
131
+ when nil then ''
132
+ else
133
+ "#{key}=#{CGI.escape(value.to_s)}"
134
+ end
135
+ end
136
+
137
+ def append_key(root_key, key)
138
+ root_key.nil? ? key : "#{root_key}[#{key}]"
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class Item; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class Payment; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class PaymentAdditionalInfo; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class Shipping; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class ShippingAssignment; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class Total; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Magento
2
+ class Value; end
3
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'magento'
5
- s.version = '0.2.0'
5
+ s.version = '0.3.0'
6
6
  s.date = '2020-07-31'
7
7
  s.summary = 'Magento Ruby library'
8
8
  s.description = 'Magento Ruby library'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magento
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wallas Faria
@@ -48,23 +48,34 @@ files:
48
48
  - Gemfile
49
49
  - README.md
50
50
  - lib/magento.rb
51
+ - lib/magento/category.rb
51
52
  - lib/magento/country.rb
52
53
  - lib/magento/customer.rb
53
54
  - lib/magento/errors.rb
54
55
  - lib/magento/model.rb
56
+ - lib/magento/model_mapper.rb
57
+ - lib/magento/order.rb
55
58
  - lib/magento/product.rb
59
+ - lib/magento/query.rb
56
60
  - lib/magento/request.rb
57
61
  - lib/magento/shared/address.rb
58
62
  - lib/magento/shared/available_regions.rb
59
63
  - lib/magento/shared/category_link.rb
60
64
  - lib/magento/shared/custom_attribute.rb
61
65
  - lib/magento/shared/extension_attribute.rb
66
+ - lib/magento/shared/item.rb
62
67
  - lib/magento/shared/media_gallery_entry.rb
63
68
  - lib/magento/shared/option.rb
69
+ - lib/magento/shared/payment.rb
70
+ - lib/magento/shared/payment_additional_info.rb
64
71
  - lib/magento/shared/product_link.rb
65
72
  - lib/magento/shared/region.rb
73
+ - lib/magento/shared/shipping.rb
74
+ - lib/magento/shared/shipping_assignment.rb
66
75
  - lib/magento/shared/stock_item.rb
67
76
  - lib/magento/shared/tier_price.rb
77
+ - lib/magento/shared/total.rb
78
+ - lib/magento/shared/value.rb
68
79
  - magento.gemspec
69
80
  homepage: https://github.com/WallasFaria/magento-ruby
70
81
  licenses: []