magento 0.24.0 → 0.28.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 +4 -4
- data/.gitignore +4 -2
- data/Gemfile +5 -3
- data/README.md +636 -226
- data/lib/magento.rb +7 -1
- data/lib/magento/cart.rb +65 -0
- data/lib/magento/order.rb +47 -2
- data/lib/magento/params/create_image.rb +43 -0
- data/lib/magento/params/create_product_link.rb +30 -0
- data/lib/magento/product.rb +96 -1
- data/lib/magento/query.rb +13 -10
- data/lib/magento/sales_rule.rb +4 -0
- data/lib/magento/version.rb +1 -1
- data/spec/magento/core/model_mapper_spec.rb +74 -0
- data/spec/magento/core/model_spec.rb +71 -0
- data/spec/magento/core/query_spec.rb +207 -0
- data/spec/magento/core/record_collection_spec.rb +116 -0
- data/spec/magento/core/request_spec.rb +141 -0
- data/spec/magento/order_spec.rb +37 -0
- data/spec/{product_spec.rb → magento/product_spec.rb} +21 -0
- data/spec/spec_helper.rb +17 -3
- data/spec/vcr_cassettes/order/send_email.yml +65 -0
- data/spec/vcr_cassettes/product/find.yml +72 -0
- metadata +13 -4
- data/.rspec_status +0 -5
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
|
data/lib/magento/cart.rb
ADDED
@@ -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'))
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Magento
|
4
|
+
module Params
|
5
|
+
class CreateProductLink < Dry::Struct
|
6
|
+
LinkType = Type::String.enum(
|
7
|
+
'related',
|
8
|
+
'upsell',
|
9
|
+
'crosssell',
|
10
|
+
'associated'
|
11
|
+
)
|
12
|
+
|
13
|
+
attribute :link_type, LinkType
|
14
|
+
attribute :linked_product_sku, Type::String
|
15
|
+
attribute :linked_product_type, Magento::Params::CreateProduct::ProductTypes
|
16
|
+
attribute :position, Type::Integer
|
17
|
+
attribute :sku, Type::String
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{
|
21
|
+
link_type: link_type,
|
22
|
+
linked_product_sku: linked_product_sku,
|
23
|
+
linked_product_type: linked_product_type,
|
24
|
+
position: position,
|
25
|
+
sku: sku
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/magento/product.rb
CHANGED
@@ -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
|
@@ -47,7 +75,6 @@ module Magento
|
|
47
75
|
self.class.remove_media(sku, media_id)
|
48
76
|
end
|
49
77
|
|
50
|
-
#
|
51
78
|
# Add {price} on product {sku} for specified {customer_group_id}
|
52
79
|
#
|
53
80
|
# Param {quantity} is the minimun amount to apply the price
|
@@ -89,9 +116,57 @@ module Magento
|
|
89
116
|
self.class.update_stock(sku, id, attributes)
|
90
117
|
end
|
91
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
|
+
|
92
141
|
class << self
|
93
142
|
alias_method :find_by_sku, :find
|
94
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
|
+
#
|
95
170
|
def add_media(sku, attributes)
|
96
171
|
request.post("products/#{sku}/media", { entry: attributes }).parse
|
97
172
|
end
|
@@ -134,6 +209,26 @@ module Magento
|
|
134
209
|
def update_stock(sku, id, attributes)
|
135
210
|
request.put("products/#{sku}/stockItems/#{id}", stockItem: attributes).parse
|
136
211
|
end
|
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
|
+
#
|
225
|
+
def create_links(sku, product_links)
|
226
|
+
request.post("products/#{sku}/links", { items: product_links })
|
227
|
+
end
|
228
|
+
|
229
|
+
def remove_link(sku, link_type:, linked_product_sku:)
|
230
|
+
request.delete("products/#{sku}/links/#{link_type}/#{linked_product_sku}")
|
231
|
+
end
|
137
232
|
end
|
138
233
|
end
|
139
234
|
end
|
data/lib/magento/query.rb
CHANGED
@@ -23,7 +23,7 @@ module Magento
|
|
23
23
|
'to' # The end of a range. Must be used with from
|
24
24
|
].freeze
|
25
25
|
|
26
|
-
def initialize(model, request: Request.new)
|
26
|
+
def initialize(model, request: Request.new, api_resource: nil)
|
27
27
|
@model = model
|
28
28
|
@request = request
|
29
29
|
@filter_groups = nil
|
@@ -31,6 +31,7 @@ module Magento
|
|
31
31
|
@page_size = 50
|
32
32
|
@sort_orders = nil
|
33
33
|
@fields = nil
|
34
|
+
@endpoint = api_resource || model.api_resource
|
34
35
|
end
|
35
36
|
|
36
37
|
def where(attributes)
|
@@ -69,15 +70,17 @@ module Magento
|
|
69
70
|
self
|
70
71
|
end
|
71
72
|
|
72
|
-
def order(attributes)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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)
|
79
81
|
|
80
|
-
|
82
|
+
sort_orders << { field: verify_id(field), direction: direction }
|
83
|
+
end
|
81
84
|
end
|
82
85
|
end
|
83
86
|
self
|
@@ -131,7 +134,7 @@ module Magento
|
|
131
134
|
attr_accessor :current_page, :filter_groups, :request, :sort_orders, :model, :fields
|
132
135
|
|
133
136
|
def endpoint
|
134
|
-
|
137
|
+
@endpoint
|
135
138
|
end
|
136
139
|
|
137
140
|
def verify_id(field)
|
data/lib/magento/sales_rule.rb
CHANGED
data/lib/magento/version.rb
CHANGED
@@ -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
|