spree_core 4.1.12 → 4.2.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/base_controller.rb +1 -2
  3. data/app/finders/spree/addresses/find.rb +1 -12
  4. data/app/finders/spree/base_finder.rb +14 -0
  5. data/app/finders/spree/countries/find.rb +11 -3
  6. data/app/finders/spree/credit_cards/find.rb +2 -2
  7. data/app/finders/spree/orders/find_current.rb +1 -1
  8. data/app/helpers/spree/base_helper.rb +61 -20
  9. data/app/helpers/spree/mail_helper.rb +29 -0
  10. data/app/helpers/spree/products_helper.rb +2 -1
  11. data/app/mailers/spree/base_mailer.rb +19 -5
  12. data/app/mailers/spree/order_mailer.rb +13 -4
  13. data/app/mailers/spree/reimbursement_mailer.rb +4 -2
  14. data/app/mailers/spree/shipment_mailer.rb +4 -2
  15. data/app/models/concerns/spree/default_price.rb +3 -6
  16. data/app/models/concerns/spree/user_methods.rb +11 -5
  17. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  18. data/app/models/spree/ability.rb +2 -6
  19. data/app/models/spree/address.rb +17 -1
  20. data/app/models/spree/adjustment.rb +1 -0
  21. data/app/models/spree/app_configuration.rb +4 -0
  22. data/app/models/spree/app_dependencies.rb +4 -2
  23. data/app/models/spree/base.rb +5 -0
  24. data/app/models/spree/credit_card.rb +5 -0
  25. data/app/models/spree/fulfilment_changer.rb +58 -16
  26. data/app/models/spree/inventory_unit.rb +2 -7
  27. data/app/models/spree/line_item.rb +11 -7
  28. data/app/models/spree/log_entry.rb +1 -1
  29. data/app/models/spree/option_type.rb +7 -1
  30. data/app/models/spree/order.rb +27 -5
  31. data/app/models/spree/order/address_book.rb +7 -20
  32. data/app/models/spree/order/payments.rb +10 -2
  33. data/app/models/spree/payment.rb +18 -4
  34. data/app/models/spree/payment/processing.rb +2 -2
  35. data/app/models/spree/payment_method.rb +3 -3
  36. data/app/models/spree/preferences/store.rb +1 -1
  37. data/app/models/spree/price.rb +25 -6
  38. data/app/models/spree/product.rb +29 -9
  39. data/app/models/spree/promotion.rb +10 -15
  40. data/app/models/spree/promotion/rules/product.rb +2 -1
  41. data/app/models/spree/promotion/rules/user.rb +2 -1
  42. data/app/models/spree/promotion_handler/coupon.rb +2 -3
  43. data/app/models/spree/promotion_handler/promotion_duplicator.rb +9 -3
  44. data/app/models/spree/refund.rb +2 -2
  45. data/app/models/spree/reimbursement.rb +2 -0
  46. data/app/models/spree/return_item/eligibility_validator/default.rb +0 -2
  47. data/app/models/spree/return_item/eligibility_validator/{r_m_a_required.rb → rma_required.rb} +0 -0
  48. data/app/models/spree/shipment.rb +3 -6
  49. data/app/models/spree/shipping_method.rb +1 -5
  50. data/app/models/spree/shipping_rate.rb +2 -11
  51. data/app/models/spree/stock/availability_validator.rb +3 -4
  52. data/app/models/spree/stock_item.rb +1 -5
  53. data/app/models/spree/stock_location.rb +13 -2
  54. data/app/models/spree/store.rb +51 -2
  55. data/app/models/spree/store_credit.rb +1 -1
  56. data/app/models/spree/variant.rb +16 -10
  57. data/app/models/spree/zone.rb +17 -4
  58. data/app/presenters/spree/variant_presenter.rb +9 -1
  59. data/app/presenters/spree/variants/option_types_presenter.rb +1 -0
  60. data/app/services/spree/account/addresses/create.rb +6 -1
  61. data/app/services/spree/account/addresses/{base.rb → helper.rb} +1 -3
  62. data/app/services/spree/account/addresses/update.rb +6 -1
  63. data/app/services/spree/compare_line_items.rb +4 -2
  64. data/app/sorters/spree/base_sorter.rb +35 -0
  65. data/app/sorters/spree/orders/sort.rb +1 -37
  66. data/app/sorters/spree/products/sort.rb +9 -32
  67. data/app/validators/email_validator.rb +1 -1
  68. data/app/views/layouts/spree/base_mailer.html.erb +45 -40
  69. data/app/views/spree/order_mailer/cancel_email.html.erb +19 -25
  70. data/app/views/spree/order_mailer/cancel_email.text.erb +24 -2
  71. data/app/views/spree/order_mailer/confirm_email.html.erb +18 -65
  72. data/app/views/spree/order_mailer/confirm_email.text.erb +2 -1
  73. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +23 -0
  74. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +38 -0
  75. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +53 -58
  76. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +3 -1
  77. data/app/views/spree/shared/_base_mailer_footer.html.erb +6 -14
  78. data/app/views/spree/shared/_base_mailer_header.html.erb +12 -32
  79. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +293 -625
  80. data/app/views/spree/shared/_purchased_items_table.html.erb +60 -0
  81. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +13 -0
  82. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +27 -0
  83. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +13 -0
  84. data/app/views/spree/shared/purchased_items_table/_total.html.erb +13 -0
  85. data/app/views/spree/shipment_mailer/shipped_email.html.erb +31 -36
  86. data/app/views/spree/shipment_mailer/shipped_email.text.erb +2 -1
  87. data/config/initializers/assets.rb +1 -0
  88. data/config/initializers/inflections.rb +3 -0
  89. data/config/initializers/rails61_fixes.rb +3 -0
  90. data/config/locales/en.yml +145 -19
  91. data/db/default/spree/countries.rb +10 -4
  92. data/db/default/spree/states.rb +42 -5
  93. data/db/default/spree/stores.rb +17 -12
  94. data/db/default/spree/zones.rb +1 -1
  95. data/db/migrate/20130326175857_add_stock_location_to_rma.rb +1 -1
  96. data/db/migrate/20140309033438_create_store_from_preferences.rb +1 -1
  97. data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +10 -0
  98. data/db/migrate/20200102141311_add_social_to_spree_stores.rb +3 -0
  99. data/db/migrate/20200308210757_add_default_locale_to_spree_store.rb +7 -0
  100. data/db/migrate/20200310145140_add_customer_support_email_to_spree_store.rb +7 -0
  101. data/db/migrate/20200421095017_add_compare_at_amount_to_spree_prices.rb +7 -0
  102. data/db/migrate/20200423123001_add_default_country_id_to_spree_store.rb +9 -0
  103. data/db/migrate/20200430072209_add_footer_fields_to_spree_stores.rb +8 -0
  104. data/db/migrate/20200513154939_add_show_property_to_spree_product_properties.rb +5 -0
  105. data/db/migrate/20200607161221_add_store_owner_order_notification_delivered_to_spree_orders.rb +7 -0
  106. data/db/migrate/20200607161222_add_new_order_notifications_email_to_spree_stores.rb +7 -0
  107. data/db/migrate/20200610113542_add_label_to_spree_addresses.rb +5 -0
  108. data/db/migrate/20200826075557_add_unique_index_on_taxon_id_and_product_id_to_spree_products_taxons.rb +5 -0
  109. data/db/migrate/20201006110150_add_checkout_zone_field_to_store.rb +12 -0
  110. data/db/migrate/20201012091259_add_filterable_column_to_spree_option_types.rb +6 -0
  111. data/db/migrate/20201013084504_add_seo_robots_to_spree_stores.rb +5 -0
  112. data/db/migrate/20201127084048_add_default_country_kind_to_spree_zones.rb +5 -0
  113. data/db/migrate/20210112193440_remove_contact_email_from_spree_stores.rb +5 -0
  114. data/db/migrate/20210114182625_create_spree_payment_methods_stores.rb +10 -0
  115. data/db/migrate/20210114220232_migrate_data_payment_methods_stores.rb +15 -0
  116. data/db/migrate/20210117112551_remove_store_id_from_spree_payment_methods.rb +5 -0
  117. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -2
  118. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -2
  119. data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +23 -0
  120. data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +13 -0
  121. data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +5 -0
  122. data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +5 -0
  123. data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +11 -0
  124. data/lib/spree/core.rb +2 -0
  125. data/lib/spree/core/controller_helpers/common.rb +1 -0
  126. data/lib/spree/core/controller_helpers/currency_helpers.rb +15 -0
  127. data/lib/spree/core/controller_helpers/order.rb +9 -4
  128. data/lib/spree/core/controller_helpers/store.rb +12 -1
  129. data/lib/spree/core/importer/order.rb +9 -9
  130. data/lib/spree/core/product_filters.rb +3 -3
  131. data/lib/spree/core/version.rb +1 -1
  132. data/lib/spree/i18n.rb +7 -21
  133. data/lib/spree/permitted_attributes.rb +8 -5
  134. data/lib/spree/service_module.rb +6 -2
  135. data/lib/spree/testing_support/authorization_helpers.rb +7 -4
  136. data/lib/spree/testing_support/capybara_config.rb +1 -1
  137. data/lib/spree/testing_support/factories/promotion_factory.rb +29 -17
  138. data/lib/spree/testing_support/factories/shipment_factory.rb +7 -9
  139. data/lib/spree/testing_support/factories/store_factory.rb +11 -8
  140. data/lib/spree/testing_support/factories/zone_factory.rb +16 -13
  141. data/lib/spree/testing_support/i18n.rb +1 -1
  142. data/lib/spree/testing_support/order_walkthrough.rb +8 -3
  143. data/lib/spree/testing_support/rspec_retry_config.rb +10 -0
  144. data/spree_core.gemspec +10 -8
  145. data/vendor/assets/javascripts/cleave.js +1669 -0
  146. metadata +105 -30
  147. data/app/views/spree/order_mailer/_adjustment.html.erb +0 -8
  148. data/app/views/spree/order_mailer/_subtotal.html.erb +0 -8
  149. data/app/views/spree/order_mailer/_total.html.erb +0 -8
  150. data/lib/spree/i18n/base.rb +0 -17
  151. data/lib/spree/i18n/initializer.rb +0 -1
