solidus_core 2.1.1 → 2.2.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/Rakefile +0 -1
- data/app/assets/config/solidus_core_manifest.js +1 -0
- data/app/assets/javascripts/spree.js.erb +72 -0
- data/app/helpers/spree/store_helper.rb +5 -0
- data/app/jobs/spree/promotion_code_batch_job.rb +24 -0
- data/app/mailers/spree/promotion_code_batch_mailer.rb +13 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +1 -1
- data/app/models/concerns/spree/ordered_property_value_list.rb +2 -2
- data/app/models/concerns/spree/user_address_book.rb +4 -4
- data/app/models/concerns/spree/user_methods.rb +7 -0
- data/app/models/concerns/spree/user_payment_source.rb +12 -5
- data/app/models/spree/address.rb +14 -3
- data/app/models/spree/adjustment.rb +13 -1
- data/app/models/spree/app_configuration.rb +0 -19
- data/app/models/spree/base.rb +2 -0
- data/app/models/spree/credit_card.rb +34 -43
- data/app/models/spree/gateway/bogus.rb +1 -1
- data/app/models/spree/gateway.rb +6 -4
- data/app/models/spree/inventory_unit.rb +3 -2
- data/app/models/spree/order/checkout.rb +187 -273
- data/app/models/spree/order.rb +137 -71
- data/app/models/spree/order_contents.rb +1 -1
- data/app/models/spree/order_inventory.rb +11 -11
- data/app/models/spree/order_promotion.rb +2 -0
- data/app/models/spree/order_update_attributes.rb +1 -8
- data/app/models/spree/order_updater.rb +67 -63
- data/app/models/spree/payment.rb +0 -1
- data/app/models/spree/payment_create.rb +27 -7
- data/app/models/spree/payment_method/store_credit.rb +3 -3
- data/app/models/spree/payment_method.rb +4 -1
- data/app/models/spree/payment_source.rb +45 -0
- data/app/models/spree/product/scopes.rb +24 -24
- data/app/models/spree/product.rb +4 -4
- data/app/models/spree/promotion.rb +2 -0
- data/app/models/spree/promotion_code/batch_builder.rb +63 -0
- data/app/models/spree/promotion_code.rb +1 -0
- data/app/models/spree/promotion_code_batch.rb +25 -0
- data/app/models/spree/promotion_handler/cart.rb +2 -2
- data/app/models/spree/promotion_handler/coupon.rb +1 -2
- data/app/models/spree/promotion_handler/free_shipping.rb +32 -21
- data/app/models/spree/promotion_handler/page.rb +1 -1
- data/app/models/spree/reimbursement.rb +1 -1
- data/app/models/spree/return_authorization.rb +0 -28
- data/app/models/spree/return_item.rb +1 -1
- data/app/models/spree/shipment.rb +4 -4
- data/app/models/spree/shipping_method.rb +2 -2
- data/app/models/spree/shipping_rate.rb +1 -1
- data/app/models/spree/stock/availability_validator.rb +16 -17
- data/app/models/spree/stock/coordinator.rb +3 -3
- data/app/models/spree/stock/package.rb +1 -1
- data/app/models/spree/stock/quantifier.rb +5 -4
- data/app/models/spree/stock_location.rb +2 -2
- data/app/models/spree/store.rb +2 -2
- data/app/models/spree/store_credit.rb +1 -1
- data/app/models/spree/tax/tax_helpers.rb +3 -3
- data/app/models/spree/tax_rate.rb +7 -1
- data/app/models/spree/taxonomy.rb +1 -1
- data/app/models/spree/variant/scopes.rb +5 -5
- data/app/models/spree/variant/vat_price_generator.rb +8 -5
- data/app/models/spree/variant.rb +1 -0
- data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +19 -10
- data/app/models/spree/wallet/default_payment_builder.rb +6 -6
- data/app/models/spree/wallet.rb +71 -0
- data/app/models/spree/wallet_payment_source.rb +17 -0
- data/app/models/spree/zone.rb +1 -1
- data/app/views/spree/carton_mailer/shipped_email.text.erb +1 -1
- data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
- data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
- data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -7
- data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -5
- data/app/views/spree/shared/_error_messages.html.erb +1 -1
- data/app/views/spree/shipment_mailer/shipped_email.html.erb +1 -1
- data/config/initializers/assets.rb +1 -1
- data/config/initializers/friendly_id.rb +1 -1
- data/config/locales/en.yml +50 -12
- data/db/default/spree/store_credit.rb +2 -1
- data/db/migrate/20130826062534_add_depth_to_spree_taxons.rb +4 -6
- data/db/migrate/20160420044191_create_spree_wallet_payment_sources.rb +23 -0
- data/db/migrate/20160420181916_migrate_credit_cards_to_wallet_payment_sources.rb +26 -0
- data/db/migrate/20161017102621_create_spree_promotion_code_batch.rb +36 -0
- data/db/migrate/20161129035810_add_index_to_spree_payments_number.rb +5 -0
- data/db/migrate/20170223235001_remove_spree_store_credits_column.rb +5 -0
- data/lib/generators/spree/dummy/templates/rails/application.rb +1 -1
- data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
- data/lib/generators/spree/install/install_generator.rb +6 -5
- data/lib/spree/core/controller_helpers/payment_parameters.rb +54 -0
- data/lib/spree/core/engine.rb +6 -9
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +0 -1
- data/lib/spree/money.rb +18 -0
- data/lib/spree/permission_sets/default_customer.rb +1 -1
- data/lib/spree/permitted_attributes.rb +1 -1
- data/lib/spree/testing_support/authorization_helpers.rb +1 -0
- data/lib/spree/testing_support/capybara_ext.rb +13 -0
- data/lib/spree/testing_support/factories/order_factory.rb +5 -1
- data/lib/spree/testing_support/factories/payment_factory.rb +1 -1
- data/lib/spree/testing_support/factories/shipment_factory.rb +0 -1
- data/solidus_core.gemspec +3 -3
- data/spec/jobs/promotion_code_batch_job_spec.rb +65 -0
- data/spec/lib/calculated_adjustments_spec.rb +105 -1
- data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +4 -1
- data/spec/lib/spree/core/testing_support/factories/payment_factory_spec.rb +8 -0
- data/spec/lib/spree/money_spec.rb +32 -0
- data/spec/lib/spree/permission_sets/default_customer_spec.rb +20 -0
- data/spec/mailers/promotion_code_batch_mailer_spec.rb +45 -0
- data/spec/models/spree/credit_card_spec.rb +86 -86
- data/spec/models/spree/gateway_spec.rb +3 -1
- data/spec/models/spree/inventory_unit_spec.rb +12 -4
- data/spec/models/spree/order/checkout_spec.rb +11 -32
- data/spec/models/spree/order/tax_spec.rb +2 -2
- data/spec/models/spree/order_contents_spec.rb +24 -1
- data/spec/models/spree/order_inventory_spec.rb +130 -83
- data/spec/models/spree/order_spec.rb +15 -117
- data/spec/models/spree/order_update_attributes_spec.rb +1 -44
- data/spec/models/spree/order_updater_spec.rb +10 -13
- data/spec/models/spree/payment_create_spec.rb +5 -1
- data/spec/models/spree/payment_method_spec.rb +16 -0
- data/spec/models/spree/payment_spec.rb +14 -8
- data/spec/models/spree/promotion_code/batch_builder_spec.rb +61 -0
- data/spec/models/spree/promotion_code_batch_spec.rb +58 -0
- data/spec/models/spree/promotion_code_spec.rb +4 -0
- data/spec/models/spree/promotion_spec.rb +3 -6
- data/spec/models/spree/return_authorization_spec.rb +0 -59
- data/spec/models/spree/shipment_spec.rb +4 -4
- data/spec/models/spree/stock/availability_validator_spec.rb +64 -9
- data/spec/models/spree/tax/item_adjuster_spec.rb +1 -2
- data/spec/models/spree/unit_cancel_spec.rb +0 -85
- data/spec/models/spree/user_spec.rb +3 -1
- data/spec/models/spree/variant/vat_price_generator_spec.rb +8 -2
- data/spec/models/spree/variant_spec.rb +16 -4
- data/spec/models/spree/wallet_payment_source_spec.rb +46 -0
- data/spec/models/spree/wallet_spec.rb +128 -0
- data/spec/support/concerns/payment_source.rb +64 -0
- metadata +51 -25
- data/app/assets/javascripts/spree.js.coffee.erb +0 -64
- data/app/models/spree/promotion_builder.rb +0 -55
- data/app/models/spree/promotion_code/code_builder.rb +0 -62
- data/config/initializers/premailer_assets.rb +0 -1
- data/lib/spree/core/unreturned_item_charger.rb +0 -106
- data/lib/tasks/exchanges.rake +0 -47
- data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -126
- data/spec/lib/tasks/exchanges_spec.rb +0 -220
- data/spec/models/spree/promotion_builder_spec.rb +0 -120
- data/spec/models/spree/promotion_code/code_builder_spec.rb +0 -77
data/app/models/spree/order.rb
CHANGED
|
@@ -2,11 +2,11 @@ require 'spree/core/validators/email'
|
|
|
2
2
|
require 'spree/order/checkout'
|
|
3
3
|
|
|
4
4
|
module Spree
|
|
5
|
-
# The customers cart until completed, then acts as
|
|
5
|
+
# The customers cart until completed, then acts as permanent record of the transaction.
|
|
6
6
|
#
|
|
7
7
|
# `Spree::Order` is the heart of the Solidus system, as it acts as the customer's
|
|
8
8
|
# cart as they shop. Once an order is complete, it serves as the
|
|
9
|
-
#
|
|
9
|
+
# permanent record of their purchase. It has many responsibilities:
|
|
10
10
|
#
|
|
11
11
|
# * Records and validates attributes like `total` and relationships like
|
|
12
12
|
# `Spree::LineItem` as an ActiveRecord model.
|
|
@@ -43,17 +43,20 @@ module Spree
|
|
|
43
43
|
go_to_state :confirm
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
self.whitelisted_ransackable_associations = %w[shipments user promotions bill_address ship_address line_items]
|
|
46
|
+
self.whitelisted_ransackable_associations = %w[shipments user order_promotions promotions bill_address ship_address line_items]
|
|
47
47
|
self.whitelisted_ransackable_attributes = %w[completed_at created_at email number state payment_state shipment_state total store_id]
|
|
48
48
|
|
|
49
49
|
attr_reader :coupon_code
|
|
50
|
-
attr_accessor :temporary_address
|
|
50
|
+
attr_accessor :temporary_address
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
attr_accessor :temporary_payment_source
|
|
53
|
+
alias_method :temporary_credit_card, :temporary_payment_source
|
|
54
|
+
alias_method :temporary_credit_card=, :temporary_payment_source=
|
|
55
|
+
deprecate temporary_credit_card: :temporary_payment_source, deprecator: Spree::Deprecation
|
|
56
|
+
deprecate :temporary_credit_card= => :temporary_payment_source=, deprecator: Spree::Deprecation
|
|
56
57
|
|
|
58
|
+
# Customer info
|
|
59
|
+
belongs_to :user, class_name: Spree::UserClassHandle.new
|
|
57
60
|
belongs_to :bill_address, foreign_key: :bill_address_id, class_name: 'Spree::Address'
|
|
58
61
|
alias_attribute :billing_address, :bill_address
|
|
59
62
|
|
|
@@ -62,36 +65,48 @@ module Spree
|
|
|
62
65
|
alias_attribute :ship_total, :shipment_total
|
|
63
66
|
|
|
64
67
|
belongs_to :store, class_name: 'Spree::Store'
|
|
65
|
-
|
|
68
|
+
|
|
69
|
+
# Items
|
|
66
70
|
has_many :line_items, -> { order(:created_at, :id) }, dependent: :destroy, inverse_of: :order
|
|
67
|
-
has_many :
|
|
68
|
-
has_many :
|
|
69
|
-
|
|
71
|
+
has_many :variants, through: :line_items
|
|
72
|
+
has_many :products, through: :variants
|
|
73
|
+
|
|
74
|
+
# Shipping
|
|
75
|
+
has_many :inventory_units, inverse_of: :order
|
|
76
|
+
has_many :cartons, -> { distinct }, through: :inventory_units
|
|
77
|
+
has_many :shipments, dependent: :destroy, inverse_of: :order do
|
|
78
|
+
def states
|
|
79
|
+
pluck(:state).uniq
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
has_many :order_stock_locations, class_name: "Spree::OrderStockLocation"
|
|
83
|
+
has_many :stock_locations, through: :order_stock_locations
|
|
84
|
+
|
|
85
|
+
# Adjustments and promotions
|
|
70
86
|
has_many :adjustments, -> { order(:created_at) }, as: :adjustable, inverse_of: :adjustable, dependent: :destroy
|
|
71
87
|
has_many :line_item_adjustments, through: :line_items, source: :adjustments
|
|
72
88
|
has_many :shipment_adjustments, through: :shipments, source: :adjustments
|
|
73
|
-
has_many :inventory_units, inverse_of: :order
|
|
74
|
-
has_many :products, through: :variants
|
|
75
|
-
has_many :variants, through: :line_items
|
|
76
|
-
has_many :refunds, through: :payments
|
|
77
89
|
has_many :all_adjustments,
|
|
78
90
|
class_name: 'Spree::Adjustment',
|
|
79
91
|
foreign_key: :order_id,
|
|
80
92
|
dependent: :destroy,
|
|
81
93
|
inverse_of: :order
|
|
82
|
-
|
|
83
|
-
has_many :order_stock_locations, class_name: "Spree::OrderStockLocation"
|
|
84
|
-
has_many :stock_locations, through: :order_stock_locations
|
|
85
|
-
|
|
86
94
|
has_many :order_promotions, class_name: 'Spree::OrderPromotion'
|
|
87
95
|
has_many :promotions, through: :order_promotions
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
has_many :
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
# Payments
|
|
98
|
+
has_many :payments, dependent: :destroy, inverse_of: :order
|
|
99
|
+
|
|
100
|
+
# Returns
|
|
101
|
+
has_many :return_authorizations, dependent: :destroy, inverse_of: :order
|
|
102
|
+
has_many :reimbursements, inverse_of: :order
|
|
103
|
+
has_many :refunds, through: :payments
|
|
104
|
+
|
|
105
|
+
# Logging
|
|
106
|
+
has_many :state_changes, as: :stateful
|
|
107
|
+
belongs_to :created_by, class_name: Spree::UserClassHandle.new
|
|
108
|
+
belongs_to :approver, class_name: Spree::UserClassHandle.new
|
|
109
|
+
belongs_to :canceler, class_name: Spree::UserClassHandle.new
|
|
95
110
|
|
|
96
111
|
accepts_nested_attributes_for :line_items
|
|
97
112
|
accepts_nested_attributes_for :bill_address
|
|
@@ -111,6 +126,7 @@ module Spree
|
|
|
111
126
|
|
|
112
127
|
validates :email, presence: true, if: :require_email
|
|
113
128
|
validates :email, email: true, allow_blank: true
|
|
129
|
+
validates :guest_token, presence: { allow_nil: true }
|
|
114
130
|
validates :number, presence: true, uniqueness: { allow_blank: true }
|
|
115
131
|
validates :store_id, presence: true
|
|
116
132
|
|
|
@@ -134,7 +150,6 @@ module Spree
|
|
|
134
150
|
|
|
135
151
|
# shows completed orders first, by their completed_at date, then uncompleted orders by their created_at
|
|
136
152
|
scope :reverse_chronological, -> { order('spree_orders.completed_at IS NULL', completed_at: :desc, created_at: :desc) }
|
|
137
|
-
scope :unreturned_exchange, -> { joins(:shipments).where('spree_orders.created_at > spree_shipments.created_at') }
|
|
138
153
|
|
|
139
154
|
def self.by_customer(customer)
|
|
140
155
|
joins(:user).where("#{Spree.user_class.table_name}.email" => customer)
|
|
@@ -220,7 +235,7 @@ module Spree
|
|
|
220
235
|
# Returns the relevant zone (if any) to be used for taxation purposes.
|
|
221
236
|
# Uses default tax zone unless there is a specific match
|
|
222
237
|
def tax_zone
|
|
223
|
-
Zone.match(tax_address) || Zone.default_tax
|
|
238
|
+
Spree::Zone.match(tax_address) || Spree::Zone.default_tax
|
|
224
239
|
end
|
|
225
240
|
deprecate tax_zone: "Please use Spree::Order#tax_address instead.",
|
|
226
241
|
deprecator: Spree::Deprecation
|
|
@@ -235,7 +250,7 @@ module Spree
|
|
|
235
250
|
end
|
|
236
251
|
|
|
237
252
|
def updater
|
|
238
|
-
@updater ||= OrderUpdater.new(self)
|
|
253
|
+
@updater ||= Spree::OrderUpdater.new(self)
|
|
239
254
|
end
|
|
240
255
|
|
|
241
256
|
def update!
|
|
@@ -381,12 +396,12 @@ module Spree
|
|
|
381
396
|
|
|
382
397
|
def credit_cards
|
|
383
398
|
credit_card_ids = payments.from_credit_card.pluck(:source_id).uniq
|
|
384
|
-
CreditCard.where(id: credit_card_ids)
|
|
399
|
+
Spree::CreditCard.where(id: credit_card_ids)
|
|
385
400
|
end
|
|
386
401
|
|
|
387
402
|
def valid_credit_cards
|
|
388
403
|
credit_card_ids = payments.from_credit_card.valid.pluck(:source_id).uniq
|
|
389
|
-
CreditCard.where(id: credit_card_ids)
|
|
404
|
+
Spree::CreditCard.where(id: credit_card_ids)
|
|
390
405
|
end
|
|
391
406
|
|
|
392
407
|
# Finalizes an in progress order after checkout is complete.
|
|
@@ -418,7 +433,7 @@ module Spree
|
|
|
418
433
|
end
|
|
419
434
|
|
|
420
435
|
def deliver_order_confirmation_email
|
|
421
|
-
OrderMailer.confirm_email(self).deliver_later
|
|
436
|
+
Spree::OrderMailer.confirm_email(self).deliver_later
|
|
422
437
|
update_column(:confirmation_delivered, true)
|
|
423
438
|
end
|
|
424
439
|
|
|
@@ -429,10 +444,10 @@ module Spree
|
|
|
429
444
|
|
|
430
445
|
def available_payment_methods
|
|
431
446
|
@available_payment_methods ||= Spree::PaymentMethod
|
|
447
|
+
.active
|
|
432
448
|
.available_to_store(store)
|
|
433
449
|
.available_to_users
|
|
434
|
-
.
|
|
435
|
-
.sort_by(&:position)
|
|
450
|
+
.order(:position)
|
|
436
451
|
end
|
|
437
452
|
|
|
438
453
|
def insufficient_stock_lines
|
|
@@ -458,17 +473,14 @@ module Spree
|
|
|
458
473
|
|
|
459
474
|
def empty!
|
|
460
475
|
line_items.destroy_all
|
|
461
|
-
updater.update_item_count
|
|
462
476
|
adjustments.destroy_all
|
|
463
477
|
shipments.destroy_all
|
|
464
478
|
|
|
465
|
-
|
|
466
|
-
persist_totals
|
|
479
|
+
update!
|
|
467
480
|
end
|
|
468
481
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
end
|
|
482
|
+
alias_method :has_step?, :has_checkout_step?
|
|
483
|
+
deprecate has_step?: :has_checkout_step?, deprecator: Spree::Deprecation
|
|
472
484
|
|
|
473
485
|
def state_changed(name)
|
|
474
486
|
state = "#{name}_state"
|
|
@@ -509,8 +521,6 @@ module Spree
|
|
|
509
521
|
end
|
|
510
522
|
|
|
511
523
|
def create_proposed_shipments
|
|
512
|
-
return shipments if unreturned_exchange?
|
|
513
|
-
|
|
514
524
|
if completed?
|
|
515
525
|
raise CannotRebuildShipments.new(Spree.t(:cannot_rebuild_shipments_order_completed))
|
|
516
526
|
elsif shipments.any? { |s| !s.pending? }
|
|
@@ -559,9 +569,9 @@ module Spree
|
|
|
559
569
|
|
|
560
570
|
def set_shipments_cost
|
|
561
571
|
shipments.each(&:update_amounts)
|
|
562
|
-
|
|
563
|
-
persist_totals
|
|
572
|
+
update!
|
|
564
573
|
end
|
|
574
|
+
deprecate set_shipments_cost: :update!, deprecator: Spree::Deprecation
|
|
565
575
|
|
|
566
576
|
def is_risky?
|
|
567
577
|
payments.risky.count > 0
|
|
@@ -599,18 +609,6 @@ module Spree
|
|
|
599
609
|
guest_token
|
|
600
610
|
end
|
|
601
611
|
|
|
602
|
-
def unreturned_exchange?
|
|
603
|
-
# created_at - 1 is a hack to ensure that this doesn't blow up on MySQL,
|
|
604
|
-
# records loaded from the DB on MySQL will have a precision of 1 second,
|
|
605
|
-
# but records in memory may still have miliseconds on them, causing this
|
|
606
|
-
# to be true where it shouldn't be.
|
|
607
|
-
#
|
|
608
|
-
# FIXME: find a better way to determine if an order is an unreturned
|
|
609
|
-
# exchange
|
|
610
|
-
shipment = shipments.first
|
|
611
|
-
shipment.present? ? (shipment.created_at < created_at - 1) : false
|
|
612
|
-
end
|
|
613
|
-
|
|
614
612
|
def tax_total
|
|
615
613
|
additional_tax_total + included_tax_total
|
|
616
614
|
end
|
|
@@ -690,25 +688,90 @@ module Spree
|
|
|
690
688
|
Spree::Money.new(total_available_store_credit - total_applicable_store_credit, { currency: currency })
|
|
691
689
|
end
|
|
692
690
|
|
|
693
|
-
def
|
|
694
|
-
|
|
695
|
-
|
|
691
|
+
def bill_address_attributes=(attributes)
|
|
692
|
+
self.bill_address = Spree::Address.immutable_merge(bill_address, attributes)
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
def ship_address_attributes=(attributes)
|
|
696
|
+
self.ship_address = Spree::Address.immutable_merge(ship_address, attributes)
|
|
696
697
|
end
|
|
697
698
|
|
|
698
|
-
def
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
699
|
+
def assign_default_addresses!
|
|
700
|
+
if user
|
|
701
|
+
# this is one of 2 places still using User#bill_address
|
|
702
|
+
self.bill_address ||= user.bill_address if user.bill_address.try!(:valid?)
|
|
703
|
+
# Skip setting ship address if order doesn't have a delivery checkout step
|
|
704
|
+
# to avoid triggering validations on shipping address
|
|
705
|
+
self.ship_address ||= user.ship_address if user.ship_address.try!(:valid?) && checkout_steps.include?("delivery")
|
|
706
|
+
end
|
|
707
|
+
end
|
|
704
708
|
|
|
705
|
-
|
|
706
|
-
|
|
709
|
+
def persist_user_address!
|
|
710
|
+
if !temporary_address && user && user.respond_to?(:persist_order_address) && bill_address_id
|
|
711
|
+
user.persist_order_address(self)
|
|
707
712
|
end
|
|
708
713
|
end
|
|
709
714
|
|
|
715
|
+
def add_payment_sources_to_wallet
|
|
716
|
+
Spree::Config.
|
|
717
|
+
add_payment_sources_to_wallet_class.new(self).
|
|
718
|
+
add_to_wallet
|
|
719
|
+
end
|
|
720
|
+
alias_method :persist_user_credit_card, :add_payment_sources_to_wallet
|
|
721
|
+
deprecate persist_user_credit_card: :add_payment_sources_to_wallet, deprecator: Spree::Deprecation
|
|
722
|
+
|
|
723
|
+
def add_default_payment_from_wallet
|
|
724
|
+
builder = Spree::Config.default_payment_builder_class.new(self)
|
|
725
|
+
|
|
726
|
+
if payment = builder.build
|
|
727
|
+
payments << payment
|
|
728
|
+
|
|
729
|
+
if bill_address.nil?
|
|
730
|
+
# this is one of 2 places still using User#bill_address
|
|
731
|
+
self.bill_address = payment.source.try(:address) ||
|
|
732
|
+
user.bill_address
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
alias_method :assign_default_credit_card, :add_default_payment_from_wallet
|
|
737
|
+
deprecate assign_default_credit_card: :add_default_payment_from_wallet, deprecator: Spree::Deprecation
|
|
738
|
+
|
|
710
739
|
private
|
|
711
740
|
|
|
741
|
+
def process_payments_before_complete
|
|
742
|
+
return if !payment_required?
|
|
743
|
+
|
|
744
|
+
if payments.valid.empty?
|
|
745
|
+
errors.add(:base, Spree.t(:no_payment_found))
|
|
746
|
+
return false
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
if process_payments!
|
|
750
|
+
true
|
|
751
|
+
else
|
|
752
|
+
saved_errors = errors[:base]
|
|
753
|
+
payment_failed!
|
|
754
|
+
saved_errors.each { |error| errors.add(:base, error) }
|
|
755
|
+
false
|
|
756
|
+
end
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
# In case a existing credit card is provided it needs to build the payment
|
|
760
|
+
# attributes from scratch so we can set the amount. example payload:
|
|
761
|
+
#
|
|
762
|
+
# {
|
|
763
|
+
# "order": {
|
|
764
|
+
# "existing_card": "2"
|
|
765
|
+
# }
|
|
766
|
+
# }
|
|
767
|
+
#
|
|
768
|
+
def update_params_payment_source
|
|
769
|
+
if @updating_params[:order] && (@updating_params[:order][:payments_attributes] || @updating_params[:order][:existing_card])
|
|
770
|
+
@updating_params[:order][:payments_attributes] ||= [{}]
|
|
771
|
+
@updating_params[:order][:payments_attributes].first[:amount] = total
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
|
|
712
775
|
def associate_store
|
|
713
776
|
self.store ||= Spree::Store.default
|
|
714
777
|
end
|
|
@@ -723,7 +786,7 @@ module Spree
|
|
|
723
786
|
end
|
|
724
787
|
|
|
725
788
|
def ensure_inventory_units
|
|
726
|
-
if
|
|
789
|
+
if has_checkout_step?("delivery")
|
|
727
790
|
inventory_validator = Spree::Stock::InventoryValidator.new
|
|
728
791
|
|
|
729
792
|
errors = line_items.map { |line_item| inventory_validator.validate(line_item) }.compact
|
|
@@ -732,9 +795,12 @@ module Spree
|
|
|
732
795
|
end
|
|
733
796
|
|
|
734
797
|
def ensure_promotions_eligible
|
|
735
|
-
|
|
736
|
-
|
|
798
|
+
adjustment_changed = all_adjustments.eligible.promotion.any? do |adjustment|
|
|
799
|
+
!adjustment.calculate_eligibility
|
|
800
|
+
end
|
|
801
|
+
if adjustment_changed
|
|
737
802
|
restart_checkout_flow
|
|
803
|
+
update!
|
|
738
804
|
errors.add(:base, Spree.t(:promotion_total_changed_before_complete))
|
|
739
805
|
end
|
|
740
806
|
errors.empty?
|
|
@@ -770,7 +836,7 @@ module Spree
|
|
|
770
836
|
end
|
|
771
837
|
|
|
772
838
|
def send_cancel_email
|
|
773
|
-
OrderMailer.cancel_email(self).deliver_later
|
|
839
|
+
Spree::OrderMailer.cancel_email(self).deliver_later
|
|
774
840
|
end
|
|
775
841
|
|
|
776
842
|
def after_resume
|
|
@@ -18,13 +18,13 @@ module Spree
|
|
|
18
18
|
def verify(shipment = nil)
|
|
19
19
|
if order.completed? || shipment.present?
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
shipment
|
|
25
|
-
add_to_shipment(shipment,
|
|
26
|
-
elsif
|
|
27
|
-
remove(
|
|
21
|
+
existing_quantity = inventory_units.count
|
|
22
|
+
desired_quantity = line_item.quantity - existing_quantity
|
|
23
|
+
if desired_quantity > 0
|
|
24
|
+
shipment ||= determine_target_shipment
|
|
25
|
+
add_to_shipment(shipment, desired_quantity)
|
|
26
|
+
elsif desired_quantity < 0
|
|
27
|
+
remove(-desired_quantity, shipment)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -35,9 +35,7 @@ module Spree
|
|
|
35
35
|
|
|
36
36
|
private
|
|
37
37
|
|
|
38
|
-
def remove(
|
|
39
|
-
quantity = item_units.size - line_item.quantity
|
|
40
|
-
|
|
38
|
+
def remove(quantity, shipment = nil)
|
|
41
39
|
if shipment.present?
|
|
42
40
|
remove_from_shipment(shipment, quantity)
|
|
43
41
|
else
|
|
@@ -100,7 +98,9 @@ module Spree
|
|
|
100
98
|
removed_quantity += 1
|
|
101
99
|
end
|
|
102
100
|
|
|
103
|
-
|
|
101
|
+
if shipment.inventory_units.count.zero?
|
|
102
|
+
order.shipments.destroy(shipment)
|
|
103
|
+
end
|
|
104
104
|
|
|
105
105
|
# removing this from shipment, and adding to stock_location
|
|
106
106
|
if order.completed?
|
|
@@ -14,17 +14,10 @@ module Spree
|
|
|
14
14
|
# Assign the attributes to the order and save the order
|
|
15
15
|
# @return true if saved, otherwise false and errors will be set on the order
|
|
16
16
|
def apply
|
|
17
|
-
order.validate_payments_attributes(@payments_attributes)
|
|
18
|
-
|
|
19
17
|
assign_order_attributes
|
|
20
18
|
assign_payments_attributes
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
order.set_shipments_cost if order.shipments.any?
|
|
24
|
-
true
|
|
25
|
-
else
|
|
26
|
-
false
|
|
27
|
-
end
|
|
20
|
+
order.save
|
|
28
21
|
end
|
|
29
22
|
|
|
30
23
|
private
|
|
@@ -17,6 +17,7 @@ module Spree
|
|
|
17
17
|
def update
|
|
18
18
|
@order.transaction do
|
|
19
19
|
update_item_count
|
|
20
|
+
update_shipment_amounts
|
|
20
21
|
update_totals
|
|
21
22
|
if order.completed?
|
|
22
23
|
update_payment_state
|
|
@@ -32,6 +33,65 @@ module Spree
|
|
|
32
33
|
update_hooks.each { |hook| order.send hook }
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
# Updates the +shipment_state+ attribute according to the following logic:
|
|
37
|
+
#
|
|
38
|
+
# shipped when all Shipments are in the "shipped" state
|
|
39
|
+
# partial when at least one Shipment has a state of "shipped" and there is another Shipment with a state other than "shipped"
|
|
40
|
+
# or there are InventoryUnits associated with the order that have a state of "sold" but are not associated with a Shipment.
|
|
41
|
+
# ready when all Shipments are in the "ready" state
|
|
42
|
+
# backorder when there is backordered inventory associated with an order
|
|
43
|
+
# pending when all Shipments are in the "pending" state
|
|
44
|
+
#
|
|
45
|
+
# The +shipment_state+ value helps with reporting, etc. since it provides a quick and easy way to locate Orders needing attention.
|
|
46
|
+
def update_shipment_state
|
|
47
|
+
if order.backordered?
|
|
48
|
+
order.shipment_state = 'backorder'
|
|
49
|
+
else
|
|
50
|
+
# get all the shipment states for this order
|
|
51
|
+
shipment_states = shipments.states
|
|
52
|
+
if shipment_states.size > 1
|
|
53
|
+
# multiple shiment states means it's most likely partially shipped
|
|
54
|
+
order.shipment_state = 'partial'
|
|
55
|
+
else
|
|
56
|
+
# will return nil if no shipments are found
|
|
57
|
+
order.shipment_state = shipment_states.first
|
|
58
|
+
# TODO: inventory unit states?
|
|
59
|
+
# if order.shipment_state && order.inventory_units.where(:shipment_id => nil).exists?
|
|
60
|
+
# shipments exist but there are unassigned inventory units
|
|
61
|
+
# order.shipment_state = 'partial'
|
|
62
|
+
# end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
order.state_changed('shipment')
|
|
67
|
+
order.shipment_state
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Updates the +payment_state+ attribute according to the following logic:
|
|
71
|
+
#
|
|
72
|
+
# paid when +payment_total+ is equal to +total+
|
|
73
|
+
# balance_due when +payment_total+ is less than +total+
|
|
74
|
+
# credit_owed when +payment_total+ is greater than +total+
|
|
75
|
+
# failed when most recent payment is in the failed state
|
|
76
|
+
#
|
|
77
|
+
# The +payment_state+ value helps with reporting, etc. since it provides a quick and easy way to locate Orders needing attention.
|
|
78
|
+
def update_payment_state
|
|
79
|
+
last_state = order.payment_state
|
|
80
|
+
if payments.present? && payments.valid.size == 0 && order.outstanding_balance != 0
|
|
81
|
+
order.payment_state = 'failed'
|
|
82
|
+
elsif order.state == 'canceled' && order.payment_total == 0
|
|
83
|
+
order.payment_state = 'void'
|
|
84
|
+
else
|
|
85
|
+
order.payment_state = 'balance_due' if order.outstanding_balance > 0
|
|
86
|
+
order.payment_state = 'credit_owed' if order.outstanding_balance < 0
|
|
87
|
+
order.payment_state = 'paid' if !order.outstanding_balance?
|
|
88
|
+
end
|
|
89
|
+
order.state_changed('payment') if last_state != order.payment_state
|
|
90
|
+
order.payment_state
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
35
95
|
# This will update and select the best promotion adjustment, update tax
|
|
36
96
|
# adjustments, update cancellation adjustments, and then update the total
|
|
37
97
|
# fields (promo_total, included_tax_total, additional_tax_total, and
|
|
@@ -64,13 +124,16 @@ module Spree
|
|
|
64
124
|
update_adjustment_total
|
|
65
125
|
end
|
|
66
126
|
|
|
127
|
+
def update_shipment_amounts
|
|
128
|
+
shipments.each do |shipment|
|
|
129
|
+
shipment.update_amounts
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
67
133
|
# give each of the shipments a chance to update themselves
|
|
68
134
|
def update_shipments
|
|
69
135
|
shipments.each do |shipment|
|
|
70
|
-
next unless shipment.persisted?
|
|
71
136
|
shipment.update!(order)
|
|
72
|
-
shipment.refresh_rates
|
|
73
|
-
shipment.update_amounts
|
|
74
137
|
end
|
|
75
138
|
end
|
|
76
139
|
|
|
@@ -102,7 +165,7 @@ module Spree
|
|
|
102
165
|
end
|
|
103
166
|
|
|
104
167
|
def update_item_count
|
|
105
|
-
order.item_count = quantity
|
|
168
|
+
order.item_count = line_items.to_a.sum(&:quantity)
|
|
106
169
|
end
|
|
107
170
|
|
|
108
171
|
def update_item_total
|
|
@@ -114,65 +177,6 @@ module Spree
|
|
|
114
177
|
order.save!(validate: false)
|
|
115
178
|
end
|
|
116
179
|
|
|
117
|
-
# Updates the +shipment_state+ attribute according to the following logic:
|
|
118
|
-
#
|
|
119
|
-
# shipped when all Shipments are in the "shipped" state
|
|
120
|
-
# partial when at least one Shipment has a state of "shipped" and there is another Shipment with a state other than "shipped"
|
|
121
|
-
# or there are InventoryUnits associated with the order that have a state of "sold" but are not associated with a Shipment.
|
|
122
|
-
# ready when all Shipments are in the "ready" state
|
|
123
|
-
# backorder when there is backordered inventory associated with an order
|
|
124
|
-
# pending when all Shipments are in the "pending" state
|
|
125
|
-
#
|
|
126
|
-
# The +shipment_state+ value helps with reporting, etc. since it provides a quick and easy way to locate Orders needing attention.
|
|
127
|
-
def update_shipment_state
|
|
128
|
-
if order.backordered?
|
|
129
|
-
order.shipment_state = 'backorder'
|
|
130
|
-
else
|
|
131
|
-
# get all the shipment states for this order
|
|
132
|
-
shipment_states = shipments.states
|
|
133
|
-
if shipment_states.size > 1
|
|
134
|
-
# multiple shiment states means it's most likely partially shipped
|
|
135
|
-
order.shipment_state = 'partial'
|
|
136
|
-
else
|
|
137
|
-
# will return nil if no shipments are found
|
|
138
|
-
order.shipment_state = shipment_states.first
|
|
139
|
-
# TODO: inventory unit states?
|
|
140
|
-
# if order.shipment_state && order.inventory_units.where(:shipment_id => nil).exists?
|
|
141
|
-
# shipments exist but there are unassigned inventory units
|
|
142
|
-
# order.shipment_state = 'partial'
|
|
143
|
-
# end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
order.state_changed('shipment')
|
|
148
|
-
order.shipment_state
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
# Updates the +payment_state+ attribute according to the following logic:
|
|
152
|
-
#
|
|
153
|
-
# paid when +payment_total+ is equal to +total+
|
|
154
|
-
# balance_due when +payment_total+ is less than +total+
|
|
155
|
-
# credit_owed when +payment_total+ is greater than +total+
|
|
156
|
-
# failed when most recent payment is in the failed state
|
|
157
|
-
#
|
|
158
|
-
# The +payment_state+ value helps with reporting, etc. since it provides a quick and easy way to locate Orders needing attention.
|
|
159
|
-
def update_payment_state
|
|
160
|
-
last_state = order.payment_state
|
|
161
|
-
if payments.present? && payments.valid.size == 0 && order.outstanding_balance != 0
|
|
162
|
-
order.payment_state = 'failed'
|
|
163
|
-
elsif order.state == 'canceled' && order.payment_total == 0
|
|
164
|
-
order.payment_state = 'void'
|
|
165
|
-
else
|
|
166
|
-
order.payment_state = 'balance_due' if order.outstanding_balance > 0
|
|
167
|
-
order.payment_state = 'credit_owed' if order.outstanding_balance < 0
|
|
168
|
-
order.payment_state = 'paid' if !order.outstanding_balance?
|
|
169
|
-
end
|
|
170
|
-
order.state_changed('payment') if last_state != order.payment_state
|
|
171
|
-
order.payment_state
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
private
|
|
175
|
-
|
|
176
180
|
def round_money(n)
|
|
177
181
|
(n * 100).round / 100.0
|
|
178
182
|
end
|