magento 0.26.1 → 0.27.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.
data/lib/magento/order.rb CHANGED
@@ -34,7 +34,6 @@ module Magento
34
34
  self.class.invoice(id, params)
35
35
  end
36
36
 
37
-
38
37
  #
39
38
  # Create offline refund for order
40
39
  #
@@ -65,6 +64,22 @@ module Magento
65
64
  self.class.send_email(id)
66
65
  end
67
66
 
67
+ #
68
+ # Creates a comment on the given Order
69
+ #
70
+ # order = Magento::Order.find(order_id)
71
+ #
72
+ # order.add_comment(
73
+ # 'comment',
74
+ # is_customer_notified: 0,
75
+ # is_visible_on_front: 1
76
+ # )
77
+ #
78
+ # Return true on success
79
+ def add_comment(comment, comment_params = nil)
80
+ self.class.add_comment(id, comment, comment_params)
81
+ end
82
+
68
83
  class << self
69
84
  def update(entity_id, attributes)
70
85
  attributes[:entity_id] = entity_id
@@ -104,7 +119,6 @@ module Magento
104
119
  request.post("order/#{order_id}/invoice", invoice_params).parse
105
120
  end
106
121
 
107
-
108
122
  #
109
123
  # Create offline refund for order
110
124
  #
@@ -180,6 +194,29 @@ module Magento
180
194
  def send_email(order_id)
181
195
  request.post("orders/#{order_id}/emails").parse
182
196
  end
197
+
198
+ #
199
+ # Creates a comment on the given Order
200
+ #
201
+ # Magento::Order.add_comment(
202
+ # order_id,
203
+ # 'comment',
204
+ # is_customer_notified: 0,
205
+ # is_visible_on_front: 1
206
+ # )
207
+ #
208
+ # to complete [documentation](https://magento.redoc.ly/2.4.2-admin/tag/ordersidcomments#operation/salesOrderManagementV1AddCommentPost)
209
+ #
210
+ # @return {Boolean}: return true on success
211
+ def add_comment(order_id, comment, comment_params = nil)
212
+ request.post(
213
+ "orders/#{order_id}/comments",
214
+ statusHistory: {
215
+ comment: comment,
216
+ **comment_params
217
+ }
218
+ ).parse
219
+ end
183
220
  end
184
221
  end
185
222
  end
@@ -5,6 +5,35 @@ require 'mini_magick'
5
5
 
6
6
  module Magento
7
7
  module Params
8
+
9
+ # Helper class to create product image params.
10
+ # before generating the hash, the following image treatments are performed:
11
+ # - resize image
12
+ # - remove alpha
13
+ # - leaves square
14
+ # - convert image to jpg
15
+ #
16
+ # Example:
17
+ #
18
+ # params = Magento::Params::CreateImage.new(
19
+ # title: 'Image title',
20
+ # path: '/path/to/image.jpg', # or url
21
+ # position: 1,
22
+ # size: 'small', # options: 'large'(defaut), 'medium' and 'small',
23
+ # disabled: true, # default is false,
24
+ # main: true, # default is false,
25
+ # ).to_h
26
+ #
27
+ # Magento::Product.add_media('sku', params)
28
+ #
29
+ # The resize defaut confiruration is:
30
+ #
31
+ # Magento.configure do |config|
32
+ # config.product_image.small_size = '200x200>'
33
+ # config.product_image.medium_size = '400x400>'
34
+ # config.product_image.large_size = '800x800>'
35
+ # end
36
+ #
8
37
  class CreateImage < Dry::Struct
9
38
  VARIANTS = {
10
39
  'large' => :image,
@@ -34,6 +63,20 @@ module Magento
34
63
  }
35
64
  end
36
65
 
66
+ # Generates a list containing an Magento::Params::CreateImage
67
+ # instance for each size of the same image.
68
+ #
69
+ # Example:
70
+ #
71
+ # params = Magento::Params::CreateImage.new(
72
+ # title: 'Image title',
73
+ # path: '/path/to/image.jpg', # or url
74
+ # position: 1,
75
+ # ).variants
76
+ #
77
+ # params.map(&:size)
78
+ # => ['large', 'medium', 'small']
79
+ #
37
80
  def variants
