spree_core 2.1.12 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/base_helper.rb +4 -7
  3. data/app/helpers/spree/products_helper.rb +11 -9
  4. data/app/helpers/spree/store_helper.rb +5 -0
  5. data/app/models/spree/ability.rb +4 -0
  6. data/app/models/spree/address.rb +6 -6
  7. data/app/models/spree/adjustment.rb +40 -61
  8. data/app/models/spree/app_configuration.rb +1 -14
  9. data/app/models/spree/calculator.rb +12 -4
  10. data/app/models/spree/calculator/default_tax.rb +42 -38
  11. data/app/models/spree/calculator/flat_percent_item_total.rb +2 -4
  12. data/app/models/spree/calculator/free_shipping.rb +5 -2
  13. data/app/models/spree/calculator/percent_on_line_item.rb +15 -0
  14. data/app/models/spree/calculator/percent_per_item.rb +3 -0
  15. data/app/models/spree/classification.rb +3 -2
  16. data/app/models/spree/credit_card.rb +7 -25
  17. data/app/models/spree/gateway/bogus.rb +5 -5
  18. data/app/models/spree/gateway/bogus_simple.rb +0 -8
  19. data/app/models/spree/image.rb +0 -9
  20. data/app/models/spree/inventory_unit.rb +10 -4
  21. data/app/models/spree/item_adjustments.rb +65 -0
  22. data/app/models/spree/legacy_user.rb +1 -0
  23. data/app/models/spree/line_item.rb +33 -13
  24. data/app/models/spree/option_type.rb +2 -2
  25. data/app/models/spree/option_value.rb +1 -1
  26. data/app/models/spree/order.rb +109 -89
  27. data/app/models/spree/order/checkout.rb +48 -0
  28. data/app/models/spree/order_contents.rb +72 -37
  29. data/app/models/spree/order_inventory.rb +65 -68
  30. data/app/models/spree/order_populator.rb +3 -17
  31. data/app/models/spree/order_updater.rb +63 -44
  32. data/app/models/spree/payment.rb +20 -5
  33. data/app/models/spree/payment/processing.rb +19 -25
  34. data/app/models/spree/payment_capture_event.rb +9 -0
  35. data/app/models/spree/payment_method/check.rb +0 -2
  36. data/app/models/spree/price.rb +1 -1
  37. data/app/models/spree/product.rb +14 -16
  38. data/app/models/spree/product/scopes.rb +4 -6
  39. data/app/models/spree/product_option_type.rb +2 -2
  40. data/app/models/spree/product_property.rb +2 -2
  41. data/app/models/spree/promotion.rb +71 -50
  42. data/app/models/spree/promotion/actions/create_adjustment.rb +31 -32
  43. data/app/models/spree/promotion/actions/create_item_adjustments.rb +83 -0
  44. data/app/models/spree/promotion/actions/free_shipping.rb +36 -0
  45. data/app/models/spree/promotion/rules/first_order.rb +4 -0
  46. data/app/models/spree/promotion/rules/item_total.rb +5 -1
  47. data/app/models/spree/promotion/rules/product.rb +4 -0
  48. data/app/models/spree/promotion/rules/user.rb +5 -6
  49. data/app/models/spree/promotion/rules/user_logged_in.rb +4 -0
  50. data/app/models/spree/promotion_action.rb +1 -5
  51. data/app/models/spree/promotion_handler/cart.rb +38 -0
  52. data/app/models/spree/promotion_handler/coupon.rb +76 -0
  53. data/app/models/spree/promotion_handler/free_shipping.rb +31 -0
  54. data/app/models/spree/promotion_handler/page.rb +24 -0
  55. data/app/models/spree/promotion_rule.rb +15 -7
  56. data/app/models/spree/property.rb +1 -1
  57. data/app/models/spree/return_authorization.rb +7 -1
  58. data/app/models/spree/shipment.rb +113 -49
  59. data/app/models/spree/shipping_calculator.rb +4 -5
  60. data/app/models/spree/shipping_category.rb +2 -2
  61. data/app/models/spree/shipping_method.rb +12 -6
  62. data/app/models/spree/shipping_rate.rb +27 -7
  63. data/app/models/spree/stock/availability_validator.rb +1 -1
  64. data/app/models/spree/stock/estimator.rb +13 -1
  65. data/app/models/spree/stock/package.rb +11 -7
  66. data/app/models/spree/stock/packer.rb +3 -3
  67. data/app/models/spree/stock/quantifier.rb +9 -1
  68. data/app/models/spree/stock_item.rb +11 -6
  69. data/app/models/spree/stock_movement.rb +1 -2
  70. data/app/models/spree/tax_category.rb +6 -1
  71. data/app/models/spree/tax_rate.rb +57 -49
  72. data/app/models/spree/taxon.rb +10 -5
  73. data/app/models/spree/taxonomy.rb +5 -2
  74. data/app/models/spree/variant.rb +33 -16
  75. data/app/models/spree/zone.rb +24 -24
  76. data/app/views/spree/shared/_routes.html.erb +3 -0
  77. data/config/locales/en.yml +42 -26
  78. data/db/migrate/20130213191427_create_default_stock.rb +3 -3
  79. data/db/migrate/20130413230529_add_name_to_spree_credit_cards.rb +5 -0
  80. data/db/migrate/20130414000512_update_name_fields_on_spree_credit_cards.rb +13 -0
  81. data/db/migrate/20130417120035_update_adjustment_states.rb +2 -2
  82. data/db/migrate/20130417123427_add_shipping_rates_to_shipments.rb +1 -1
  83. data/db/migrate/20130509115210_add_number_to_stock_transfer.rb +1 -1
  84. data/db/migrate/20130611054351_rename_shipping_methods_zones_to_spree_shipping_methods_zones.rb +0 -5
  85. data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +7 -5
  86. data/db/migrate/20130807024301_upgrade_adjustments.rb +39 -0
  87. data/db/migrate/20130807024302_rename_adjustment_fields.rb +17 -0
  88. data/db/migrate/20130813004002_add_shipment_total_to_spree_orders.rb +5 -0
  89. data/db/migrate/20130813232134_rename_activators_to_promotions.rb +5 -0
  90. data/db/migrate/20130815000406_add_adjustment_total_to_line_items.rb +5 -0
  91. data/db/migrate/20130815024413_add_adjustment_total_to_shipments.rb +5 -0
  92. data/db/migrate/20130828234942_add_tax_total_to_line_items_shipments_and_orders.rb +8 -0
  93. data/db/migrate/20130830001159_migrate_old_shipping_calculators.rb +1 -1
  94. data/db/migrate/20130903183026_add_code_to_spree_promotion_rules.rb +5 -0
  95. data/db/migrate/20130917024658_remove_promotions_event_name_field.rb +5 -0
  96. data/db/migrate/20130924040529_add_promo_total_to_line_items_and_shipments_and_orders.rb +7 -0
  97. data/db/migrate/20131001013410_remove_unused_credit_card_fields.rb +7 -3
  98. data/db/migrate/20131107132123_add_tax_category_to_variants.rb +6 -0
  99. data/db/migrate/20131118043959_add_included_to_adjustments.rb +5 -0
  100. data/db/migrate/20131118050234_rename_tax_total_fields.rb +11 -0
  101. data/db/migrate/20131118183431_add_line_item_id_to_spree_inventory_units.rb +21 -0
  102. data/db/migrate/20131127001002_add_position_to_classifications.rb +5 -0
  103. data/db/migrate/20131211112807_create_spree_orders_promotions.rb +8 -0
  104. data/db/migrate/20131218054603_add_item_count_to_spree_orders.rb +5 -0
  105. data/db/migrate/20140106224208_rename_permalink_to_slug_for_products.rb +5 -0
  106. data/db/migrate/20140124023232_rename_activator_id_in_rules_and_actions_to_promotion_id.rb +6 -0
  107. data/db/migrate/20140203161722_add_approver_id_and_approved_at_to_orders.rb +6 -0
  108. data/db/migrate/20140204115338_add_confirmation_delivered_to_spree_orders.rb +5 -0
  109. data/db/migrate/20140205120320_create_spree_payment_capture_events.rb +12 -0
  110. data/db/migrate/20140205144710_add_uncaptured_amount_to_payments.rb +5 -0
  111. data/db/migrate/20140207085910_add_tax_category_id_to_shipping_methods.rb +5 -0
  112. data/db/migrate/20140207093021_add_tax_rate_id_to_shipping_rates.rb +5 -0
  113. data/db/migrate/20140211040159_add_pre_tax_amount_to_line_items_and_shipments.rb +6 -0
  114. data/db/migrate/20140213184916_add_more_indexes.rb +13 -0
  115. data/db/migrate/20140219060952_add_considered_risky_to_orders.rb +5 -0
  116. data/lib/generators/spree/dummy/dummy_generator.rb +1 -6
  117. data/lib/generators/spree/install/install_generator.rb +6 -6
  118. data/lib/generators/spree/install/templates/{app/assets/javascripts/admin → vendor/assets/javascripts/spree/backend}/all.js +3 -3
  119. data/lib/generators/spree/install/templates/{app/assets/javascripts/store → vendor/assets/javascripts/spree/frontend}/all.js +3 -3
  120. data/lib/generators/spree/install/templates/{app/assets/stylesheets/store → vendor/assets/stylesheets/spree/backend}/all.css +3 -3
  121. data/lib/generators/spree/install/templates/{app/assets/stylesheets/admin → vendor/assets/stylesheets/spree/frontend}/all.css +3 -3
  122. data/lib/spree/core.rb +21 -8
  123. data/lib/spree/core/calculated_adjustments.rb +0 -40
  124. data/lib/spree/core/controller_helpers.rb +5 -0
  125. data/lib/spree/core/controller_helpers/auth.rb +2 -2
  126. data/lib/spree/core/controller_helpers/common.rb +0 -5
  127. data/lib/spree/core/controller_helpers/order.rb +8 -9
  128. data/lib/spree/core/engine.rb +10 -17
  129. data/lib/spree/core/permalinks.rb +1 -1
  130. data/lib/spree/core/product_duplicator.rb +3 -8
  131. data/lib/spree/core/user_address.rb +1 -1
  132. data/lib/spree/core/validators/email.rb +23 -1
  133. data/lib/spree/core/version.rb +1 -1
  134. data/lib/spree/money.rb +1 -1
  135. data/lib/spree/permitted_attributes.rb +2 -2
  136. data/lib/spree/testing_support/caching.rb +47 -0
  137. data/lib/spree/testing_support/factories/adjustment_factory.rb +11 -2
  138. data/lib/spree/testing_support/factories/credit_card_factory.rb +2 -1
  139. data/lib/spree/testing_support/factories/order_factory.rb +10 -5
  140. data/lib/spree/testing_support/factories/payment_factory.rb +2 -2
  141. data/lib/spree/testing_support/factories/payment_method_factory.rb +3 -3
  142. data/lib/spree/testing_support/factories/promotion_factory.rb +16 -1
  143. data/lib/spree/testing_support/factories/shipment_factory.rb +8 -4
  144. data/lib/spree/testing_support/factories/shipping_method_factory.rb +1 -3
  145. data/lib/spree/testing_support/factories/stock_factory.rb +1 -1
  146. data/lib/spree/testing_support/factories/tax_rate_factory.rb +2 -2
  147. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  148. data/lib/tasks/core.rake +2 -2
  149. data/vendor/assets/fonts/FontAwesome.otf +0 -0
  150. data/vendor/assets/fonts/fontawesome-webfont.eot +0 -0
  151. data/vendor/assets/fonts/fontawesome-webfont.svg +399 -0
  152. data/vendor/assets/fonts/fontawesome-webfont.ttf +0 -0
  153. data/vendor/assets/fonts/fontawesome-webfont.woff +0 -0
  154. data/vendor/assets/stylesheets/font-awesome.scss +1475 -0
  155. metadata +73 -44
  156. data/app/assets/javascripts/admin/handlebar_extensions.js +0 -9
  157. data/app/helpers/spree/admin/adjustments_helper.rb +0 -26
  158. data/app/helpers/spree/admin/images_helper.rb +0 -18
  159. data/app/helpers/spree/promotion_rules_helper.rb +0 -13
  160. data/app/models/spree/activator.rb +0 -29
  161. data/app/models/spree/calculator/per_item.rb +0 -41
  162. data/app/models/spree/stock/remaining_packer.rb +0 -22
  163. data/app/views/spree/payments/_payment.html.erb +0 -18
  164. data/db/migrate/20131118041203_add_tax_total_to_spree_orders.rb +0 -5
  165. data/db/migrate/20131118043021_add_order_id_to_spree_adjustments.rb +0 -6
  166. data/db/migrate/20131118074808_add_included_to_spree_adjustments.rb +0 -5
  167. data/db/migrate/20140415041315_add_user_id_created_by_id_index_to_order.rb +0 -5
  168. data/lib/spree/core/gateway_error.rb +0 -5
  169. data/lib/spree/core/preference_rescue.rb +0 -25
  170. data/lib/spree/core/s3_support.rb +0 -25
  171. data/lib/spree/promo/coupon_applicator.rb +0 -71
  172. data/lib/spree/testing_support/factories/activator_factory.rb +0 -8
