solidus_core 2.0.3 → 2.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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