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.
- checksums.yaml +4 -4
- data/README.md +62 -3
- data/app/assets/javascripts/spree.js.coffee.erb +4 -1
- data/app/helpers/spree/base_helper.rb +7 -48
- data/app/models/spree/address.rb +5 -1
- data/app/models/spree/adjustment.rb +3 -3
- data/app/models/spree/app_configuration.rb +13 -0
- data/app/models/spree/calculator.rb +3 -2
- data/app/models/spree/calculator/default_tax.rb +6 -10
- data/app/models/spree/calculator/flat_percent_item_total.rb +0 -4
- data/app/models/spree/calculator/flat_rate.rb +0 -4
- data/app/models/spree/calculator/flexi_rate.rb +0 -4
- data/app/models/spree/calculator/free_shipping.rb +0 -3
- data/app/models/spree/calculator/percent_on_line_item.rb +0 -4
- data/app/models/spree/calculator/percent_per_item.rb +0 -4
- data/app/models/spree/calculator/price_sack.rb +0 -4
- data/app/models/spree/calculator/returns/default_refund_amount.rb +0 -3
- data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +0 -4
- data/app/models/spree/calculator/shipping/flat_rate.rb +0 -4
- data/app/models/spree/calculator/shipping/flexi_rate.rb +0 -4
- data/app/models/spree/calculator/shipping/per_item.rb +0 -4
- data/app/models/spree/calculator/shipping/price_sack.rb +0 -4
- data/app/models/spree/calculator/tiered_flat_rate.rb +0 -4
- data/app/models/spree/calculator/tiered_percent.rb +0 -4
- data/app/models/spree/credit_card.rb +27 -14
- data/app/models/spree/gateway.rb +4 -0
- data/app/models/spree/inventory_unit.rb +2 -0
- data/app/models/spree/line_item.rb +31 -26
- data/app/models/spree/option_type.rb +0 -3
- data/app/models/spree/order.rb +28 -31
- data/app/models/spree/order/checkout.rb +0 -2
- data/app/models/spree/order_contents.rb +0 -45
- data/app/models/spree/order_merger.rb +6 -6
- data/app/models/spree/order_update_attributes.rb +0 -2
- data/app/models/spree/order_updater.rb +91 -13
- data/app/models/spree/payment.rb +9 -2
- data/app/models/spree/payment/processing.rb +15 -9
- data/app/models/spree/payment_method.rb +48 -5
- data/app/models/spree/price.rb +7 -9
- data/app/models/spree/product.rb +1 -25
- data/app/models/spree/promotion.rb +22 -14
- data/app/models/spree/promotion/actions/create_adjustment.rb +12 -1
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -1
- data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +5 -3
- data/app/models/spree/promotion/actions/free_shipping.rb +14 -0
- data/app/models/spree/promotion/rules/taxon.rb +7 -2
- data/app/models/spree/promotion/rules/user_role.rb +43 -0
- data/app/models/spree/promotion_action.rb +19 -2
- data/app/models/spree/promotion_handler/coupon.rb +1 -4
- data/app/models/spree/promotion_handler/free_shipping.rb +22 -17
- data/app/models/spree/promotion_rule_role.rb +6 -0
- data/app/models/spree/property.rb +0 -3
- data/app/models/spree/return_authorization.rb +2 -0
- data/app/models/spree/shipment.rb +5 -21
- data/app/models/spree/shipping_method.rb +23 -2
- data/app/models/spree/shipping_rate.rb +3 -0
- data/app/models/spree/stock/estimator.rb +1 -1
- data/app/models/spree/stock_location.rb +3 -0
- data/app/models/spree/store.rb +7 -0
- data/app/models/spree/tax/item_adjuster.rb +27 -12
- data/app/models/spree/tax/order_adjuster.rb +2 -5
- data/app/models/spree/tax/tax_helpers.rb +4 -8
- data/app/models/spree/tax_rate.rb +1 -15
- data/app/models/spree/taxon.rb +0 -3
- data/app/models/spree/transfer_item.rb +1 -1
- data/app/models/spree/user_class_handle.rb +14 -9
- data/app/models/spree/variant/pricing_options.rb +1 -1
- data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +1 -1
- data/app/models/spree/zone.rb +20 -13
- data/config/locales/en.yml +144 -62
- data/db/migrate/20120831092320_spree_one_two.rb +0 -7
- data/db/migrate/20150723224133_remove_unnecessary_indexes.rb +0 -2
- data/db/migrate/20160924135758_remove_is_default_from_prices.rb +5 -0
- data/db/migrate/20161009141333_remove_currency_from_line_items.rb +5 -0
- data/db/migrate/20161014221052_add_available_to_columns_and_remove_display_on_from_payment_methods.rb +28 -0
- data/db/migrate/20161123154034_add_available_to_users_and_remove_display_on_from_shipping_methods.rb +20 -0
- data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +4 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +0 -2
- data/lib/spree/core.rb +0 -5
- data/lib/spree/core/controller_helpers/pricing.rb +2 -1
- data/lib/spree/core/engine.rb +14 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/deprecation.rb +1 -1
- data/lib/spree/localized_number.rb +3 -2
- data/lib/spree/permission_sets/configuration_display.rb +0 -1
- data/lib/spree/permission_sets/configuration_management.rb +0 -1
- data/lib/spree/permission_sets/product_display.rb +0 -1
- data/lib/spree/permission_sets/product_management.rb +0 -1
- data/lib/spree/permission_sets/user_management.rb +2 -4
- data/lib/spree/permitted_attributes.rb +3 -2
- data/lib/spree/testing_support/capybara_ext.rb +0 -12
- data/lib/spree/testing_support/factories/address_factory.rb +1 -1
- data/lib/spree/testing_support/factories/line_item_factory.rb +0 -1
- data/lib/spree/testing_support/factories/payment_factory.rb +4 -0
- data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -1
- data/lib/spree/testing_support/factories/user_factory.rb +2 -2
- data/solidus_core.gemspec +4 -3
- data/spec/helpers/base_helper_spec.rb +0 -40
- data/spec/lib/spree/core/controller_helpers/pricing_spec.rb +16 -0
- data/spec/lib/spree/core/importer/order_spec.rb +27 -18
- data/spec/lib/spree/core/price_migrator_spec.rb +3 -1
- data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +16 -0
- data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -2
- data/spec/lib/tasks/exchanges_spec.rb +4 -2
- data/spec/lib/tasks/migrations/create_vat_prices_spec.rb +5 -3
- data/spec/models/spree/adjustment_spec.rb +136 -0
- data/spec/models/spree/calculator/default_tax_spec.rb +13 -7
- data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +3 -0
- data/spec/models/spree/calculator/flat_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/flexi_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/free_shipping_spec.rb +6 -0
- data/spec/models/spree/calculator/percent_on_line_item_spec.rb +9 -4
- data/spec/models/spree/calculator/percent_per_item_spec.rb +10 -0
- data/spec/models/spree/calculator/price_sack_spec.rb +3 -0
- data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/per_item_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/price_sack_spec.rb +4 -1
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/tiered_percent_spec.rb +3 -0
- data/spec/models/spree/credit_card_spec.rb +27 -1
- data/spec/models/spree/line_item_spec.rb +58 -65
- data/spec/models/spree/order/checkout_spec.rb +2 -1
- data/spec/models/spree/order/payment_spec.rb +9 -10
- data/spec/models/spree/order/tax_spec.rb +22 -7
- data/spec/models/spree/order/updating_spec.rb +1 -3
- data/spec/models/spree/order_cancellations_spec.rb +6 -4
- data/spec/models/spree/order_contents_spec.rb +34 -50
- data/spec/models/spree/order_inventory_spec.rb +3 -5
- data/spec/models/spree/order_merger_spec.rb +20 -0
- data/spec/models/spree/order_spec.rb +28 -64
- data/spec/models/spree/order_update_attributes_spec.rb +1 -5
- data/spec/models/spree/order_updater_spec.rb +251 -0
- data/spec/models/spree/payment_method_spec.rb +178 -28
- data/spec/models/spree/payment_spec.rb +35 -19
- data/spec/models/spree/permission_sets/configuration_display.rb +0 -4
- data/spec/models/spree/permission_sets/configuration_management_spec.rb +0 -2
- data/spec/models/spree/permission_sets/product_display_spec.rb +0 -4
- data/spec/models/spree/permission_sets/product_management_spec.rb +0 -2
- data/spec/models/spree/permission_sets/user_management_spec.rb +9 -2
- data/spec/models/spree/price_spec.rb +16 -1
- data/spec/models/spree/product_spec.rb +0 -75
- data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +20 -0
- data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +39 -15
- data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +203 -22
- data/spec/models/spree/promotion/actions/free_shipping_spec.rb +22 -3
- data/spec/models/spree/promotion/rules/taxon_spec.rb +26 -0
- data/spec/models/spree/promotion/rules/user_role_spec.rb +86 -0
- data/spec/models/spree/promotion_action_spec.rb +38 -0
- data/spec/models/spree/promotion_handler/coupon_spec.rb +36 -33
- data/spec/models/spree/promotion_handler/free_shipping_spec.rb +21 -22
- data/spec/models/spree/promotion_spec.rb +46 -6
- data/spec/models/spree/reimbursement_spec.rb +1 -1
- data/spec/models/spree/reimbursement_tax_calculator_spec.rb +2 -2
- data/spec/models/spree/shipment_spec.rb +68 -50
- data/spec/models/spree/shipping_method_spec.rb +41 -0
- data/spec/models/spree/shipping_rate_spec.rb +9 -3
- data/spec/models/spree/stock/estimator_spec.rb +4 -2
- data/spec/models/spree/store_credit_spec.rb +3 -3
- data/spec/models/spree/tax/item_adjuster_spec.rb +31 -21
- data/spec/models/spree/tax/order_adjuster_spec.rb +6 -10
- data/spec/models/spree/tax/taxation_integration_spec.rb +19 -0
- data/spec/models/spree/tax_rate_spec.rb +5 -26
- data/spec/models/spree/transfer_item_spec.rb +11 -0
- data/spec/models/spree/variant/pricing_options_spec.rb +7 -17
- data/spec/models/spree/variant_spec.rb +2 -4
- data/spec/models/spree/zone_spec.rb +60 -20
- data/spec/shared_examples/calculator_shared_examples.rb +8 -0
- metadata +19 -24
- data/app/models/spree/item_adjustments.rb +0 -89
- data/app/models/spree/option_type_prototype.rb +0 -6
- data/app/models/spree/property_prototype.rb +0 -6
- data/app/models/spree/prototype.rb +0 -14
- data/app/models/spree/prototype_taxon.rb +0 -6
- data/app/models/spree/tracker.rb +0 -8
- data/db/migrate/20150128032538_remove_environment_from_tracker.rb +0 -6
- data/lib/generators/spree/dummy/templates/initializers/custom_user.rb +0 -1
- data/lib/spree/core/delegate_belongs_to.rb +0 -94
- data/lib/spree/testing_support/factories/prototype_factory.rb +0 -8
- data/lib/spree/testing_support/factories/tracker_factory.rb +0 -6
- data/spec/lib/spree/core/delegate_belongs_to_spec.rb +0 -24
- data/spec/lib/spree/core/testing_support/factories/prototype_factory_spec.rb +0 -12
- data/spec/lib/spree/core/testing_support/factories/tracker_factory_spec.rb +0 -12
- data/spec/models/spree/item_adjustments_spec.rb +0 -306
- 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,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
|
data/app/models/spree/tracker.rb
DELETED
@@ -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,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
|