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.
- 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
|