38
81
  VARIANTS.keys.map do |size|
39
82
  CreateImage.new(attributes.merge(size: size, disabled: size != 'large'))
@@ -38,6 +38,34 @@ module Magento
38
38
  super || @custom_attributes&.any? { |a| a.attribute_code == attribute_code.to_s }
39
39
  end
40
40
 
41
+ # Create new gallery entry
42
+ #
43
+ # Example:
44
+ #
45
+ # product = Magento::Product.find('sku')
46
+ #
47
+ # product.add_media(
48
+ # media_type: 'image',
49
+ # label: 'Image label',
50
+ # position: 1,
51
+ # content: {
52
+ # base64_encoded_data: 'image-string-base64',
53
+ # type: 'image/jpg',
54
+ # name: 'filename.jpg'
55
+ # },
56
+ # types: ['image']
57
+ # )
58
+ #
59
+ # Or you can use the Magento::Params::CreateImage helper class
60
+ #
61
+ # params = Magento::Params::CreateImage.new(
62
+ # title: 'Image title',
63
+ # path: '/path/to/image.jpg', # or url
64
+ # position: 1,
65
+ # ).to_h
66
+ #
67
+ # product.add_media(params)
68
+ #
41
69
  def add_media(attributes)
42
70
  self.class.add_media(sku, attributes)
43
71
  end
@@ -88,9 +116,57 @@ module Magento
88
116
  self.class.update_stock(sku, id, attributes)
89
117
  end
90
118
 
119
+ # Assign a product link to another product
120
+ #
121
+ # product = Magento::Product.find('sku')
122
+ #
123
+ # product.create_links([
124
+ # {
125
+ # link_type: 'upsell',
126
+ # linked_product_sku: 'linked_product_sku',
127
+ # linked_product_type: 'simple',
128
+ # position: position,
129
+ # sku: 'product-sku'
130
+ # }
131
+ # ])
132
+ #
133
+ def create_links(product_links)
134
+ self.class.create_links(sku, product_links)
135
+ end
136
+
137
+ def remove_link(link_type:, linked_product_sku:)
138
+ self.class.remove_link(sku, link_type: link_type, linked_product_sku: linked_product_sku)
139
+ end
140
+
91
141
  class << self
92
142
  alias_method :find_by_sku, :find
93
143
 
144
+ # Create new gallery entry
145
+ #
146
+ # Example:
147
+ #
148
+ # Magento::Product.add_media('sku', {
149
+ # media_type: 'image',
150
+ # label: 'Image title',
151
+ # position: 1,
152
+ # content: {
153
+ # base64_encoded_data: 'image-string-base64',
154
+ # type: 'image/jpg',
155
+ # name: 'filename.jpg'
156
+ # },
157
+ # types: ['image']
158
+ # })
159
+ #
160
+ # Or you can use the Magento::Params::CreateImage helper class
161
+ #
162
+ # params = Magento::Params::CreateImage.new(
163
+ # title: 'Image title',
164
+ # path: '/path/to/image.jpg', # or url
165
+ # position: 1,
166
+ # ).to_h
167
+ #
168
+ # Magento::Product.add_media('sku', params)
169
+ #
94
170
  def add_media(sku, attributes)
95
171
  request.post("products/#{sku}/media", { entry: attributes }).parse
96
172
  end
@@ -134,6 +210,18 @@ module Magento
134
210
  request.put("products/#{sku}/stockItems/#{id}", stockItem: attributes).parse
135
211
  end
136
212
 
213
+ # Assign a product link to another product
214
+ #
215
+ # Product.create_links('product-sku', [
216
+ # {
217
+ # link_type: 'upsell',
218
+ # linked_product_sku: 'linked_product_sku',
219
+ # linked_product_type: 'simple',
220
+ # position: position,
221
+ # sku: 'product-sku'
222
+ # }
223
+ # ])
224
+ #
137
225
  def create_links(sku, product_links)
138
226
  request.post("products/#{sku}/links", { items: product_links })
139
227
  end
