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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 413409a6e11793b4c41aac79f57541c2b4b6c8b4
4
- data.tar.gz: 61e14410d4987119dd34a5694b97acefb0578cb3
3
+ metadata.gz: bec161c547d1c0a301e068937cff9a461ff7a6cc
4
+ data.tar.gz: 5ea11fca1a903043e7776db55c5092a676a31c40
5
5
  SHA512:
6
- metadata.gz: 2c6a19efdbfd4a44dde5cf6a42532c2c59e95fe94e6700aaf6816b47312a46ee1987376cb13646701ba0c8b0195c842abf8cc129e40cb23faf63b71372a52294
7
- data.tar.gz: a69ffad30b460d6e910f825c0b60e346030a0c120d361bdbebd27ff324eb9783e34d243cca4d7a8ac4c80aca0ed031bfc5639f3a08fd608529e4ad6752f6b0cd
6
+ metadata.gz: 1f618e1c470a7a552a2b6b97d72b2702c52d8beba2298d6ab6400982f024a466bc9b857af1e3b447ca5ab8c079d8d44bac78877516baa1a8962ef7f9eac0b244
7
+ data.tar.gz: 3be703d2a9d163edb81d227463859a7cb5a181091539780f5b0eb4173ad2f69cf8ff74e824361d312e6571ffbbedef6c8f12eb06fb6649cd2902771f5f537754
@@ -13,16 +13,14 @@ module Spree
13
13
  end
14
14
 
15
15
  def link_to_cart(text = nil)
16
- return "" if current_spree_page?(spree.cart_path)
17
-
18
16
  text = text ? h(text) : Spree.t('cart')
19
17
  css_class = nil
20
18
 
21
- if current_order.nil? or current_order.item_count.zero?
19
+ if simple_current_order.nil? or simple_current_order.item_count.zero?
22
20
  text = "#{text}: (#{Spree.t('empty')})"
23
21
  css_class = 'empty'
24
22
  else
25
- text = "#{text}: (#{current_order.item_count}) <span class='amount'>#{current_order.display_total.to_html}</span>".html_safe
23
+ text = "#{text}: (#{simple_current_order.item_count}) <span class='amount'>#{simple_current_order.display_total.to_html}</span>".html_safe
26
24
  css_class = 'full'
27
25
  end
28
26
 
@@ -120,7 +118,7 @@ module Spree
120
118
  countries.collect do |country|
121
119
  country.name = Spree.t(country.iso, scope: 'country_names', default: country.name)
122
120
  country
123
- end.sort_by { |c| c.name.parameterize }
121
+ end.sort { |a, b| a.name.parameterize <=> b.name.parameterize }
124
122
  end
125
123
 
126
124
  def seo_url(taxon)
@@ -164,10 +162,9 @@ module Spree
164
162
  end
165
163
 
166
164
  private
167
-
168
165
  # Returns style of image or nil
169
166
  def image_style_from_method_name(method_name)
170
- if method_name.to_s.match(/_image$/) && style = method_name.to_s.sub(/_image$/, '')
167
+ if style = method_name.to_s.sub(/_image$/, '')
171
168
  possible_styles = Spree::Image.attachment_definitions[:attachment][:styles]
172
169
  style if style.in? possible_styles.with_indifferent_access
173
170
  end
@@ -12,13 +12,14 @@ module Spree
12
12
 
13
13
  # returns the formatted price for the specified variant as a difference from product price
14
14
  def variant_price_diff(variant)
15
- variant_amount = variant.amount_in(current_currency)
16
- product_amount = variant.product.amount_in(current_currency)
17
- return if variant_amount == product_amount || product_amount.nil?
18
- diff = variant.amount_in(current_currency) - product_amount
19
- amount = Spree::Money.new(diff.abs, currency: current_currency).to_html
20
- label = diff > 0 ? :add : :subtract
21
- "(#{Spree.t(label)}: #{amount})".html_safe
15
+ diff = variant.amount_in(current_currency) - variant.product.amount_in(current_currency)
16
+ return nil if diff == 0
17
+ amount = Spree::Money.new(diff.abs, { currency: current_currency }).to_html
18
+ if diff > 0
19
+ "(#{Spree.t(:add)}: #{amount})".html_safe
20
+ else
21
+ "(#{Spree.t(:subtract)}: #{amount})".html_safe
22
+ end
22
23
  end
