magento 0.26.1 → 0.29.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.
@@ -0,0 +1,104 @@
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
+ #
35
+ # Place order for cart
36
+ #
37
+ # Example:
38
+ #
39
+ # cart = Magento::Cart.find('12345')
40
+ #
41
+ # # or use "build" to not request information from the magento API
42
+ # cart = Magento::GuestCart.build({ 'cart_id' => '12345' })
43
+ #
44
+ # cart.order(
45
+ # email: 'customer@gmail.com',
46
+ # payment: { method: 'cashondelivery' }
47
+ # )
48
+ #
49
+ # @return String: return the order id
50
+ def order(email:, payment:)
51
+ attributes = { cartId: id, paymentMethod: payment, email: email }
52
+ self.class.order(attributes)
53
+ end
54
+
55
+ class << self
56
+ #
57
+ # Add a coupon by code to a specified cart.
58
+ #
59
+ # Example:
60
+ #
61
+ # Magento::Cart.add_coupon(
62
+ # 1,
63
+ # 'COAU4HXE0I'
64
+ # )
65
+ #
66
+ # @return Boolean: true on success, false otherwise
67
+ def add_coupon(id, coupon)
68
+ url = "#{api_resource}/#{id}/coupons/#{coupon}"
69
+ request.put(url, nil).parse
70
+ end
71
+
72
+ #
73
+ # Delete a coupon from a specified cart.
74
+ #
75
+ # Example:
76
+ #
77
+ # Magento::Cart.delete_coupon(1)
78
+ #
79
+ # @return Boolean: true on success, raise exception otherwise
80
+ def delete_coupon(id)
81
+ url = "#{api_resource}/#{id}/coupons"
82
+ request.delete(url).parse
83
+ end
84
+
85
+ #
86
+ # Place order for cart
87
+ #
88
+ # Example:
89
+ #
90
+ # Magento::Cart.order(
91
+ # cartId: '12345',
92
+ # paymentMethod: { method: 'cashondelivery' },
93
+ # email: email
94
+ # )
95
+ #
96
+ # @return String: return the order id
97
+ def order(attributes)
98
+ attributes.transform_keys(&:to_sym)
99
+ url = "#{api_resource}/#{attributes[:cartId]}/order"
100
+ request.put(url, attributes).parse
101
+ end
102
+ end
103
+ end
104
+ 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
  #
@@ -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
@@ -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.26.1'
2
+ VERSION = '0.29.0'
3
3
  end
data/lib/magento.rb CHANGED
@@ -25,6 +25,7 @@ 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'
28
29
 
29
30
  require_relative 'magento/params/create_custom_attribute'
30
31
  require_relative 'magento/params/create_image'
@@ -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