@@ -10,7 +10,7 @@ module Spree
10
10
  quantity = line_item.quantity
11
11
  end
12
12
 
13
- quantifier = Stock::Quantifier.new(line_item.variant)
13
+ quantifier = Stock::Quantifier.new(line_item.variant_id)
14
14
 
15
15
  unless quantifier.can_supply? quantity
16
16
  variant = line_item.variant
@@ -29,7 +29,19 @@ module Spree
29
29
  def calculate_shipping_rates(package)
30
30
  shipping_methods(package).map do |shipping_method|
31
31
  cost = shipping_method.calculator.compute(package)
32
- shipping_method.shipping_rates.new(cost: cost) if cost
32
+ tax_category = shipping_method.tax_category
33
+ if tax_category
34
+ tax_rate = tax_category.tax_rates.detect do |rate|
35
+ rate.zone == package.order.tax_zone
36
+ end
37
+ end
38
+
39
+ if cost
40
+ rate = shipping_method.shipping_rates.new(cost: cost)
41
+ rate.tax_rate = tax_rate if tax_rate
42
+ end
43
+
44
+ rate
33
45
  end.compact
34
46
  end
35
47
 
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  module Stock
3
3
  class Package
4
- ContentItem = Struct.new(:variant, :quantity, :state)
4
+ ContentItem = Struct.new(:line_item, :variant, :quantity, :state)
5
5
 