23
24
 
24
25
  # returns the formatted full price for the variant, if at least one variant price differs from product price
@@ -52,8 +53,9 @@ module Spree
52
53
  end
53
54
  end
54
55
 
55
- def get_taxonomies
56
- @taxonomies ||= Spree::Taxonomy.includes(root: :children)
56
+ def cache_key_for_products
57
+ max_updated_at = @products.maximum(:updated_at).to_s(:number)
58
+ "#{current_currency}/spree/products/all-#{params[:page]}-#{max_updated_at}"
57
59
  end
58
60
  end
59
61
  end
@@ -7,5 +7,10 @@ module Spree
7
7
  %w{thank_you}.exclude? params[:action]
8
8
  end
9
9
 
10
+ def cache_key_for_taxons
11
+ max_updated_at = @taxons.maximum(:updated_at).to_i
12
+ parts = [@taxon.try(:id), max_updated_at].compact.join("-")
13
+ "taxons/#{parts}"
14
+ end
10
15
  end
11
16
  end
@@ -47,6 +47,10 @@ module Spree
47
47
  can :update, Order do |order, token|
48
48
  order.user == user || order.token && token == order.token
49
49
  end
50
+ can [:create, :read], Address
51
+ can :update, Address do |address|
52
+ user.bill_address == address || user.ship_address == address
53
+ end
50
54
  can [:index, :read], Product
51
55
  can [:index, :read], ProductProperty
52
56
  can [:index, :read], Property
@@ -3,7 +3,7 @@ module Spree
3
3
  belongs_to :country, class_name: "Spree::Country"
4
4
  belongs_to :state, class_name: "Spree::State"
5
5
 
6
- has_many :shipments
6
+ has_many :shipments, inverse_of: :address
7
7
 
8
8
  validates :firstname, :lastname, :address1, :city, :country, presence: true
9
9
  validates :zipcode, presence: true, if: :require_zipcode?
@@ -19,11 +19,6 @@ module Spree
19
19
  new(country: country)
20
20
  end
21
21
 
22
- # Can modify an address if it's not been used in an order (but checkouts controller has finer control)
23
- # def editable?
24
- # new_record? || (shipments.empty? && checkouts.empty?)
25
- # end
26
-
27
22
  def self.default(user = nil, kind = "bill")
28
23
  if user
29
24
  user.send(:"#{kind}_address") || build_default
@@ -32,6 +27,11 @@ module Spree
32
27
  end
33
28
  end
34
29
 
30
+ # Can modify an address if it's not been used in an order (but checkouts controller has finer control)
31
+ # def editable?
32
+ # new_record? || (shipments.empty? && checkouts.empty?)
33
+ # end
34
+
35
35
  def full_name
36
36
  "#{firstname} #{lastname}".strip
37
37
  end
@@ -1,10 +1,8 @@
1
1
  # Adjustments represent a change to the +item_total+ of an Order. Each adjustment
2
2
  # has an +amount+ that can be either positive or negative.
3
3
  #
4
- # Adjustments can be open/closed/finalized
5
- #
6
- # Once an adjustment is finalized, it cannot be changed, but an adjustment can
7
- # toggle between open/closed as needed
4
+ # Adjustments can be "opened" or "closed".
5
+ # Once an adjustment is closed, it will not be automatically updated.
8
6
  #
9
7
  # Boolean attributes:
10
8
  #
@@ -26,83 +24,67 @@ module Spree
26
24
  class Adjustment < ActiveRecord::Base
27
25
  belongs_to :adjustable, polymorphic: true
28
26
  belongs_to :source, polymorphic: true
29
- belongs_to :originator, polymorphic: true
30
- belongs_to :order, :class_name => 'Spree::Order'
27
+ belongs_to :order, :class_name => "Spree::Order"
31
28
 
32
29
  validates :label, presence: true
33
30
  validates :amount, numericality: true
34
31
 
35
- after_save :update_adjustable
36
- after_destroy :update_adjustable
37
-
38
32
  state_machine :state, initial: :open do
39
33
  event :close do
