magento 0.16.0 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54c756e43ba125d24cfd2695f5b3b362acf6a489cb0ccc7b7abd853b8488164c
4
- data.tar.gz: 103375f7ba57dae9d78e93d19e0cb95d6192365390b4d05005c465eea6737908
3
+ metadata.gz: bd6a94c17db3ebc55bcc96cbae5118128326e3d7ca2d0e96bfb5b530edea5561
4
+ data.tar.gz: a0e86d4bc16f5c4338281fcadb07ee62f18017cc59bcd89cb15804110472021c
5
5
  SHA512:
6
- metadata.gz: d839bf8cc47b2a7e639de881d2e8505cd8b3bb2d52428a1e8c58438e96e3bbf84392ccf22498b393a5ec60b812afca078e9f2cd33568f2475081501601f0c919
7
- data.tar.gz: 3192fd700e6356b0a58039b26fe8c5b25ab577328d67cce6a4495465f84c4dc9f6aa48e37cacbaafc7068b61ac91a983fe7b41287ff4316920b09951079a0dcf
6
+ metadata.gz: 1a7ebe7b9a4b24d0644ef31ddaee95ff17c07e702f001ec18ad632886e538187ff5a02ef841fe648d8c5eb0a5348b13579a15c9450c9442ad08f5fd29c17333f
7
+ data.tar.gz: 3252ea89c262918fce7b206e842197510929e1acb998da5613ba8f7d37f4f68de4b0cde29e765199f0bb0f177882dd33bd16efe98454231e909ee3cd3cb76b34
@@ -3,8 +3,6 @@ name: Ruby Gem
3
3
  on:
4
4
  push:
5
5
  branches: [ release ]
6
- pull_request:
7
- branches: [ release ]
8
6
 
9
7
  jobs:
10
8
  build:
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  Add in your Gemfile
6
6
 
7
7
  ```rb
8
- gem 'magento', '~> 0.15.1'
8
+ gem 'magento', '~> 0.19.0'
9
9
  ```
10
10
 
11
11
  or run
@@ -83,6 +83,23 @@ product.respond_to? :description
83
83
  > true
84
84
  ```
85
85
 
86
+ ## add tier price
87
+
88
+ Add `price` on product `sku` for specified `customer_group_id`
89
+
90
+ Param `quantity` is the minimun amount to apply the price
91
+
92
+ ```rb
93
+ product = Magento::Product.find(1)
94
+ product.add_tier_price(3.99, quantity: 1, customer_group_id: :all)
95
+ > true
96
+
97
+ # OR
98
+
99
+ Magento::Product.add_tier_price(1, 3.99, quantity: 1, customer_group_id: :all)
100
+ > true
101
+ ```
102
+
86
103
  ## Get List
87
104
 
88
105
  ```rb
@@ -5,6 +5,7 @@ require 'dry/inflector'
5
5
  require 'active_support/core_ext/string/inflections'
6
6
  require 'active_support/core_ext/hash/keys'
7
7
 
8
+ require_relative 'magento/configuration'
8
9
  require_relative 'magento/errors'
9
10
  require_relative 'magento/request'
10
11
  require_relative 'magento/model_mapper'
@@ -28,7 +29,9 @@ Dir[File.expand_path('magento/params/*.rb', __dir__)].map { |f| require f }
28
29
 
29
30
  module Magento
30
31
  class << self
31
- attr_accessor :url, :open_timeout, :timeout, :token, :store
32
+ attr_writer :configuration
33
+
34
+ delegate :url=, :token=, :store=, :open_timeout=, :timeout=, to: :configuration
32
35
 
33
36
  def inflector
34
37
  @inflector ||= Dry::Inflector.new do |inflections|
@@ -37,26 +40,24 @@ module Magento
37
40
  end
38
41
  end
39
42
 
40
- self.url = ENV['MAGENTO_URL']
41
- self.open_timeout = 30
42
- self.timeout = 90
43
- self.token = ENV['MAGENTO_TOKEN']
44
- self.store = ENV['MAGENTO_STORE'] || :all
43
+ def self.configuration
44
+ @configuration ||= Configuration.new
45
+ end
45
46
 
46
- def self.with_config(url: Magento.url, token: Magento.token, store: Magento.store)
47
- @old_url = self.url
48
- @old_token = self.token
49
- @old_store = self.store
47
+ def self.reset
48
+ @configuration = Configuration.new
49
+ end
50
50
 
