6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
|
# File 'lib/spree_promo.rb', line 6
def self.activate
Product.class_eval do
has_and_belongs_to_many :promotion_rules
def possible_promotions
rules_with_matching_product_groups = product_groups.map(&:promotion_rules).flatten
all_rules = promotion_rules + rules_with_matching_product_groups
promotion_ids = all_rules.map(&:promotion_id).uniq
Promotion.automatic.scoped(:conditions => {:id => promotion_ids})
end
end
ProductGroup.class_eval do
has_many :promotion_rules
end
Order.class_eval do
has_many :promotion_credits, :conditions => "source_type='Promotion'", :dependent => :destroy
attr_accessible :coupon_code
attr_accessor :coupon_code
before_save :process_coupon_code, :if => "@coupon_code.present?"
def finalized?
self.class.finalized_states.include?(state)
end
def self.finalized_states
["complete", "awaiting_return", "returned"]
end
def promotion_credit_exists?(credit)
promotion_credits.reload.detect { |c| c.source_id == credit.id }
end
def process_coupon_code
coupon = Promotion.find(:first, :conditions => ["UPPER(code) = ?", @coupon_code.upcase])
if coupon
coupon.create_discount(self)
end
end
def products
line_items.map {|li| li.variant.product}
end
def update_totals(force_adjustment_recalculation=false)
self.payment_total = payments.completed.map(&:amount).sum
self.item_total = line_items.map(&:amount).sum
process_automatic_promotions unless finalized?
if force_adjustment_recalculation
applicable_adjustments, adjustments_to_destroy = adjustments.partition{|a| a.applicable?}
self.adjustments = applicable_adjustments
adjustments_to_destroy.each(&:destroy)
end
self.adjustment_total = self.adjustments.map(&:amount).sum
self.total = self.item_total + self.adjustment_total
end
def process_automatic_promotions
self.promotion_credits.each do |credit|
if credit.source.eligible?(self)
amount = credit.source.compute(self)
if credit.amount != amount
PromotionCredit.update_all("amount = #{amount}", { :id => credit.id })
end
else
credit.destroy
end
end
current_promotions = self.promotion_credits.map(&:source)
return if current_promotions.any? { |promotion| !promotion.combine? }
new_promotions = eligible_automatic_promotions - current_promotions
new_promotions.each do |promotion|
next if current_promotions.present? && !promotion.combine?
amount = credit.source.compute(self)
if amount > 0
self.promotion_credits.create(
:source => promotion,
:amount => amount,
:label => promotion.name
)
end
end
end
def eligible_automatic_promotions
@eligible_automatic_coupons ||= Promotion.automatic.select{|c| c.eligible?(self)}
end
end
if File.basename( $0 ) != "rake"
[Promotion::Rules::ItemTotal, Promotion::Rules::Product, Promotion::Rules::User, Promotion::Rules::FirstOrder].each &:register
[
Calculator::FlatPercentItemTotal,
Calculator::FlatRate,
Calculator::FlexiRate,
Calculator::PerItem,
Calculator::FreeShipping
].each{|c_model|
begin
Promotion.register_calculator(c_model) if c_model.table_exists?
rescue Exception => e
$stderr.puts "Error registering promotion calculator #{c_model}"
end
}
end
end
|