Class: Shoppe::Product

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/shoppe/product.rb,
app/models/shoppe/product/variants.rb,
app/models/shoppe/product/product_attributes.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#product_attributes_arrayObject

Used for setting an array of product attributes which will be updated. Usually received from a web browser.



9
10
11
# File 'app/models/shoppe/product/product_attributes.rb', line 9

def product_attributes_array
  @product_attributes_array
end

Class Method Details

.import(file) ⇒ Object

Imports products from a spreadsheet file Example:

Shoppe:Product.import("path/to/file.csv")


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/shoppe/product.rb', line 113

def self.import(file)
  spreadsheet = open_spreadsheet(file)
  spreadsheet.default_sheet = spreadsheet.sheets.first
  header = spreadsheet.row(1)
  (2..spreadsheet.last_row).each do |i|
    row = Hash[[header, spreadsheet.row(i)].transpose]

    # Don't import products where the name is blank
    unless row["name"].nil?
      if product = find_by(name: row["name"])
        # Dont import products with the same name but update quantities if they're not the same
        qty = row["qty"].to_i
        if qty > 0 && qty != product.stock
          product.stock_level_adjustments.create!(description: I18n.t('shoppe.import'), adjustment: qty)
        end
      else
        product = new
        product.name = row["name"]
        product.sku = row["sku"]
        product.description = row["description"]
        product.short_description = row["short_description"]
        product.weight = row["weight"]
        product.price = row["price"].nil? ? 0 : row["price"]

        product.product_category_id = begin
          if Shoppe::ProductCategory.find_by(name: row["category_name"]).present?
            # Find and set the category
            Shoppe::ProductCategory.find_by(name: row["category_name"]).id
          else
            # Create the category
            Shoppe::ProductCategory.create(name: row["category_name"]).id
          end
        end

        product.save!

        # Create quantities
        qty = row["qty"].to_i
        if qty > 0
          product.stock_level_adjustments.create!(description: I18n.t('shoppe.import'), adjustment: qty)
        end
      end
    end
  end
end

.open_spreadsheet(file) ⇒ Object



159
160
161
162
163
164
165
166
# File 'app/models/shoppe/product.rb', line 159

def self.open_spreadsheet(file)
  case File.extname(file.original_filename)
  when ".csv" then Roo::CSV.new(file.path)
  when ".xls" then Roo::Excel.new(file.path)
  when ".xlsx" then Roo::Excelx.new(file.path)
  else raise I18n.t('shoppe.imports.errors.unknown_format', filename: File.original_filename)
  end
end

.with_attributes(key, values) ⇒ Enumerable

Search for products which include the given attributes and return an active record scope of these products. Chainable with other scopes and with_attributes methods. For example:

Shoppe::Product.active.with_attribute('Manufacturer', 'Apple').with_attribute('Model', ['Macbook', 'iPhone'])

Returns:

  • (Enumerable)


104
105
106
107
# File 'app/models/shoppe/product.rb', line 104

def self.with_attributes(key, values)
  product_ids = Shoppe::ProductAttribute.searchable.where(:key => key, :value => values).pluck(:product_id).uniq
  where(:id => product_ids)
end

Instance Method Details

#default_variantShoppe::Product

Returns the default variant for the product or nil if none exists.

Returns:



38
39
40
41
# File 'app/models/shoppe/product/variants.rb', line 38

def default_variant
  return nil if self.parent
  @default_variant ||= self.variants.select { |v| v.default? }.first
end

#full_nameString

Return the name of the product

Returns:

  • (String)


63
64
65
# File 'app/models/shoppe/product.rb', line 63

def full_name
  self.parent ? "#{self.parent.name} (#{name})" : name
end

#has_variants?Boolean

Does this product have any variants?

Returns:

  • (Boolean)


31
32
33
# File 'app/models/shoppe/product/variants.rb', line 31

def has_variants?
  !variants.empty?
end

#in_stock?Boolean

Is this product currently in stock?

Returns:

  • (Boolean)


86
87
88
# File 'app/models/shoppe/product.rb', line 86

def in_stock?
  self.default_variant ? self.default_variant.in_stock? : (stock_control? ? stock > 0 : true)
end

#orderable?Boolean

Is this product orderable?

Returns:

  • (Boolean)


70
71
72
73
74
# File 'app/models/shoppe/product.rb', line 70

def orderable?
  return false unless self.active?
  return false if self.has_variants?
  true
end

#priceBigDecimal

The price for the product

Returns:

  • (BigDecimal)


79
80
81
# File 'app/models/shoppe/product.rb', line 79

def price
  self.default_variant ? self.default_variant.price : read_attribute(:price)
end

#product_categoryShoppe::ProductCategory

The product’s category



19
# File 'app/models/shoppe/product.rb', line 19

belongs_to :product_category, :class_name => 'Shoppe::ProductCategory'

#stockFixnum

Return the total number of items currently in stock

Returns:

  • (Fixnum)


93
94
95
# File 'app/models/shoppe/product.rb', line 93

def stock
  self.stock_level_adjustments.sum(:adjustment)
end

#tax_rateShoppe::TaxRate

The product’s tax rate

Returns:



24
# File 'app/models/shoppe/product.rb', line 24

belongs_to :tax_rate, :class_name => "Shoppe::TaxRate"

#variant?Boolean

Is this product a variant of another?

Returns:

  • (Boolean)


46
47
48
# File 'app/models/shoppe/product/variants.rb', line 46

def variant?
  !self.parent_id.blank?
end