data/lib/magento/query.rb CHANGED
@@ -70,15 +70,17 @@ module Magento
70
70
  self
71
71
  end
72
72
 
73
- def order(attributes)
74
- if attributes.is_a?(String)
75
- self.sort_orders = [{ field: verify_id(attributes), direction: :asc }]
76
- elsif attributes.is_a?(Hash)
77
- self.sort_orders = []
78
- attributes.each do |field, direction|
79
- raise "Invalid sort order direction '#{direction}'" unless %w[asc desc].include?(direction.to_s)
80
-
81
- sort_orders << { field: verify_id(field), direction: direction }
73
+ def order(*attributes)
74
+ self.sort_orders = []
75
+ attributes.each do |sort_order|
76
+ if sort_order.is_a?(String) || sort_order.is_a?(Symbol)
77
+ sort_orders << { field: verify_id(sort_order), direction: :asc }
78
+ elsif sort_order.is_a?(Hash)
79
+ sort_order.each do |field, direction|
80
+ raise "Invalid sort order direction '#{direction}'" unless %w[asc desc].include?(direction.to_s)
81
+
82
+ sort_orders << { field: verify_id(field), direction: direction }
83
+ end
82
84
  end
83
85
  end
84
86
  self
@@ -1,3 +1,3 @@
1
1
  module Magento
2
- VERSION = '0.26.1'
2
+ VERSION = '0.27.0'
3
3
  end
