Class: Spree::Promotion

Inherits:
Base
  • Object
show all
Defined in:
app/models/spree/promotion.rb,
app/models/spree/promotion/rules/user.rb,
app/models/spree/promotion/rules/product.rb,
app/models/spree/promotion/rules/item_total.rb,
app/models/spree/promotion/rules/first_order.rb,
app/models/spree/promotion/rules/user_logged_in.rb,
app/models/spree/promotion/actions/free_shipping.rb,
app/models/spree/promotion/actions/create_adjustment.rb,
app/models/spree/promotion/actions/create_line_items.rb,
app/models/spree/promotion/actions/create_item_adjustments.rb

Defined Under Namespace

Modules: Actions, Rules

Constant Summary collapse

MATCH_POLICIES =
%w(all any)
UNACTIVATABLE_ORDER_STATES =
["complete", "awaiting_return", "returned"]

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

page

Methods included from Spree::Preferences::Preferable

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

Class Method Details

.activeObject



36
37
38
39
# File 'app/models/spree/promotion.rb', line 36

def self.active
  where('starts_at IS NULL OR starts_at < ?', Time.now).
    where('expires_at IS NULL OR expires_at > ?', Time.now)
end

.advertisedObject



28
29
30
# File 'app/models/spree/promotion.rb', line 28

def self.advertised
  where(advertise: true)
end

.order_activatable?(order) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
# File 'app/models/spree/promotion.rb', line 41

def self.order_activatable?(order)
  order && !UNACTIVATABLE_ORDER_STATES.include?(order.state)
end

.with_coupon_code(coupon_code) ⇒ Object



32
33
34
# File 'app/models/spree/promotion.rb', line 32

def self.with_coupon_code(coupon_code)
  where("lower(#{self.table_name}.code) = ?", coupon_code.strip.downcase).first
end

Instance Method Details

#activate(payload) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'app/models/spree/promotion.rb', line 49

def activate(payload)
  order = payload[:order]
  return unless self.class.order_activatable?(order)

  # Track results from actions to see if any action has been taken.
  # Actions should return nil/false if no action has been taken.
  # If an action returns true, then an action has been taken.
  results = actions.map do |action|
    action.perform(payload)
  end
  # If an action has been taken, report back to whatever activated this promotion.
  action_taken = results.include?(true)

  if action_taken
  # connect to the order
  # create the join_table entry.
    self.orders << order
    self.save
  end

  return action_taken
end

#adjusted_credits_count(promotable) ⇒ Object



110
111
112
# File 'app/models/spree/promotion.rb', line 110

def adjusted_credits_count(promotable)
  credits_count - promotable.adjustments.promotion.where(:source_id => actions.pluck(:id)).count
end

#creditsObject



114
115
116
# File 'app/models/spree/promotion.rb', line 114

def credits
  Adjustment.eligible.promotion.where(source_id: actions.map(&:id))
end

#credits_countObject



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

def credits_count
  credits.count
end

#eligible?(promotable) ⇒ Boolean

called anytime order.update! happens

Returns:

  • (Boolean)


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

def eligible?(promotable)
  return false if expired? || usage_limit_exceeded?(promotable)
  rules_are_eligible?(promotable, {})
end

#expired?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'app/models/spree/promotion.rb', line 45

def expired?
  !!(starts_at && Time.now < starts_at || expires_at && Time.now > expires_at)
end

#product_idsObject



102
103
104
# File 'app/models/spree/promotion.rb', line 102

def product_ids
  products.map(&:id)
end

#productsObject

Products assigned to all product rules



96
97
98
99
100
# File 'app/models/spree/promotion.rb', line 96

def products
  @products ||= self.rules.to_a.inject([]) do |products, rule|
    rule.respond_to?(:products) ? products << rule.products : products
  end.flatten.uniq
end

#rules_are_eligible?(promotable, options = {}) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/models/spree/promotion.rb', line 78

def rules_are_eligible?(promotable, options = {})
  # Promotions without rules are eligible by default.
  return true if rules.none?
  eligible = lambda { |r| r.eligible?(promotable, options) }
  specific_rules = rules.for(promotable)
  return true if specific_rules.none?
  if match_policy == 'all'
    # If there are rules for this promotion, but no rules for this
    # particular promotable, then the promotion is ineligible by default.
    specific_rules.any? && specific_rules.all?(&eligible)
  else
    # If there are no rules for this promotable, then this will return false.
    # If there are rules for this promotable, but they are ineligible, this will return false.
    specific_rules.any?(&eligible)
  end
end

#usage_limit_exceeded?(promotable) ⇒ Boolean

Returns:

  • (Boolean)


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

def usage_limit_exceeded?(promotable)
  usage_limit.present? && usage_limit > 0 && adjusted_credits_count(promotable) >= usage_limit
end