51
- self.url = url
52
- self.token = token
53
- self.store = store
51
+ def self.configure
52
+ yield(configuration)
53
+ end
54
54
 
55
+ def self.with_config(params)
56
+ @old_configuration = configuration
57
+ self.configuration = configuration.copy_with(**params)
55
58
  yield
56
59
  ensure
57
- self.url = @old_url
58
- self.token = @old_token
59
- self.store = @old_store
60
+ @configuration = @old_configuration
60
61
  end
61
62
 
62
63
  def self.production?
@@ -0,0 +1,31 @@
1
+ module Magento
2
+ class Configuration
3
+ attr_accessor :url, :open_timeout, :timeout, :token, :store, :product_image
4
+
5
+ def initialize(url: nil, token: nil, store: nil)
6
+ self.url = url || ENV['MAGENTO_URL']
7
+ self.open_timeout = 30
8
+ self.timeout = 90
9
+ self.token = token || ENV['MAGENTO_TOKEN']
10
+ self.store = store || ENV['MAGENTO_STORE'] || :all
11
+
12
+ self.product_image = ProductImageConfiguration.new
13
+ end
14
+
15
+ def copy_with(params = {})
16
+ clone.tap do |config|
17
+ params.each { |key, value| config.send("#{key}=", value) }
18
+ end
19
+ end
20
+ end
21
+
22
+ class ProductImageConfiguration
23
+ attr_accessor :small_size, :medium_size, :large_size
24
+
25
+ def initialize
26
+ self.small_size = '200x200>'
27
+ self.medium_size = '400x400>'
28
+ self.large_size = '800x800>'
29
+ end
30
+ end
31
+ end
@@ -33,7 +33,7 @@ module Magento
33
33
  end
34
34
 
35
35
  def find_by_token(token)
36
- user_request = Request.new(token: token)
36
+ user_request = Request.new(config: Magento.configuration.copy_with(token: token))
37
37
  customer_hash = user_request.get('customers/me').parse
38
38
  build(customer_hash)
39
39
  end
@@ -1,13 +1,18 @@
1
+ require_relative 'import/image_finder'
1
2
  require_relative 'import/csv_reader'
2
3
  require_relative 'import/category'
3
4
  require_relative 'import/product'
4
5
 
5
6
  module Magento
6
7
  module Import
7
- def self.from_csv(file, image_path:, website_ids: [0])
8
+ def self.from_csv(file, images_folder: nil, website_ids: [0])
8
9
  products = CSVReader.new(file).get_products
9
10
  products = Category.new(products).associate
10
- Product.new(image_path, website_ids).import(products)
11
+ Product.new(website_ids, images_folder).import(products)
12
+ end
13
+
14
+ def self.get_csv_template
15
+ File.open(__dir__ + '/import/template/products.csv')
11
16
  end
12
17
  end
13
18
  end
@@ -41,7 +41,7 @@ module Magento
41
41
  params = Magento::Params::CreateCategoria.new(
42
42
  name: name,
43
43
  parent_id: parent.id,
44
- url: "#{Magento.store}-#{parent.id}-#{name.parameterize}"
44
+ url: "#{Magento.configuration.store}-#{parent.id}-#{name.parameterize}"
45
45
  )
46
46
 
47
47
  Magento::Category.create(params.to_h).tap { |c| puts "Create: #{c.id} => #{c.name}" }
@@ -10,18 +10,18 @@ module Magento
10
10
 
11
11
  def get_products
12
12
  @csv[1..].map do |row|
13
- name, sku, ean, description, price, special_price, quantity, cat1, cat2, cat3 = row
14
13
  OpenStruct.new({
15
- name: name,
16
- sku: sku,
17
- ean: ean,
18
- description: description,
19
- price: price,
20
- special_price: special_price,
21
- quantity: quantity,
22
- cat1: cat1,
23
- cat2: cat2,
24
- cat3: cat3
14
+ name: row[0],
15
+ sku: row[1],
16
+ ean: row[2],
17
+ description: row[3],
18
+ price: row[4],
19
+ special_price: row[5],
20
+ quantity: row[6],
21
+ cat1: row[7],
22
+ cat2: row[8],
23
+ cat3: row[9],
24
+ main_image: row[10]
25
25
  })
26
26
  end
27
27
  end
