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.
Files changed (108) hide show
  1. data/Rakefile +2 -1
  2. data/VERSION +1 -1
  3. data/app/controllers/admin/shop/discounts/discountables_controller.rb +44 -0
  4. data/app/controllers/admin/shop/discounts_controller.rb +64 -0
  5. data/app/controllers/admin/shop/orders_controller.rb +19 -3
  6. data/app/controllers/admin/shop/packages_controller.rb +1 -3
  7. data/app/controllers/admin/shop/products_controller.rb +1 -2
  8. data/app/controllers/admin/shop/variants_controller.rb +3 -4
  9. data/app/models/form_address.rb +4 -2
  10. data/app/models/form_discount.rb +39 -0
  11. data/app/models/form_line_item.rb +1 -11
  12. data/app/models/shop_category.rb +3 -0
  13. data/app/models/shop_customer.rb +0 -9
  14. data/app/models/shop_discount.rb +37 -0
  15. data/app/models/shop_discountable.rb +64 -0
  16. data/app/models/shop_line_item.rb +24 -1
  17. data/app/models/shop_order.rb +41 -28
  18. data/app/models/shop_product.rb +11 -0
  19. data/app/models/shop_product_variant.rb +3 -0
  20. data/app/models/shop_variant.rb +1 -3
  21. data/app/views/admin/shop/discounts/edit.html.haml +11 -0
  22. data/app/views/admin/shop/discounts/edit/_foot.html.haml +16 -0
  23. data/app/views/admin/shop/discounts/edit/_form.html.haml +15 -0
  24. data/app/views/admin/shop/discounts/edit/_head.html.haml +4 -0
  25. data/app/views/admin/shop/discounts/edit/_inputs.html.haml +2 -0
  26. data/app/views/admin/shop/discounts/edit/_meta.html.haml +8 -0
  27. data/app/views/admin/shop/discounts/edit/_parts.html.haml +9 -0
  28. data/app/views/admin/shop/discounts/edit/_popups.html.haml +4 -0
  29. data/app/views/admin/shop/discounts/edit/buttons/_browse_categories.html.haml +1 -0
  30. data/app/views/admin/shop/discounts/edit/buttons/_browse_products.html.haml +1 -0
  31. data/app/views/admin/shop/discounts/edit/inputs/_amount.html.haml +3 -0
  32. data/app/views/admin/shop/discounts/edit/inputs/_code.html.haml +3 -0
  33. data/app/views/admin/shop/discounts/edit/inputs/_name.html.haml +3 -0
  34. data/app/views/admin/shop/discounts/edit/meta/_finish.html.haml +5 -0
  35. data/app/views/admin/shop/discounts/edit/meta/_start.html.haml +5 -0
  36. data/app/views/admin/shop/discounts/edit/parts/_categories.html.haml +3 -0
  37. data/app/views/admin/shop/discounts/edit/parts/_products.html.haml +3 -0
  38. data/app/views/admin/shop/discounts/edit/popups/_browse_categories.html.haml +6 -0
  39. data/app/views/admin/shop/discounts/edit/popups/_browse_products.html.haml +6 -0
  40. data/app/views/admin/shop/discounts/edit/shared/_category.html.haml +11 -0
  41. data/app/views/admin/shop/discounts/edit/shared/_product.html.haml +12 -0
  42. data/app/views/admin/shop/discounts/index.html.haml +13 -0
  43. data/app/views/admin/shop/discounts/index/_discount.html.haml +13 -0
  44. data/app/views/admin/shop/discounts/index/_foot.html.haml +5 -0
  45. data/app/views/admin/shop/discounts/index/_head.html.haml +2 -0
  46. data/app/views/admin/shop/discounts/index/buttons/_new_discount.html.haml +1 -0
  47. data/app/views/admin/shop/discounts/new.html.haml +11 -0
  48. data/app/views/admin/shop/discounts/remove.html.haml +12 -0
  49. data/app/views/admin/shop/orders/index.html.haml +1 -1
  50. data/app/views/admin/shop/orders/index/_foot.html.haml +3 -1
  51. data/app/views/admin/shop/orders/index/_head.html.haml +1 -3
  52. data/app/views/admin/shop/packages/index.html.haml +1 -1
  53. data/app/views/admin/shop/packages/index/_foot.html.haml +3 -2
  54. data/app/views/admin/shop/packages/index/_head.html.haml +1 -3
  55. data/app/views/admin/shop/packages/index/buttons/_new_package.html.haml +1 -0
  56. data/app/views/admin/shop/products/index.html.haml +1 -1
  57. data/app/views/admin/shop/products/index/_foot.html.haml +3 -2
  58. data/app/views/admin/shop/products/index/_head.html.haml +1 -3
  59. data/app/views/admin/shop/products/index/buttons/_add_category.html.haml +1 -0
  60. data/app/views/admin/shop/products/index/buttons/_variants.html.haml +1 -1
  61. data/app/views/admin/shop/variants/index.html.haml +1 -1
  62. data/app/views/admin/shop/variants/index/_foot.html.haml +3 -2
  63. data/app/views/admin/shop/variants/index/_head.html.haml +1 -3
  64. data/app/views/admin/shop/variants/index/buttons/_add_variant.html.haml +1 -0
  65. data/app/views/admin/shop/variants/index/buttons/_categories.html.haml +1 -0
  66. data/config/routes.rb +11 -5
  67. data/db/migrate/20101010071143_create_discounts.rb +29 -0
  68. data/db/migrate/20101010072225_modify_categories_remove_variant.rb +9 -0
  69. data/db/migrate/20101010130034_change_discountables_add_observer.rb +15 -0
  70. data/db/migrate/20101011063133_change_orders_set_limits_to_null.rb +11 -0
  71. data/lib/shop/interface/discounts.rb +34 -0
  72. data/lib/shop/interface/orders.rb +2 -2
  73. data/lib/shop/interface/packages.rb +2 -2
  74. data/lib/shop/interface/products.rb +2 -2
  75. data/lib/shop/interface/variants.rb +2 -2
  76. data/lib/shop/models/form_extension.rb +12 -1
  77. data/lib/shop/models/user.rb +18 -0
  78. data/lib/shop/tags/cart.rb +24 -0
  79. data/lib/shop/tags/helpers.rb +1 -1
  80. data/lib/shop/tags/item.rb +26 -11
  81. data/lib/shop/tags/tax.rb +73 -0
  82. data/lib/tasks/shop_extension_tasks.rake +1 -1
  83. data/mockups/discounts/new-edit.bmml +49 -49
  84. data/public/javascripts/admin/extensions/shop/discounts/edit.js +76 -0
  85. data/public/stylesheets/sass/admin/extensions/shop/discounts/edit.sass +125 -0
  86. data/public/stylesheets/sass/admin/extensions/shop/index.sass +14 -40
  87. data/radiant-shop-extension.gemspec +70 -7
  88. data/shop_extension.rb +23 -12
  89. data/spec/controllers/admin/shop/discounts/discountables_controller_spec.rb +73 -0
  90. data/spec/controllers/admin/shop/discounts_controller_spec.rb +81 -0
  91. data/spec/controllers/admin/shop/orders_controller_spec.rb +35 -0
  92. data/spec/datasets/forms.rb +23 -12
  93. data/spec/datasets/shop_discountables.rb +22 -0
  94. data/spec/datasets/shop_discounts.rb +29 -0
  95. data/spec/lib/shop/tags/cart_spec.rb +75 -1
  96. data/spec/lib/shop/tags/item_spec.rb +4 -7
  97. data/spec/lib/shop/tags/tax_spec.rb +201 -0
  98. data/spec/models/form_discount_spec.rb +63 -0
  99. data/spec/models/shop_category_spec.rb +8 -0
  100. data/spec/models/shop_discount_spec.rb +130 -0
  101. data/spec/models/shop_discountable_spec.rb +114 -0
  102. data/spec/models/shop_line_item_spec.rb +9 -1
  103. data/spec/models/shop_order_spec.rb +253 -199
  104. data/spec/models/shop_product_spec.rb +31 -2
  105. data/spec/models/shop_variant_spec.rb +0 -15
  106. metadata +97 -21
  107. data/app/views/admin/shop/products/index/buttons/_discounts.html.haml +0 -1
  108. 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.1'
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.5
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
- private
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
@@ -25,9 +25,7 @@ private
25
25
  end
26
26
 
27
27
  def config_index
28
- @buttons << 'packages'
29
- @buttons << 'variants'
30
- @buttons << 'discounts'
28
+ @buttons << 'new_package'
31
29
  end
32
30
 
33
31
  def config_new
@@ -163,9 +163,8 @@ private
163
163
  end
164
164
 
165
165
  def config_index
166
- @buttons << 'packages'
166
+ @buttons << 'add_category'
167
167
  @buttons << 'variants'
168
- @buttons << 'discounts'
169
168
  end
170
169
 
171
170
  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 << 'packages'
28
- @buttons << 'variants'
29
- @buttons << 'discounts'
27
+ @buttons << 'add_variant'
28
+ @buttons << 'categories'
30
29
  end
31
30
 
32
31
  def config_new
@@ -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]
@@ -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
@@ -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
- (item.price.to_f * self.quantity.to_f).to_f
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