magento 0.25.0 → 0.28.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/magento.rb CHANGED
@@ -25,9 +25,15 @@ require_relative 'magento/guest_cart'
25
25
  require_relative 'magento/sales_rule'
26
26
  require_relative 'magento/inventory'
27
27
  require_relative 'magento/import'
28
+ require_relative 'magento/cart'
29
+
30
+ require_relative 'magento/params/create_custom_attribute'
31
+ require_relative 'magento/params/create_image'
32
+ require_relative 'magento/params/create_category'
33
+ require_relative 'magento/params/create_product'
34
+ require_relative 'magento/params/create_product_link'
28
35
 
29
36
  Dir[File.expand_path('magento/shared/*.rb', __dir__)].map { |f| require f }
30
- Dir[File.expand_path('magento/params/*.rb', __dir__)].map { |f| require f }
31
37
 
32
38
  module Magento
33
39
  class << self
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magento
4
+ class Cart < Model
5
+ self.endpoint = 'carts'
6
+ self.primary_key = :id
7
+
8
+ #
9
+ # Add a coupon by code to the current cart.
10
+ #
11
+ # Example:
12
+ #
13
+ # cart = Magento::Cart.find(1)
14
+ # cart.add_coupon('COAU4HXE0I')
15
+ #
16
+ # @return Boolean: true on success, false otherwise
17
+ def add_coupon(coupon)
18
+ self.class.add_coupon(id, coupon)
19
+ end
20
+
21
+ #
22
+ # Delete cart's coupon
23
+ #
24
+ # Example:
25
+ #
26
+ # cart = Magento::Cart.find(1)
27
+ # cart.delete_coupon()
28
+ #
29
+ # @return Boolean: true on success, raise exception otherwise
30
+ def delete_coupon
31
+ self.class.delete_coupon(id)
32
+ end
33
+
34
+ class << self
35
+ #
36
+ # Add a coupon by code to a specified cart.
37
+ #
38
+ # Example:
39
+ #
40
+ # Magento::Cart.add_coupon(
41
+ # 1,
42
+ # 'COAU4HXE0I'
43
+ # )
44
+ #
45
+ # @return Boolean: true on success, false otherwise
46
+ def add_coupon(id, coupon)
47
+ url = "#{api_resource}/#{id}/coupons/#{coupon}"
48
+ request.put(url, nil).parse
49
+ end
50
+
51
+ #
52
+ # Delete a coupon from a specified cart.
53
+ #
54
+ # Example:
55
+ #
56
+ # Magento::Cart.delete_coupon(1)
57
+ #
58
+ # @return Boolean: true on success, raise exception otherwise
59
+ def delete_coupon(id)
60
+ url = "#{api_resource}/#{id}/coupons"
61
+ request.delete(url).parse
62
+ end
63
+ end
64
+ end
65
+ end
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
  #
@@ -61,6 +60,26 @@ module Magento
61
60
  self.class.ship(id, params)
62
61
  end
63
62
 
63
+ def send_email
64
+ self.class.send_email(id)
65
+ end
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
+
64
83
  class << self
65
84
  def update(entity_id, attributes)
66
85
  attributes[:entity_id] = entity_id
@@ -100,7 +119,6 @@ module Magento
100
119
  request.post("order/#{order_id}/invoice", invoice_params).parse
101
120
  end
102
121
 
103
-
104
122
  #
105
123
  # Create offline refund for order
106
124
  #
@@ -172,6 +190,33 @@ module Magento
172
190
  def ship(order_id, shipment_params = nil)
173
191
  request.post("order/#{order_id}/ship", shipment_params).parse
174
192
  end
193
+
194
+ def send_email(order_id)
195
+ request.post("orders/#{order_id}/emails").parse
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
175
220
  end
176
221
  end
177
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
@@ -54,7 +54,12 @@ module Magento
54
54
  begin
55
55
  msg = resp.parse['message']
56
56
  errors = resp.parse['errors'] || resp.parse['parameters']
57
- resp.parse['parameters'].each { |k, v| msg.sub! "%#{k}", v } if resp.parse['parameters'].is_a? Hash
57
+ case errors
58
+ when Hash
59
+ errors.each { |k, v| msg.sub! "%#{k}", v }
60
+ when Array
61
+ errors.each_with_index { |v, i| msg.sub! "%#{i + 1}", v.to_s }
62
+ end
58
63
  rescue StandardError
59
64
  msg = 'Failed access to the magento server'
60
65
  errors = []
@@ -1,3 +1,3 @@
1
1
  module Magento
2
- VERSION = '0.25.0'
2
+ VERSION = '0.28.1'
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