6
6
  attr_reader :stock_location, :order, :contents
7
7
  attr_accessor :shipping_rates
@@ -13,8 +13,8 @@ module Spree
13
13
  @shipping_rates = Array.new
14
14
  end
15
15
 
16
- def add(variant, quantity, state=:on_hand)
17
- contents << ContentItem.new(variant, quantity, state)
16
+ def add(line_item, quantity, state = :on_hand, variant = nil)
17
+ contents << ContentItem.new(line_item, variant || line_item.variant, quantity, state)
18
18
  end
19
19
 
20
20
  def weight
@@ -29,10 +29,13 @@ module Spree
29
29
  contents.select { |item| item.state == :backordered }
30
30
  end
31
31
 
32
- def find_item(variant, state=:on_hand)
32
+ # Consider extensions and applications might create a inventory unit
33
+ # where the variant and the line_item might not refer to the same product
34
+ def find_item(variant, state = :on_hand, line_item = nil)
33
35
  contents.select do |item|
34
36
  item.variant == variant &&
35
- item.state == state
37
+ item.state == state &&
38
+ (line_item.nil? || line_item == item.line_item)
36
39
  end.first
37
40
  end
38
41
 
@@ -55,7 +58,7 @@ module Spree
55
58
  flat = []
56
59
  contents.each do |item|
