Class: Spree::Variant

Inherits:
Base
  • Object
show all
Includes:
DefaultPrice
Defined in:
app/models/spree/variant.rb

Constant Summary collapse

LOCALIZED_NUMBERS =
%w(cost_price weight depth width height)

Instance Method Summary collapse

Methods inherited from Base

belongs_to_required_by_default, page, spree_base_scopes

Methods included from Preferences::Preferable

#clear_preferences, #default_preferences, #defined_preferences, #get_preference, #has_preference!, #has_preference?, #preference_default, #preference_type, #set_preference

Instance Method Details

#amount_in(currency) ⇒ Object



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

def amount_in(currency)
  price_in(currency).try(:amount)
end

#available?Boolean

Returns:

  • (Boolean)


106
107
108
# File 'app/models/spree/variant.rb', line 106

def available?
  !discontinued? && product.available?
end

#backordered?Boolean

Returns:

  • (Boolean)


268
269
270
# File 'app/models/spree/variant.rb', line 268

def backordered?
  total_on_hand <= 0 && stock_items.exists?(backorderable: true)
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)


134
135
136
# File 'app/models/spree/variant.rb', line 134

def deleted?
  !!deleted_at
end

#descriptive_nameObject



127
128
129
# File 'app/models/spree/variant.rb', line 127

def descriptive_name
  is_master? ? name + ' - Master' : name + ' - ' + options_text
end

#dimensionObject



256
257
258
# File 'app/models/spree/variant.rb', line 256

def dimension
  (width || 0) + (height || 0) + (depth || 0)
end

#discontinue!Object



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

def discontinue!
  update_attribute(:discontinue_on, Time.current)
end

#discontinued?Boolean

Returns:

  • (Boolean)


264
265
266
# File 'app/models/spree/variant.rb', line 264

def discontinued?
  !!discontinue_on && discontinue_on <= Time.current
end

#exchange_nameObject

Default to master name



123
124
125
# File 'app/models/spree/variant.rb', line 123

def exchange_name
  is_master? ? name : options_text
end

#in_stock?Boolean

Returns:

  • (Boolean)


228
229
230
231
232
# File 'app/models/spree/variant.rb', line 228

def in_stock?
  Rails.cache.fetch(in_stock_cache_key) do
    total_on_hand > 0
  end
end

#name_and_skuObject



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

def name_and_sku
  "#{name} - #{sku}"
end

#option_value(opt_name) ⇒ Object



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

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

#options=(options = {}) ⇒ Object



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

def options=(options = {})
  options.each do |option|
    set_option_value(option[:name], option[:value])
  end
end

#options_textObject



118
119
120
# File 'app/models/spree/variant.rb', line 118

def options_text
  Spree::Variants::OptionsPresenter.new(self).to_sentence
end

#price_in(currency) ⇒ Object



186
187
188
# File 'app/models/spree/variant.rb', line 186

def price_in(currency)
  prices.detect { |price| price.currency == currency } || prices.build(currency: currency)
end

#price_modifier_amount(options = {}) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/models/spree/variant.rb', line 207

def price_modifier_amount(options = {})
  return 0 unless options.present?

  options.keys.map do |key|
    m = "#{key}_price_modifier_amount".to_sym
    if respond_to? m
      send(m, options[key])
    else
      0
    end
  end.sum
end

#price_modifier_amount_in(currency, options = {}) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
# File 'app/models/spree/variant.rb', line 194

def price_modifier_amount_in(currency, options = {})
  return 0 unless options.present?

  options.keys.map do |key|
    m = "#{key}_price_modifier_amount_in".to_sym
    if respond_to? m
      send(m, currency, options[key])
    else
      0
    end
  end.sum
end

#productObject

Product may be created with deleted_at already set, which would make AR’s default finder return nil. This is a stopgap for that little problem.



141
142
143
# File 'app/models/spree/variant.rb', line 141

def product
  Spree::Product.unscoped { super }
end

#purchasable?Boolean

Returns:

  • (Boolean)


238
239
240
# File 'app/models/spree/variant.rb', line 238

def purchasable?
  in_stock? || backorderable?
end

#set_option_value(opt_name, opt_value) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'app/models/spree/variant.rb', line 151

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

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

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

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

    option_values.delete(current_value)
  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

  option_values << option_value
  save
end

#should_track_inventory?Boolean

Shortcut method to determine if inventory tracking is enabled for this variant This considers both variant tracking flag and site-wide inventory tracking settings

Returns:

  • (Boolean)


244
245
246
# File 'app/models/spree/variant.rb', line 244

def should_track_inventory?
  track_inventory? && Spree::Config.track_inventory_levels
end

#sku_and_options_textObject



224
225
226
# File 'app/models/spree/variant.rb', line 224

def sku_and_options_text
  "#{sku} #{options_text}".strip
end

#tax_categoryObject



110
111
112
113
114
115
116
# File 'app/models/spree/variant.rb', line 110

def tax_category
  if self[:tax_category_id].nil?
    product.tax_category
  else
    Spree::TaxCategory.find(self[:tax_category_id])
  end
end

#track_inventoryObject



248
249
250
# File 'app/models/spree/variant.rb', line 248

def track_inventory
  should_track_inventory?
end

#volumeObject



252
253
254
# File 'app/models/spree/variant.rb', line 252

def volume
  (width || 0) * (height || 0) * (depth || 0)
end