@@ -0,0 +1,18 @@
1
+ module Magento
2
+ module Import
3
+ class ImageFinder
4
+ EXTENTIONS = %w[jpg jpeg png webp gif].freeze
5
+
6
+ def initialize(images_folder)
7
+ @images_folder = images_folder
8
+ end
9
+
10
+ def find_by_name(name)
11
+ prefix = "#{@images_folder}/#{name}"
12
+
13
+ EXTENTIONS.map { |e| ["#{prefix}.#{e}", "#{prefix}.#{e.upcase}"] }.flatten
14
+ .find { |file| File.exist?(file) }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,9 +1,11 @@
1
+ require 'uri'
2
+
1
3
  module Magento
2
4
  module Import
3
5
  class Product
4
- def initialize(images_path, website_ids)
5
- @images_path = images_path
6
+ def initialize(website_ids, images_folder = nil)
6
7
  @website_ids = website_ids
8
+ @image_finder = images_folder ? ImageFinder.new(images_folder) : nil
7
9
  end
8
10
 
9
11
  def import(products)
@@ -26,17 +28,19 @@ module Magento
26
28
 
27
29
  product = Magento::Product.create(params)
28
30
 
29
- puts "Produto criado: #{product.sku} => #{product.name}"
31
+ puts "Created product: #{product.sku} => #{product.name}"
30
32
  rescue => e
31
- puts "Erro ao criado: #{product.sku} => #{product.name}"
32
- puts " - Detalhes do erro: #{e}"
33
+ puts "Error on create: #{product.sku} => #{product.name}"
34
+ puts " - Error details: #{e}"
33
35
  end
34
36
  end
35
37
 
36
38
  private
37
39
 
38
40
  def images(product)
39
- image = find_image(product)
41
+ return [] unless product.main_image.to_s =~ URI::regexp || @image_finder
42
+
43
+ image = product.main_image || @image_finder.find_by_name(product.sku)
40
44
  return [] unless image
41
45
 
42
46
  Magento::Params::CreateImage.new(
@@ -46,15 +50,7 @@ module Magento
46
50
  main: true
47
51
  ).variants
48
52
  end
49
-
50
- def find_image(product)
51
- prefix = "#{@images_path}/#{product.sku}"
52
-
53
- extensions = %w[jpg jpeg png webp]
54
- extensions.map { |e| ["#{prefix}.#{e}", "#{prefix}.#{e.upcase}"] }.flatten
55
- .find { |file| File.exist?(file) }
56
- end
57
-
53
+
58
54
  def numeric?(value)
59
55
  !!(value.to_s =~ /^[\d]+$/)
60
56
  end
@@ -0,0 +1,2 @@
1
+ name;sku;gtin;description;price;special price;quantity;category level 1;category level 2;category level 3;main image url
2
+ Apple iPhone 11 Pro;iphone-11-pro;9999999999;"Description: New Apple iPhone 11 Pro Max 64/256/512GB Space Gray Midnight Green Silver Gold\nIncludes all new accessories\n\niPhone is unlocked to work on any GSM carrier!\n\nNo warranty - Warranty can be purchased through squaretrade\n\nShipping: We Normally Ship Out Same or Next Business Day Via USPS. \nDelivery Time Varies Especially During Holidays.\nWe Do NOT Ship Out On Saturday/Sunday\nWe Are Not Responsible For Late Packages, But We Will Find Out If There Are Any Issues.\nWe Only Ship To PayPal Confirmed Address.\nPick Up Also Available In Queens NY (Message For Details)\nPriority Mail USPS Free (1-4 Business Days; Not Guaranteed Service)\nExpress Overnight USPS $25 (Guaranteed By USPS Overnight To Most Places) \n\nAdditional return policy details: \nAs a leading seller of electronics, we want to guarantee that each transaction ends with a five star experience. That's why we offer a FREE no questions asked 30-day return policy. Please message us for more details.\n\nSales Tax:\nNew York orders will have a sales tax of 8.875% add to your cost";1099.99;999.00;45;Technology;Smartphone;Apple;"https://store.storeimages.cdn-apple.com/4982/as-images.apple.com/is/iphone-11-pro-select-2019-family?wid=882&amp;hei=1058&amp;fmt=jpeg&amp;qlt=80&amp;op_usm=0.5,0.5&amp;.v=1586586488946"
@@ -35,7 +35,7 @@ module Magento
35
35
  class << self
36
36
  extend Forwardable
37
37
 
38
- def_delegators :query, :all, :page, :per, :page_size, :order, :select,
38
+ def_delegators :query, :all, :find_each, :page, :per, :page_size, :order, :select,
39
39
  :where, :first, :find_by, :count
