spree_core 4.1.13 → 4.2.0.rc4
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/controllers/spree/base_controller.rb +1 -2
- data/app/finders/spree/addresses/find.rb +1 -12
- data/app/finders/spree/base_finder.rb +14 -0
- data/app/finders/spree/countries/find.rb +11 -3
- data/app/finders/spree/credit_cards/find.rb +2 -2
- data/app/finders/spree/orders/find_current.rb +1 -1
- data/app/helpers/spree/base_helper.rb +61 -20
- data/app/helpers/spree/mail_helper.rb +29 -0
- data/app/helpers/spree/products_helper.rb +2 -1
- data/app/mailers/spree/base_mailer.rb +19 -5
- data/app/mailers/spree/order_mailer.rb +13 -4
- data/app/mailers/spree/reimbursement_mailer.rb +4 -2
- data/app/mailers/spree/shipment_mailer.rb +4 -2
- data/app/models/concerns/spree/default_price.rb +3 -6
- data/app/models/concerns/spree/user_methods.rb +11 -5
- data/app/models/concerns/spree/user_payment_source.rb +1 -1
- data/app/models/spree/ability.rb +45 -34
- data/app/models/spree/address.rb +17 -1
- data/app/models/spree/adjustment.rb +1 -0
- data/app/models/spree/app_configuration.rb +4 -0
- data/app/models/spree/app_dependencies.rb +4 -2
- data/app/models/spree/base.rb +5 -0
- data/app/models/spree/credit_card.rb +5 -0
- data/app/models/spree/fulfilment_changer.rb +58 -16
- data/app/models/spree/inventory_unit.rb +2 -7
- data/app/models/spree/line_item.rb +8 -7
- data/app/models/spree/log_entry.rb +1 -1
- data/app/models/spree/option_type.rb +7 -1
- data/app/models/spree/order.rb +27 -5
- data/app/models/spree/order/payments.rb +10 -2
- data/app/models/spree/payment.rb +18 -4
- data/app/models/spree/payment/processing.rb +2 -2
- data/app/models/spree/payment_method.rb +3 -3
- data/app/models/spree/preferences/store.rb +1 -1
- data/app/models/spree/price.rb +25 -6
- data/app/models/spree/product.rb +29 -9
- data/app/models/spree/promotion.rb +10 -15
- data/app/models/spree/promotion/rules/product.rb +2 -1
- data/app/models/spree/promotion/rules/user.rb +2 -1
- data/app/models/spree/promotion_handler/coupon.rb +1 -1
- data/app/models/spree/promotion_handler/promotion_duplicator.rb +9 -3
- data/app/models/spree/refund.rb +2 -2
- data/app/models/spree/reimbursement.rb +2 -0
- data/app/models/spree/return_item/eligibility_validator/default.rb +0 -2
- data/app/models/spree/return_item/eligibility_validator/{r_m_a_required.rb → rma_required.rb} +0 -0
- data/app/models/spree/shipment.rb +3 -6
- data/app/models/spree/shipping_method.rb +1 -5
- data/app/models/spree/shipping_rate.rb +2 -11
- data/app/models/spree/stock/availability_validator.rb +3 -4
- data/app/models/spree/stock_item.rb +1 -5
- data/app/models/spree/stock_location.rb +13 -2
- data/app/models/spree/store.rb +51 -2
- data/app/models/spree/store_credit.rb +1 -1
- data/app/models/spree/variant.rb +16 -10
- data/app/models/spree/zone.rb +17 -4
- data/app/presenters/spree/variant_presenter.rb +9 -1
- data/app/presenters/spree/variants/option_types_presenter.rb +1 -0
- data/app/services/spree/account/addresses/create.rb +6 -1
- data/app/services/spree/account/addresses/{base.rb → helper.rb} +1 -3
- data/app/services/spree/account/addresses/update.rb +6 -1
- data/app/services/spree/compare_line_items.rb +4 -2
- data/app/sorters/spree/base_sorter.rb +35 -0
- data/app/sorters/spree/orders/sort.rb +1 -37
- data/app/sorters/spree/products/sort.rb +9 -32
- data/app/validators/email_validator.rb +1 -1
- data/app/views/layouts/spree/base_mailer.html.erb +45 -40
- data/app/views/spree/order_mailer/cancel_email.html.erb +19 -25
- data/app/views/spree/order_mailer/cancel_email.text.erb +24 -2
- data/app/views/spree/order_mailer/confirm_email.html.erb +18 -65
- data/app/views/spree/order_mailer/confirm_email.text.erb +2 -1
- data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +23 -0
- data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +38 -0
- data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +53 -58
- data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +3 -1
- data/app/views/spree/shared/_base_mailer_footer.html.erb +6 -14
- data/app/views/spree/shared/_base_mailer_header.html.erb +12 -32
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +293 -625
- data/app/views/spree/shared/_purchased_items_table.html.erb +60 -0
- data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +13 -0
- data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +27 -0
- data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +13 -0
- data/app/views/spree/shared/purchased_items_table/_total.html.erb +13 -0
- data/app/views/spree/shipment_mailer/shipped_email.html.erb +31 -36
- data/app/views/spree/shipment_mailer/shipped_email.text.erb +2 -1
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/inflections.rb +3 -0
- data/config/initializers/rails61_fixes.rb +3 -0
- data/config/locales/en.yml +145 -19
- data/db/default/spree/countries.rb +10 -4
- data/db/default/spree/states.rb +42 -5
- data/db/default/spree/stores.rb +17 -12
- data/db/default/spree/zones.rb +5 -2
- data/db/migrate/20130326175857_add_stock_location_to_rma.rb +1 -1
- data/db/migrate/20140309033438_create_store_from_preferences.rb +1 -1
- data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +10 -0
- data/db/migrate/20200102141311_add_social_to_spree_stores.rb +3 -0
- data/db/migrate/20200308210757_add_default_locale_to_spree_store.rb +7 -0
- data/db/migrate/20200310145140_add_customer_support_email_to_spree_store.rb +7 -0
- data/db/migrate/20200421095017_add_compare_at_amount_to_spree_prices.rb +7 -0
- data/db/migrate/20200423123001_add_default_country_id_to_spree_store.rb +9 -0
- data/db/migrate/20200430072209_add_footer_fields_to_spree_stores.rb +8 -0
- data/db/migrate/20200513154939_add_show_property_to_spree_product_properties.rb +5 -0
- data/db/migrate/20200607161221_add_store_owner_order_notification_delivered_to_spree_orders.rb +7 -0
- data/db/migrate/20200607161222_add_new_order_notifications_email_to_spree_stores.rb +7 -0
- data/db/migrate/20200610113542_add_label_to_spree_addresses.rb +5 -0
- data/db/migrate/20200826075557_add_unique_index_on_taxon_id_and_product_id_to_spree_products_taxons.rb +5 -0
- data/db/migrate/20201006110150_add_checkout_zone_field_to_store.rb +12 -0
- data/db/migrate/20201012091259_add_filterable_column_to_spree_option_types.rb +6 -0
- data/db/migrate/20201013084504_add_seo_robots_to_spree_stores.rb +5 -0
- data/db/migrate/20201127084048_add_default_country_kind_to_spree_zones.rb +5 -0
- data/db/migrate/20210112193440_remove_contact_email_from_spree_stores.rb +5 -0
- data/db/migrate/20210114182625_create_spree_payment_methods_stores.rb +10 -0
- data/db/migrate/20210114220232_migrate_data_payment_methods_stores.rb +15 -0
- data/db/migrate/20210117112551_remove_store_id_from_spree_payment_methods.rb +5 -0
- data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -2
- data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -2
- data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +23 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +13 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +5 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +5 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +11 -0
- data/lib/spree/core.rb +2 -0
- data/lib/spree/core/controller_helpers/common.rb +1 -0
- data/lib/spree/core/controller_helpers/currency_helpers.rb +15 -0
- data/lib/spree/core/controller_helpers/order.rb +9 -4
- data/lib/spree/core/controller_helpers/store.rb +16 -1
- data/lib/spree/core/importer/order.rb +9 -9
- data/lib/spree/core/product_filters.rb +3 -3
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/i18n.rb +7 -21
- data/lib/spree/permitted_attributes.rb +8 -5
- data/lib/spree/service_module.rb +6 -2
- data/lib/spree/testing_support/authorization_helpers.rb +7 -4
- data/lib/spree/testing_support/capybara_config.rb +1 -1
- data/lib/spree/testing_support/factories/promotion_factory.rb +29 -17
- data/lib/spree/testing_support/factories/shipment_factory.rb +7 -9
- data/lib/spree/testing_support/factories/store_factory.rb +11 -8
- data/lib/spree/testing_support/factories/zone_factory.rb +16 -13
- data/lib/spree/testing_support/i18n.rb +1 -1
- data/lib/spree/testing_support/order_walkthrough.rb +8 -3
- data/lib/spree/testing_support/rspec_retry_config.rb +10 -0
- data/spree_core.gemspec +10 -8
- data/vendor/assets/javascripts/cleave.js +1669 -0
- metadata +105 -30
- data/app/views/spree/order_mailer/_adjustment.html.erb +0 -8
- data/app/views/spree/order_mailer/_subtotal.html.erb +0 -8
- data/app/views/spree/order_mailer/_total.html.erb +0 -8
- data/lib/spree/i18n/base.rb +0 -17
- data/lib/spree/i18n/initializer.rb +0 -1
data/app/models/spree/ability.rb
CHANGED
|
@@ -23,59 +23,70 @@ module Spree
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def initialize(user)
|
|
26
|
-
|
|
27
|
-
alias_action :delete, to: :destroy
|
|
28
|
-
alias_action :create, :update, :destroy, to: :modify
|
|
26
|
+
alias_cancan_delete_action
|
|
29
27
|
|
|
30
28
|
user ||= Spree.user_class.new
|
|
31
29
|
|
|
32
30
|
if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin')
|
|
33
|
-
|
|
31
|
+
apply_admin_permissions(user)
|
|
34
32
|
else
|
|
35
|
-
|
|
36
|
-
can :read, OptionType
|
|
37
|
-
can :read, OptionValue
|
|
38
|
-
can :create, Order
|
|
39
|
-
can :show, Order do |order, token|
|
|
40
|
-
order.user == user || order.token && token == order.token
|
|
41
|
-
end
|
|
42
|
-
can :update, Order do |order, token|
|
|
43
|
-
!order.completed? && (order.user == user || order.token && token == order.token)
|
|
44
|
-
end
|
|
45
|
-
can :manage, Spree::Address do |address|
|
|
46
|
-
address.user == user
|
|
47
|
-
end
|
|
48
|
-
can :create, Spree::Address do |_address|
|
|
49
|
-
user.id.present?
|
|
50
|
-
end
|
|
51
|
-
can :read, CreditCard, user_id: user.id
|
|
52
|
-
can :read, Product
|
|
53
|
-
can :read, ProductProperty
|
|
54
|
-
can :read, Property
|
|
55
|
-
can :create, Spree.user_class
|
|
56
|
-
can [:show, :update, :destroy], Spree.user_class, id: user.id
|
|
57
|
-
can :read, State
|
|
58
|
-
can :read, Taxon
|
|
59
|
-
can :read, Taxonomy
|
|
60
|
-
can :read, Variant
|
|
61
|
-
can :read, Zone
|
|
33
|
+
apply_user_permissions(user)
|
|
62
34
|
end
|
|
63
35
|
|
|
64
36
|
# Include any abilities registered by extensions, etc.
|
|
37
|
+
# this is legacy behaviour and should be removed in Spree 5.0
|
|
65
38
|
Ability.abilities.merge(abilities_to_register).each do |clazz|
|
|
66
39
|
merge clazz.new(user)
|
|
67
40
|
end
|
|
68
41
|
|
|
69
|
-
|
|
70
|
-
cannot [:update, :destroy], Role, name: ['admin']
|
|
42
|
+
protect_admin_role
|
|
71
43
|
end
|
|
72
44
|
|
|
73
|
-
|
|
45
|
+
protected
|
|
74
46
|
|
|
75
47
|
# you can override this method to register your abilities
|
|
76
48
|
# this method has to return array of classes
|
|
77
49
|
def abilities_to_register
|
|
78
50
|
[]
|
|
79
51
|
end
|
|
52
|
+
|
|
53
|
+
def alias_cancan_delete_action
|
|
54
|
+
alias_action :delete, to: :destroy
|
|
55
|
+
alias_action :create, :update, :destroy, to: :modify
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def apply_admin_permissions(user)
|
|
59
|
+
can :manage, :all
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def apply_user_permissions(user)
|
|
63
|
+
can :read, ::Spree::Country
|
|
64
|
+
can :read, ::Spree::OptionType
|
|
65
|
+
can :read, ::Spree::OptionValue
|
|
66
|
+
can :create, ::Spree::Order
|
|
67
|
+
can :show, ::Spree::Order do |order, token|
|
|
68
|
+
order.user == user || order.token && token == order.token
|
|
69
|
+
end
|
|
70
|
+
can :update, ::Spree::Order do |order, token|
|
|
71
|
+
!order.completed? && (order.user == user || order.token && token == order.token)
|
|
72
|
+
end
|
|
73
|
+
can :manage, ::Spree::Address, user_id: user.id
|
|
74
|
+
can :read, ::Spree::CreditCard, user_id: user.id
|
|
75
|
+
can :read, ::Spree::Product
|
|
76
|
+
can :read, ::Spree::ProductProperty
|
|
77
|
+
can :read, ::Spree::Property
|
|
78
|
+
can :create, ::Spree.user_class
|
|
79
|
+
can [:show, :update, :destroy], ::Spree.user_class, id: user.id
|
|
80
|
+
can :read, ::Spree::State
|
|
81
|
+
can :read, ::Spree::Store
|
|
82
|
+
can :read, ::Spree::Taxon
|
|
83
|
+
can :read, ::Spree::Taxonomy
|
|
84
|
+
can :read, ::Spree::Variant
|
|
85
|
+
can :read, ::Spree::Zone
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def protect_admin_role
|
|
89
|
+
cannot [:update, :destroy], ::Spree::Role, name: ['admin']
|
|
90
|
+
end
|
|
80
91
|
end
|
|
81
92
|
end
|
data/app/models/spree/address.rb
CHANGED
|
@@ -2,6 +2,10 @@ module Spree
|
|
|
2
2
|
class Address < Spree::Base
|
|
3
3
|
require 'twitter_cldr'
|
|
4
4
|
|
|
5
|
+
if Rails::VERSION::STRING >= '6.1'
|
|
6
|
+
serialize :preferences, Hash, default: {}
|
|
7
|
+
end
|
|
8
|
+
|
|
5
9
|
NO_ZIPCODE_ISO_CODES ||= [
|
|
6
10
|
'AO', 'AG', 'AW', 'BS', 'BZ', 'BJ', 'BM', 'BO', 'BW', 'BF', 'BI', 'CM', 'CF', 'KM', 'CG',
|
|
7
11
|
'CD', 'CK', 'CUW', 'CI', 'DJ', 'DM', 'GQ', 'ER', 'FJ', 'TF', 'GAB', 'GM', 'GH', 'GD', 'GN',
|
|
@@ -10,10 +14,16 @@ module Spree
|
|
|
10
14
|
'TO', 'TV', 'UG', 'AE', 'VU', 'YE', 'ZW'
|
|
11
15
|
].freeze
|
|
12
16
|
|
|
17
|
+
# The required states listed below match those used by PayPal and Shopify.
|
|
18
|
+
STATES_REQUIRED = [
|
|
19
|
+
'AU', 'AE', 'BR', 'CA', 'CN', 'ES', 'HK', 'IE', 'IN',
|
|
20
|
+
'IT', 'MY', 'MX', 'NZ', 'PT', 'RO', 'TH', 'US', 'ZA'
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
13
23
|
# we're not freezing this on purpose so developers can extend and manage
|
|
14
24
|
# those attributes depending of the logic of their applications
|
|
15
25
|
ADDRESS_FIELDS = %w(firstname lastname company address1 address2 city state zipcode country phone)
|
|
16
|
-
EXCLUDED_KEYS_FOR_COMPARISION = %w(id updated_at created_at deleted_at user_id)
|
|
26
|
+
EXCLUDED_KEYS_FOR_COMPARISION = %w(id updated_at created_at deleted_at label user_id)
|
|
17
27
|
|
|
18
28
|
belongs_to :country, class_name: 'Spree::Country'
|
|
19
29
|
belongs_to :state, class_name: 'Spree::State', optional: true
|
|
@@ -31,6 +41,12 @@ module Spree
|
|
|
31
41
|
|
|
32
42
|
validate :state_validate, :postal_code_validate
|
|
33
43
|
|
|
44
|
+
validates :label, uniqueness: { conditions: -> { where(deleted_at: nil) },
|
|
45
|
+
scope: :user_id,
|
|
46
|
+
case_sensitive: false,
|
|
47
|
+
allow_blank: true,
|
|
48
|
+
allow_nil: true }
|
|
49
|
+
|
|
34
50
|
delegate :name, :iso3, :iso, :iso_name, to: :country, prefix: true
|
|
35
51
|
delegate :abbr, to: :state, prefix: true, allow_nil: true
|
|
36
52
|
|
|
@@ -27,6 +27,7 @@ module Spree
|
|
|
27
27
|
belongs_to :source
|
|
28
28
|
end
|
|
29
29
|
belongs_to :order, class_name: 'Spree::Order', inverse_of: :all_adjustments
|
|
30
|
+
belongs_to :promotion_action, class_name: 'Spree::PromotionAction', foreign_key: :source_id, optional: true # created only for has_free_shipping?
|
|
30
31
|
|
|
31
32
|
validates :adjustable, :order, :label, presence: true
|
|
32
33
|
validates :amount, numericality: true
|
|
@@ -49,6 +49,7 @@ module Spree
|
|
|
49
49
|
preference :expedited_exchanges_days_window, :integer, default: 14 # the amount of days the customer has to return their item after the expedited exchange is shipped in order to avoid being charged
|
|
50
50
|
preference :layout, :string, default: 'spree/layouts/spree_application'
|
|
51
51
|
preference :logo, :string, default: 'logo/spree_50.png'
|
|
52
|
+
preference :mailer_logo, :string, default: 'logo/spree_50.png'
|
|
52
53
|
preference :max_level_in_taxons_menu, :integer, default: 1 # maximum nesting level in taxons menu
|
|
53
54
|
preference :products_per_page, :integer, default: 12
|
|
54
55
|
preference :require_master_price, :boolean, default: true
|
|
@@ -67,6 +68,9 @@ module Spree
|
|
|
67
68
|
preference :non_expiring_credit_types, :array, default: []
|
|
68
69
|
preference :credit_to_new_allocation, :boolean, default: false
|
|
69
70
|
|
|
71
|
+
# Multi store configurations
|
|
72
|
+
preference :show_store_selector, :boolean, default: false
|
|
73
|
+
|
|
70
74
|
# searcher_class allows spree extension writers to provide their own Search class
|
|
71
75
|
def searcher_class
|
|
72
76
|
@searcher_class ||= Spree::Core::Search::Base
|
|
@@ -12,7 +12,8 @@ module Spree
|
|
|
12
12
|
:coupon_handler, :country_finder, :current_order_finder, :credit_card_finder,
|
|
13
13
|
:completed_order_finder, :order_sorter, :cart_compare_line_items_service, :collection_paginator, :products_sorter,
|
|
14
14
|
:products_finder, :taxon_finder, :line_item_by_variant_finder, :cart_estimate_shipping_rates_service,
|
|
15
|
-
:account_create_address_service, :account_update_address_service, :address_finder
|
|
15
|
+
:account_create_address_service, :account_update_address_service, :address_finder,
|
|
16
|
+
:collection_sorter
|
|
16
17
|
].freeze
|
|
17
18
|
|
|
18
19
|
attr_accessor *INJECTION_POINTS
|
|
@@ -51,7 +52,8 @@ module Spree
|
|
|
51
52
|
@checkout_get_shipping_rates_service = 'Spree::Checkout::GetShippingRates'
|
|
52
53
|
|
|
53
54
|
# sorter
|
|
54
|
-
@
|
|
55
|
+
@collection_sorter = 'Spree::BaseSorter'
|
|
56
|
+
@order_sorter = 'Spree::BaseSorter'
|
|
55
57
|
@products_sorter = 'Spree::Products::Sort'
|
|
56
58
|
|
|
57
59
|
# paginator
|
data/app/models/spree/base.rb
CHANGED
|
@@ -37,6 +37,11 @@ module Spree
|
|
|
37
37
|
|
|
38
38
|
scope :with_payment_profile, -> { where.not(gateway_customer_profile_id: nil) }
|
|
39
39
|
scope :default, -> { where(default: true) }
|
|
40
|
+
scope :not_expired, lambda {
|
|
41
|
+
where('CAST(spree_credit_cards.year AS DECIMAL) > ?', Time.current.year).
|
|
42
|
+
or(where('CAST(spree_credit_cards.year AS DECIMAL) = ?', Time.current.year).
|
|
43
|
+
where('CAST(spree_credit_cards.month AS DECIMAL) >= ?', Time.current.month))
|
|
44
|
+
}
|
|
40
45
|
|
|
41
46
|
# needed for some of the ActiveMerchant gateways (eg. SagePay)
|
|
42
47
|
alias_attribute :brand, :cc_type
|
|
@@ -36,7 +36,7 @@ module Spree
|
|
|
36
36
|
private
|
|
37
37
|
|
|
38
38
|
attr_reader :variant, :quantity, :current_stock_location, :desired_stock_location,
|
|
39
|
-
|
|
39
|
+
:current_shipment, :desired_shipment, :available_quantity
|
|
40
40
|
|
|
41
41
|
def handle_stock
|
|
42
42
|
ActiveRecord::Base.transaction do
|
|
@@ -45,13 +45,64 @@ module Spree
|
|
|
45
45
|
desired_stock_location.unstock(variant, unstock_quantity, desired_shipment)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
move_inventory_units_between_shipments
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def move_inventory_units_between_shipments
|
|
53
|
+
update_desired_shipment_inventory_units
|
|
54
|
+
update_current_shipment_inventory_units
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def current_shipment_units
|
|
58
|
+
@current_shipment_units ||= current_shipment.inventory_units.on_hand_or_backordered.where(variant_id: variant.id)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def update_desired_shipment_inventory_units
|
|
62
|
+
on_hand_unit = get_desired_shipment_inventory_unit(:on_hand)
|
|
63
|
+
on_hand_unit.update(quantity: on_hand_unit.quantity + new_on_hand_quantity)
|
|
64
|
+
|
|
65
|
+
new_backorder_quantity = current_on_hand_quantity - new_on_hand_quantity
|
|
66
|
+
if new_backorder_quantity > 0
|
|
67
|
+
backordered_unit = get_desired_shipment_inventory_unit(:backordered)
|
|
68
|
+
backordered_unit.update(quantity: backordered_unit.quantity + new_backorder_quantity)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def update_current_shipment_inventory_units
|
|
73
|
+
reduced_quantity = current_on_hand_quantity
|
|
74
|
+
|
|
75
|
+
# Reduce quantities from all backordered units first in case there is more than one.
|
|
76
|
+
backorder_units = current_shipment_units.backordered
|
|
77
|
+
reduced_quantity = reduce_units_quantities(reduced_quantity, backorder_units) if backorder_units.any?
|
|
78
|
+
|
|
79
|
+
# Reduce quantities from all on_hand units in case there is more than one.
|
|
80
|
+
if reduced_quantity > 0
|
|
81
|
+
on_hand_units = current_shipment_units.on_hand
|
|
82
|
+
reduce_units_quantities(reduced_quantity, on_hand_units) if on_hand_units.any?
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def reduce_units_quantities(reduced_quantity, units)
|
|
87
|
+
units.each do |unit|
|
|
88
|
+
unit.quantity > reduced_quantity ? unit.update(quantity: unit.quantity - reduced_quantity) : unit.destroy!
|
|
89
|
+
reduced_quantity -= unit.quantity
|
|
90
|
+
end
|
|
91
|
+
reduced_quantity
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def get_desired_shipment_inventory_unit(state)
|
|
95
|
+
desired_shipment.inventory_units.find_or_create_by(state: state) do |unit|
|
|
96
|
+
current_shipment_unit = current_shipment_units.first
|
|
97
|
+
unit.variant_id = current_shipment_unit.variant_id
|
|
98
|
+
unit.order_id = current_shipment_unit.order_id
|
|
99
|
+
unit.line_item_id = current_shipment_unit.line_item_id
|
|
100
|
+
unit.quantity = 0
|
|
50
101
|
end
|
|
51
102
|
end
|
|
52
103
|
|
|
53
104
|
def after_process_shipments
|
|
54
|
-
if current_shipment.inventory_units.
|
|
105
|
+
if current_shipment.inventory_units.sum(:quantity).zero?
|
|
55
106
|
current_shipment.destroy!
|
|
56
107
|
else
|
|
57
108
|
current_shipment.refresh_rates
|
|
@@ -64,7 +115,7 @@ module Spree
|
|
|
64
115
|
end
|
|
65
116
|
|
|
66
117
|
def new_on_hand_quantity
|
|
67
|
-
[available_quantity,
|
|
118
|
+
[available_quantity, current_on_hand_quantity].min
|
|
68
119
|
end
|
|
69
120
|
|
|
70
121
|
def unstock_quantity
|
|
@@ -72,16 +123,7 @@ module Spree
|
|
|
72
123
|
end
|
|
73
124
|
|
|
74
125
|
def current_on_hand_quantity
|
|
75
|
-
[current_shipment.inventory_units.on_hand_or_backordered.
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def update_current_shipment_inventory_units(quantity, state)
|
|
79
|
-
current_shipment.
|
|
80
|
-
inventory_units.
|
|
81
|
-
where(variant: variant).
|
|
82
|
-
order(state: :asc).
|
|
83
|
-
limit(quantity).
|
|
84
|
-
update_all(shipment_id: desired_shipment.id, state: state)
|
|
126
|
+
[current_shipment.inventory_units.on_hand_or_backordered.sum(:quantity), quantity].min
|
|
85
127
|
end
|
|
86
128
|
|
|
87
129
|
def reload_shipment_inventory_units
|
|
@@ -105,7 +147,7 @@ module Spree
|
|
|
105
147
|
def enough_stock_at_desired_location
|
|
106
148
|
return if Spree::Stock::Quantifier.new(variant, desired_stock_location).can_supply?(quantity)
|
|
107
149
|
|
|
108
|
-
errors.add(:desired_shipment, :
|
|
150
|
+
errors.add(:desired_shipment, :has_not_enough_stock_at_desired_location)
|
|
109
151
|
end
|
|
110
152
|
|
|
111
153
|
def desired_shipment_different_from_current
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class InventoryUnit < Spree::Base
|
|
3
3
|
with_options inverse_of: :inventory_units do
|
|
4
|
-
belongs_to :variant, class_name: 'Spree::Variant'
|
|
4
|
+
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
|
5
5
|
belongs_to :order, class_name: 'Spree::Order'
|
|
6
6
|
belongs_to :shipment, class_name: 'Spree::Shipment', touch: true, optional: true
|
|
7
|
-
has_many :return_items
|
|
7
|
+
has_many :return_items, inverse_of: :inventory_unit
|
|
8
8
|
has_many :return_authorizations, class_name: 'Spree::ReturnAuthorization', through: :return_items
|
|
9
9
|
belongs_to :line_item, class_name: 'Spree::LineItem'
|
|
10
10
|
end
|
|
@@ -84,11 +84,6 @@ module Spree
|
|
|
84
84
|
split_inventory!(1)
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
# Remove variant default_scope `deleted_at: nil`
|
|
88
|
-
def variant
|
|
89
|
-
Spree::Variant.unscoped { super }
|
|
90
|
-
end
|
|
91
|
-
|
|
92
87
|
def current_or_new_return_item
|
|
93
88
|
Spree::ReturnItem.from_inventory_unit(self)
|
|
94
89
|
end
|
|
@@ -4,7 +4,7 @@ module Spree
|
|
|
4
4
|
|
|
5
5
|
with_options inverse_of: :line_items do
|
|
6
6
|
belongs_to :order, class_name: 'Spree::Order', touch: true
|
|
7
|
-
belongs_to :variant, class_name: 'Spree::Variant'
|
|
7
|
+
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
|
8
8
|
end
|
|
9
9
|
belongs_to :tax_category, class_name: 'Spree::TaxCategory'
|
|
10
10
|
|
|
@@ -57,7 +57,13 @@ module Spree
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def update_price
|
|
60
|
-
|
|
60
|
+
currency_price = variant.price_in(order.currency)
|
|
61
|
+
|
|
62
|
+
self.price = if currency_price.amount.present?
|
|
63
|
+
currency_price.price_including_vat_for(tax_zone: tax_zone)
|
|
64
|
+
else
|
|
65
|
+
0
|
|
66
|
+
end
|
|
61
67
|
end
|
|
62
68
|
|
|
63
69
|
def copy_tax_category
|
|
@@ -111,11 +117,6 @@ module Spree
|
|
|
111
117
|
assign_attributes opts
|
|
112
118
|
end
|
|
113
119
|
|
|
114
|
-
# Remove variant default_scope `deleted_at: nil`
|
|
115
|
-
def variant
|
|
116
|
-
Spree::Variant.unscoped { super }
|
|
117
|
-
end
|
|
118
|
-
|
|
119
120
|
private
|
|
120
121
|
|
|
121
122
|
def ensure_valid_quantity
|
|
@@ -19,12 +19,18 @@ module Spree
|
|
|
19
19
|
|
|
20
20
|
default_scope { order(:position) }
|
|
21
21
|
|
|
22
|
+
scope :filterable, -> { where(filterable: true) }
|
|
23
|
+
|
|
22
24
|
accepts_nested_attributes_for :option_values, reject_if: ->(ov) { ov[:name].blank? || ov[:presentation].blank? }, allow_destroy: true
|
|
23
25
|
|
|
24
26
|
after_touch :touch_all_products
|
|
25
27
|
|
|
26
28
|
def filter_param
|
|
27
|
-
|
|
29
|
+
name.titleize.delete(' ').downcase
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.color
|
|
33
|
+
find_by(name: 'color')
|
|
28
34
|
end
|
|
29
35
|
|
|
30
36
|
private
|
data/app/models/spree/order.rb
CHANGED
|
@@ -157,6 +157,7 @@ module Spree
|
|
|
157
157
|
scope :completed_between, ->(start_date, end_date) { where(completed_at: start_date..end_date) }
|
|
158
158
|
scope :complete, -> { where.not(completed_at: nil) }
|
|
159
159
|
scope :incomplete, -> { where(completed_at: nil) }
|
|
160
|
+
scope :not_canceled, -> { where.not(state: 'canceled') }
|
|
160
161
|
|
|
161
162
|
# shows completed orders first, by their completed_at date, then uncompleted orders by their created_at
|
|
162
163
|
scope :reverse_chronological, -> { order(Arel.sql('spree_orders.completed_at IS NULL'), completed_at: :desc, created_at: :desc) }
|
|
@@ -302,15 +303,15 @@ module Spree
|
|
|
302
303
|
def outstanding_balance
|
|
303
304
|
if canceled?
|
|
304
305
|
-1 * payment_total
|
|
305
|
-
elsif refunds.exists?
|
|
306
|
-
# If refund has happened add it back to total to prevent balance_due payment state
|
|
307
|
-
# See: https://github.com/spree/spree/issues/6229 & https://github.com/spree/spree/issues/8136
|
|
308
|
-
total - (payment_total + refunds.sum(:amount))
|
|
309
306
|
else
|
|
310
|
-
total - payment_total
|
|
307
|
+
total - (payment_total + reimbursement_paid_total)
|
|
311
308
|
end
|
|
312
309
|
end
|
|
313
310
|
|
|
311
|
+
def reimbursement_paid_total
|
|
312
|
+
reimbursements.sum(&:paid_amount)
|
|
313
|
+
end
|
|
314
|
+
|
|
314
315
|
def outstanding_balance?
|
|
315
316
|
outstanding_balance != 0
|
|
316
317
|
end
|
|
@@ -356,6 +357,8 @@ module Spree
|
|
|
356
357
|
|
|
357
358
|
deliver_order_confirmation_email unless confirmation_delivered?
|
|
358
359
|
|
|
360
|
+
deliver_store_owner_order_notification_email if deliver_store_owner_order_notification_email?
|
|
361
|
+
|
|
359
362
|
consider_risk
|
|
360
363
|
end
|
|
361
364
|
|
|
@@ -646,6 +649,13 @@ module Spree
|
|
|
646
649
|
sum(:amount)
|
|
647
650
|
end
|
|
648
651
|
|
|
652
|
+
def has_free_shipping?
|
|
653
|
+
shipment_adjustments.
|
|
654
|
+
joins(:promotion_action).
|
|
655
|
+
where(spree_adjustments: { eligible: true, source_type: 'Spree::PromotionAction' },
|
|
656
|
+
spree_promotion_actions: { type: 'Spree::Promotion::Actions::FreeShipping' }).exists?
|
|
657
|
+
end
|
|
658
|
+
|
|
649
659
|
private
|
|
650
660
|
|
|
651
661
|
def link_by_email
|
|
@@ -711,5 +721,17 @@ module Spree
|
|
|
711
721
|
def credit_card_nil_payment?(attributes)
|
|
712
722
|
payments.store_credits.present? && attributes[:amount].to_f.zero?
|
|
713
723
|
end
|
|
724
|
+
|
|
725
|
+
# Returns true if:
|
|
726
|
+
# 1. an email address is set for new order notifications AND
|
|
727
|
+
# 2. no notification for this order has been sent yet.
|
|
728
|
+
def deliver_store_owner_order_notification_email?
|
|
729
|
+
store.new_order_notifications_email.present? && !store_owner_notification_delivered?
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
def deliver_store_owner_order_notification_email
|
|
733
|
+
OrderMailer.store_owner_notification_email(id).deliver_later
|
|
734
|
+
update_column(:store_owner_notification_delivered, true)
|
|
735
|
+
end
|
|
714
736
|
end
|
|
715
737
|
end
|