57
60
  item.quantity.times do
58
- flat << ContentItem.new(item.variant, 1, item.state)
61
+ flat << ContentItem.new(item.line_item, item.variant, 1, item.state)
59
62
  end
60
63
  end
61
64
  flat
@@ -68,7 +71,7 @@ module Spree
68
71
  if current_item
69
72
  current_item.quantity += 1
70
73
  else
71
- add(item.variant, item.quantity, item.state)
74
+ add(item.line_item, item.quantity, item.state)
72
75
  end
73
76
  end
74
77
  end
@@ -105,6 +108,7 @@ module Spree
105
108
  unit.pending = true
106
109
  unit.order = order
107
110
  unit.variant = item.variant
111
+ unit.line_item = item.line_item
108
112
  unit.state = item.state.to_s
109
113
  end
110
114
  end
@@ -24,10 +24,10 @@ module Spree
24
24
  next unless stock_location.stock_item(line_item.variant)
25
25
 
26
26
  on_hand, backordered = stock_location.fill_status(line_item.variant, line_item.quantity)
27
- package.add line_item.variant, on_hand, :on_hand if on_hand > 0
28
- package.add line_item.variant, backordered, :backordered if backordered > 0
27
+ package.add line_item, on_hand, :on_hand if on_hand > 0
28
+ package.add line_item, backordered, :backordered if backordered > 0
29
29
  else
