Class: Variant

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/variant.rb

Overview

Schema Information

Table name: variants

id           :integer(4)      not null, primary key
product_id   :integer(4)      not null
sku          :string(255)     not null
name         :string(255)
price        :decimal(8, 2)   default(0.0), not null
cost         :decimal(8, 2)   default(0.0), not null
deleted_at   :datetime
master       :boolean(1)      default(FALSE), not null
created_at   :datetime
updated_at   :datetime
brand_id     :integer(4)
inventory_id :integer(4)

Constant Summary

ADMIN_OUT_OF_STOCK_QTY =
0
OUT_OF_STOCK_QTY =
2
LOW_STOCK_QTY =
6

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Array[Variant]) admin_grid(product, params = {})

paginated results from the admin Variant grid

Parameters:

Returns:



313
314
315
316
317
318
319
# File 'app/models/variant.rb', line 313

def self.admin_grid(product, params = {})
  grid = where({:variants => { :product_id => product.id} })
  grid = grid.includes(:product)
  grid = grid.where({:products => {:name => params[:product_name]}})  if params[:product_name].present?
  grid = grid.where(['sku LIKE ? ', "#{params[:sku]}%"])  if params[:sku].present?
  grid
end

Instance Method Details

- (Boolean) active?

Returns:

  • (Boolean)


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

def active?
  deleted_at.nil? || deleted_at > Time.zone.now
end

- (none) add_count_on_hand(num)

with SQL math add to count_on_hand attribute

Parameters:

  • number (Integer)

    of variants to add

Returns:

  • (none)


244
245
246
247
248
249
250
251
252
253
254
# File 'app/models/variant.rb', line 244

def add_count_on_hand(num)
  ### don't lock if we have plenty of stock.
  if low_stock?
    inventory.lock!
      self.inventory.count_on_hand = inventory.count_on_hand + num.to_i
    inventory.save!
  else
    sql = "UPDATE inventories SET count_on_hand = (#{num} + count_on_hand) WHERE id = #{self.inventory.id}"
    ActiveRecord::Base.connection.execute(sql)
  end
end

- (none) add_pending_to_customer(num = 1)

with SQL math add to count_pending_to_customer attribute

Parameters:

  • number (Integer)

    of variants to add

Returns:

  • (none)


268
269
270
271
272
273
274
275
276
277
278
279
# File 'app/models/variant.rb', line 268

def add_pending_to_customer(num = 1)
  ### don't lock if we have plenty of stock.
  if low_stock?
    # If the stock is low lock the inventory.  This ensures
    inventory.lock!
    self.inventory.count_pending_to_customer = inventory.count_pending_to_customer.to_i + num.to_i
    inventory.save!
  else
    sql = "UPDATE inventories SET count_pending_to_customer = (#{num} + count_pending_to_customer) WHERE id = #{self.inventory.id}"
    ActiveRecord::Base.connection.execute(sql)
  end
end

- (String) brand_name

returns the brand's name or a blank string

ex: obj.brand_name => 'Nike'

Parameters:

  • (none)

Returns:

  • (String)


200
201
202
# File 'app/models/variant.rb', line 200

def brand_name
  brand_id ? brand.name : product.brand_name
end

- (Integer) count_available(reload_variant = true)

returns number available to purchase

Parameters:

  • reload (Boolean)

    the object from the DB

Returns:

  • (Integer)

    number available to purchase



235
236
237
238
# File 'app/models/variant.rb', line 235

def count_available(reload_variant = true)
  self.reload if reload_variant
  count_on_hand - count_pending_to_customer
end

- (String) display_property_details(separator = '<br/>')

returns a string the display name and description of all the variant properties

ex: obj.sub_name => 'color: green <br/> size: 9.0']

Parameters:

  • separator (Optional String) (defaults to: '<br/>')

    (default == <br/>)

Returns:

  • (String)


173
174
175
# File 'app/models/variant.rb', line 173

def display_property_details(separator = '<br/>')
  property_details.join(separator)
end

- (String) display_stock_status(start = '(', finish = ')')

returns "(Sold Out)" or "(Low Stock)" or "" depending on if the variant is out of stock / low stock or has enough stock.

Parameters:

  • (Optional String)
  • (Optional String)

Returns:

  • (String)


113
114
115
116
117
# File 'app/models/variant.rb', line 113

def display_stock_status(start = '(', finish = ')')
  return "#{start}Sold Out#{finish}"  if sold_out?
  return "#{start}Low Stock#{finish}" if low_stock?
  ''
end

- (Object) inactivate



88
89
90
# File 'app/models/variant.rb', line 88

def inactivate
  deleted_at ? true : false
end

- (Object) inactivate=(val)

This is a form helper to inactivate a variant



84
85
86
# File 'app/models/variant.rb', line 84

def inactivate=(val)
  self.deleted_at = Time.zone.now if !deleted_at && (val && (val == '1' || val.to_s == 'true'))
end

- (Boolean) is_available?

returns true or false based on if the count_available is above 0

Parameters:

  • number (Integer)

    of variants to subtract

Returns:

  • (Boolean)


227
228
229
# File 'app/models/variant.rb', line 227

def is_available?
  count_available > 0
end

- (Boolean) low_stock?

returns true if the stock level is above or == the low stock level

Parameters:

  • (none)

Returns:

  • (Boolean)


104
105
106
# File 'app/models/variant.rb', line 104

def low_stock?
  (quantity_available) <= LOW_STOCK_QTY
end

- (String) name_with_sku

returns the product name with sku

ex: obj.name_with_sku => Nike: 1234-12345-1234

