radiant-shop-extension 0.11.5 → 0.11.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/app/controllers/admin/shop/discounts/discountables_controller.rb +44 -0
- data/app/controllers/admin/shop/discounts_controller.rb +64 -0
- data/app/controllers/admin/shop/orders_controller.rb +19 -3
- data/app/controllers/admin/shop/packages_controller.rb +1 -3
- data/app/controllers/admin/shop/products_controller.rb +1 -2
- data/app/controllers/admin/shop/variants_controller.rb +3 -4
- data/app/models/form_address.rb +4 -2
- data/app/models/form_discount.rb +39 -0
- data/app/models/form_line_item.rb +1 -11
- data/app/models/shop_category.rb +3 -0
- data/app/models/shop_customer.rb +0 -9
- data/app/models/shop_discount.rb +37 -0
- data/app/models/shop_discountable.rb +64 -0
- data/app/models/shop_line_item.rb +24 -1
- data/app/models/shop_order.rb +41 -28
- data/app/models/shop_product.rb +11 -0
- data/app/models/shop_product_variant.rb +3 -0
- data/app/models/shop_variant.rb +1 -3
- data/app/views/admin/shop/discounts/edit.html.haml +11 -0
- data/app/views/admin/shop/discounts/edit/_foot.html.haml +16 -0
- data/app/views/admin/shop/discounts/edit/_form.html.haml +15 -0
- data/app/views/admin/shop/discounts/edit/_head.html.haml +4 -0
- data/app/views/admin/shop/discounts/edit/_inputs.html.haml +2 -0
- data/app/views/admin/shop/discounts/edit/_meta.html.haml +8 -0
- data/app/views/admin/shop/discounts/edit/_parts.html.haml +9 -0
- data/app/views/admin/shop/discounts/edit/_popups.html.haml +4 -0
- data/app/views/admin/shop/discounts/edit/buttons/_browse_categories.html.haml +1 -0
- data/app/views/admin/shop/discounts/edit/buttons/_browse_products.html.haml +1 -0
- data/app/views/admin/shop/discounts/edit/inputs/_amount.html.haml +3 -0
- data/app/views/admin/shop/discounts/edit/inputs/_code.html.haml +3 -0
- data/app/views/admin/shop/discounts/edit/inputs/_name.html.haml +3 -0
- data/app/views/admin/shop/discounts/edit/meta/_finish.html.haml +5 -0
- data/app/views/admin/shop/discounts/edit/meta/_start.html.haml +5 -0
- data/app/views/admin/shop/discounts/edit/parts/_categories.html.haml +3 -0
- data/app/views/admin/shop/discounts/edit/parts/_products.html.haml +3 -0
- data/app/views/admin/shop/discounts/edit/popups/_browse_categories.html.haml +6 -0
- data/app/views/admin/shop/discounts/edit/popups/_browse_products.html.haml +6 -0
- data/app/views/admin/shop/discounts/edit/shared/_category.html.haml +11 -0
- data/app/views/admin/shop/discounts/edit/shared/_product.html.haml +12 -0
- data/app/views/admin/shop/discounts/index.html.haml +13 -0
- data/app/views/admin/shop/discounts/index/_discount.html.haml +13 -0
- data/app/views/admin/shop/discounts/index/_foot.html.haml +5 -0
- data/app/views/admin/shop/discounts/index/_head.html.haml +2 -0
- data/app/views/admin/shop/discounts/index/buttons/_new_discount.html.haml +1 -0
- data/app/views/admin/shop/discounts/new.html.haml +11 -0
- data/app/views/admin/shop/discounts/remove.html.haml +12 -0
- data/app/views/admin/shop/orders/index.html.haml +1 -1
- data/app/views/admin/shop/orders/index/_foot.html.haml +3 -1
- data/app/views/admin/shop/orders/index/_head.html.haml +1 -3
- data/app/views/admin/shop/packages/index.html.haml +1 -1
- data/app/views/admin/shop/packages/index/_foot.html.haml +3 -2
- data/app/views/admin/shop/packages/index/_head.html.haml +1 -3
- data/app/views/admin/shop/packages/index/buttons/_new_package.html.haml +1 -0
- data/app/views/admin/shop/products/index.html.haml +1 -1
- data/app/views/admin/shop/products/index/_foot.html.haml +3 -2
- data/app/views/admin/shop/products/index/_head.html.haml +1 -3
- data/app/views/admin/shop/products/index/buttons/_add_category.html.haml +1 -0
- data/app/views/admin/shop/products/index/buttons/_variants.html.haml +1 -1
- data/app/views/admin/shop/variants/index.html.haml +1 -1
- data/app/views/admin/shop/variants/index/_foot.html.haml +3 -2
- data/app/views/admin/shop/variants/index/_head.html.haml +1 -3
- data/app/views/admin/shop/variants/index/buttons/_add_variant.html.haml +1 -0
- data/app/views/admin/shop/variants/index/buttons/_categories.html.haml +1 -0
- data/config/routes.rb +11 -5
- data/db/migrate/20101010071143_create_discounts.rb +29 -0
- data/db/migrate/20101010072225_modify_categories_remove_variant.rb +9 -0
- data/db/migrate/20101010130034_change_discountables_add_observer.rb +15 -0
- data/db/migrate/20101011063133_change_orders_set_limits_to_null.rb +11 -0
- data/lib/shop/interface/discounts.rb +34 -0
- data/lib/shop/interface/orders.rb +2 -2
- data/lib/shop/interface/packages.rb +2 -2
- data/lib/shop/interface/products.rb +2 -2
- data/lib/shop/interface/variants.rb +2 -2
- data/lib/shop/models/form_extension.rb +12 -1
- data/lib/shop/models/user.rb +18 -0
- data/lib/shop/tags/cart.rb +24 -0
- data/lib/shop/tags/helpers.rb +1 -1
- data/lib/shop/tags/item.rb +26 -11
- data/lib/shop/tags/tax.rb +73 -0
- data/lib/tasks/shop_extension_tasks.rake +1 -1
- data/mockups/discounts/new-edit.bmml +49 -49
- data/public/javascripts/admin/extensions/shop/discounts/edit.js +76 -0
- data/public/stylesheets/sass/admin/extensions/shop/discounts/edit.sass +125 -0
- data/public/stylesheets/sass/admin/extensions/shop/index.sass +14 -40
- data/radiant-shop-extension.gemspec +70 -7
- data/shop_extension.rb +23 -12
- data/spec/controllers/admin/shop/discounts/discountables_controller_spec.rb +73 -0
- data/spec/controllers/admin/shop/discounts_controller_spec.rb +81 -0
- data/spec/controllers/admin/shop/orders_controller_spec.rb +35 -0
- data/spec/datasets/forms.rb +23 -12
- data/spec/datasets/shop_discountables.rb +22 -0
- data/spec/datasets/shop_discounts.rb +29 -0
- data/spec/lib/shop/tags/cart_spec.rb +75 -1
- data/spec/lib/shop/tags/item_spec.rb +4 -7
- data/spec/lib/shop/tags/tax_spec.rb +201 -0
- data/spec/models/form_discount_spec.rb +63 -0
- data/spec/models/shop_category_spec.rb +8 -0
- data/spec/models/shop_discount_spec.rb +130 -0
- data/spec/models/shop_discountable_spec.rb +114 -0
- data/spec/models/shop_line_item_spec.rb +9 -1
- data/spec/models/shop_order_spec.rb +253 -199
- data/spec/models/shop_product_spec.rb +31 -2
- data/spec/models/shop_variant_spec.rb +0 -15
- metadata +97 -21
- data/app/views/admin/shop/products/index/buttons/_discounts.html.haml +0 -1
- data/app/views/admin/shop/products/index/buttons/_packages.html.haml +0 -1
data/Rakefile
CHANGED
@@ -9,11 +9,12 @@ begin
|
|
9
9
|
gem.authors = ["Dirk Kelly", "John Barker"]
|
10
10
|
gem.add_dependency 'radiant', '>= 0.9.1'
|
11
11
|
gem.add_dependency 'activemerchant', '>= 1.8.0'
|
12
|
+
gem.add_dependency 'fastercsv', '>= 1.5.3'
|
12
13
|
gem.add_dependency 'radiant-layouts-extension', '>= 0.9.1'
|
13
14
|
gem.add_dependency 'radiant-settings-extension', '>= 1.1.1'
|
14
15
|
gem.add_dependency 'radiant-images-extension', '>= 0.3.2'
|
15
16
|
gem.add_dependency 'radiant-forms-extension', '>= 3.1.1'
|
16
|
-
gem.add_dependency 'radiant-scoped-extension', '>= 0.2.
|
17
|
+
gem.add_dependency 'radiant-scoped-extension', '>= 0.2.2'
|
17
18
|
gem.add_dependency 'radiant-drag-extension', '>= 0.1.0'
|
18
19
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
20
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.11.
|
1
|
+
0.11.6
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Admin::Shop::Discounts::DiscountablesController < Admin::ResourceController
|
2
|
+
|
3
|
+
model_class ShopDiscountable
|
4
|
+
|
5
|
+
def create
|
6
|
+
error = 'Could not attach Discount.'
|
7
|
+
begin
|
8
|
+
@shop_discountable.attributes = {
|
9
|
+
:discount_id => params[:discount_id],
|
10
|
+
:discounted_id => params[:discounted_id],
|
11
|
+
:discounted_type => params[:discounted_type]
|
12
|
+
}
|
13
|
+
@shop_discountable.save!
|
14
|
+
|
15
|
+
discounted_type = @shop_discountable.discounted_type.gsub('Shop','').underscore
|
16
|
+
|
17
|
+
respond_to do |format|
|
18
|
+
format.js { render :partial => "admin/shop/discounts/edit/shared/#{discounted_type}", :locals => { discounted_type.to_sym => @shop_discountable } }
|
19
|
+
end
|
20
|
+
rescue
|
21
|
+
respond_to do |format|
|
22
|
+
format.js { render :text => error, :status => :unprocessable_entity }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy
|
28
|
+
error = 'Could not remove Discount.'
|
29
|
+
begin
|
30
|
+
discounted_type = @shop_discountable.discounted_type.gsub('Shop','').underscore
|
31
|
+
|
32
|
+
@shop_discountable.destroy
|
33
|
+
|
34
|
+
respond_to do |format|
|
35
|
+
format.js { render :partial => "admin/shop/discounts/edit/shared/#{discounted_type}", :locals => { discounted_type.to_sym => @shop_discountable } }
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
respond_to do |format|
|
39
|
+
format.js { render :text => error, :status => :unprocessable_entity }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Admin::Shop::DiscountsController < Admin::ResourceController
|
2
|
+
|
3
|
+
model_class ShopDiscount
|
4
|
+
|
5
|
+
before_filter :config_global
|
6
|
+
before_filter :config_index, :only => [ :index ]
|
7
|
+
before_filter :config_new, :only => [ :new, :create ]
|
8
|
+
before_filter :config_edit, :only => [ :edit, :update ]
|
9
|
+
before_filter :assets_global, :except => [ :remove, :destroy ]
|
10
|
+
before_filter :assets_edit, :only => [ :edit, :update ]
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def config_global
|
15
|
+
@inputs ||= []
|
16
|
+
@meta ||= []
|
17
|
+
@buttons ||= []
|
18
|
+
@parts ||= []
|
19
|
+
@popups ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
def config_index
|
23
|
+
@buttons << 'new_discount'
|
24
|
+
end
|
25
|
+
|
26
|
+
def config_new
|
27
|
+
@inputs << 'name'
|
28
|
+
@inputs << 'amount'
|
29
|
+
@inputs << 'code'
|
30
|
+
|
31
|
+
@meta << 'start'
|
32
|
+
@meta << 'finish'
|
33
|
+
end
|
34
|
+
|
35
|
+
def config_edit
|
36
|
+
@buttons << 'browse_categories'
|
37
|
+
@buttons << 'browse_products'
|
38
|
+
|
39
|
+
@inputs << 'name'
|
40
|
+
@inputs << 'amount'
|
41
|
+
@inputs << 'code'
|
42
|
+
|
43
|
+
@meta << 'start'
|
44
|
+
@meta << 'finish'
|
45
|
+
|
46
|
+
@parts << 'categories'
|
47
|
+
@parts << 'products'
|
48
|
+
|
49
|
+
@popups << 'browse_categories'
|
50
|
+
@popups << 'browse_products'
|
51
|
+
end
|
52
|
+
|
53
|
+
def assets_global
|
54
|
+
include_stylesheet 'admin/extensions/shop/edit'
|
55
|
+
include_stylesheet 'admin/extensions/shop/index'
|
56
|
+
end
|
57
|
+
|
58
|
+
def assets_edit
|
59
|
+
include_javascript 'admin/extensions/shop/edit'
|
60
|
+
include_javascript 'admin/extensions/shop/discounts/edit'
|
61
|
+
include_stylesheet 'admin/extensions/shop/discounts/edit'
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fastercsv'
|
2
|
+
|
1
3
|
class Admin::Shop::OrdersController < Admin::ResourceController
|
2
4
|
model_class ShopOrder
|
3
5
|
|
@@ -9,7 +11,21 @@ class Admin::Shop::OrdersController < Admin::ResourceController
|
|
9
11
|
before_filter :assets_index, :only => [ :index ]
|
10
12
|
before_filter :assets_edit, :only => [ :edit, :update ]
|
11
13
|
|
12
|
-
|
14
|
+
alias_method :resource_controller_loads_models, :load_models
|
15
|
+
# Applies a scope to the orders result based on the params status
|
16
|
+
def load_models
|
17
|
+
model_class.scope_by_status(params[:status]) do
|
18
|
+
resource_controller_loads_models
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# You can overide this to export what you desire
|
23
|
+
def export
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
protected
|
13
29
|
|
14
30
|
def config_global
|
15
31
|
@inputs ||= []
|
@@ -20,10 +36,10 @@ class Admin::Shop::OrdersController < Admin::ResourceController
|
|
20
36
|
end
|
21
37
|
|
22
38
|
def config_index
|
39
|
+
@buttons << 'all'
|
40
|
+
@buttons << 'new'
|
23
41
|
@buttons << 'shipped'
|
24
42
|
@buttons << 'paid'
|
25
|
-
@buttons << 'new'
|
26
|
-
@buttons << 'all'
|
27
43
|
end
|
28
44
|
|
29
45
|
def config_new
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Admin::Shop::VariantsController < Admin::ResourceController
|
2
2
|
|
3
3
|
model_class ShopVariant
|
4
|
-
|
4
|
+
|
5
5
|
before_filter :config_global
|
6
6
|
before_filter :config_index, :only => [ :index ]
|
7
7
|
before_filter :config_new, :only => [ :new, :create ]
|
@@ -24,9 +24,8 @@ class Admin::Shop::VariantsController < Admin::ResourceController
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def config_index
|
27
|
-
@buttons << '
|
28
|
-
@buttons << '
|
29
|
-
@buttons << 'discounts'
|
27
|
+
@buttons << 'add_variant'
|
28
|
+
@buttons << 'categories'
|
30
29
|
end
|
31
30
|
|
32
31
|
def config_new
|
data/app/models/form_address.rb
CHANGED
@@ -51,8 +51,9 @@ class FormAddress
|
|
51
51
|
|
52
52
|
# Attaches a billing address to the order (and current customer)
|
53
53
|
def create_order_billing_address
|
54
|
+
|
54
55
|
# Billing Address
|
55
|
-
if billing[:id]
|
56
|
+
if billing[:id] and current_customer.present?
|
56
57
|
begin
|
57
58
|
# Use an existing Address and update its values
|
58
59
|
@billing = current_customer.billings.find(billing[:id])
|
@@ -63,6 +64,7 @@ class FormAddress
|
|
63
64
|
end
|
64
65
|
|
65
66
|
elsif @order.billing.present?
|
67
|
+
|
66
68
|
# Use the current billing and update its values
|
67
69
|
@billing = @order.billing
|
68
70
|
@billing.update_attributes(billing)
|
@@ -73,8 +75,8 @@ class FormAddress
|
|
73
75
|
if @billing.save
|
74
76
|
@order.update_attribute(:billing, @billing)
|
75
77
|
end
|
76
|
-
|
77
78
|
end
|
79
|
+
|
78
80
|
end
|
79
81
|
|
80
82
|
# Attaches a shipping address to the order (and current customer)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class FormDiscount
|
2
|
+
include Forms::Models::Extension
|
3
|
+
include Shop::Models::FormExtension
|
4
|
+
|
5
|
+
def create
|
6
|
+
@result ||= { process.to_sym => false }
|
7
|
+
|
8
|
+
find_current_order
|
9
|
+
|
10
|
+
case process
|
11
|
+
when 'add'
|
12
|
+
if @discount = ShopDiscount.find_by_code(discount_code)
|
13
|
+
@discountable = @discount.discountables.create(:discounted_id => @order.id, :discounted_type => @order.class.name)
|
14
|
+
@result[process.to_sym] = @discountable.valid?
|
15
|
+
end
|
16
|
+
when 'remove'
|
17
|
+
if @discountable = @order.discountables.find(discountable_id)
|
18
|
+
@result[process.to_sym] = @discountable.destroy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
@result
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def process
|
28
|
+
@config[:process]
|
29
|
+
end
|
30
|
+
|
31
|
+
def discount_code
|
32
|
+
@data[:discount][:code]
|
33
|
+
end
|
34
|
+
|
35
|
+
def discountable_id
|
36
|
+
@data[:discountable][:id]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class FormLineItem
|
2
2
|
include Forms::Models::Extension
|
3
|
+
include Shop::Models::FormExtension
|
3
4
|
|
4
5
|
# line_item:
|
5
6
|
# process: add|update|remove
|
@@ -21,17 +22,6 @@ class FormLineItem
|
|
21
22
|
end
|
22
23
|
|
23
24
|
protected
|
24
|
-
|
25
|
-
# Uses the page session data to find the current order
|
26
|
-
def find_or_create_current_order
|
27
|
-
begin
|
28
|
-
@order = ShopOrder.find(@page.request.session[:shop_order])
|
29
|
-
rescue
|
30
|
-
@order = ShopOrder.create
|
31
|
-
@result[:session] = { :shop_order => @order.id }
|
32
|
-
end
|
33
|
-
@order.update_attribute(:customer_id, (current_customer.id rescue nil)) # either assign it to a user, or don't
|
34
|
-
end
|
35
25
|
|
36
26
|
def process
|
37
27
|
@config[:process]
|
data/app/models/shop_category.rb
CHANGED
@@ -8,6 +8,9 @@ class ShopCategory < ActiveRecord::Base
|
|
8
8
|
belongs_to :updated_by, :class_name => 'User'
|
9
9
|
belongs_to :product_layout, :class_name => 'Layout'
|
10
10
|
|
11
|
+
has_many :discountables, :class_name => 'ShopDiscountable', :foreign_key => :discounted_id
|
12
|
+
has_many :discounts, :class_name => 'ShopDiscount', :through => :discountables
|
13
|
+
|
11
14
|
before_validation :assign_slug, :assign_breadcrumb
|
12
15
|
|
13
16
|
accepts_nested_attributes_for :page
|
data/app/models/shop_customer.rb
CHANGED
@@ -2,15 +2,6 @@ class ShopCustomer < User
|
|
2
2
|
|
3
3
|
include Scoped::Models::User::Scoped
|
4
4
|
|
5
|
-
has_many :orders, :class_name => 'ShopOrder', :foreign_key => :customer_id
|
6
|
-
has_many :billings, :through => :orders
|
7
|
-
has_many :shippings, :through => :orders
|
8
|
-
|
9
|
-
belongs_to :created_by, :class_name => 'User'
|
10
|
-
belongs_to :updated_by, :class_name => 'User'
|
11
|
-
|
12
|
-
accepts_nested_attributes_for :orders, :allow_destroy => true
|
13
|
-
|
14
5
|
def first_name
|
15
6
|
name = ''
|
16
7
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class ShopDiscount < ActiveRecord::Base
|
2
|
+
|
3
|
+
# Return all discounts which are valid
|
4
|
+
default_scope :conditions => [
|
5
|
+
'(starts_at IS NULL and finishes_at IS NULL) OR (starts_at >= :now AND finishes_at <= :now) OR (starts_at IS NULL and finishes_at <= :now)',
|
6
|
+
{ :now => Time.now }
|
7
|
+
]
|
8
|
+
|
9
|
+
belongs_to :created_by, :class_name => 'User'
|
10
|
+
belongs_to :updated_by, :class_name => 'User'
|
11
|
+
|
12
|
+
has_many :discountables, :class_name => 'ShopDiscountable', :foreign_key => :discount_id
|
13
|
+
has_many :categories, :through => :discountables, :source => :category, :conditions => "shop_discountables.discounted_type = 'ShopCategory'"
|
14
|
+
has_many :products, :through => :discountables, :source => :product, :conditions => "shop_discountables.discounted_type = 'ShopProduct'"
|
15
|
+
has_many :orders, :through => :discountables, :source => :order, :conditions => "shop_discountables.discounted_type = 'ShopOrder'"
|
16
|
+
has_many :line_items, :through => :discountables, :source => :line_item,:conditions => "shop_discountables.discounted_type = 'ShopLineItem'"
|
17
|
+
|
18
|
+
validates_presence_of :name, :code, :amount
|
19
|
+
validates_uniqueness_of :name, :code
|
20
|
+
validates_numericality_of :amount
|
21
|
+
|
22
|
+
# This will override the default scope
|
23
|
+
def self.all_including_invalid(*attrs)
|
24
|
+
with_exclusive_scope{find(:all,*attrs)}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return all categories minus its own
|
28
|
+
def available_categories
|
29
|
+
ShopCategory.all - categories
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns all products minus its own
|
33
|
+
def available_products
|
34
|
+
ShopProduct.all - products
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class ShopDiscountable < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :discount, :class_name => 'ShopDiscount', :foreign_key => :discount_id
|
4
|
+
belongs_to :discounted, :foreign_key => :discounted_id, :polymorphic => true
|
5
|
+
belongs_to :category, :class_name => 'ShopCategory', :foreign_key => :discounted_id
|
6
|
+
belongs_to :product, :class_name => 'ShopProduct', :foreign_key => :discounted_id
|
7
|
+
belongs_to :order, :class_name => 'ShopOrder', :foreign_key => :discounted_id
|
8
|
+
belongs_to :line_item, :class_name => 'ShopLineItem', :foreign_key => :discounted_id
|
9
|
+
|
10
|
+
validates_presence_of :discount, :discounted
|
11
|
+
validates_uniqueness_of :discounted_id, :scope => [ :discount_id, :discounted_type ]
|
12
|
+
|
13
|
+
before_validation :create_shop_products_if_shop_category
|
14
|
+
before_destroy :destroy_shop_products_if_shop_category
|
15
|
+
|
16
|
+
before_validation :create_shop_line_items_if_shop_order
|
17
|
+
before_destroy :destroy_shop_line_items_if_shop_order
|
18
|
+
|
19
|
+
# Returns discount of a class
|
20
|
+
def self.for(type)
|
21
|
+
all(:conditions => { :discounted_type => type.pluralize.classify })
|
22
|
+
end
|
23
|
+
|
24
|
+
# Adds discount to a category's products
|
25
|
+
def create_shop_products_if_shop_category
|
26
|
+
if discounted_type === 'ShopCategory'
|
27
|
+
discounted.products.each do |product|
|
28
|
+
# Attach discount to the child product
|
29
|
+
ShopDiscountable.create(:discount => discount, :discounted => product)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Removes discount from a category's products
|
35
|
+
def destroy_shop_products_if_shop_category
|
36
|
+
if discounted_type === 'ShopCategory'
|
37
|
+
discount.discountables.for('ShopProduct').each do |discountable|
|
38
|
+
discountable.destroy
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Adds discount to an order's line_items
|
44
|
+
def create_shop_line_items_if_shop_order
|
45
|
+
if discounted_type === 'ShopOrder'
|
46
|
+
discounted.line_items.each do |line_item|
|
47
|
+
if line_item.item.discounts.include?(discount)
|
48
|
+
# We're here if the item associated with the line item can be discounted
|
49
|
+
discount = ShopDiscountable.create(:discount_id => discount_id, :discounted => line_item)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Removes discount from an order's line_items
|
56
|
+
def destroy_shop_line_items_if_shop_order
|
57
|
+
if discounted_type === 'ShopOrder'
|
58
|
+
discount.discountables.for('ShopLineItem').each do |discountable|
|
59
|
+
discountable.destroy
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -4,18 +4,41 @@ class ShopLineItem < ActiveRecord::Base
|
|
4
4
|
has_one :customer, :class_name => 'ShopCustomer', :through => :order, :source => :customer
|
5
5
|
belongs_to :item, :polymorphic => true
|
6
6
|
|
7
|
+
has_many :discountables, :class_name => 'ShopDiscountable', :foreign_key => :discounted_id
|
8
|
+
has_many :discounts, :class_name => 'ShopDiscount', :through => :discountables
|
9
|
+
|
7
10
|
before_validation :adjust_quantity
|
8
11
|
validates_uniqueness_of :item_id, :scope => [ :order_id, :item_type ]
|
9
12
|
validates_presence_of :item
|
10
13
|
|
11
14
|
def price
|
12
|
-
|
15
|
+
price = value
|
16
|
+
price -= discounted
|
17
|
+
|
18
|
+
# We never want to return a negative cost
|
19
|
+
[0.00,price.to_f].max
|
20
|
+
end
|
21
|
+
|
22
|
+
def value
|
23
|
+
price = (item.price * self.quantity)
|
24
|
+
end
|
25
|
+
|
26
|
+
def discounted
|
27
|
+
(item.price * self.quantity * discount)
|
13
28
|
end
|
14
29
|
|
15
30
|
def weight
|
16
31
|
(item.weight.to_f * self.quantity.to_f).to_f
|
17
32
|
end
|
18
33
|
|
34
|
+
def discount
|
35
|
+
discount = BigDecimal.new('0.00')
|
36
|
+
self.discounts.map { |d| discount += d.amount }
|
37
|
+
|
38
|
+
# Convert to a percentage
|
39
|
+
discount * 0.01
|
40
|
+
end
|
41
|
+
|
19
42
|
class << self
|
20
43
|
|
21
44
|
def params
|