30
- package.add line_item.variant, line_item.quantity, :on_hand
30
+ package.add line_item, line_item.quantity, :on_hand
31
31
  end
32
32
  end
33
33
  package
@@ -4,7 +4,7 @@ module Spree
4
4
  attr_reader :stock_items
5
5
 
6
6
  def initialize(variant)
7
- @variant = variant
7
+ @variant = resolve_variant_id(variant)
8
8
  @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant, Spree::StockLocation.table_name =>{ :active => true})
9
9
  end
10
10
 
@@ -24,6 +24,14 @@ module Spree
24
24
  total_on_hand >= required || backorderable?
25
25
  end
26
26
 
27
+ private
28
+
29
+ # return variant when passed either variant object or variant id
30
+ def resolve_variant_id(variant)
31
+ variant = Spree::Variant.find_by_id(variant) unless variant.respond_to?(:should_track_inventory?)
32
+ variant
33
+ end
34
+
27
35
  end
28
36
  end
29
37
  end
@@ -3,14 +3,17 @@ module Spree
3
3
  acts_as_paranoid
4
4
 
5
5
  belongs_to :stock_location, class_name: 'Spree::StockLocation'
6
- belongs_to :variant, class_name: 'Spree::Variant', touch: true
7
- has_many :stock_movements
6
+ belongs_to :variant, class_name: 'Spree::Variant', inverse_of: :stock_items
7
+ has_many :stock_movements, inverse_of: :stock_item
8
8
 
9
9
  validates_presence_of :stock_location, :variant
10
10
  validates_uniqueness_of :variant_id, scope: [:stock_location_id, :deleted_at]
11
11
 
12
12
  delegate :weight, :should_track_inventory?, to: :variant
13
13
 
14
+ after_save :conditional_variant_touch
15
+ after_touch { variant.touch }
16
+
14
17
  def backordered_inventory_units
15
18
  Spree::InventoryUnit.backordered_for_stock_item(self)
16
19
  end
@@ -44,10 +47,6 @@ module Spree
44
47
  self.in_stock? || self.backorderable?
45
48
  end
46
49
 
47
- def variant
48
- Spree::Variant.unscoped { super }
49
- end
50
-
51
50
  private
52
51
  def count_on_hand=(value)
53
52
  write_attribute(:count_on_hand, value)
@@ -63,5 +62,11 @@ module Spree
63
62
  end
64
63
  end
65
64
  end
65
+
66
+ def conditional_variant_touch
67
+ if !Spree::Config.binary_inventory_cache || (count_on_hand_changed? && count_on_hand_change.any?(&:zero?))
68
+ variant.touch
69
+ end
70
+ end
66
71
  end
67
72
  end
@@ -1,9 +1,8 @@
1
1
  module Spree
2
2
  class StockMovement < ActiveRecord::Base
3
- belongs_to :stock_item, class_name: 'Spree::StockItem'
3
+ belongs_to :stock_item, class_name: 'Spree::StockItem', inverse_of: :stock_movements
4
4
  belongs_to :originator, polymorphic: true
5
5
 
6
-
7
6
  after_create :update_stock_item_quantity
8
7
 
9
8
  validates :stock_item, presence: true
