solidus_core 2.0.3 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_core might be problematic. Click here for more details.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +62 -3
  3. data/app/assets/javascripts/spree.js.coffee.erb +4 -1
  4. data/app/helpers/spree/base_helper.rb +7 -48
  5. data/app/models/spree/address.rb +5 -1
  6. data/app/models/spree/adjustment.rb +3 -3
  7. data/app/models/spree/app_configuration.rb +13 -0
  8. data/app/models/spree/calculator.rb +3 -2
  9. data/app/models/spree/calculator/default_tax.rb +6 -10
  10. data/app/models/spree/calculator/flat_percent_item_total.rb +0 -4
  11. data/app/models/spree/calculator/flat_rate.rb +0 -4
  12. data/app/models/spree/calculator/flexi_rate.rb +0 -4
  13. data/app/models/spree/calculator/free_shipping.rb +0 -3
  14. data/app/models/spree/calculator/percent_on_line_item.rb +0 -4
  15. data/app/models/spree/calculator/percent_per_item.rb +0 -4
  16. data/app/models/spree/calculator/price_sack.rb +0 -4
  17. data/app/models/spree/calculator/returns/default_refund_amount.rb +0 -3
  18. data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +0 -4
  19. data/app/models/spree/calculator/shipping/flat_rate.rb +0 -4
  20. data/app/models/spree/calculator/shipping/flexi_rate.rb +0 -4
  21. data/app/models/spree/calculator/shipping/per_item.rb +0 -4
  22. data/app/models/spree/calculator/shipping/price_sack.rb +0 -4
  23. data/app/models/spree/calculator/tiered_flat_rate.rb +0 -4
  24. data/app/models/spree/calculator/tiered_percent.rb +0 -4
  25. data/app/models/spree/credit_card.rb +27 -14
  26. data/app/models/spree/gateway.rb +4 -0
  27. data/app/models/spree/inventory_unit.rb +2 -0
  28. data/app/models/spree/line_item.rb +31 -26
  29. data/app/models/spree/option_type.rb +0 -3
  30. data/app/models/spree/order.rb +28 -31
  31. data/app/models/spree/order/checkout.rb +0 -2
  32. data/app/models/spree/order_contents.rb +0 -45
  33. data/app/models/spree/order_merger.rb +6 -6
  34. data/app/models/spree/order_update_attributes.rb +0 -2
  35. data/app/models/spree/order_updater.rb +91 -13
  36. data/app/models/spree/payment.rb +9 -2
  37. data/app/models/spree/payment/processing.rb +15 -9
  38. data/app/models/spree/payment_method.rb +48 -5
  39. data/app/models/spree/price.rb +7 -9
  40. data/app/models/spree/product.rb +1 -25
  41. data/app/models/spree/promotion.rb +22 -14
  42. data/app/models/spree/promotion/actions/create_adjustment.rb +12 -1
  43. data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -1
  44. data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +5 -3
  45. data/app/models/spree/promotion/actions/free_shipping.rb +14 -0
  46. data/app/models/spree/promotion/rules/taxon.rb +7 -2
  47. data/app/models/spree/promotion/rules/user_role.rb +43 -0
  48. data/app/models/spree/promotion_action.rb +19 -2
  49. data/app/models/spree/promotion_handler/coupon.rb +1 -4
  50. data/app/models/spree/promotion_handler/free_shipping.rb +22 -17
  51. data/app/models/spree/promotion_rule_role.rb +6 -0
  52. data/app/models/spree/property.rb +0 -3
  53. data/app/models/spree/return_authorization.rb +2 -0
  54. data/app/models/spree/shipment.rb +5 -21
  55. data/app/models/spree/shipping_method.rb +23 -2
  56. data/app/models/spree/shipping_rate.rb +3 -0
  57. data/app/models/spree/stock/estimator.rb +1 -1
  58. data/app/models/spree/stock_location.rb +3 -0
  59. data/app/models/spree/store.rb +7 -0
  60. data/app/models/spree/tax/item_adjuster.rb +27 -12
  61. data/app/models/spree/tax/order_adjuster.rb +2 -5
  62. data/app/models/spree/tax/tax_helpers.rb +4 -8
  63. data/app/models/spree/tax_rate.rb +1 -15
  64. data/app/models/spree/taxon.rb +0 -3
  65. data/app/models/spree/transfer_item.rb +1 -1
  66. data/app/models/spree/user_class_handle.rb +14 -9
  67. data/app/models/spree/variant/pricing_options.rb +1 -1
  68. data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +1 -1
  69. data/app/models/spree/zone.rb +20 -13
  70. data/config/locales/en.yml +144 -62
  71. data/db/migrate/20120831092320_spree_one_two.rb +0 -7
  72. data/db/migrate/20150723224133_remove_unnecessary_indexes.rb +0 -2
  73. data/db/migrate/20160924135758_remove_is_default_from_prices.rb +5 -0
  74. data/db/migrate/20161009141333_remove_currency_from_line_items.rb +5 -0
  75. data/db/migrate/20161014221052_add_available_to_columns_and_remove_display_on_from_payment_methods.rb +28 -0
  76. data/db/migrate/20161123154034_add_available_to_users_and_remove_display_on_from_shipping_methods.rb +20 -0
  77. data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +4 -0
  78. data/lib/generators/spree/dummy/dummy_generator.rb +0 -2
  79. data/lib/spree/core.rb +0 -5
  80. data/lib/spree/core/controller_helpers/pricing.rb +2 -1
  81. data/lib/spree/core/engine.rb +14 -0
  82. data/lib/spree/core/version.rb +1 -1
  83. data/lib/spree/deprecation.rb +1 -1
  84. data/lib/spree/localized_number.rb +3 -2
  85. data/lib/spree/permission_sets/configuration_display.rb +0 -1
  86. data/lib/spree/permission_sets/configuration_management.rb +0 -1
  87. data/lib/spree/permission_sets/product_display.rb +0 -1
  88. data/lib/spree/permission_sets/product_management.rb +0 -1
  89. data/lib/spree/permission_sets/user_management.rb +2 -4
  90. data/lib/spree/permitted_attributes.rb +3 -2
  91. data/lib/spree/testing_support/capybara_ext.rb +0 -12
  92. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  93. data/lib/spree/testing_support/factories/line_item_factory.rb +0 -1
  94. data/lib/spree/testing_support/factories/payment_factory.rb +4 -0
  95. data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -1
  96. data/lib/spree/testing_support/factories/user_factory.rb +2 -2
  97. data/solidus_core.gemspec +4 -3
  98. data/spec/helpers/base_helper_spec.rb +0 -40
  99. data/spec/lib/spree/core/controller_helpers/pricing_spec.rb +16 -0
  100. data/spec/lib/spree/core/importer/order_spec.rb +27 -18
  101. data/spec/lib/spree/core/price_migrator_spec.rb +3 -1
  102. data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +16 -0
  103. data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -2
  104. data/spec/lib/tasks/exchanges_spec.rb +4 -2
  105. data/spec/lib/tasks/migrations/create_vat_prices_spec.rb +5 -3
  106. data/spec/models/spree/adjustment_spec.rb +136 -0
  107. data/spec/models/spree/calculator/default_tax_spec.rb +13 -7
  108. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +3 -0
  109. data/spec/models/spree/calculator/flat_rate_spec.rb +3 -0
  110. data/spec/models/spree/calculator/flexi_rate_spec.rb +3 -0
  111. data/spec/models/spree/calculator/free_shipping_spec.rb +6 -0
  112. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +9 -4
  113. data/spec/models/spree/calculator/percent_per_item_spec.rb +10 -0
  114. data/spec/models/spree/calculator/price_sack_spec.rb +3 -0
  115. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +3 -0
  116. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +3 -0
  117. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +3 -0
  118. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +3 -0
  119. data/spec/models/spree/calculator/shipping/per_item_spec.rb +3 -0
  120. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +4 -1
  121. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +3 -0
  122. data/spec/models/spree/calculator/tiered_percent_spec.rb +3 -0
  123. data/spec/models/spree/credit_card_spec.rb +27 -1
  124. data/spec/models/spree/line_item_spec.rb +58 -65
  125. data/spec/models/spree/order/checkout_spec.rb +2 -1
  126. data/spec/models/spree/order/payment_spec.rb +9 -10
  127. data/spec/models/spree/order/tax_spec.rb +22 -7
  128. data/spec/models/spree/order/updating_spec.rb +1 -3
  129. data/spec/models/spree/order_cancellations_spec.rb +6 -4
  130. data/spec/models/spree/order_contents_spec.rb +34 -50
  131. data/spec/models/spree/order_inventory_spec.rb +3 -5
  132. data/spec/models/spree/order_merger_spec.rb +20 -0
  133. data/spec/models/spree/order_spec.rb +28 -64
  134. data/spec/models/spree/order_update_attributes_spec.rb +1 -5
  135. data/spec/models/spree/order_updater_spec.rb +251 -0
  136. data/spec/models/spree/payment_method_spec.rb +178 -28
  137. data/spec/models/spree/payment_spec.rb +35 -19
  138. data/spec/models/spree/permission_sets/configuration_display.rb +0 -4
  139. data/spec/models/spree/permission_sets/configuration_management_spec.rb +0 -2
  140. data/spec/models/spree/permission_sets/product_display_spec.rb +0 -4
  141. data/spec/models/spree/permission_sets/product_management_spec.rb +0 -2
  142. data/spec/models/spree/permission_sets/user_management_spec.rb +9 -2
  143. data/spec/models/spree/price_spec.rb +16 -1
  144. data/spec/models/spree/product_spec.rb +0 -75
  145. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +20 -0
  146. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +39 -15
  147. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +203 -22
  148. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +22 -3
  149. data/spec/models/spree/promotion/rules/taxon_spec.rb +26 -0
  150. data/spec/models/spree/promotion/rules/user_role_spec.rb +86 -0
  151. data/spec/models/spree/promotion_action_spec.rb +38 -0
  152. data/spec/models/spree/promotion_handler/coupon_spec.rb +36 -33
  153. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +21 -22
  154. data/spec/models/spree/promotion_spec.rb +46 -6
  155. data/spec/models/spree/reimbursement_spec.rb +1 -1
  156. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +2 -2
  157. data/spec/models/spree/shipment_spec.rb +68 -50
  158. data/spec/models/spree/shipping_method_spec.rb +41 -0
  159. data/spec/models/spree/shipping_rate_spec.rb +9 -3
  160. data/spec/models/spree/stock/estimator_spec.rb +4 -2
  161. data/spec/models/spree/store_credit_spec.rb +3 -3
  162. data/spec/models/spree/tax/item_adjuster_spec.rb +31 -21
  163. data/spec/models/spree/tax/order_adjuster_spec.rb +6 -10
  164. data/spec/models/spree/tax/taxation_integration_spec.rb +19 -0
  165. data/spec/models/spree/tax_rate_spec.rb +5 -26
  166. data/spec/models/spree/transfer_item_spec.rb +11 -0
  167. data/spec/models/spree/variant/pricing_options_spec.rb +7 -17
  168. data/spec/models/spree/variant_spec.rb +2 -4
  169. data/spec/models/spree/zone_spec.rb +60 -20
  170. data/spec/shared_examples/calculator_shared_examples.rb +8 -0
  171. metadata +19 -24
  172. data/app/models/spree/item_adjustments.rb +0 -89
  173. data/app/models/spree/option_type_prototype.rb +0 -6
  174. data/app/models/spree/property_prototype.rb +0 -6
  175. data/app/models/spree/prototype.rb +0 -14
  176. data/app/models/spree/prototype_taxon.rb +0 -6
  177. data/app/models/spree/tracker.rb +0 -8
  178. data/db/migrate/20150128032538_remove_environment_from_tracker.rb +0 -6
  179. data/lib/generators/spree/dummy/templates/initializers/custom_user.rb +0 -1
  180. data/lib/spree/core/delegate_belongs_to.rb +0 -94
  181. data/lib/spree/testing_support/factories/prototype_factory.rb +0 -8
  182. data/lib/spree/testing_support/factories/tracker_factory.rb +0 -6
  183. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +0 -24
  184. data/spec/lib/spree/core/testing_support/factories/prototype_factory_spec.rb +0 -12
  185. data/spec/lib/spree/core/testing_support/factories/tracker_factory_spec.rb +0 -12
  186. data/spec/models/spree/item_adjustments_spec.rb +0 -306
  187. data/spec/models/spree/tracker_spec.rb +0 -21