40
34
  transition from: :open, to: :closed
41
35
  end
42
36
 
43
- event :open do
44
- transition from: :closed, to: :open
45
- end
46
-
47
- event :finalize do
48
- transition from: [:open, :closed], to: :finalized
37
+ event :close do
38
+ transition from: :close, to: :open
49
39
  end
50
40
  end
51
41
 
52
- scope :tax, -> { where(originator_type: 'Spree::TaxRate') }
42
+ after_create :update_adjustable_adjustment_total
43
+
44
+ scope :open, -> { where(state: 'open') }
45
+ scope :tax, -> { where(source_type: 'Spree::TaxRate') }
53
46
  scope :price, -> { where(adjustable_type: 'Spree::LineItem') }
54
- scope :shipping, -> { where(originator_type: 'Spree::ShippingMethod') }
47
+ scope :shipping, -> { where(adjustable_type: 'Spree::Shipment') }
55
48
  scope :optional, -> { where(mandatory: false) }
56
49
  scope :eligible, -> { where(eligible: true) }
57
50
  scope :charge, -> { where("#{quoted_table_name}.amount >= 0") }
58
51
  scope :credit, -> { where("#{quoted_table_name}.amount < 0") }
59
- scope :promotion, -> { where(originator_type: 'Spree::PromotionAction') }
60
- scope :manual, -> { where(originator_type: nil) }
52
+ scope :promotion, -> { where(source_type: 'Spree::PromotionAction') }
61
53
  scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
62
54
  scope :included, -> { where(included: true) }
63
55
  scope :additional, -> { where(included: false) }
64
56
 
65
- def promotion?
66
- originator_type == 'Spree::PromotionAction'
67
- end
68
-
69
- # Update the boolean _eligible_ attribute which determines which adjustments
70
- # count towards the order's adjustment_total.
71
- def set_eligibility
72
- result = mandatory || ((amount != 0 || promotion?) && eligible_for_originator?)
73
- update_column(:eligible, result)
57
+ def closed?
58
+ state == "closed"
74
59
  end
75
60
 
76
- # Allow originator of the adjustment to perform an additional eligibility of the adjustment
77
- # Should return _true_ if originator is absent or doesn't implement _eligible?_
78
- def eligible_for_originator?
79
- return true if originator.nil?
80
- !originator.respond_to?(:eligible?) || originator.eligible?(source)
61
+ def promotion?
62
+ source.class < Spree::PromotionAction
81
63
  end
82
64
 
83
- # Update both the eligibility and amount of the adjustment. Adjustments
84
- # delegate updating of amount to their Originator when present, but only if
85
- # +locked+ is false. Adjustments that are +locked+ will never change their amount.
65
+ # Recalculate amount given a target e.g. Order, Shipment, LineItem
86
66
  #
87
- # Adjustments delegate updating of amount to their Originator when present,
88
- # but only if when they're in "open" state, closed or finalized adjustments
89
- # are not recalculated.
67
+ # Passing a target here would always be recommended as it would avoid
68
+ # hitting the database again and would ensure you're compute values over
69
+ # the specific object amount passed here.
90
70
  #
91
- # It receives +calculable+ as the updated source here so calculations can be
92
- # performed on the current values of that source. If we used +source+ it
93
- # could load the old record from db for the association. e.g. when updating
94
- # more than on line items at once via accepted_nested_attributes the order
95
- # object on the association would be in a old state and therefore the
96
- # adjustment calculations would not performed on proper values
97
- def update!(calculable = nil)
98
- return if immutable?
99
- # Fix for #3381
100
- # If we attempt to call 'source' before the reload, then source is currently
101
- # the order object. After calling a reload, the source is the Shipment.
102
- reload
103
- calculable = source unless calculable == source
104
- originator.update_adjustment(self, calculable) if originator.present?
105
- set_eligibility
71
+ # Noop if the adjustment is locked.
72
+ #
73
+ # If the adjustment has no source, do not attempt to re-calculate the amount.
74
+ # Chances are likely that this was a manually created adjustment in the admin backend.
75
+ def update!(target = nil)
76
+ return amount if closed?
77
+ if source.present?
78
+ amount = source.compute_amount(target || adjustable)
79
+ self.update_columns(
80
+ amount: amount,
81
+ updated_at: Time.now,
82
+ )
83
+ if promotion?
84
+ self.update_column(:eligible, source.promotion.eligible?(adjustable))
85
+ end
86
+ end
87
+ amount
106
88
  end