@@ -11,7 +11,12 @@ module Spree
11
11
  #set existing default tax category to false if this one has been marked as default
12
12
 
13
13
  if is_default && tax_category = self.class.where(is_default: true).first
14
- tax_category.update_column(:is_default, false) unless tax_category == self
14
+ unless tax_category == self
15
+ tax_category.update_columns(
16
+ is_default: false,
17
+ updated_at: Time.now,
18
+ )
19
+ end
15
20
  end
16
21
  end
17
22
  end
@@ -15,6 +15,8 @@ module Spree
15
15
  belongs_to :zone, class_name: "Spree::Zone"
16
16
  belongs_to :tax_category, class_name: "Spree::TaxCategory"
17
17
 
18
+ has_many :adjustments, as: :source, dependent: :destroy
19
+
18
20
  validates :amount, presence: true, numericality: true
19
21
  validates :tax_category_id, presence: true
20
22
  validates_with DefaultTaxZoneValidator
@@ -23,20 +25,40 @@ module Spree
23
25
 
24
26
  # Gets the array of TaxRates appropriate for the specified order
25
27
  def self.match(order)
26
- order_zone = order.tax_zone
27
- return [] unless order_zone
28
- includes(zone: { zone_members: :zoneable }).load.select do |rate|
28
+ return [] unless order.tax_zone
29
+ all.select do |rate|
29
30
  (!rate.included_in_price && (rate.zone == order.tax_zone || rate.zone.contains?(order.tax_zone) || (order.tax_address.nil? && rate.zone.default_tax))) ||
30
31
  rate.included_in_price
31
32
  end
32
33
  end
33
34
 
34
- def self.adjust(order)
35
- order.adjustments.tax.destroy_all
36
- order.line_item_adjustments.where(originator_type: 'Spree::TaxRate').destroy_all
35
+ # Pre-tax amounts must be stored so that we can calculate
36
+ # correct rate amounts in the future. For example:
37
+ # https://github.com/spree/spree/issues/4318#issuecomment-34723428
38
+ def self.store_pre_tax_amount(item, rates)
39
+ if rates.any? { |r| r.included_in_price }
40
+ case item
41
+ when Spree::LineItem
42
+ item_amount = item.discounted_amount
43
+ when Spree::Shipment
44
+ item_amount = item.discounted_cost
45
+ end
46
+ pre_tax_amount = item_amount / (1 + rates.map(&:amount).sum)
47
+ item.update_column(:pre_tax_amount, pre_tax_amount)
48
+ end
49
+ end
37
50
 
38
- self.match(order).each do |rate|
39
- rate.adjust(order)
51
+ def self.adjust(order, items)
52
+ rates = self.match(order)
53
+ tax_categories = rates.map(&:tax_category)
54
+ relevant_items = items.select { |item| tax_categories.include?(item.tax_category) }
55
+ relevant_items.each do |item|
56
+ item.adjustments.tax.delete_all
57
+ relevant_rates = rates.select { |rate| rate.tax_category == item.tax_category }
58
+ store_pre_tax_amount(item, relevant_rates)
59
+ relevant_rates.each do |rate|
60
+ rate.adjust(order, item)
61
+ end
40
62
  end
41
63
  end
42
64
 
@@ -54,51 +76,37 @@ module Spree
54
76
  end
55
77
 
56
78
  # Creates necessary tax adjustments for the order.
57
- def adjust(order)
58
- # (rate.included_in_price && !order.tax_address.nil? && !rate.zone.contains?(order.tax_zone) && rate.zone.default_tax)
59
- label = create_label
79
+ def adjust(order, item)
80
+ amount = calculator.compute(item)
81
+ return if amount == 0
82
+
83
+ included = included_in_price &&
84
+ Zone.default_tax.contains?(item.order.tax_zone)
85
+
86
+ if amount < 0
87
+ label = Spree.t(:refund) + ' ' + create_label
88
+ end
89
+
90
+ self.adjustments.create!({
91
+ :adjustable => item,
92
+ :amount => amount,
93
+ :order => order,
94
+ :label => label || create_label,
95
+ :included => included
96
+ })
97
+ end
98
+
99
+ # This method is used by Adjustment#update to recalculate the cost.
100
+ def compute_amount(item)
60
101
  if included_in_price