Parameters:

  • (none)

Returns:

  • (String)


219
220
221
# File 'app/models/variant.rb', line 219

def name_with_sku
  [product_name, sku].compact.join(': ')
end

- (VariantProperty) primary_property

The variant has many properties. but only one is the primary property

this will return the primary property.  (good for primary info)

Parameters:

  • (none)

Returns:



209
210
211
212
# File 'app/models/variant.rb', line 209

def primary_property
  pp = self.variant_properties.where({ :variant_properties => {:primary => true}}).first
  pp ? pp : self.variant_properties.first
end

- (String) product_name

returns the product name

ex: obj.product_name => Nike

Parameters:

  • (none)

Returns:

  • (String)


182
183
184
# File 'app/models/variant.rb', line 182

def product_name
  name? ? name : [product.name, sub_name].reject{ |a| a.strip.length == 0 }.join(' - ')
end

- (TaxRate) product_tax_rate(state_id, tax_time = Time.now)

gives you the tax rate for the give state_id and the time.

Tax rates can change from year to year so Time is a factor

Parameters:

  • state.id (Integer)
  • Time (Optional Time)

    now if no value is passed in

Returns:

  • (TaxRate)

    TaxRate for the state at a given time



147
148
149
# File 'app/models/variant.rb', line 147

def product_tax_rate(state_id, tax_time = Time.now)
  product.tax_rate(state_id, tax_time)
end

- (Array) property_details(separator = ': ')

returns an array of the display name and description of all the variant properties

ex: obj.sub_name => ['color: green', 'size: 9.0']

Parameters:

  • (Optional String)

Returns:

  • (Array)


164
165
166
# File 'app/models/variant.rb', line 164

def property_details(separator = ': ')
  variant_properties.collect {|vp| [vp.property.display_name ,vp.description].join(separator) }
end

- (Integer) qty_to_add

method used by forms to set the initial qty_to_add for variants

Parameters:

  • (none)

Returns:

  • (Integer)

    0



304
305
306
# File 'app/models/variant.rb', line 304

def qty_to_add
  0
end

- (none) qty_to_add=(num)

in the admin form qty_to_add to the count on hand

Parameters:

  • number (Integer)

    of variants to add or subtract (negative sign is subtract)

Returns:

  • (none)


293
294
295
296
297
298
# File 'app/models/variant.rb', line 293

def qty_to_add=(num)
  ###  TODO this method needs a history of who did what
  inventory.lock!
  self.inventory.count_on_hand = inventory.count_on_hand.to_i + num.to_i
  inventory.save!
end

- (Boolean) quantity_available

returns quantity available in stock

Parameters:

  • (none)

Returns:

  • (Boolean)


75
76
77
# File 'app/models/variant.rb', line 75

def quantity_available
  (count_on_hand - count_pending_to_customer)
end

- (Boolean) quantity_purchaseable(admin_purchase = false)

returns quantity available to purchase

Parameters:

  • (none)

Returns:

  • (Boolean)


67
68
69
# File 'app/models/variant.rb', line 67

def quantity_purchaseable(admin_purchase = false)
  admin_purchase ? (quantity_available - ADMIN_OUT_OF_STOCK_QTY) : (quantity_available - OUT_OF_STOCK_QTY)
end

- (Integer) shipping_category_id

convienence method to get the shipping_category_id of the product

Parameters:

  • (none)

Returns:

  • (Integer)

    shipping_category_id



155
156
157
# File 'app/models/variant.rb', line 155

def shipping_category_id
  product.shipping_category_id
end

- (Boolean) sold_out?

returns true if the stock level is above or == the out of stock level

Parameters:

  • (none)

Returns:

  • (Boolean)


96
97
98
# File 'app/models/variant.rb', line 96

def sold_out?
  (quantity_available) <= OUT_OF_STOCK_QTY
end

- (Object) stock_status



119
120
121
122
123
# File 'app/models/variant.rb', line 119

def stock_status
  return "sold_out"  if sold_out?
  return "low_stock" if low_stock?
  "available"
end

- (String) sub_name

returns the primary_property's description or a blank string

ex: obj.sub_name => 'great shoes, blah blah blah'

Parameters:

  • (none)

Returns:

  • (String)


191
192
193
# File 'app/models/variant.rb', line 191

def sub_name
  primary_property ? "#{primary_property.description}" : ''
end

- (none) subtract_count_on_hand(num)

with SQL math subtract to count_on_hand attribute

Parameters:

  • number (Integer)

    of variants to subtract

Returns:

  • (none)


260
261
262
# File 'app/models/variant.rb', line 260

def subtract_count_on_hand(num)
  add_count_on_hand((num.to_i * -1))
end

- (none) subtract_pending_to_customer(num)

with SQL math subtract to count_pending_to_customer attribute

Parameters:

  • number (Integer)

    of variants to subtract

Returns:

  • (none)


285
286
287
# File 'app/models/variant.rb', line 285

def subtract_pending_to_customer(num)
  add_pending_to_customer((num.to_i * -1))
end

- (Decimal) tax_percentage(tax_rate)

get the percent tax rate for the tax rate

Parameters:

Returns:

  • (Decimal)

    tax rate percentage



137
138
139
# File 'app/models/variant.rb', line 137

def tax_percentage(tax_rate)
  tax_rate ? tax_rate.tax_percentage : 0.0
end

- (Decimal) total_price(tax_rate)

price times the tax %

Parameters:

Returns:

  • (Decimal)


129
130
131
# File 'app/models/variant.rb', line 129

def total_price(tax_rate)
  ((1 + tax_percentage(tax_rate)) * price)
end