107
89
 
108
90
  def currency
@@ -113,14 +95,11 @@ module Spree
113
95
  Spree::Money.new(amount, { currency: currency })
114
96
  end
115
97
 
116
- def immutable?
117
- state != "open"
118
- end
119
-
120
98
  private
121
99
 
122
- def update_adjustable
123
- adjustable.update! if adjustable.is_a? Order
124
- end
100
+ def update_adjustable_adjustment_total
101
+ # Cause adjustable's total to be recalculated
102
+ Spree::ItemAdjustments.new(adjustable).update if adjustable
103
+ end
125
104
  end
126
105
  end
@@ -35,6 +35,7 @@ module Spree
35
35
  preference :always_include_confirm_step, :boolean, default: false # Ensures confirmation step is always in checkout_progress bar, but does not force a confirm step if your payment methods do not support it.
36
36
  preference :always_put_site_name_in_title, :boolean, default: true
37
37
  preference :auto_capture, :boolean, default: false # automatically capture the credit card (as opposed to just authorize and capture later)
38
+ preference :binary_inventory_cache, :boolean, default: false # only invalidate product cache when a stock item changes whether it is in_stock
38
39
  preference :check_for_spree_alerts, :boolean, default: true
39
40
  preference :checkout_zone, :string, default: nil # replace with the name of a zone if you would like to limit the countries
40
41
  preference :company, :boolean, default: false # Request company field for billing and shipping addr
@@ -70,20 +71,6 @@ module Spree
70
71
  preference :tax_using_ship_address, :boolean, default: true
71
72
  preference :track_inventory_levels, :boolean, default: true # Determines whether to track on_hand values for variants / products.
72
73
 
73
- # Preferences related to image settings
74
- preference :attachment_default_url, :string, default: '/spree/products/:id/:style/:basename.:extension'
75
- preference :attachment_path, :string, default: ':rails_root/public/spree/products/:id/:style/:basename.:extension'
76
- preference :attachment_url, :string, default: '/spree/products/:id/:style/:basename.:extension'
77
- preference :attachment_styles, :string, default: "{\"mini\":\"48x48>\",\"small\":\"100x100>\",\"product\":\"240x240>\",\"large\":\"600x600>\"}"
78
- preference :attachment_default_style, :string, default: 'product'
79
- preference :s3_access_key, :string
80
- preference :s3_bucket, :string
81
- preference :s3_secret, :string
82
- preference :s3_headers, :string, default: "{\"Cache-Control\":\"max-age=31557600\"}"
83
- preference :use_s3, :boolean, default: false # Use S3 for images rather than the file system
84
- preference :s3_protocol, :string
85
- preference :s3_host_alias, :string
86
-
87
74
  # Default mail headers settings
88
75
  preference :enable_mail_delivery, :boolean, :default => false
89
76
  preference :send_core_emails, :boolean, :default => true
@@ -2,11 +2,19 @@ module Spree
2
2
  class Calculator < ActiveRecord::Base
3
3
  belongs_to :calculable, polymorphic: true
4
4
 
5
- # This method must be overriden in concrete calculator.
5
+ # This method calls a compute_<computable> method. must be overriden in concrete calculator.
6
6
  #
7
- # It should return amount computed based on #calculable and/or optional parameter
8
- def compute(something = nil)
9
- raise NotImplementedError, 'please use concrete calculator'
7
+ # It should return amount computed based on #calculable and the computable parameter
8
+ def compute(computable)
9
+ # Spree::LineItem -> :compute_line_item
10
+ computable_name = computable.class.name.demodulize.underscore
11
+ method = "compute_#{computable_name}".to_sym
12
+ calculator_class = self.class
13
+ begin
14
+ self.send(method, computable)
15
+ rescue NoMethodError
16
+ raise NotImplementedError, "Please implement '#{method}(#{computable_name})' in your calculator: #{calculator_class.name}"
17
+ end
10
18
  end
11
19
 
12
20
  # overwrite to provide description for your calculators