61
- if Zone.default_tax.contains? order.tax_zone
62
- order.line_items.each do |line_item|
63
- amount = calculator.compute(line_item)
64
- unless amount == 0
65
- line_item.adjustments.create(
66
- order: order,
67
- amount: amount,
68
- source: line_item,
69
- originator: self,
70
- label: label,
71
- mandatory: false,
72
- state: "closed",
73
- included: true
74
- )
75
- end
76
- end
102
+ if Zone.default_tax.contains? item.order.tax_zone
103
+ calculator.compute(item)
77
104
  else
78
- amount = -1 * calculator.compute(order)
79
- label = Spree.t(:refund) + label
80
-
81
- order.adjustments.create(
82
- order: order,
83
- amount: amount,
84
- source: order,
85
- originator: self,
86
- state: "closed",
87
- label: label
88
- )
105
+ # In this case, it's a refund.
106
+ calculator.compute(item) * - 1
89
107
  end
90
108
  else
91
- amount = calculator.compute(order)
92
- unless amount == 0
93
- order.adjustments.create(
94
- order: order,
95
- amount: amount,
96
- source: order,
97
- originator: self,
98
- state: "closed",
99
- label: label
100
- )
101
- end
109
+ calculator.compute(item)
102
110
  end
103
111
  end
104
112
 
@@ -2,14 +2,16 @@ module Spree
2
2
  class Taxon < ActiveRecord::Base
3
3
  acts_as_nested_set dependent: :destroy
4
4
 
5
- belongs_to :taxonomy, class_name: 'Spree::Taxonomy', :touch => true
6
- has_many :classifications, dependent: :delete_all
5
+ belongs_to :taxonomy, class_name: 'Spree::Taxonomy', touch: true, inverse_of: :taxons
6
+ has_many :classifications, -> { order(:position) }, dependent: :delete_all, inverse_of: :taxon
7
7
  has_many :products, through: :classifications
8
8
 
9
9
  before_create :set_permalink
10
10
 
11
11
  validates :name, presence: true
12
12
 
13
+ after_touch :touch_parent
14
+
13
15
  has_attached_file :icon,
14
16
  styles: { mini: '32x32>', normal: '128x128>' },
15
17
  default_style: :mini,
@@ -17,9 +19,6 @@ module Spree
17
19
  path: ':rails_root/public/spree/taxons/:id/:style/:basename.:extension',
18
20
  default_url: '/assets/default_taxon.png'
19
21
 
20
- include Spree::Core::S3Support
21
- supports_s3 :icon
22
-
23
22
  include Spree::Core::ProductFilters # for detailed defs of filters
24
23
 
25
24
  # indicate which filters should be used for a taxon
@@ -78,5 +77,11 @@ module Spree
78
77
  def child_index=(idx)
79
78
  move_to_child_with_index(parent, idx.to_i) unless self.new_record?
80
79
  end
80
+
81
+ private
82
+
83
+ def touch_parent
84
+ parent.touch if parent
85
+ end
81
86
  end
82
87
  end
@@ -2,7 +2,7 @@ module Spree
2
2
  class Taxonomy < ActiveRecord::Base
3
3
  validates :name, presence: true
4
4
 
5
- has_many :taxons
5
+ has_many :taxons, inverse_of: :taxonomy
6
6
  has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy
7
7
 
8
8
  after_save :set_name
@@ -12,7 +12,10 @@ module Spree
12
12
  private
13
13
  def set_name
14
14
  if root
15
- root.update_column(:name, name)
15
+ root.update_columns(
16
+ name: name,
17
+ updated_at: Time.now,
18
+ )
16
19
  else
17
20
  self.root = Taxon.create!(taxonomy_id: id, name: name)
18
21
  end
@@ -2,20 +2,21 @@ module Spree
2
2
  class Variant < ActiveRecord::Base
3
3
  acts_as_paranoid
4
4
 
5
- belongs_to :product, touch: true, class_name: 'Spree::Product'
5
+ belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :variants
6
+ belongs_to :tax_category, class_name: 'Spree::TaxCategory'
6
7
 