@@ -0,0 +1,74 @@
1
+ RSpec.describe Magento::ModelMapper do
2
+ describe '.to_hash' do
3
+ it 'serializes object to hash' do
4
+ class Magento::SameClass
5
+ attr_accessor :name, :description, :items
6
+ end
7
+
8
+ object = Magento::SameClass.new
9
+ object.name = 'Some name'
10
+ object.description = 'Some description'
11
+ object.items = [object.dup]
12
+
13
+ expect(Magento::ModelMapper.to_hash(object)).to eql({
14
+ 'name' => 'Some name',
15
+ 'description' => 'Some description',
16
+ 'items' => [{ 'name' => 'Some name', 'description' => 'Some description' }]
17
+ })
18
+ end
19
+ end
20
+
21
+ describe '.map_hash' do
22
+ it 'returns magento object from hash' do
23
+ class Magento::SameClass; end
24
+ hash = { name: 'Some name', price: 10.99 }
25
+
26
+ object = Magento::ModelMapper.map_hash(Magento::SameClass, hash)
27
+
28
+ expect(object).to be_instance_of(Magento::SameClass)
29
+ expect(object.name).to eql hash[:name]
30
+ expect(object.price).to eql hash[:price]
31
+ end
32
+ end
33
+
34
+ describe '.map_array' do
35
+ it 'returns magento object list from array of hash' do
36
+ class Magento::SameClass; end
37
+ array = [{ name: 'Some name', price: 10.99 }]
38
+
39
+ object = Magento::ModelMapper.map_array('same_class', array)
40
+
41
+ expect(object).to be_a(Array)
42
+ expect(object).to all be_instance_of(Magento::SameClass)
43
+ end
44
+ end
45
+
46
+ describe 'include ModelParser' do
47
+ before do
48
+ class Magento::SameClass
49
+ include Magento::ModelParser
50
+ end
51
+ end
52
+
53
+ let(:hash) { { name: 'Same name' } }
54
+
55
+ describe '.build' do
56
+ it 'calls Magento::ModelMapper.map_hash' do
57
+ expect(Magento::ModelMapper).to receive(:map_hash)
58
+ .with(Magento::SameClass, hash)
59
+
60
+ Magento::SameClass.build(hash)
61
+ end
62
+ end
63
+
64
+ describe '#to_h' do
65
+ it 'calls Magento::ModelMapper.to_hash' do
66
+ object = Magento::SameClass.build(hash)
67
+
68
+ expect(Magento::ModelMapper).to receive(:to_hash).with(object)
69
+
70
+ object.to_h
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,71 @@
1
+ RSpec.describe Magento::Model do
2
+ describe 'public method' do
3
+ describe '.find' do
4
+ it 'is pending'
5
+ end
6
+
7
+ describe '.create' do
8
+ it 'is pending'
9
+ end
10
+
11
+ describe '.update' do
12
+ it 'is pending'
13
+ end
14
+
15
+ describe '.delete' do
16
+ it 'is pending'
17
+ end
18
+
19
+ describe '#save' do
20
+ it 'calls the update class method'
21
+ end
22
+
23
+ describe '#update' do
24
+ it 'calls the update class method'
25
+ end
26
+
27
+ describe '#delete' do
28
+ it 'calls the delete class method'
29
+ end
30
+
31
+ describe '.api_resource' do
32
+ it 'is pending'
33
+ end
34
+
35
+ describe '.entity_name' do
36
+ it 'is pending'
37
+ end
38
+
39
+ describe '.primary_key' do
40
+ it 'is pending'
41
+ end
42
+
43
+ describe 'delegated methods from query' do
44
+ it 'respond to .all'
45
+ it 'respond to .find_each'
46
+ it 'respond to .page'
47
+ it 'respond to .per'
48
+ it 'respond to .page_size'
49
+ it 'respond to .order'
50
+ it 'respond to .select'
51
+ it 'respond to .where'
52
+ it 'respond to .first'
53
+ it 'respond to .find_by'
54
+ it 'respond to .count'
55
+ end
56
+ end
57
+
58
+ describe 'protected method' do
59
+ describe '.entity_key' do
60
+ it 'is pending'
61
+ end
62
+
63
+ describe '.query' do
64
+ it 'is pending'
65
+ end
66
+
67
+ describe '.request' do
68
+ it 'is pending'
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,207 @@
1
+ class Magento::Faker < Magento::Model; end
2
+
3
+ RSpec.describe Magento::Query do
4
+ subject { Magento::Query.new(Magento::Faker) }
5
+
6
+ describe '#where' do
7
+ it 'add the filter to group of filters' do
8
+ subject.where(price_gt: 50)
9
+
10
+ expect(subject.send(:filter_groups)).to eql([
11
+ { filters: [{ field: 'price', conditionType: 'gt', value: 50 }] }
12
+ ])
13
+ end
14
+
15
+ context 'when the condition is not passed' do
16
+ it 'the "eq" condition is used as default' do
17
+ subject.where(price: 50)
18
+
19
+ expect(subject.send(:filter_groups)).to eql([
20
+ { filters: [{ field: :price, conditionType: 'eq', value: 50 }] }
21
+ ])
22
+ end
23
+ end
24
+
25
+ context 'when it is called more than once' do
26
+ it 'adds filter in diferent groups' do
27
+ subject.where(price_gt: 10).where(price_lt: 20)
28
+
29
+ expect(subject.send(:filter_groups)).to eql([
30
+ { filters: [{ field: 'price', conditionType: 'gt', value: 10 }] },
31
+ { filters: [{ field: 'price', conditionType: 'lt', value: 20 }] }
32
+ ])
33
+ end
34
+ end
35
+
36
+ context 'when it is called with more than one filter' do
37
+ it 'adds the filters in same group' do
38
+ subject.where(price_gt: 10, price_lt: 20)
39
+
40
+ expect(subject.send(:filter_groups)).to eql([
41
+ {
42
+ filters: [
43
+ { field: 'price', conditionType: 'gt', value: 10 },
44
+ { field: 'price', conditionType: 'lt', value: 20 }
45
+ ]
46
+ }
47
+ ])
48
+ end
49
+ end
50
+
51
+ context 'when the condition is "in" or "nin" and value is a Array' do
52
+ it 'converts the value to string' do
53
+ subject.where(status_in: [:pending, :new])
54
+ subject.where(entity_id_nin: [123, 321])
55
+
56
+ expect(subject.send(:filter_groups)).to eql([
57
+ { filters: [{ field: 'status', conditionType: 'in', value: 'pending,new' }] },
58
+ { filters: [{ field: 'entity_id', conditionType: 'nin', value: '123,321' }] }
59
+ ])
60
+ end
61
+ end
62
+ end
63
+
64
+ describe '#page' do
65
+ it do
66
+ subject.page(2)
67
+ expect(subject.send(:current_page)).to eql(2)
68
+ end
69
+ end
70
+
71
+ describe '#page_size' do
72
+ it do
73
+ subject.page_size(5)
74
+ expect(subject.instance_variable_get(:@page_size)).to eql(5)
75
+ end
76
+ end
77
+
78
+ describe '#select' do
79
+ it 'set fields inside items[]' do
80
+ subject.select(:id, :name)
81
+
82
+ expect(subject.send(:fields)).to eql('items[id,name],search_criteria,total_count')
83
+ end
84
+
85
+ it 'allow hash' do
86
+ subject.select(:id, nested_attribute: :name)
87
+
88
+ expect(subject.send(:fields)).to eql('items[id,nested_attribute[name]],search_criteria,total_count')
89
+ end
90
+
91
+ it 'allow hash with key and value as array' do
92
+ subject.select(:id, nested_attribute: [:id, :name])
93
+
94
+ expect(subject.send(:fields)).to eql('items[id,nested_attribute[id,name]],search_criteria,total_count')
95
+ end
96
+
97
+ it 'allow hash multiple level' do
98
+ subject.select(:id, nested_attribute: [:id, :name, stock: :quantity])
99
+
100
+ expect(subject.send(:fields)).to eql(
101
+ 'items[id,nested_attribute[id,name,stock[quantity]]],search_criteria,total_count'
102
+ )
103
+ end
104
+
105
+ context 'when model is Magento::Category' do
106
+ class Magento::Category < Magento::Model; end
107
+
108
+ subject { Magento::Query.new(Magento::Category) }
109
+
110
+ it 'set fields inseide children_data[]' do
111
+ subject.select(:id, :name)
112
+
113
+ expect(subject.send(:fields)).to eql('children_data[id,name]')
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#order' do
119
+ it 'set order in sort_orders' do
120
+ subject.order(name: :desc)
121
+
122
+ expect(subject.send(:sort_orders)).to eql(
123
+ [{ field: :name, direction: :desc }]
124
+ )
125
+
126
+ subject.order(created_at: :desc, name: :asc)
127
+
128
+ expect(subject.send(:sort_orders)).to eql(
129
+ [
130
+ { field: :created_at, direction: :desc },
131
+ { field: :name, direction: :asc }
132
+ ]
133
+ )
134
+ end
135
+
136
+ context 'when the direction is not passed' do
137
+ it 'the :asc direction is used as default' do
138
+ subject.order(:name)
139
+
140
+ expect(subject.send(:sort_orders)).to eql(
141
+ [{ field: :name, direction: :asc }]
142
+ )
143
+
144
+ subject.order(:created_at, :name)
145
+
146
+ expect(subject.send(:sort_orders)).to eql([
147
+ { field: :created_at, direction: :asc },
148
+ { field: :name, direction: :asc }
149
+ ])
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '#all' do
155
+ it 'is pending'
156
+ end
157
+
158
+ describe '#first' do
159
+ it 'is pending'
160
+ end
161
+
162
+ describe '#find_by' do
163
+ it 'is pending'
164
+ end
165
+
166
+ describe '#count' do
167
+ it 'is pending'
168
+ end
169
+
170
+ describe '#find_each' do
171
+ it 'is pending'
172
+ end
173
+
174
+ describe 'private mathods' do
175
+ describe 'endpoint' do
176
+ it 'is pending'
177
+ end
178
+
179
+ describe 'verify_id' do
180
+ it 'is pending'
181
+ end
182
+
183
+ describe 'query_params' do
184
+ it 'is pending'
185
+ end
186
+
187
+ describe 'parse_filter' do
188
+ it 'is pending'
189
+ end
190
+
191
+ describe 'parse_value_filter' do
192
+ it 'is pending'
193
+ end
194
+
195
+ describe 'parse_field' do
196
+ it 'is pending'
197
+ end
198
+
199
+ describe 'encode' do
200
+ it 'is pending'
201
+ end
202
+
203
+ describe 'append_key' do
204
+ it 'is pending'
205
+ end
206
+ end
207
+ end