spree_core 2.3.13 → 2.4.0.rc1
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/app/assets/javascripts/spree.js.coffee.erb +1 -5
- data/app/helpers/spree/base_helper.rb +22 -11
- data/app/helpers/spree/products_helper.rb +8 -7
- data/app/mailers/spree/base_mailer.rb +1 -0
- data/app/mailers/spree/reimbursement_mailer.rb +10 -0
- data/app/mailers/spree/test_mailer.rb +2 -3
- data/app/models/concerns/spree/adjustment_source.rb +24 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +33 -0
- data/app/models/concerns/spree/named_type.rb +12 -0
- data/app/models/concerns/spree/user_address.rb +30 -0
- data/app/models/concerns/spree/user_payment_source.rb +19 -0
- data/app/models/spree/address.rb +13 -6
- data/app/models/spree/adjustment.rb +5 -5
- data/app/models/spree/app_configuration.rb +8 -4
- data/app/models/spree/asset.rb +1 -1
- data/app/models/spree/base.rb +0 -3
- data/app/models/spree/calculator/flat_rate.rb +1 -5
- data/app/models/spree/calculator/returns/default_refund_amount.rb +36 -0
- data/app/models/spree/classification.rb +1 -1
- data/app/models/spree/credit_card.rb +18 -22
- data/app/models/spree/customer_return.rb +70 -0
- data/app/models/spree/exchange.rb +42 -0
- data/app/models/spree/gateway/bogus.rb +3 -3
- data/app/models/spree/image.rb +1 -1
- data/app/models/spree/inventory_unit.rb +32 -8
- data/app/models/spree/item_adjustments.rb +7 -11
- data/app/models/spree/legacy_user.rb +2 -2
- data/app/models/spree/line_item.rb +25 -12
- data/app/models/spree/option_type.rb +1 -1
- data/app/models/spree/option_value.rb +1 -8
- data/app/models/spree/order.rb +163 -145
- data/app/models/spree/order/checkout.rb +35 -23
- data/app/models/spree/order/payments.rb +66 -0
- data/app/models/spree/order_contents.rb +34 -24
- data/app/models/spree/order_populator.rb +6 -4
- data/app/models/spree/order_updater.rb +10 -1
- data/app/models/spree/payment.rb +19 -16
- data/app/models/spree/payment/processing.rb +40 -72
- data/app/models/spree/payment_method.rb +1 -1
- data/app/models/spree/payment_method/check.rb +0 -2
- data/app/models/spree/preference.rb +1 -1
- data/app/models/spree/preferences/preferable.rb +20 -0
- data/app/models/spree/price.rb +13 -3
- data/app/models/spree/product.rb +24 -29
- data/app/models/spree/product_property.rb +0 -2
- data/app/models/spree/promotion.rb +66 -24
- data/app/models/spree/promotion/actions/create_adjustment.rb +2 -2
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -11
- data/app/models/spree/promotion/actions/create_line_items.rb +2 -12
- data/app/models/spree/promotion/rules/first_order.rb +6 -2
- data/app/models/spree/promotion/rules/item_total.rb +42 -4
- data/app/models/spree/promotion/rules/one_use_per_user.rb +24 -0
- data/app/models/spree/promotion/rules/product.rb +13 -11
- data/app/models/spree/promotion/rules/taxon.rb +61 -0
- data/app/models/spree/promotion/rules/user.rb +1 -1
- data/app/models/spree/promotion/rules/user_logged_in.rb +4 -1
- data/app/models/spree/promotion_category.rb +6 -0
- data/app/models/spree/promotion_handler/cart.rb +14 -18
- data/app/models/spree/promotion_handler/coupon.rb +25 -16
- data/app/models/spree/promotion_rule.rb +13 -0
- data/app/models/spree/property.rb +1 -3
- data/app/models/spree/refund.rb +91 -0
- data/app/models/spree/refund_reason.rb +13 -0
- data/app/models/spree/reimbursement.rb +148 -0
- data/app/models/spree/reimbursement/credit.rb +25 -0
- data/app/models/spree/reimbursement/reimbursement_type_engine.rb +56 -0
- data/app/models/spree/reimbursement/reimbursement_type_validator.rb +12 -0
- data/app/models/spree/reimbursement_performer.rb +43 -0
- data/app/models/spree/reimbursement_tax_calculator.rb +38 -0
- data/app/models/spree/reimbursement_type.rb +16 -0
- data/app/models/spree/reimbursement_type/credit.rb +13 -0
- data/app/models/spree/reimbursement_type/exchange.rb +9 -0
- data/app/models/spree/reimbursement_type/original_payment.rb +13 -0
- data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +50 -0
- data/app/models/spree/return_authorization.rb +52 -68
- data/app/models/spree/return_authorization_reason.rb +7 -0
- data/app/models/spree/return_item.rb +230 -0
- data/app/models/spree/return_item/default_eligibility_validator.rb +27 -0
- data/app/models/spree/return_item/eligibility_validator/base_validator.rb +24 -0
- data/app/models/spree/return_item/eligibility_validator/rma_required.rb +17 -0
- data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +16 -0
- data/app/models/spree/return_item/exchange_variant_eligibility/same_option_value.rb +34 -0
- data/app/models/spree/return_item/exchange_variant_eligibility/same_product.rb +10 -0
- data/app/models/spree/returns_calculator.rb +8 -0
- data/app/models/spree/shipment.rb +209 -154
- data/app/models/spree/shipment_handler.rb +43 -0
- data/app/models/spree/shipping_calculator.rb +1 -1
- data/app/models/spree/shipping_category.rb +2 -2
- data/app/models/spree/shipping_method.rb +1 -1
- data/app/models/spree/shipping_method_category.rb +1 -1
- data/app/models/spree/shipping_rate.rb +4 -0
- data/app/models/spree/stock/adjuster.rb +10 -11
- data/app/models/spree/stock/availability_validator.rb +6 -10
- data/app/models/spree/stock/content_item.rb +48 -0
- data/app/models/spree/stock/coordinator.rb +14 -7
- data/app/models/spree/stock/estimator.rb +1 -1
- data/app/models/spree/stock/inventory_unit_builder.rb +21 -0
- data/app/models/spree/stock/package.rb +38 -51
- data/app/models/spree/stock/packer.rb +13 -11
- data/app/models/spree/stock/prioritizer.rb +7 -7
- data/app/models/spree/stock/splitter/base.rb +2 -2
- data/app/models/spree/stock_item.rb +6 -9
- data/app/models/spree/stock_location.rb +17 -25
- data/app/models/spree/stock_movement.rb +1 -8
- data/app/models/spree/stock_transfer.rb +0 -2
- data/app/models/spree/store.rb +1 -1
- data/app/models/spree/tax_category.rb +2 -2
- data/app/models/spree/tax_rate.rb +16 -22
- data/app/models/spree/taxon.rb +1 -1
- data/app/models/spree/variant.rb +45 -23
- data/app/models/spree/zone.rb +17 -17
- data/app/models/spree/zone_member.rb +1 -1
- data/app/views/layouts/spree/base_mailer.html.erb +784 -0
- data/app/views/spree/order_mailer/cancel_email.html.erb +45 -0
- data/app/views/spree/order_mailer/cancel_email.text.erb +2 -2
- data/app/views/spree/order_mailer/confirm_email.html.erb +84 -0
- data/app/views/spree/order_mailer/confirm_email.text.erb +2 -2
- data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +22 -0
- data/app/views/spree/shared/_base_mailer_footer.html.erb +20 -0
- data/app/views/spree/shared/_base_mailer_header.html.erb +31 -0
- data/app/views/spree/shipment_mailer/shipped_email.html.erb +34 -0
- data/app/views/spree/test_mailer/test_email.html.erb +40 -0
- data/app/views/spree/test_mailer/test_email.text.erb +2 -2
- data/config/initializers/friendly_id.rb +88 -0
- data/config/initializers/premailer_assets.rb +1 -0
- data/config/initializers/user_class_extensions.rb +9 -22
- data/config/locales/en.yml +180 -12
- data/db/default/spree/states.rb +73 -55
- data/db/migrate/20130213191427_create_default_stock.rb +1 -0
- data/db/migrate/20130807024301_upgrade_adjustments.rb +4 -5
- data/db/migrate/20140309033438_create_store_from_preferences.rb +0 -7
- data/db/migrate/20140318191500_create_spree_taxons_promotion_rules.rb +8 -0
- data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +1 -1
- data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +5 -3
- data/db/migrate/20140625214618_create_spree_refunds.rb +12 -0
- data/db/migrate/20140702140656_create_spree_return_authorization_inventory_unit.rb +12 -0
- data/db/migrate/20140707125621_rename_return_authorization_inventory_unit_to_return_items.rb +5 -0
- data/db/migrate/20140709160534_backfill_line_item_pre_tax_amount.rb +10 -0
- data/db/migrate/20140710041921_recreate_spree_return_authorizations.rb +55 -0
- data/db/migrate/20140710181204_add_amount_fields_to_return_items.rb +7 -0
- data/db/migrate/20140710190048_drop_return_authorization_amount.rb +5 -0
- data/db/migrate/20140713140455_create_spree_return_authorization_reasons.rb +28 -0
- data/db/migrate/20140713140527_create_spree_refund_reasons.rb +14 -0
- data/db/migrate/20140713142214_rename_return_authorization_reason.rb +5 -0
- data/db/migrate/20140715182625_create_spree_promotion_categories.rb +11 -0
- data/db/migrate/20140716204111_drop_received_at_on_return_items.rb +9 -0
- data/db/migrate/20140716212330_add_reception_and_acceptance_status_to_return_items.rb +6 -0
- data/db/migrate/20140717155155_create_default_refund_reason.rb +9 -0
- data/db/migrate/20140717185932_add_default_to_spree_stock_locations.rb +5 -0
- data/db/migrate/20140718133010_create_spree_customer_returns.rb +9 -0
- data/db/migrate/20140718133349_add_customer_return_id_to_return_item.rb +6 -0
- data/db/migrate/20140718195325_create_friendly_id_slugs.rb +15 -0
- data/db/migrate/20140723004419_rename_spree_refund_return_authorization_id.rb +5 -0
- data/db/migrate/20140723152808_increase_return_item_pre_tax_amount_precision.rb +13 -0
- data/db/migrate/20140723214541_copy_product_slugs_to_slug_history.rb +15 -0
- data/db/migrate/20140725131539_create_spree_reimbursements.rb +21 -0
- data/db/migrate/20140728225422_add_promotionable_to_spree_products.rb +5 -0
- data/db/migrate/20140729133613_add_exchange_inventory_unit_foreign_keys.rb +7 -0
- data/db/migrate/20140730155938_add_acceptance_status_errors_to_return_item.rb +5 -0
- data/db/migrate/20140731150017_create_spree_reimbursement_types.rb +20 -0
- data/db/migrate/20140805171035_add_default_to_spree_credit_cards.rb +5 -0
- data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +10 -0
- data/db/migrate/20140806144901_add_type_to_reimbursement_type.rb +9 -0
- data/db/migrate/20140808184039_create_spree_reimbursement_credits.rb +10 -0
- data/db/migrate/20140827170513_add_meta_title_to_spree_products.rb +7 -0
- data/db/migrate/20140924164824_add_code_to_spree_tax_categories.rb +5 -0
- data/db/migrate/20141002191113_add_code_to_spree_shipping_methods.rb +5 -0
- data/db/migrate/20141007230328_add_cancel_audit_fields_to_spree_orders.rb +6 -0
- data/db/migrate/20141009204607_add_store_id_to_orders.rb +8 -0
- data/lib/generators/spree/install/install_generator.rb +7 -3
- data/lib/spree/core.rb +11 -10
- data/lib/spree/core/controller_helpers/common.rb +3 -10
- data/lib/spree/core/controller_helpers/order.rb +15 -12
- data/lib/spree/core/controller_helpers/strong_parameters.rb +9 -9
- data/lib/spree/core/engine.rb +8 -1
- data/lib/spree/core/importer/order.rb +5 -17
- data/lib/spree/core/search/base.rb +1 -1
- data/lib/spree/core/validators/email.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/instrumentation.rb +41 -0
- data/lib/spree/migrations.rb +3 -7
- data/lib/spree/money.rb +2 -2
- data/lib/spree/permitted_attributes.rb +10 -9
- data/lib/spree/testing_support/ability_helpers.rb +25 -25
- data/lib/spree/testing_support/authorization_helpers.rb +3 -5
- data/lib/spree/testing_support/capybara_ext.rb +2 -2
- data/lib/spree/testing_support/factories/calculator_factory.rb +0 -8
- data/lib/spree/testing_support/factories/credit_card_factory.rb +1 -1
- data/lib/spree/testing_support/factories/customer_return_factory.rb +31 -0
- data/lib/spree/testing_support/factories/inventory_unit_factory.rb +1 -0
- data/lib/spree/testing_support/factories/line_item_factory.rb +2 -1
- data/lib/spree/testing_support/factories/order_factory.rb +11 -6
- data/lib/spree/testing_support/factories/promotion_category_factory.rb +6 -0
- data/lib/spree/testing_support/factories/promotion_factory.rb +9 -7
- data/lib/spree/testing_support/factories/refund_factory.rb +14 -0
- data/lib/spree/testing_support/factories/reimbursement_factory.rb +16 -0
- data/lib/spree/testing_support/factories/reimbursement_type_factory.rb +7 -0
- data/lib/spree/testing_support/factories/return_authorization_factory.rb +9 -3
- data/lib/spree/testing_support/factories/return_item_factory.rb +10 -0
- data/lib/spree/testing_support/factories/shipment_factory.rb +1 -0
- data/lib/spree/testing_support/factories/shipping_method_factory.rb +3 -2
- data/lib/spree/testing_support/factories/stock_factory.rb +12 -11
- data/lib/spree/testing_support/flash.rb +2 -2
- data/lib/tasks/email.rake +7 -0
- data/lib/tasks/exchanges.rake +70 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
- metadata +163 -47
- data/app/models/concerns/spree/ransackable_attributes.rb +0 -19
- data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +0 -5
- data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +0 -13
- data/db/migrate/20141105213646_update_classifications_positions.rb +0 -9
- data/db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb +0 -5
- data/db/migrate/20150515211137_fix_adjustment_order_id.rb +0 -70
- data/lib/spree/core/adjustment_source.rb +0 -26
- data/lib/spree/core/calculated_adjustments.rb +0 -35
- data/lib/spree/core/controller_helpers.rb +0 -20
- data/lib/spree/core/user_address.rb +0 -32
- data/lib/spree/core/user_payment_source.rb +0 -20
- data/lib/spree/localized_number.rb +0 -20
|
@@ -8,15 +8,8 @@ module Spree
|
|
|
8
8
|
|
|
9
9
|
after_touch :touch_all_variants
|
|
10
10
|
|
|
11
|
-
self.whitelisted_ransackable_attributes = ['presentation']
|
|
12
|
-
|
|
13
11
|
def touch_all_variants
|
|
14
|
-
|
|
15
|
-
# To disable it in Rails 4.1, we can do this:
|
|
16
|
-
# https://github.com/rails/rails/pull/12772
|
|
17
|
-
# Spree::Product.no_touching do
|
|
18
|
-
variants.find_each(&:touch)
|
|
19
|
-
# end
|
|
12
|
+
variants.update_all(updated_at: Time.current)
|
|
20
13
|
end
|
|
21
14
|
end
|
|
22
15
|
end
|
data/app/models/spree/order.rb
CHANGED
|
@@ -3,8 +3,14 @@ require 'spree/order/checkout'
|
|
|
3
3
|
|
|
4
4
|
module Spree
|
|
5
5
|
class Order < Spree::Base
|
|
6
|
+
|
|
7
|
+
ORDER_NUMBER_LENGTH = 9
|
|
8
|
+
ORDER_NUMBER_LETTERS = false
|
|
9
|
+
ORDER_NUMBER_PREFIX = 'R'
|
|
10
|
+
|
|
6
11
|
include Spree::Order::Checkout
|
|
7
12
|
include Spree::Order::CurrencyUpdater
|
|
13
|
+
include Spree::Order::Payments
|
|
8
14
|
|
|
9
15
|
checkout_flow do
|
|
10
16
|
go_to_state :address
|
|
@@ -15,20 +21,19 @@ module Spree
|
|
|
15
21
|
remove_transition from: :delivery, to: :confirm
|
|
16
22
|
end
|
|
17
23
|
|
|
18
|
-
self.whitelisted_ransackable_associations = %w[shipments user promotions bill_address ship_address line_items]
|
|
19
|
-
self.whitelisted_ransackable_attributes = %w[completed_at created_at email number state payment_state shipment_state total considered_risky]
|
|
20
|
-
|
|
21
24
|
attr_reader :coupon_code
|
|
22
|
-
attr_accessor :temporary_address
|
|
25
|
+
attr_accessor :temporary_address, :temporary_credit_card
|
|
23
26
|
|
|
24
27
|
if Spree.user_class
|
|
25
28
|
belongs_to :user, class_name: Spree.user_class.to_s
|
|
26
29
|
belongs_to :created_by, class_name: Spree.user_class.to_s
|
|
27
30
|
belongs_to :approver, class_name: Spree.user_class.to_s
|
|
31
|
+
belongs_to :canceler, class_name: Spree.user_class.to_s
|
|
28
32
|
else
|
|
29
33
|
belongs_to :user
|
|
30
34
|
belongs_to :created_by
|
|
31
35
|
belongs_to :approver
|
|
36
|
+
belongs_to :canceler
|
|
32
37
|
end
|
|
33
38
|
|
|
34
39
|
belongs_to :bill_address, foreign_key: :bill_address_id, class_name: 'Spree::Address'
|
|
@@ -40,20 +45,17 @@ module Spree
|
|
|
40
45
|
alias_attribute :ship_total, :shipment_total
|
|
41
46
|
|
|
42
47
|
has_many :state_changes, as: :stateful
|
|
43
|
-
has_many :line_items, -> { order(
|
|
48
|
+
has_many :line_items, -> { order('created_at ASC') }, dependent: :destroy, inverse_of: :order
|
|
44
49
|
has_many :payments, dependent: :destroy
|
|
45
|
-
has_many :return_authorizations, dependent: :destroy
|
|
50
|
+
has_many :return_authorizations, dependent: :destroy
|
|
51
|
+
has_many :reimbursements, inverse_of: :order
|
|
46
52
|
has_many :adjustments, -> { order("#{Adjustment.table_name}.created_at ASC") }, as: :adjustable, dependent: :destroy
|
|
47
53
|
has_many :line_item_adjustments, through: :line_items, source: :adjustments
|
|
48
54
|
has_many :shipment_adjustments, through: :shipments, source: :adjustments
|
|
49
55
|
has_many :inventory_units, inverse_of: :order
|
|
50
56
|
has_many :products, through: :variants
|
|
51
57
|
has_many :variants, through: :line_items
|
|
52
|
-
has_many :
|
|
53
|
-
class_name: 'Spree::Adjustment',
|
|
54
|
-
foreign_key: :order_id,
|
|
55
|
-
dependent: :destroy,
|
|
56
|
-
inverse_of: :order
|
|
58
|
+
has_many :refunds, through: :payments
|
|
57
59
|
|
|
58
60
|
has_and_belongs_to_many :promotions, join_table: 'spree_orders_promotions'
|
|
59
61
|
|
|
@@ -82,7 +84,7 @@ module Spree
|
|
|
82
84
|
|
|
83
85
|
validates :email, presence: true, if: :require_email
|
|
84
86
|
validates :email, email: true, if: :require_email, allow_blank: true
|
|
85
|
-
validates :number,
|
|
87
|
+
validates :number, uniqueness: true
|
|
86
88
|
validate :has_available_shipment
|
|
87
89
|
|
|
88
90
|
make_permalink field: :number
|
|
@@ -92,6 +94,9 @@ module Spree
|
|
|
92
94
|
class_attribute :update_hooks
|
|
93
95
|
self.update_hooks = Set.new
|
|
94
96
|
|
|
97
|
+
class_attribute :line_item_comparison_hooks
|
|
98
|
+
self.line_item_comparison_hooks = Set.new
|
|
99
|
+
|
|
95
100
|
def self.by_number(number)
|
|
96
101
|
where(number: number)
|
|
97
102
|
end
|
|
@@ -99,7 +104,8 @@ module Spree
|
|
|
99
104
|
scope :created_between, ->(start_date, end_date) { where(created_at: start_date..end_date) }
|
|
100
105
|
scope :completed_between, ->(start_date, end_date) { where(completed_at: start_date..end_date) }
|
|
101
106
|
|
|
102
|
-
|
|
107
|
+
# shows completed orders first, by their completed_at date, then uncompleted orders by their created_at
|
|
108
|
+
scope :reverse_chronological, -> { order('spree_orders.completed_at IS NULL', completed_at: :desc, created_at: :desc) }
|
|
103
109
|
|
|
104
110
|
def self.by_customer(customer)
|
|
105
111
|
joins(:user).where("#{Spree.user_class.table_name}.email" => customer)
|
|
@@ -129,11 +135,21 @@ module Spree
|
|
|
129
135
|
self.line_item_comparison_hooks.add(hook)
|
|
130
136
|
end
|
|
131
137
|
|
|
138
|
+
def all_adjustments
|
|
139
|
+
Adjustment.where("order_id = :order_id OR (adjustable_id = :order_id AND adjustable_type = 'Spree::Order')",
|
|
140
|
+
order_id: self.id)
|
|
141
|
+
end
|
|
142
|
+
|
|
132
143
|
# For compatiblity with Calculator::PriceSack
|
|
133
144
|
def amount
|
|
134
145
|
line_items.inject(0.0) { |sum, li| sum + li.amount }
|
|
135
146
|
end
|
|
136
147
|
|
|
148
|
+
# Sum of all line item amounts pre-tax
|
|
149
|
+
def pre_tax_item_amount
|
|
150
|
+
line_items.to_a.sum(&:pre_tax_amount)
|
|
151
|
+
end
|
|
152
|
+
|
|
137
153
|
def currency
|
|
138
154
|
self[:currency] || Spree::Config[:currency]
|
|
139
155
|
end
|
|
@@ -243,8 +259,8 @@ module Spree
|
|
|
243
259
|
shipment_state.nil? || %w{ready backorder pending}.include?(shipment_state)
|
|
244
260
|
end
|
|
245
261
|
|
|
246
|
-
def
|
|
247
|
-
|
|
262
|
+
def all_inventory_units_returned?
|
|
263
|
+
inventory_units.all? { |inventory_unit| inventory_unit.returned? }
|
|
248
264
|
end
|
|
249
265
|
|
|
250
266
|
def contents
|
|
@@ -265,35 +281,62 @@ module Spree
|
|
|
265
281
|
end
|
|
266
282
|
end
|
|
267
283
|
|
|
268
|
-
def generate_order_number(
|
|
284
|
+
def generate_order_number(options = {})
|
|
285
|
+
options[:length] ||= ORDER_NUMBER_LENGTH
|
|
286
|
+
options[:letters] ||= ORDER_NUMBER_LETTERS
|
|
287
|
+
options[:prefix] ||= ORDER_NUMBER_PREFIX
|
|
288
|
+
|
|
289
|
+
possible = (0..9).to_a
|
|
290
|
+
possible += ('A'..'Z').to_a if options[:letters]
|
|
291
|
+
|
|
269
292
|
self.number ||= loop do
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
293
|
+
# Make a random number.
|
|
294
|
+
random = "#{options[:prefix]}#{(0...options[:length]).map { possible.shuffle.first }.join}"
|
|
295
|
+
# Use the random number if no other order exists with it.
|
|
296
|
+
if self.class.exists?(number: random)
|
|
297
|
+
# If over half of all possible options are taken add another digit.
|
|
298
|
+
options[:length] += 1 if self.class.count > (10 ** options[:length] / 2)
|
|
299
|
+
else
|
|
300
|
+
break random
|
|
301
|
+
end
|
|
302
|
+
end
|
|
280
303
|
end
|
|
281
304
|
|
|
282
305
|
def shipped_shipments
|
|
283
306
|
shipments.shipped
|
|
284
307
|
end
|
|
285
308
|
|
|
286
|
-
def contains?(variant)
|
|
287
|
-
find_line_item_by_variant(variant).present?
|
|
309
|
+
def contains?(variant, options = {})
|
|
310
|
+
find_line_item_by_variant(variant, options).present?
|
|
288
311
|
end
|
|
289
312
|
|
|
290
|
-
def quantity_of(variant)
|
|
291
|
-
line_item = find_line_item_by_variant(variant)
|
|
313
|
+
def quantity_of(variant, options = {})
|
|
314
|
+
line_item = find_line_item_by_variant(variant, options)
|
|
292
315
|
line_item ? line_item.quantity : 0
|
|
293
316
|
end
|
|
294
317
|
|
|
295
|
-
def find_line_item_by_variant(variant)
|
|
296
|
-
line_items.detect { |line_item|
|
|
318
|
+
def find_line_item_by_variant(variant, options = {})
|
|
319
|
+
line_items.detect { |line_item|
|
|
320
|
+
line_item.variant_id == variant.id &&
|
|
321
|
+
line_item_options_match(line_item, options)
|
|
322
|
+
}
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# This method enables extensions to participate in the
|
|
326
|
+
# "Are these line items equal" decision.
|
|
327
|
+
#
|
|
328
|
+
# When adding to cart, an extension would send something like:
|
|
329
|
+
# params[:product_customizations]={...}
|
|
330
|
+
#
|
|
331
|
+
# and would provide:
|
|
332
|
+
#
|
|
333
|
+
# def product_customizations_match
|
|
334
|
+
def line_item_options_match(line_item, options)
|
|
335
|
+
return true unless options
|
|
336
|
+
|
|
337
|
+
self.line_item_comparison_hooks.all? { |hook|
|
|
338
|
+
self.send(hook, line_item, options)
|
|
339
|
+
}
|
|
297
340
|
end
|
|
298
341
|
|
|
299
342
|
# Creates new tax charges if there are any applicable rates. If prices already
|
|
@@ -306,7 +349,7 @@ module Spree
|
|
|
306
349
|
end
|
|
307
350
|
|
|
308
351
|
def outstanding_balance
|
|
309
|
-
if state == 'canceled'
|
|
352
|
+
if self.state == 'canceled' && self.payments.present? && self.payments.completed.size > 0
|
|
310
353
|
-1 * payment_total
|
|
311
354
|
else
|
|
312
355
|
total - payment_total
|
|
@@ -314,7 +357,7 @@ module Spree
|
|
|
314
357
|
end
|
|
315
358
|
|
|
316
359
|
def outstanding_balance?
|
|
317
|
-
|
|
360
|
+
self.outstanding_balance != 0
|
|
318
361
|
end
|
|
319
362
|
|
|
320
363
|
def name
|
|
@@ -332,6 +375,11 @@ module Spree
|
|
|
332
375
|
CreditCard.where(id: credit_card_ids)
|
|
333
376
|
end
|
|
334
377
|
|
|
378
|
+
def valid_credit_cards
|
|
379
|
+
credit_card_ids = payments.from_credit_card.valid.pluck(:source_id).uniq
|
|
380
|
+
CreditCard.where(id: credit_card_ids)
|
|
381
|
+
end
|
|
382
|
+
|
|
335
383
|
# Finalizes an in progress order after checkout is complete.
|
|
336
384
|
# Called after transition to complete state when payments will have been processed
|
|
337
385
|
def finalize!
|
|
@@ -346,7 +394,7 @@ module Spree
|
|
|
346
394
|
end
|
|
347
395
|
|
|
348
396
|
updater.update_shipment_state
|
|
349
|
-
save
|
|
397
|
+
save!
|
|
350
398
|
updater.run_hooks
|
|
351
399
|
|
|
352
400
|
touch :completed_at
|
|
@@ -356,12 +404,6 @@ module Spree
|
|
|
356
404
|
consider_risk
|
|
357
405
|
end
|
|
358
406
|
|
|
359
|
-
def fulfill!
|
|
360
|
-
shipments.each { |shipment| shipment.update!(self) if shipment.persisted? }
|
|
361
|
-
updater.update_shipment_state
|
|
362
|
-
save!
|
|
363
|
-
end
|
|
364
|
-
|
|
365
407
|
def deliver_order_confirmation_email
|
|
366
408
|
OrderMailer.confirm_email(self.id).deliver
|
|
367
409
|
update_column(:confirmation_delivered, true)
|
|
@@ -376,46 +418,6 @@ module Spree
|
|
|
376
418
|
@available_payment_methods ||= (PaymentMethod.available(:front_end) + PaymentMethod.available(:both)).uniq
|
|
377
419
|
end
|
|
378
420
|
|
|
379
|
-
def pending_payments
|
|
380
|
-
payments.select { |payment| payment.checkout? || payment.pending? }
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
# processes any pending payments and must return a boolean as it's
|
|
384
|
-
# return value is used by the checkout state_machine to determine
|
|
385
|
-
# success or failure of the 'complete' event for the order
|
|
386
|
-
#
|
|
387
|
-
# Returns:
|
|
388
|
-
#
|
|
389
|
-
# - true if all pending_payments processed successfully
|
|
390
|
-
#
|
|
391
|
-
# - true if a payment failed, ie. raised a GatewayError
|
|
392
|
-
# which gets rescued and converted to TRUE when
|
|
393
|
-
# :allow_checkout_gateway_error is set to true
|
|
394
|
-
#
|
|
395
|
-
# - false if a payment failed, ie. raised a GatewayError
|
|
396
|
-
# which gets rescued and converted to FALSE when
|
|
397
|
-
# :allow_checkout_on_gateway_error is set to false
|
|
398
|
-
#
|
|
399
|
-
def process_payments!\
|
|
400
|
-
# Don't run if there is nothing to pay.
|
|
401
|
-
return if payment_total >= total
|
|
402
|
-
# Prevent orders from transitioning to complete without a successfully processed payment.
|
|
403
|
-
raise Core::GatewayError.new(Spree.t(:no_payment_found)) if pending_payments.empty?
|
|
404
|
-
|
|
405
|
-
pending_payments.each do |payment|
|
|
406
|
-
break if payment_total >= total
|
|
407
|
-
|
|
408
|
-
payment.process!
|
|
409
|
-
|
|
410
|
-
if payment.completed?
|
|
411
|
-
self.payment_total += payment.amount
|
|
412
|
-
end
|
|
413
|
-
end
|
|
414
|
-
rescue Core::GatewayError => e
|
|
415
|
-
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
|
416
|
-
errors.add(:base, e.message) and return result
|
|
417
|
-
end
|
|
418
|
-
|
|
419
421
|
def billing_firstname
|
|
420
422
|
bill_address.try(:firstname)
|
|
421
423
|
end
|
|
@@ -425,29 +427,34 @@ module Spree
|
|
|
425
427
|
end
|
|
426
428
|
|
|
427
429
|
def insufficient_stock_lines
|
|
428
|
-
|
|
430
|
+
line_items.select(&:insufficient_stock?)
|
|
429
431
|
end
|
|
430
432
|
|
|
431
433
|
def ensure_line_items_are_in_stock
|
|
432
434
|
if insufficient_stock_lines.present?
|
|
433
|
-
errors.add(:base, Spree.t(:insufficient_stock_lines_present))
|
|
434
|
-
restart_checkout_flow
|
|
435
|
-
false
|
|
436
|
-
else
|
|
437
|
-
true
|
|
435
|
+
errors.add(:base, Spree.t(:insufficient_stock_lines_present)) and return false
|
|
438
436
|
end
|
|
439
437
|
end
|
|
440
438
|
|
|
441
439
|
def merge!(order, user = nil)
|
|
442
|
-
order.line_items.each do |
|
|
443
|
-
next unless
|
|
444
|
-
|
|
440
|
+
order.line_items.each do |other_order_line_item|
|
|
441
|
+
next unless other_order_line_item.currency == currency
|
|
442
|
+
|
|
443
|
+
# Compare the line items of the other order with mine.
|
|
444
|
+
# Make sure you allow any extensions to chime in on whether or
|
|
445
|
+
# not the extension-specific parts of the line item match
|
|
446
|
+
current_line_item = self.line_items.detect { |my_li|
|
|
447
|
+
my_li.variant == other_order_line_item.variant &&
|
|
448
|
+
self.line_item_comparison_hooks.all? { |hook|
|
|
449
|
+
self.send(hook, my_li, other_order_line_item)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
445
452
|
if current_line_item
|
|
446
|
-
current_line_item.quantity +=
|
|
447
|
-
current_line_item.save
|
|
453
|
+
current_line_item.quantity += other_order_line_item.quantity
|
|
454
|
+
current_line_item.save!
|
|
448
455
|
else
|
|
449
|
-
|
|
450
|
-
|
|
456
|
+
other_order_line_item.order_id = self.id
|
|
457
|
+
other_order_line_item.save!
|
|
451
458
|
end
|
|
452
459
|
end
|
|
453
460
|
|
|
@@ -506,15 +513,9 @@ module Spree
|
|
|
506
513
|
end
|
|
507
514
|
|
|
508
515
|
def create_proposed_shipments
|
|
509
|
-
|
|
516
|
+
adjustments.shipping.delete_all
|
|
510
517
|
shipments.destroy_all
|
|
511
|
-
|
|
512
|
-
packages = Spree::Stock::Coordinator.new(self).packages
|
|
513
|
-
packages.each do |package|
|
|
514
|
-
shipments << package.to_shipment
|
|
515
|
-
end
|
|
516
|
-
|
|
517
|
-
shipments
|
|
518
|
+
self.shipments = Spree::Stock::Coordinator.new(self).shipments
|
|
518
519
|
end
|
|
519
520
|
|
|
520
521
|
def apply_free_shipping_promotions
|
|
@@ -539,9 +540,10 @@ module Spree
|
|
|
539
540
|
|
|
540
541
|
def restart_checkout_flow
|
|
541
542
|
self.update_columns(
|
|
542
|
-
state:
|
|
543
|
+
state: 'cart',
|
|
543
544
|
updated_at: Time.now,
|
|
544
545
|
)
|
|
546
|
+
self.next! if self.line_items.size > 0
|
|
545
547
|
end
|
|
546
548
|
|
|
547
549
|
def refresh_shipment_rates
|
|
@@ -557,11 +559,22 @@ module Spree
|
|
|
557
559
|
updater.update_shipment_total
|
|
558
560
|
persist_totals
|
|
559
561
|
end
|
|
562
|
+
Spree.instrument_method self, :set_shipments_cost
|
|
560
563
|
|
|
561
564
|
def is_risky?
|
|
562
565
|
self.payments.risky.count > 0
|
|
563
566
|
end
|
|
564
567
|
|
|
568
|
+
def canceled_by(user)
|
|
569
|
+
self.transaction do
|
|
570
|
+
cancel!
|
|
571
|
+
self.update_columns(
|
|
572
|
+
canceler_id: user.id,
|
|
573
|
+
canceled_at: Time.now,
|
|
574
|
+
)
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
|
|
565
578
|
def approved_by(user)
|
|
566
579
|
self.transaction do
|
|
567
580
|
approve!
|
|
@@ -620,38 +633,43 @@ module Spree
|
|
|
620
633
|
line_items.sum(:quantity)
|
|
621
634
|
end
|
|
622
635
|
|
|
636
|
+
def has_non_reimbursement_related_refunds?
|
|
637
|
+
refunds.non_reimbursement.exists? ||
|
|
638
|
+
payments.offset_payment.exists? # how old versions of spree stored refunds
|
|
639
|
+
end
|
|
640
|
+
|
|
623
641
|
private
|
|
624
642
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
643
|
+
def link_by_email
|
|
644
|
+
self.email = user.email if self.user
|
|
645
|
+
end
|
|
628
646
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
647
|
+
# Determine if email is required (we don't want validation errors before we hit the checkout)
|
|
648
|
+
def require_email
|
|
649
|
+
true unless new_record? or ['cart', 'address'].include?(state)
|
|
650
|
+
end
|
|
633
651
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
end
|
|
652
|
+
def ensure_line_items_present
|
|
653
|
+
unless line_items.present?
|
|
654
|
+
errors.add(:base, Spree.t(:there_are_no_items_for_this_order)) and return false
|
|
638
655
|
end
|
|
656
|
+
end
|
|
639
657
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
658
|
+
def has_available_shipment
|
|
659
|
+
return unless has_step?("delivery")
|
|
660
|
+
return unless has_step?(:address) && address?
|
|
661
|
+
return unless ship_address && ship_address.valid?
|
|
662
|
+
# errors.add(:base, :no_shipping_methods_available) if available_shipping_methods.empty?
|
|
663
|
+
end
|
|
646
664
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
end
|
|
665
|
+
def ensure_available_shipping_rates
|
|
666
|
+
if shipments.empty? || shipments.any? { |shipment| shipment.shipping_rates.blank? }
|
|
667
|
+
# After this point, order redirects back to 'address' state and asks user to pick a proper address
|
|
668
|
+
# Therefore, shipments are not necessary at this point.
|
|
669
|
+
shipments.delete_all
|
|
670
|
+
errors.add(:base, Spree.t(:items_cannot_be_shipped)) and return false
|
|
654
671
|
end
|
|
672
|
+
end
|
|
655
673
|
|
|
656
674
|
def after_cancel
|
|
657
675
|
shipments.each { |shipment| shipment.cancel! }
|
|
@@ -660,28 +678,28 @@ module Spree
|
|
|
660
678
|
self.update!
|
|
661
679
|
end
|
|
662
680
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
681
|
+
def send_cancel_email
|
|
682
|
+
OrderMailer.cancel_email(self.id).deliver
|
|
683
|
+
end
|
|
666
684
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
685
|
+
def after_resume
|
|
686
|
+
shipments.each { |shipment| shipment.resume! }
|
|
687
|
+
consider_risk
|
|
688
|
+
end
|
|
671
689
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
690
|
+
def use_billing?
|
|
691
|
+
@use_billing == true || @use_billing == 'true' || @use_billing == '1'
|
|
692
|
+
end
|
|
675
693
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
694
|
+
def set_currency
|
|
695
|
+
self.currency = Spree::Config[:currency] if self[:currency].nil?
|
|
696
|
+
end
|
|
679
697
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
end
|
|
698
|
+
def create_token
|
|
699
|
+
self.guest_token ||= loop do
|
|
700
|
+
random_token = SecureRandom.urlsafe_base64(nil, false)
|
|
701
|
+
break random_token unless self.class.exists?(guest_token: random_token)
|
|
685
702
|
end
|
|
703
|
+
end
|
|
686
704
|
end
|
|
687
705
|
end
|