Class: Spree::Variant

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.has_option(option_type, *option_values) ⇒ Object Also known as: has_options

Returns variants that match a given option value

Example:

product.variants_including_master.has_option(OptionType.find_by_name(“shoe-size”),OptionValue.find_by_name(“8”))



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'app/models/spree/variant/scopes.rb', line 12

def has_option(option_type, *option_values)
  option_types = OptionType.table_name

  option_type_conditions = case option_type
  when OptionType then { "#{option_types}.name" => option_type.name }
  when String     then { "#{option_types}.name" => option_type }
  else                 { "#{option_types}.id"   => option_type }
  end

  relation = joins(:option_values => :option_type).where(option_type_conditions)

  option_values_conditions = option_values.each do |option_value|
    option_value_conditions = case option_value
    when OptionValue then { "#{OptionValue.table_name}.name" => option_value.name }
    when String      then { "#{OptionValue.table_name}.name" => option_value }
    else                  { "#{OptionValue.table_name}.id"   => option_value }
    end
    relation = relation.where(option_value_conditions)
  end

  relation
end

Instance Method Details

#available?Boolean

returns true if this variant is allowed to be placed on a new order

Returns:

  • (Boolean)


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

def available?
  Spree::Config[:track_inventory_levels] ? (Spree::Config[:allow_backorders] || in_stock?) : true
end

#cost_price=(price) ⇒ Object



58
59
60
# File 'app/models/spree/variant.rb', line 58

def cost_price=(price)
  self[:cost_price] = parse_price(price) if price.present?
end

#deleted?Boolean

use deleted? rather than checking the attribute directly. this allows extensions to override deleted? if they want to provide their own definition.

Returns:

  • (Boolean)


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

def deleted?
  deleted_at
end

#gross_profitObject



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

def gross_profit
  cost_price.nil? ? 0 : (price - cost_price)
end

#in_stock?Boolean Also known as: in_stock

returns true if at least one inventory unit of this variant is “on_hand”

Returns:

  • (Boolean)


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

def in_stock?
  Spree::Config[:track_inventory_levels] ? on_hand > 0 : true
end

#on_backorderObject

returns number of units currently on backorder for this variant.



63
64
65
# File 'app/models/spree/variant.rb', line 63

def on_backorder
  inventory_units.with_state('backordered').size
end

#on_handObject

Returns number of inventory units for this variant (new records haven’t been saved to database, yet)



31
32
33
# File 'app/models/spree/variant.rb', line 31

def on_hand
  Spree::Config[:track_inventory_levels] ? count_on_hand : (1.0 / 0) # Infinity
end

#on_hand=(new_level) ⇒ Object

Adjusts the inventory units to match the given new level.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'app/models/spree/variant.rb', line 36

def on_hand=(new_level)
  if Spree::Config[:track_inventory_levels]
    new_level = new_level.to_i

    # increase Inventory when
    if new_level > on_hand
      # fill backordered orders before creating new units
      backordered_units = inventory_units.with_state('backordered')
      backordered_units.slice(0, new_level).each(&:fill_backorder)
      new_level -= backordered_units.length
    end

    self.count_on_hand = new_level
  else
    raise 'Cannot set on_hand value when Spree::Config[:track_inventory_levels] is false'
  end
end

#option_value(opt_name) ⇒ Object



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

def option_value(opt_name)
  self.option_values.detect { |o| o.option_type.name == opt_name }.try(:presentation)
end

#options_textObject



78
79
80
81
82
83
84
85
86
# File 'app/models/spree/variant.rb', line 78

def options_text
  values = self.option_values.sort_by(&:position)

  values.map! do |ov|
    "#{ov.option_type.presentation}: #{ov.presentation}"
  end

  values.to_sentence({ :words_connector => ", ", :two_words_connector => ", " })
end

#price=(price) ⇒ Object



54
55
56
# File 'app/models/spree/variant.rb', line 54

def price=(price)
  self[:price] = parse_price(price) if price.present?
end

#set_option_value(opt_name, opt_value) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'app/models/spree/variant.rb', line 99

def set_option_value(opt_name, opt_value)
  # no option values on master
  return if self.is_master

  option_type = Spree::OptionType.where(:name => opt_name).first_or_initialize do |o|
    o.presentation = opt_name
    o.save!
  end

  current_value = self.option_values.detect { |o| o.option_type.name == opt_name }

  unless current_value.nil?
    return if current_value.name == opt_value
    self.option_values.delete(current_value)
  else
    # then we have to check to make sure that the product has the option type
    unless self.product.option_types.include? option_type
      self.product.option_types << option_type
      self.product.save
    end
  end

  option_value = Spree::OptionValue.where(:option_type_id => option_type.id, :name => opt_value).first_or_initialize do |o|
    o.presentation = opt_value
    o.save!
  end

  self.option_values << option_value
  self.save
end