@@ -9,7 +9,7 @@ module Spree
9
9
  end
10
10
 
11
11
  def payment_sources
12
- credit_cards.with_payment_profile
12
+ credit_cards.with_payment_profile.not_expired
13
13
  end
14
14
 
15
15
  def drop_payment_source(source)
@@ -42,12 +42,7 @@ module Spree
42
42
  can :update, Order do |order, token|
43
43
  !order.completed? && (order.user == user || order.token && token == order.token)
44
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
45
+ can :manage, Address, user_id: user.id
51
46
  can :read, CreditCard, user_id: user.id
52
47
  can :read, Product
53
48
  can :read, ProductProperty
@@ -55,6 +50,7 @@ module Spree
55
50
  can :create, Spree.user_class
56
51
  can [:show, :update, :destroy], Spree.user_class, id: user.id
57
52
  can :read, State
53
+ can :read, Store
58
54
  can :read, Taxon
59
55
  can :read, Taxonomy
60
56
  can :read, Variant
@@ -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 currency configurations
72
+ preference :show_store_currency_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
- @order_sorter = 'Spree::Orders::Sort'
55
+ @collection_sorter = 'Spree::BaseSorter'
56
+ @order_sorter = 'Spree::BaseSorter'
55
57
  @products_sorter = 'Spree::Products::Sort'