@@ -1,89 +0,0 @@
1
- module Spree
2
- # Manage (recalculate) item (LineItem or Shipment) adjustments
3
- class ItemAdjustments
4
- attr_reader :item
5
-
6
- # @param item [Order, LineItem, Shipment] the item whose adjustments should be updated
7
- def initialize(item)
8
- @item = item
9
- end
10
-
11
- # Update the item's adjustments and totals
12
- #
13
- # If the item is an {Order}, this will update and select the best
14
- # promotion adjustment.
15
- #
16
- # If it is a {LineItem} or {Shipment}, it will update and select the best
17
- # promotion adjustment, update tax adjustments, update cancellation
18
- # adjustments, and then update the total fields (promo_total,
19
- # included_tax_total, additional_tax_total, and adjustment_total) on the
20
- # item.
21
- #
22
- # This is a noop if the item is not persisted.
23
- def update
24
- return @item unless item.persisted?
25
-
26
- # Promotion adjustments must be applied first, then tax adjustments.
27
- # This fits the criteria for VAT tax as outlined here:
28
- # http://www.hmrc.gov.uk/vat/managing/charging/discounts-etc.htm#1
29
- #
30
- # It also fits the criteria for sales tax as outlined here:
31
- # http://www.boe.ca.gov/formspubs/pub113/
32
- #
33
- # Tax adjustments come in not one but *two* exciting flavours:
34
- # Included & additional
35
-
36
- # Included tax adjustments are those which are included in the price.
37
- # These ones should not affect the eventual total price.
38
- #
39
- # Additional tax adjustments are the opposite, affecting the final total.
40
-
41
- promotion_adjustments = adjustments.select(&:promotion?)
42
- promotion_adjustments.each(&:update!)
43
-
44
- promo_total = Spree::Config.promotion_chooser_class.new(promotion_adjustments).update
45
-
46
- # Calculating the totals for the order here would be incorrect. Order's
47
- # totals are the sum of the adjustments on all child models, as well as
48
- # its own.
49
- #
50
- # We want to select the best promotion for the order, but the remainder
51
- # of the calculations here are done in the OrderUpdater instead.
52
- return if item.is_a?(Spree::Order)
53
-
54
- @item.promo_total = promo_total
55
-
56
- tax = adjustments.select(&:tax?)
57
-
58
- @item.included_tax_total = tax.select(&:included?).map(&:update!).compact.sum
59
- @item.additional_tax_total = tax.reject(&:included?).map(&:update!).compact.sum
60
-
61
- item_cancellation_total = adjustments.select(&:cancellation?).map(&:update!).compact.sum
62
-
63
- @item.adjustment_total = @item.promo_total + @item.additional_tax_total + item_cancellation_total
64
-
65
- @item.update_columns(
66
- promo_total: @item.promo_total,
67
- included_tax_total: @item.included_tax_total,
68
- additional_tax_total: @item.additional_tax_total,
69
- adjustment_total: @item.adjustment_total,
70
- updated_at: Time.current
71
- ) if @item.changed?
72
-
73
- # In rails 4.2 update_columns isn't reflected in the changed_attributes hash,
74
- # which means that multiple updates on the same in-memory model will
75
- # behave incorrectly.
76
- # In rails 5.0 changed_attributes works with update_columns and this is
77
- # unnecessary.
78
- item.attributes_changed_by_setter.except!(:promo_total, :included_tax_total, :additional_tax_total, :adjustment_total)
79
-
80
- @item
81
- end
82
-
83
- private
84
-
85
- def adjustments
86
- @adjustments ||= item.adjustments.to_a
87
- end
88
- end
89
- end
@@ -1,6 +0,0 @@
1
- module Spree
2
- class OptionTypePrototype < Spree::Base
3
- belongs_to :option_type
4
- belongs_to :prototype
5
- end
6
- end
@@ -1,6 +0,0 @@
1
- module Spree
2
- class PropertyPrototype < Spree::Base
3
- belongs_to :prototype
4
- belongs_to :property
5
- end
6
- end
@@ -1,14 +0,0 @@
1
- module Spree
2
- class Prototype < Spree::Base
3
- has_many :property_prototypes
4
- has_many :properties, through: :property_prototypes
5
-
6
- has_many :option_type_prototypes
7
- has_many :option_types, through: :option_type_prototypes
8
-
9
- has_many :prototype_taxons, dependent: :destroy
10
- has_many :taxons, through: :prototype_taxons
11
-
12
- validates :name, presence: true
13
- end
14
- end
@@ -1,6 +0,0 @@
1
- module Spree
2
- class PrototypeTaxon < Spree::Base
3
- belongs_to :prototype
4
- belongs_to :taxon
5
- end
6
- end
@@ -1,8 +0,0 @@
1
- module Spree
2
- class Tracker < Spree::Base
3
- def self.current
4
- tracker = where(active: true).first
5
- tracker.analytics_id.present? ? tracker : nil if tracker
6
- end
7
- end
8
- end
@@ -1,6 +0,0 @@
1
- class RemoveEnvironmentFromTracker < ActiveRecord::Migration[4.2]
2
- def up
3
- Spree::Tracker.where('environment != ?', Rails.env).update_all(active: false)
4
- remove_column :spree_trackers, :environment
5
- end
6
- end
@@ -1 +0,0 @@
1
- # Spree.user_class = "User"
@@ -1,94 +0,0 @@
1
- ##
2
- # Creates methods on object which delegate to an association proxy.
3
- # see delegate_belongs_to for two uses
4
- #
5
- # Todo - integrate with ActiveRecord::Dirty to make sure changes to delegate object are noticed
6
- # Should do
7
- # class User < Spree::Base; delegate_belongs_to :contact, :firstname; end
8
- # class Contact < Spree::Base; end
9
- # u = User.first
10
- # u.changed? # => false
11
- # u.firstname = 'Bobby'
12
- # u.changed? # => true
13
- #
14
- # Right now the second call to changed? would return false
15
- #
16
- # Todo - add has_one support. fairly straightforward addition
17
- ##
18
- module DelegateBelongsTo
19
- extend ActiveSupport::Concern
20
-
21
- module ClassMethods
22
- @@default_rejected_delegate_columns = ['created_at', 'created_on', 'updated_at', 'updated_on', 'lock_version', 'type', 'id', 'position', 'parent_id', 'lft', 'rgt']
23
- mattr_accessor :default_rejected_delegate_columns
24
-
25
- ##
26
- # Creates methods for accessing and setting attributes on an association. Uses same
27
- # default list of attributes as delegates_to_association.
28
- # @todo Integrate this with ActiveRecord::Dirty, so if you set a property through one of these setters and then call save on this object, it will save the associated object automatically.
29
- # delegate_belongs_to :contact
30
- # delegate_belongs_to :contact, [:defaults] ## same as above, and useless
31
- # delegate_belongs_to :contact, [:defaults, :address, :fullname], :class_name => 'VCard'
32
- ##
33
- def delegate_belongs_to(association, *attrs)
34
- Spree::Deprecation.warn "delegate_belongs_to is deprecated. Instead use rails built in delegates.", caller
35
- opts = attrs.extract_options!
36
- initialize_association :belongs_to, association, opts
37
- attrs = get_association_column_names(association) if attrs.empty?
38
- attrs.concat get_association_column_names(association) if attrs.delete :defaults
39
- attrs.each do |attr|
40
- class_def attr do |*args|
41
- send(:delegator_for, association, attr, *args)
42
- end
43
-
44
- class_def "#{attr}=" do |val|
45
- send(:delegator_for_setter, association, attr, val)
46
- end
47
- end
48
- end
49
-
50
- protected
51
-
52
- def get_association_column_names(association, without_default_rejected_delegate_columns = true)
53
- association_klass = reflect_on_association(association).klass
54
- methods = association_klass.column_names
55
- methods.reject!{ |x| default_rejected_delegate_columns.include?(x.to_s) } if without_default_rejected_delegate_columns
56
- return methods
57
- rescue
58
- return []
59
- end
60
-
61
- ##
62
- # initialize_association :belongs_to, :contact
63
- def initialize_association(type, association, opts = {})
64
- raise 'Illegal or unimplemented association type.' unless [:belongs_to].include?(type.to_s.to_sym)
65
- send type, association, opts if reflect_on_association(association).nil?
66
- end
67
-
68
- private
69
-
70
- def class_def(name, method = nil, &blk)
71
- class_eval { method.nil? ? define_method(name, &blk) : define_method(name, method) }
72
- end
73
- end
74
-
75
- def delegator_for(association, attr, *args)
76
- return if self.class.column_names.include?(attr.to_s)
77
- send("#{association}=", self.class.reflect_on_association(association).klass.new) if send(association).nil?
78
- if args.empty?
79
- send(association).send(attr)
80
- else
81
- send(association).send(attr, *args)
82
- end
83
- end
84
-
85
- def delegator_for_setter(association, attr, val)
86
- return if self.class.column_names.include?(attr.to_s)
87
- send("#{association}=", self.class.reflect_on_association(association).klass.new) if send(association).nil?
88
- send(association).send("#{attr}=", val)
89
- end
90
- protected :delegator_for
91
- protected :delegator_for_setter
92
- end
93
-
94
- ActiveRecord::Base.send :include, DelegateBelongsTo
@@ -1,8 +0,0 @@
1
- require 'spree/testing_support/factories/property_factory'
2
-
3
- FactoryGirl.define do
4
- factory :prototype, class: Spree::Prototype do
5
- name 'Baseball Cap'
6
- properties { [create(:property)] }
7
- end
8
- end
@@ -1,6 +0,0 @@
1
- FactoryGirl.define do
2
- factory :tracker, class: Spree::Tracker do
3
- analytics_id 'A100'
4
- active true
5
- end
6
- end
@@ -1,24 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # This is a bit of a insane spec I have to admit
4
- # Chosed the spree_payment_methods table because it has a `name` column
5
- # already. Stubs wouldn't work here (the delegation runs before this spec is
6
- # loaded) and adding a column here might make the test even crazy so here we go
7
- module Spree
8
- class DelegateBelongsToStubModel < Spree::Base
9
- self.table_name = "spree_payment_methods"
10
- belongs_to :product
11
- Spree::Deprecation.silence do
12
- delegate_belongs_to :product, :name
13
- end
14
- end
15
-
16
- describe DelegateBelongsToStubModel do
17
- context "model has column attr delegated to associated object" do
18
- it "doesnt touch the associated object" do
19
- expect(subject).not_to receive(:product)
20
- subject.name
21
- end
22
- end
23
- end
24
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
- require 'spree/testing_support/factories/prototype_factory'
3
-
4
- RSpec.describe 'prototype factory' do
5
- let(:factory_class) { Spree::Prototype }
6
-
7
- describe 'plain prototype' do
8
- let(:factory) { :prototype }
9
-
10
- it_behaves_like 'a working factory'
11
- end
12
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
- require 'spree/testing_support/factories/tracker_factory'
3
-
4
- RSpec.describe 'tracker factory' do
5
- let(:factory_class) { Spree::Tracker }
6
-
7
- describe 'tracker' do
8
- let(:factory) { :tracker }
9
-
10
- it_behaves_like 'a working factory'
11
- end
12
- end
@@ -1,306 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Spree
4
- describe ItemAdjustments, type: :model do
5
- let(:order) { create :order_with_line_items, line_items_count: 1 }
6
- let(:line_item) { order.line_items.first }
7
-
8
- let(:subject) { ItemAdjustments.new(line_item) }
9
-
10
- context '#update' do
11
- it "updates a linked adjustment" do
12
- tax_rate = create(:tax_rate, amount: 0.05)
13
- create(:adjustment, order: order, source: tax_rate, adjustable: line_item)
14
- line_item.price = 10
15
- line_item.tax_category = tax_rate.tax_category
16
-
17
- subject.update
18
- expect(line_item.adjustment_total).to eq(0.5)
19
- expect(line_item.additional_tax_total).to eq(0.5)
20
- end
21
- end
22
-
23
- context "taxes and promotions" do
24
- let!(:tax_rate) do
25
- create(:tax_rate, amount: 0.05)
26
- end
27
-
28
- let!(:promotion) do
29
- Spree::Promotion.create(name: "$10 off")
30
- end
31
-
32
- let!(:promotion_action) do
33
- calculator = Calculator::FlatRate.new(preferred_amount: 10)
34
- Promotion::Actions::CreateItemAdjustments.create calculator: calculator, promotion: promotion
35
- end
36
-
37
- before do
38
- line_item.price = 20
39
- line_item.tax_category = tax_rate.tax_category
40
- line_item.save
41
- create(:adjustment, order: order, source: promotion_action, adjustable: line_item)
42
- end
43
-
44
- context "tax included in price" do
45
- before do
46
- create(:adjustment,
47
- source: tax_rate,
48
- adjustable: line_item,
49
- order: order,
50
- included: true
51
- )
52
- end
53
-
54
- it "tax has no bearing on final price" do
55
- subject.update
56
- line_item.reload
57
- expect(line_item.included_tax_total).to eq(0.5)
58
- expect(line_item.additional_tax_total).to eq(0)
59
- expect(line_item.promo_total).to eq(-10)
60
- expect(line_item.adjustment_total).to eq(-10)
61
- end
62
-
63
- it "tax linked to order" do
64
- order.update!
65
- order.reload
66
- expect(order.included_tax_total).to eq(0.5)
67
- expect(order.additional_tax_total).to eq(00)
68
- end
69
- end
70
-
71
- context "tax excluded from price" do
72
- before do
73
- create(:adjustment,
74
- source: tax_rate,
75
- adjustable: line_item,
76
- order: order,
77
- included: false
78
- )
79
- end
80
-
81
- it "tax applies to line item" do
82
- subject.update
83
- line_item.reload
84
- # Taxable amount is: $20 (base) - $10 (promotion) = $10
85
- # Tax rate is 5% (of $10).
86
- expect(line_item.included_tax_total).to eq(0)
87
- expect(line_item.additional_tax_total).to eq(0.5)
88
- expect(line_item.promo_total).to eq(-10)
89
- expect(line_item.adjustment_total).to eq(-9.5)
90
- end
91
-
92
- it "tax linked to order" do
93
- order.update!
94
- expect(order.included_tax_total).to eq(0)
95
- expect(order.additional_tax_total).to eq(0.5)
96
- end
97
- end
98
- end
99
-
100
- context "promotion chooser customization" do
101
- before do
102
- class Spree::TestPromotionChooser
103
- def initialize(_adjustments)
104
- raise "Custom promotion chooser"
105
- end
106
- end
107
-
108
- Spree::Config.promotion_chooser_class = Spree::TestPromotionChooser
109
- end
110
-
111
- it "uses the defined promotion chooser" do
112
- expect { subject.update }.to raise_error("Custom promotion chooser")
113
- end
114
- end
115
-
116
- context "default promotion chooser (best promotion is always applied)" do
117
- let(:calculator) { Calculator::FlatRate.new(preferred_amount: 10) }
118
-
119
- let(:source) do
120
- Promotion::Actions::CreateItemAdjustments.create!(
121
- calculator: calculator,
122
- promotion: promotion
123
- )
124
- end
125
- let(:promotion) { create(:promotion) }
126
-
127
- def create_adjustment(label, amount)
128
- create(:adjustment, order: order,
129
- adjustable: line_item,
130
- source: source,
131
- amount: amount,
132
- finalized: true,
133
- label: label)
134
- end
135
-
136
- it "should make all but the most valuable promotion adjustment ineligible, leaving non promotion adjustments alone" do
137
- create_adjustment("Promotion A", -100)
138
- create_adjustment("Promotion B", -200)
139
- create_adjustment("Promotion C", -300)
140
- create(:adjustment, order: order,
141
- adjustable: line_item,
142
- source: nil,
143
- amount: -500,
144
- finalized: true,
145
- label: "Some other credit")
146
- line_item.adjustments.each { |a| a.update_column(:eligible, true) }
147
-
148
- subject.update
149
-
150
- expect(line_item.adjustments.promotion.eligible.count).to eq(1)
151
- expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion C')
152
- end
153
-
154
- it "should choose the most recent promotion adjustment when amounts are equal" do
155
- # Using Timecop is a regression test
156
- Timecop.freeze do
157
- create_adjustment("Promotion A", -200)
158
- create_adjustment("Promotion B", -200)
159
- end
160
- line_item.adjustments.each { |a| a.update_column(:eligible, true) }
161
-
162
- subject.update
163
-
164
- expect(line_item.adjustments.promotion.eligible.count).to eq(1)
165
- expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion B')
166
- end
167
-
168
- it "should choose the most recent promotion adjustment when amounts are equal" do
169
- # Using Timecop is a regression test
170
- Timecop.freeze do
171
- create_adjustment("Promotion A", -200)
172
- create_adjustment("Promotion B", -200)
173
- end
174
- line_item.adjustments.each { |a| a.update_column(:eligible, true) }
175
-
176
- subject.update
177
-
178
- expect(line_item.adjustments.promotion.eligible.count).to eq(1)
179
- expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion B')
180
- end
181
-
182
- context "when previously ineligible promotions become available" do
183
- let(:order_promo1) { create(:promotion, :with_order_adjustment, :with_item_total_rule, weighted_order_adjustment_amount: 5, item_total_threshold_amount: 10) }
184
- let(:order_promo2) { create(:promotion, :with_order_adjustment, :with_item_total_rule, weighted_order_adjustment_amount: 10, item_total_threshold_amount: 20) }
185
- let(:order_promos) { [order_promo1, order_promo2] }
186
- let(:line_item_promo1) { create(:promotion, :with_line_item_adjustment, :with_item_total_rule, adjustment_rate: 2.5, item_total_threshold_amount: 10, apply_automatically: true) }
187
- let(:line_item_promo2) { create(:promotion, :with_line_item_adjustment, :with_item_total_rule, adjustment_rate: 5, item_total_threshold_amount: 20, apply_automatically: true) }
188
- let(:line_item_promos) { [line_item_promo1, line_item_promo2] }
189
- let(:order) { create(:order_with_line_items, line_items_count: 1) }
190
-
191
- # Apply promotions in different sequences. Results should be the same.
192
- promo_sequences = [
193
- [0, 1],
194
- [1, 0]
195
- ]
196
-
197
- promo_sequences.each do |promo_sequence|
198
- it "should pick the best order-level promo according to current eligibility" do
199
- # apply both promos to the order, even though only promo1 is eligible
200
- order_promos[promo_sequence[0]].activate order: order
201
- order_promos[promo_sequence[1]].activate order: order
202
-
203
- order.update!
204
- order.reload
205
- expect(order.all_adjustments.count).to eq(2), "Expected two adjustments (using sequence #{promo_sequence})"
206
- expect(order.all_adjustments.eligible.count).to eq(1), "Expected one elegible adjustment (using sequence #{promo_sequence})"
207
- expect(order.all_adjustments.eligible.first.source.promotion).to eq(order_promo1), "Expected promo1 to be used (using sequence #{promo_sequence})"
208
-
209
- order.contents.add create(:variant, price: 10), 1
210
- order.save
211
-
212
- order.reload
213
- expect(order.all_adjustments.count).to eq(2), "Expected two adjustments (using sequence #{promo_sequence})"
214
- expect(order.all_adjustments.eligible.count).to eq(1), "Expected one elegible adjustment (using sequence #{promo_sequence})"
215
- expect(order.all_adjustments.eligible.first.source.promotion).to eq(order_promo2), "Expected promo2 to be used (using sequence #{promo_sequence})"
216
- end
217
- end
218
-
219
- promo_sequences.each do |promo_sequence|
220
- it "should pick the best line-item-level promo according to current eligibility" do
221
- # apply both promos to the order, even though only promo1 is eligible
222
- line_item_promos[promo_sequence[0]].activate order: order
223
- line_item_promos[promo_sequence[1]].activate order: order
224
-
225
- order.reload
226
- expect(order.all_adjustments.count).to eq(1), "Expected one adjustment (using sequence #{promo_sequence})"
227
- expect(order.all_adjustments.eligible.count).to eq(1), "Expected one elegible adjustment (using sequence #{promo_sequence})"
228
- # line_item_promo1 is the only one that has thus far met the order total threshold, it is the only promo which should be applied.
229
- expect(order.all_adjustments.first.source.promotion).to eq(line_item_promo1), "Expected line_item_promo1 to be used (using sequence #{promo_sequence})"
230
-
231
- order.contents.add create(:variant, price: 10), 1
232
- order.save
233
-
234
- order.reload
235
- expect(order.all_adjustments.count).to eq(4), "Expected four adjustments (using sequence #{promo_sequence})"
236
- expect(order.all_adjustments.eligible.count).to eq(2), "Expected two elegible adjustments (using sequence #{promo_sequence})"
237
- order.all_adjustments.eligible.each do |adjustment|
238
- expect(adjustment.source.promotion).to eq(line_item_promo2), "Expected line_item_promo2 to be used (using sequence #{promo_sequence})"
239
- end
240
- end
241
- end
242
- end
243
-
244
- context "multiple adjustments and the best one is not eligible" do
245
- let!(:promo_a) { create_adjustment("Promotion A", -100) }
246
- let!(:promo_c) { create_adjustment("Promotion C", -300) }
247
-
248
- before do
249
- promo_a.update_column(:eligible, true)
250
- promo_c.update_column(:eligible, false)
251
- end
252
-
253
- # regression for https://github.com/spree/spree/issues/3274
254
- it "still makes the previous best eligible adjustment valid" do
255
- subject.update
256
- expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion A')
257
- end
258
- end
259
-
260
- it "should only leave one adjustment even if 2 have the same amount" do
261
- create_adjustment("Promotion A", -100)
262
- create_adjustment("Promotion B", -200)
263
- create_adjustment("Promotion C", -200)
264
-
265
- subject.update
266
-
267
- expect(line_item.adjustments.promotion.eligible.count).to eq(1)
268
- expect(line_item.adjustments.promotion.eligible.first.amount.to_i).to eq(-200)
269
- end
270
- end
271
-
272
- context "multiple updates" do
273
- let(:adjustment) { create(:tax_adjustment, amount: -10) }
274
- let(:item) { adjustment.adjustable }
275
- # we need to get this from the line item so that we're modifying the same
276
- # tax rate that is cached by line_item.adjustments
277
- let(:source) { item.adjustments.to_a.first.source }
278
-
279
- def update
280
- described_class.new(item).update
281
- end
282
-
283
- # "fresh" record from the DB
284
- def db_record
285
- Spree::LineItem.find(item.id)
286
- end
287
-
288
- it "persists each change" do
289
- source.update_attributes!(amount: 0.1)
290
- update
291
- expect(item).not_to be_changed
292
- expect(db_record).to have_attributes(adjustment_total: 1)
293
-
294
- source.update_attributes!(amount: 0.20)
295
- update
296
- expect(item).not_to be_changed
297
- expect(db_record).to have_attributes(adjustment_total: 2)
298
-
299
- source.update_attributes!(amount: 0.10)
300
- update
301
- expect(item).not_to be_changed
302
- expect(db_record).to have_attributes(adjustment_total: 1)
303
- end
304
- end
305
- end
306
- end