@@ -6,54 +6,58 @@ module Spree
6
6
  Spree.t(:default_tax)
7
7
  end
8
8
 
9
- def compute(computable)
10
- case computable
11
- when Spree::Order
12
- compute_order(computable)
13
- when Spree::LineItem
14
- compute_line_item(computable)
9
+ # Default tax calculator still needs to support orders for legacy reasons
10
+ # Orders created before Spree 2.1 had tax adjustments applied to the order, as a whole.
11
+ # Orders created with Spree 2.2 and after, have them applied to the line items individually.
12
+ def compute_order(order)
13
+
14
+ matched_line_items = order.line_items.select do |line_item|
15
+ line_item.tax_category == rate.tax_category
16
+ end
17
+
18
+ line_items_total = matched_line_items.sum(&:total)
19
+ if rate.included_in_price
20
+ round_to_two_places(line_items_total - ( line_items_total / (1 + rate.amount) ) )
21
+ else
22
+ round_to_two_places(line_items_total * rate.amount)
15
23
  end
16
24
  end
17
25
 
26
+ # When it comes to computing shipments or line items: same same.
27
+ def compute_shipment_or_line_item(item)
28
+ if rate.included_in_price
29
+ deduced_total_by_rate(item.pre_tax_amount, rate)
30
+ else
31
+ round_to_two_places(item.discounted_amount * rate.amount)
32
+ end
33
+ end
18
34
 
19
- private
35
+ alias_method :compute_shipment, :compute_shipment_or_line_item
36
+ alias_method :compute_line_item, :compute_shipment_or_line_item
20
37
 
21
- def rate
22
- self.calculable
38
+ def compute_shipping_rate(shipping_rate)
39
+ if rate.included_in_price
40
+ pre_tax_amount = shipping_rate.cost / (1 + rate.amount)
41
+ deduced_total_by_rate(pre_tax_amount, rate)
42
+ else
43
+ with_tax_amount = shipping_rate.cost * rate.amount
44
+ round_to_two_places(with_tax_amount)
23
45
  end
46
+ end
24
47
 
25
- def compute_order(order)
26
- matched_line_items = order.line_items.select do |line_item|
27
- line_item.tax_category == rate.tax_category
28
- end
29
-
30
- line_items_total = matched_line_items.sum(&:total)
31
- if rate.included_in_price
32
- deduced_total_by_rate(line_items_total, rate)
33
- else
34
- round_to_two_places(line_items_total * rate.amount)
35
- end
36
- end
48
+ private
37
49
 
38
- def compute_line_item(line_item)
39
- if line_item.tax_category == rate.tax_category
40
- if rate.included_in_price
41
- deduced_total_by_rate(line_item.total, rate)
42
- else
43
- round_to_two_places(line_item.total * rate.amount)
44
- end
45
- else
46
- 0
47
- end
48
- end
50
+ def rate
51
+ self.calculable
52
+ end
49
53
 
50
- def round_to_two_places(amount)
51
- BigDecimal.new(amount.to_s).round(2, BigDecimal::ROUND_HALF_UP)
52
- end
54
+ def round_to_two_places(amount)
55
+ BigDecimal.new(amount.to_s).round(2, BigDecimal::ROUND_HALF_UP)
56
+ end
53
57
 
54
- def deduced_total_by_rate(total, rate)
55
- round_to_two_places(total - ( total / (1 + rate.amount) ) )
56
- end
58
+ def deduced_total_by_rate(pre_tax_amount, rate)
59
+ round_to_two_places(pre_tax_amount * rate.amount)
60
+ end
57
61
 
58
62
  end
59
63
  end
@@ -8,10 +8,8 @@ module Spree
8
8
  Spree.t(:flat_percent)
9
9
  end
10
10
 
11
- def compute(object)
12
- return unless object.present? and object.respond_to?(:item_total)
13
- item_total = object.item_total
14
- value = item_total * BigDecimal(self.preferred_flat_percent.to_s) / 100.0
11
+ def compute(line_item)
12
+ value = line_item.amount * BigDecimal(self.preferred_flat_percent.to_s) / 100.0
15
13
  (value * 100).round.to_f / 100
16
14
  end
17
15
  end