40
40
 
41
41
  def find(id)
@@ -7,9 +7,9 @@ module Magento
7
7
  module Params
8
8
  class CreateImage < Dry::Struct
9
9
  VARIANTS = {
10
- 'large' => { size: '800x800', type: :image },
11
- 'medium' => { size: '300x300', type: :small_image },
12
- 'small' => { size: '100x100', type: :thumbnail }
10
+ 'large' => :image,
11
+ 'medium' => :small_image,
12
+ 'small' => :thumbnail
13
13
  }.freeze
14
14
 
15
15
  attribute :title, Type::String
@@ -30,7 +30,7 @@ module Magento
30
30
  "type": mini_type,
31
31
  "name": filename
32
32
  },
33
- "types": main ? [VARIANTS[size][:type]] : []
33
+ "types": main ? [VARIANTS[size]] : []
34
34
  }
35
35
  end
36
36
 
@@ -48,14 +48,23 @@ module Magento
48
48
 
49
49
  def file
50
50
  @file ||= MiniMagick::Image.open(path).tap do |b|
51
- b.resize VARIANTS[size][:size]
51
+ b.resize(Magento.configuration.product_image.send(size + '_size'))
52
+ bigger_side = b.dimensions.max
53
+ b.combine_options do |c|
54
+ c.background '#FFFFFF'
55
+ c.alpha 'remove'
56
+ c.gravity 'center'
57
+ c.extent "#{bigger_side}x#{bigger_side}"
58
+ c.strip
59
+ end
52
60
  b.format 'jpg'
53
- b.strip
54
61
  end
62
+ rescue => e
63
+ raise "Error on read image #{path}: #{e}"
55
64
  end
56
65
 
57
66
  def filename
58
- title.parameterize
67
+ "#{title.parameterize}-#{VARIANTS[size]}.jpg"
59
68
  end
60
69
 
61
70
  def mini_type
@@ -2,8 +2,8 @@ module Magento
2
2
  class Product < Model
3
3
  self.primary_key = :sku
4
4
 
5
- def method_missing(m)
6
- attr(m) || super
5
+ def method_missing(m, *params, &block)
6
+ attr(m) || super(m, *params, &block)
7
7
  end
8
8
 
9
9
  # returns custom_attribute value by custom_attribute code
@@ -16,8 +16,56 @@ module Magento
16
16
  super || @custom_attributes&.any? { |a| a.attribute_code == attribute_code.to_s }
17
17
  end
18
18
 
19
+ def add_media(attributes)
20
+ self.class.add_media(sku, attributes)
21
+ end
22
+
23
+ # returns true if the media was deleted
24
+ def remove_media(media_id)
25
+ self.class.remove_media(sku, media_id)
26
+ end
27
+
28
+ #
29
+ # Add {price} on product {sku} for specified {customer_group_id}
30
+ #
31
+ # Param {quantity} is the minimun amount to apply the price
32
+ #
33
+ # product = Magento::Product.find(1)
34
+ # product.add_tier_price(3.99, quantity: 1, customer_group_id: :all)
35
+ #
36
+ # OR
37
+ #
38
+ # Magento::Product.add_tier_price(1, 3.99, quantity: 1, customer_group_id: :all)
39
+ #
40
+ # @return {Boolean}
41
+ def add_tier_price(price, quantity:, customer_group_id: :all)
42
+ self.class.add_tier_price(
43
+ sku, price, quantity: quantity, customer_group_id: customer_group_id
44
+ )
45
+ end
46
+
19
47
  class << self
20
48
  alias_method :find_by_sku, :find
49
+
50
+ def add_media(sku, attributes)
51
+ request.post("products/#{sku}/media", { entry: attributes }).parse
52
+ end
53
+
54
+ # returns true if the media was deleted
55
+ def remove_media(sku, media_id)
56
+ request.delete("products/#{sku}/media/#{media_id}").parse
57
+ end
58
+
59
+ # Add {price} on product {sku} for specified {customer_group_id}
60
+ #
61
+ # Param {quantity} is the minimun amount to apply the price
62
+ #
63
+ # @return {Boolean}
64
+ def add_tier_price(sku, price, quantity:, customer_group_id: :all)
65
+ request.post(
66
+ "products/#{sku}/group-prices/#{customer_group_id}/tiers/#{quantity}/price/#{price}"
67
+ ).parse
68
+ end
21
69
  end