7
- delegate_belongs_to :product, :name, :description, :permalink, :available_on,
8
- :tax_category_id, :shipping_category_id, :meta_description,
9
- :meta_keywords, :tax_category, :shipping_category
8
+ delegate_belongs_to :product, :name, :description, :slug, :available_on,
9
+ :shipping_category_id, :meta_description, :meta_keywords,
10
+ :shipping_category
10
11
 
11
12
  has_many :inventory_units
12
- has_many :line_items
13
+ has_many :line_items, inverse_of: :variant
13
14
 
14
- has_many :stock_items, dependent: :destroy
15
+ has_many :stock_items, dependent: :destroy, inverse_of: :variant
15
16
  has_many :stock_locations, through: :stock_items
16
17
  has_many :stock_movements
17
18
 
18
- has_and_belongs_to_many :option_values, join_table: :spree_option_values_variants, class_name: "Spree::OptionValue"
19
+ has_and_belongs_to_many :option_values, join_table: :spree_option_values_variants
19
20
  has_many :images, -> { order(:position) }, as: :viewable, dependent: :destroy, class_name: "Spree::Image"
20
21
 
21
22
  has_one :default_price,
@@ -27,7 +28,8 @@ module Spree
27
28
 
28
29
  has_many :prices,
29
30
  class_name: 'Spree::Price',
30
- dependent: :destroy
31
+ dependent: :destroy,
32
+ inverse_of: :variant
31
33
 
32
34
  validate :check_price
33
35
  validates :price, numericality: { greater_than_or_equal_to: 0 }
@@ -39,6 +41,8 @@ module Spree
39
41
  after_create :create_stock_items
40
42
  after_create :set_position
41
43
 
44
+ after_touch :clear_in_stock_cache
45
+
42
46
  # default variant scope only lists non-deleted variants
43
47
  scope :deleted, lambda { where.not(deleted_at: nil) }
44
48
 
@@ -46,6 +50,14 @@ module Spree
46
50
  joins(:prices).where(deleted_at: nil).where('spree_prices.currency' => currency || Spree::Config[:currency]).where('spree_prices.amount IS NOT NULL')
47
51
  end
48
52
 
53
+ def tax_category
54
+ if self[:tax_category_id].nil?
55
+ product.tax_category
56
+ else
57
+ TaxCategory.find(self[:tax_category_id])
58
+ end
59
+ end
60
+
49
61
  def cost_price=(price)
50
62
  self[:cost_price] = parse_price(price) if price.present?
51
63
  end
@@ -75,7 +87,7 @@ module Spree
75
87
  # allows extensions to override deleted? if they want to provide
76
88
  # their own definition.
77
89
  def deleted?
78
- !!deleted_at
90
+ deleted_at
79
91
  end
80
92
 
81
93
  # Product may be created with deleted_at already set,
@@ -149,16 +161,13 @@ module Spree
149
161
  "#{sku} #{options_text}".strip
150
162
  end
151
163
 
152
- def in_stock?(quantity=:argument_here_is_deprecated)
153
- if quantity == :argument_here_is_deprecated
154
- can_stock?(1)
155
- else
156
- puts %q{[DEPRECATION] In Spree 2.2, Variant#in_stock? will no longer take a quantity. Use Variant#can_supply? instead.}
157
- can_stock?(quantity)
164
+ def in_stock?
165
+ Rails.cache.fetch(in_stock_cache_key) do
166
+ total_on_hand > 0
158
167
  end
159
168
  end
160
169
 
161
- def can_stock?(quantity=1)
170
+ def can_supply?(quantity=1)
162
171
  Spree::Stock::Quantifier.new(self).can_supply?(quantity)
163
172
  end
164
173
 
@@ -214,6 +223,14 @@ module Spree
214
223
  def set_position
215
224
  self.update_column(:position, product.variants.maximum(:position).to_i + 1)
216
225
  end
226
+
227
+ def in_stock_cache_key
228
+ "variant-#{id}-in_stock"
229
+ end
230
+
231
+ def clear_in_stock_cache
232
+ Rails.cache.delete(in_stock_cache_key)
233
+ end
217
234
  end
218
235
  end
219
236