56
58
 
57
59
  # paginator
@@ -25,4 +25,9 @@ class Spree::Base < ApplicationRecord
25
25
  def self.spree_base_scopes
26
26
  where(nil)
27
27
  end
28
+
29
+ # FIXME: https://github.com/rails/rails/issues/40943
30
+ def self.has_many_inversing
31
+ false
32
+ end
28
33
  end
@@ -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
- :current_shipment, :desired_shipment, :available_quantity
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
- update_current_shipment_inventory_units(new_on_hand_quantity, :on_hand)
49
- update_current_shipment_inventory_units(quantity - new_on_hand_quantity, :backordered)
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.length.zero?
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, quantity].min
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.size, quantity].min
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, :not_enough_stock_at_desired_location)
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,16 @@ module Spree
57
57
  end
58
58
 
59
59
  def update_price
60
- self.price = variant.price_including_vat_for(tax_zone: tax_zone)
60
+ if Spree::Config.show_store_currency_selector == true
61
+ currency_price = Spree::Price.where(
62
+ currency: order.currency,
63
+ variant_id: variant_id
64
+ ).first
65
+
66
+ self.price = currency_price.price_including_vat_for(tax_zone: tax_zone)
67
+ else
68
+ self.price = variant.price_including_vat_for(tax_zone: tax_zone)
69
+ end
61
70
  end
62
71
 
63
72
  def copy_tax_category
@@ -111,11 +120,6 @@ module Spree
111
120
  assign_attributes opts
112
121
  end
113
122
 
114
- # Remove variant default_scope `deleted_at: nil`
115
- def variant
116
- Spree::Variant.unscoped { super }
117
- end
118
-
119
123
  private
120
124
 
121
125
  def ensure_valid_quantity
@@ -11,7 +11,7 @@ module Spree
11
11
  end
12
12
 
13
13
  def parsed_details
14
- @details ||= YAML.load(details)
14
+ @details ||= YAML.safe_load(details, [ActiveMerchant::Billing::Response])
15
15
  end
16
16
  end
17
17
  end
@@ -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
- presentation.titleize.delete(' ').downcase
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
@@ -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
@@ -55,31 +55,18 @@ module Spree
55
55
  def update_or_create_address(attributes = {})
56
56
  return if attributes.blank?
57
57
 
58
- attributes = attributes.select { |_k, v| v.present? }
58
+ attributes.transform_values! { |v| v == '' ? nil : v }
59
59
 
60
- if user
61
- address = user.addresses.build(attributes.except(:id)).check
62
- return address if address.id
63
- end
64
-
65
- if attributes[:id]
66
- address = Spree::Address.find(attributes[:id])
67
- attributes.delete(:id)
60
+ default_address_scope = user ? user.addresses : ::Spree::Address
61
+ default_address = default_address_scope.find_by(id: attributes[:id])
68
62
 
69
- if address&.editable?
70
- address.update(attributes)
71
- return address
72
- else
73
- attributes.delete(:id)
74
- end
75
- end
63
+ if default_address&.editable?
64
+ default_address.update(attributes)
76
65
 
77
- unless attributes[:id]
78
- address = Spree::Address.new(attributes)
79
- address.save
66
+ return default_address
80
67
  end
81
68
 
82
- address
69
+ ::Spree::Address.find_or_create_by(attributes.except(:id, :updated_at, :created_at))
83
70
  end
84
71
  end
85
72
  end