22
70
  end
23
71
  end
@@ -58,7 +58,7 @@ module Magento
58
58
  alias_method :per, :page_size
59
59
 
60
60
  def select(*fields)
61
- fields = fields.map { |field| parse_field(field) }
61
+ fields = fields.map { |field| parse_field(field, root: true) }
62
62
 
63
63
  if model == Magento::Category
64
64
  self.fields = "children_data[#{fields.join(',')}]"
@@ -92,6 +92,28 @@ module Magento
92
92
  end
93
93
  end
94
94
 
95
+ #
96
+ # Loop all products on each page, starting from the first to the last page
97
+ def find_each
98
+ if @model == Magento::Category
99
+ raise NoMethodError, 'undefined method `find_each` for Magento::Category'
100
+ end
101
+
102
+ @current_page = 1
103
+
104
+ loop do
105
+ redords = all
106
+
107
+ redords.each do |record|
108
+ yield record
109
+ end
110
+
111
+ break if redords.last_page?
112
+
113
+ @current_page = redords.next_page
114
+ end
115
+ end
116
+
95
117
  def first
96
118
  page_size(1).page(1).all.first
97
119
  end
@@ -149,8 +171,8 @@ module Magento
149
171
  value
150
172
  end
151
173
 
152
- def parse_field(value)
153
- return verify_id(value) unless value.is_a? Hash
174
+ def parse_field(value, root: false)
175
+ return (root ? verify_id(value) : value) unless value.is_a? Hash
154
176
 
155
177
  value.map do |k, v|
156
178
  fields = v.is_a?(Array) ? v.map { |field| parse_field(field) } : [parse_field(v)]
@@ -5,11 +5,10 @@ require 'http'
5
5
 
6
6
  module Magento
7
7
  class Request
8
- attr_reader :token, :store
8
+ attr_reader :config
9
9
 
10
- def initialize(token: Magento.token, store: Magento.store)
11
- @token = token
12
- @store = store
10
+ def initialize(config: Magento.configuration)
11
+ @config = config
13
12
  end
14
13
 
15
14
  def get(resource)
@@ -36,12 +35,13 @@ module Magento
36
35
  private
37
36
 
38
37
  def http_auth
39
- HTTP.auth("Bearer #{token}")
38
+ HTTP.auth("Bearer #{config.token}")
39
+ .timeout(connect: config.timeout, read: config.open_timeout)
40
40
  end
41
41
 
42
42
  def base_url
43
- url = Magento.url.to_s.sub(%r{/$}, '')
44
- "#{url}/rest/#{store}/V1"
43
+ url = config.url.to_s.sub(%r{/$}, '')
44
+ "#{url}/rest/#{config.store}/V1"
45
45
  end
46
46
 
47
47
  def url(resource)
@@ -54,9 +54,7 @@ module Magento
54
54
  begin
55
55
  msg = resp.parse['message']
56
56
  errors = resp.parse['errors'] || resp.parse['parameters']
57
- if resp.parse['parameters'].is_a? Hash
58
- resp.parse['parameters'].each { |k, v| msg.sub! "%#{k}", v }
59
- end
57
+ resp.parse['parameters'].each { |k, v| msg.sub! "%#{k}", v } if resp.parse['parameters'].is_a? Hash
60
58
  rescue StandardError
61
59
  msg = 'Failed access to the magento server'
62
60
  errors = []
@@ -1,3 +1,3 @@
1
1
  module Magento
2
- VERSION = '0.16.0'
2
+ VERSION = '0.19.0'
3
3
  end
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.16.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wallas Faria
@@ -92,6 +92,7 @@ files:
92
92
  - README.md
93
93
  - lib/magento.rb
94
94
  - lib/magento/category.rb
95
+ - lib/magento/configuration.rb
95
96
  - lib/magento/country.rb
96
97
  - lib/magento/customer.rb
97
98
  - lib/magento/errors.rb
@@ -99,7 +100,9 @@ files:
99
100
  - lib/magento/import.rb
100
101
  - lib/magento/import/category.rb
101
102
  - lib/magento/import/csv_reader.rb
103
+ - lib/magento/import/image_finder.rb
102
104
  - lib/magento/import/product.rb
105
+ - lib/magento/import/template/products.csv
103
106
  - lib/magento/invoice.rb
104
107
  - lib/magento/model.rb
105
108
  - lib/magento/model_mapper.rb