spree_core 4.2.5 → 4.3.0

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.
Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/concerns/spree/product_filterable.rb +9 -0
  3. data/app/finders/spree/cms_pages/find.rb +41 -0
  4. data/app/finders/spree/menus/find.rb +11 -0
  5. data/app/finders/spree/option_values/find_available.rb +20 -0
  6. data/app/finders/spree/orders/find_complete.rb +14 -2
  7. data/app/finders/spree/orders/find_current.rb +1 -13
  8. data/app/finders/spree/product_properties/find_available.rb +20 -0
  9. data/app/finders/spree/products/find.rb +80 -21
  10. data/app/finders/spree/stores/find_current.rb +24 -0
  11. data/app/finders/spree/taxons/find.rb +22 -6
  12. data/app/helpers/spree/base_helper.rb +69 -7
  13. data/app/helpers/spree/locale_helper.rb +5 -1
  14. data/app/helpers/spree/products_helper.rb +7 -3
  15. data/app/models/concerns/spree/display_link.rb +42 -0
  16. data/app/models/concerns/spree/display_money.rb +6 -2
  17. data/app/models/concerns/spree/filter_param.rb +21 -0
  18. data/app/models/concerns/spree/image_methods.rb +24 -0
  19. data/app/models/concerns/spree/memoized_data.rb +24 -0
  20. data/app/models/concerns/spree/multi_store_resource.rb +24 -0
  21. data/app/models/concerns/spree/product_scopes.rb +71 -8
  22. data/app/models/concerns/spree/single_store_resource.rb +19 -0
  23. data/app/models/concerns/spree/user_address.rb +19 -0
  24. data/app/models/concerns/spree/user_methods.rb +14 -12
  25. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  26. data/app/models/concerns/spree/user_reporting.rb +35 -10
  27. data/app/models/concerns/spree/user_roles.rb +25 -0
  28. data/app/models/spree/ability.rb +3 -1
  29. data/app/models/spree/address.rb +27 -6
  30. data/app/models/spree/app_configuration.rb +8 -0
  31. data/app/models/spree/app_dependencies.rb +20 -6
  32. data/app/models/spree/base.rb +18 -0
  33. data/app/models/spree/classification.rb +3 -0
  34. data/app/models/spree/cms/pages/feature_page.rb +7 -0
  35. data/app/models/spree/cms/pages/homepage.rb +20 -0
  36. data/app/models/spree/cms/pages/standard_page.rb +4 -0
  37. data/app/models/spree/cms/sections/featured_article.rb +22 -0
  38. data/app/models/spree/cms/sections/hero_image.rb +38 -0
  39. data/app/models/spree/cms/sections/image_gallery.rb +103 -0
  40. data/app/models/spree/cms/sections/product_carousel.rb +14 -0
  41. data/app/models/spree/cms/sections/rich_text_content.rb +13 -0
  42. data/app/models/spree/cms/sections/side_by_side_images.rb +74 -0
  43. data/app/models/spree/cms_page.rb +66 -0
  44. data/app/models/spree/cms_section.rb +69 -0
  45. data/app/models/spree/country.rb +14 -6
  46. data/app/models/spree/credit_card.rb +2 -8
  47. data/app/models/spree/customer_return.rb +8 -2
  48. data/app/models/spree/gateway/bogus.rb +6 -4
  49. data/app/models/spree/icon.rb +9 -0
  50. data/app/models/spree/image/configuration/active_storage.rb +2 -0
  51. data/app/models/spree/image.rb +5 -24
  52. data/app/models/spree/inventory_unit.rb +1 -1
  53. data/app/models/spree/line_item.rb +1 -1
  54. data/app/models/spree/menu.rb +63 -0
  55. data/app/models/spree/menu_item.rb +76 -0
  56. data/app/models/spree/option_type.rb +1 -1
  57. data/app/models/spree/option_value.rb +11 -0
  58. data/app/models/spree/option_value_variant.rb +1 -1
  59. data/app/models/spree/order/address_book.rb +3 -5
  60. data/app/models/spree/order/currency_updater.rb +1 -1
  61. data/app/models/spree/order/emails.rb +32 -0
  62. data/app/models/spree/order/payments.rb +1 -1
  63. data/app/models/spree/order/store_credit.rb +1 -1
  64. data/app/models/spree/order.rb +46 -45
  65. data/app/models/spree/payment.rb +7 -0
  66. data/app/models/spree/payment_method.rb +16 -0
  67. data/app/models/spree/preferences/preferable.rb +12 -0
  68. data/app/models/spree/preferences/preferable_class_methods.rb +10 -1
  69. data/app/models/spree/product.rb +37 -30
  70. data/app/models/spree/product_property.rb +19 -4
  71. data/app/models/spree/promotion/rules/country.rb +1 -1
  72. data/app/models/spree/promotion/rules/first_order.rb +4 -3
  73. data/app/models/spree/promotion/rules/taxon.rb +10 -7
  74. data/app/models/spree/promotion.rb +6 -15
  75. data/app/models/spree/promotion_handler/cart.rb +7 -2
  76. data/app/models/spree/promotion_handler/coupon.rb +5 -4
  77. data/app/models/spree/promotion_handler/free_shipping.rb +5 -6
  78. data/app/models/spree/promotion_handler/page.rb +3 -2
  79. data/app/models/spree/promotion_handler/promotion_duplicator.rb +1 -0
  80. data/app/models/spree/promotion_rule.rb +2 -0
  81. data/app/models/spree/property.rb +28 -1
  82. data/app/models/spree/reimbursement.rb +3 -1
  83. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +2 -1
  84. data/app/models/spree/shipment_handler.rb +4 -2
  85. data/app/models/spree/stock/quantifier.rb +6 -6
  86. data/app/models/spree/stock_location.rb +9 -0
  87. data/app/models/spree/store.rb +90 -7
  88. data/app/models/spree/store_credit.rb +7 -3
  89. data/app/models/spree/store_credit_event.rb +2 -2
  90. data/app/models/spree/store_payment_method.rb +11 -0
  91. data/app/models/spree/store_product.rb +11 -0
  92. data/app/models/spree/store_promotion.rb +11 -0
  93. data/app/models/spree/taxon.rb +22 -1
  94. data/app/models/spree/taxon_image/configuration/active_storage.rb +2 -0
  95. data/app/models/spree/taxon_image.rb +1 -0
  96. data/app/models/spree/taxonomy.rb +3 -1
  97. data/app/models/spree/variant.rb +21 -6
  98. data/app/presenters/spree/filters/options_presenter.rb +47 -0
  99. data/app/presenters/spree/filters/price_presenter.rb +22 -0
  100. data/app/presenters/spree/filters/price_range_presenter.rb +29 -0
  101. data/app/presenters/spree/filters/properties_presenter.rb +23 -0
  102. data/app/presenters/spree/filters/property_presenter.rb +42 -0
  103. data/app/presenters/spree/filters/quantified_price_range_presenter.rb +44 -0
  104. data/app/services/spree/account/addresses/create.rb +1 -0
  105. data/app/services/spree/account/addresses/helper.rb +6 -0
  106. data/app/services/spree/account/addresses/update.rb +9 -3
  107. data/app/services/spree/account/create.rb +17 -0
  108. data/app/services/spree/account/update.rb +15 -0
  109. data/app/services/spree/build_localized_redirect_url.rb +1 -1
  110. data/app/services/spree/cart/associate.rb +16 -0
  111. data/app/services/spree/cart/change_currency.rb +27 -0
  112. data/app/services/spree/cart/create.rb +5 -3
  113. data/app/services/spree/cart/destroy.rb +40 -0
  114. data/app/services/spree/cart/empty.rb +36 -0
  115. data/app/services/spree/cart/estimate_shipping_rates.rb +3 -3
  116. data/app/services/spree/checkout/add_store_credit.rb +1 -1
  117. data/app/services/spree/classifications/reposition.rb +18 -0
  118. data/app/services/spree/credit_cards/destroy.rb +41 -0
  119. data/app/sorters/spree/base_sorter.rb +23 -11
  120. data/app/sorters/spree/products/sort.rb +23 -7
  121. data/app/validators/db_maximum_length_validator.rb +5 -0
  122. data/app/validators/email_validator.rb +3 -1
  123. data/config/initializers/active_storage.rb +2 -0
  124. data/config/locales/en.yml +177 -3
  125. data/config/routes.rb +0 -5
  126. data/db/migrate/20201023152810_add_filterable_to_spree_properties.rb +8 -0
  127. data/db/migrate/20210407200948_create_spree_menus.rb +16 -0
  128. data/db/migrate/20210408092939_create_spree_menu_items.rb +31 -0
  129. data/db/migrate/20210504163720_add_filter_param_to_spree_product_properties.rb +8 -0
  130. data/db/migrate/20210505114659_add_filter_param_to_spree_properties.rb +8 -0
  131. data/db/migrate/20210512191732_create_spree_cms_pages.rb +24 -0
  132. data/db/migrate/20210514204251_create_spree_cms_sections.rb +22 -0
  133. data/db/migrate/20210527094055_create_spree_products_stores.rb +36 -0
  134. data/db/migrate/20210608045519_ensure_store_default_country_is_set.rb +5 -0
  135. data/db/migrate/20210702112334_add_missing_timestamp_columns.rb +46 -0
  136. data/db/migrate/20210713131614_add_unique_index_on_property_id_and_product_id_to_product_properties.rb +29 -0
  137. data/db/migrate/20210715091956_add_store_id_to_spree_store_credits.rb +10 -0
  138. data/db/migrate/20210716093151_add_store_id_to_spree_taxonomies.rb +11 -0
  139. data/db/migrate/20210716104141_add_index_on_name_parent_id_and_taxonomy_id_on_spree_taxons.rb +31 -0
  140. data/db/migrate/20210721120857_add_index_on_permalink_parent_id_and_taxonomy_id_on_spree_taxons.rb +31 -0
  141. data/db/migrate/20210721125657_create_spree_promotions_stores.rb +29 -0
  142. data/db/migrate/20210722090705_add_store_id_to_spree_customer_returns.rb +11 -0
  143. data/db/migrate/20210726065456_change_integer_id_columns_into_bigint.rb +305 -0
  144. data/db/migrate/20210730154425_fix_promotion_code_and_path_unique_indexes.rb +9 -0
  145. data/lib/generators/spree/dummy/dummy_generator.rb +11 -6
  146. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -0
  147. data/lib/generators/spree/dummy_model/templates/model.rb.tt +1 -1
  148. data/lib/generators/spree/install/install_generator.rb +12 -24
  149. data/lib/spree/core/components.rb +8 -0
  150. data/lib/spree/core/controller_helpers/auth.rb +7 -1
  151. data/lib/spree/core/controller_helpers/common.rb +1 -1
  152. data/lib/spree/core/controller_helpers/order.rb +4 -4
  153. data/lib/spree/core/controller_helpers/search.rb +1 -0
  154. data/lib/spree/core/controller_helpers/store.rb +24 -1
  155. data/lib/spree/core/engine.rb +6 -0
  156. data/lib/spree/core/importer/product.rb +3 -1
  157. data/lib/spree/core/product_duplicator.rb +1 -0
  158. data/lib/spree/core/search/base.rb +17 -22
  159. data/lib/spree/core/version.rb +1 -1
  160. data/lib/spree/core.rb +8 -4
  161. data/lib/spree/i18n.rb +1 -1
  162. data/lib/spree/money.rb +2 -1
  163. data/lib/spree/permitted_attributes.rb +21 -3
  164. data/lib/spree/testing_support/authorization_helpers.rb +6 -3
  165. data/lib/spree/testing_support/capybara_config.rb +3 -1
  166. data/lib/spree/testing_support/common_rake.rb +17 -4
  167. data/lib/spree/testing_support/extension_rake.rb +2 -2
  168. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  169. data/lib/spree/testing_support/factories/classification_factory.rb +8 -0
  170. data/lib/spree/testing_support/factories/cms_page_factory.rb +20 -0
  171. data/lib/spree/testing_support/factories/cms_section_factory.rb +31 -0
  172. data/lib/spree/testing_support/factories/customer_return_factory.rb +24 -17
  173. data/lib/spree/testing_support/factories/icon_factory.rb +7 -0
  174. data/lib/spree/testing_support/factories/line_item_factory.rb +6 -2
  175. data/lib/spree/testing_support/factories/menu_factory.rb +16 -0
  176. data/lib/spree/testing_support/factories/menu_item_factory.rb +10 -0
  177. data/lib/spree/testing_support/factories/options_factory.rb +5 -0
  178. data/lib/spree/testing_support/factories/order_factory.rb +11 -2
  179. data/lib/spree/testing_support/factories/payment_method_factory.rb +6 -2
  180. data/lib/spree/testing_support/factories/product_factory.rb +17 -1
  181. data/lib/spree/testing_support/factories/product_property_factory.rb +1 -1
  182. data/lib/spree/testing_support/factories/promotion_factory.rb +18 -9
  183. data/lib/spree/testing_support/factories/property_factory.rb +22 -0
  184. data/lib/spree/testing_support/factories/stock_location_factory.rb +5 -4
  185. data/lib/spree/testing_support/factories/store_credit_factory.rb +1 -0
  186. data/lib/spree/testing_support/factories/store_factory.rb +11 -0
  187. data/lib/spree/testing_support/factories/taxon_factory.rb +3 -1
  188. data/lib/spree/testing_support/factories/taxon_image_factory.rb +7 -0
  189. data/lib/spree/testing_support/factories/taxonomy_factory.rb +1 -0
  190. data/lib/spree/testing_support/factories/user_factory.rb +7 -2
  191. data/lib/spree/testing_support/factories/variant_factory.rb +2 -2
  192. data/lib/spree/testing_support/flatpickr_capybara.rb +58 -35
  193. data/lib/spree/testing_support/locale_helpers.rb +1 -1
  194. data/lib/spree/testing_support/order_walkthrough.rb +9 -9
  195. data/lib/spree/testing_support/rspec_retry_config.rb +5 -0
  196. data/lib/tasks/core.rake +1 -1
  197. data/spec/fixtures/favicon.ico +0 -0
  198. data/spec/fixtures/files/icon_256x256.gif +0 -0
  199. data/spec/fixtures/files/icon_256x256.png +0 -0
  200. data/spec/fixtures/files/icon_512x512.png +0 -0
  201. data/spec/fixtures/files/img_256x128.png +0 -0
  202. data/spree_core.gemspec +12 -11
  203. metadata +211 -159
  204. data/app/assets/images/logo/spree_50.png +0 -0
  205. data/app/assets/images/noimage/large.png +0 -0
  206. data/app/assets/images/noimage/mini.png +0 -0
  207. data/app/assets/images/noimage/product.png +0 -0
  208. data/app/assets/images/noimage/small.png +0 -0
  209. data/app/assets/javascripts/spree.js +0 -78
  210. data/app/controllers/spree/errors_controller.rb +0 -11
  211. data/app/helpers/spree/mail_helper.rb +0 -29
  212. data/app/mailers/spree/base_mailer.rb +0 -46
  213. data/app/mailers/spree/order_mailer.rb +0 -26
  214. data/app/mailers/spree/reimbursement_mailer.rb +0 -12
  215. data/app/mailers/spree/shipment_mailer.rb +0 -12
  216. data/app/mailers/spree/test_mailer.rb +0 -8
  217. data/app/models/spree/validations/db_maximum_length_validator.rb +0 -22
  218. data/app/views/layouts/spree/base_mailer.html.erb +0 -46
  219. data/app/views/spree/errors/forbidden.html.erb +0 -0
  220. data/app/views/spree/errors/unauthorized.html.erb +0 -0
  221. data/app/views/spree/order_mailer/cancel_email.html.erb +0 -24
  222. data/app/views/spree/order_mailer/cancel_email.text.erb +0 -38
  223. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -23
  224. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -39
  225. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +0 -23
  226. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +0 -38
  227. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -56
  228. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -24
  229. data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -12
  230. data/app/views/spree/shared/_base_mailer_header.html.erb +0 -13
  231. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -456
  232. data/app/views/spree/shared/_error_messages.html.erb +0 -11
  233. data/app/views/spree/shared/_mailer_line_item.html.erb +0 -16
  234. data/app/views/spree/shared/_paths.html.erb +0 -8
  235. data/app/views/spree/shared/_purchased_items_table.html.erb +0 -69
  236. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +0 -13
  237. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +0 -27
  238. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +0 -13
  239. data/app/views/spree/shared/purchased_items_table/_total.html.erb +0 -13
  240. data/app/views/spree/shipment_mailer/shipped_email.html.erb +0 -36
  241. data/app/views/spree/shipment_mailer/shipped_email.text.erb +0 -17
  242. data/app/views/spree/test_mailer/test_email.html.erb +0 -40
  243. data/app/views/spree/test_mailer/test_email.text.erb +0 -4
  244. data/config/initializers/assets.rb +0 -2
  245. data/config/initializers/premailer_assets.rb +0 -1
  246. data/config/initializers/premailer_rails.rb +0 -3
  247. data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +0 -10
  248. data/lib/generators/spree/dummy/templates/initializers/bullet.rb +0 -5
  249. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -15
  250. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -16
  251. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/backend/all.css +0 -16
  252. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -16
  253. data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +0 -23
  254. data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +0 -13
  255. data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +0 -5
  256. data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +0 -5
  257. data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +0 -11
  258. data/lib/tasks/email.rake +0 -10
  259. data/vendor/assets/javascripts/cleave.js +0 -1669
  260. data/vendor/assets/javascripts/fetch.umd.js +0 -531
  261. data/vendor/assets/javascripts/jquery.payment.js +0 -652
  262. data/vendor/assets/javascripts/jsuri.js +0 -458
  263. data/vendor/assets/javascripts/polyfill.min.js +0 -1
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Order < Spree::Base
3
3
  module Payments
4
- extend ActiveSupport::Concern
4
+ extend ActiveSupport::Concern # FIXME: this module is not required to be a concern
5
5
  included do
6
6
  # processes any pending payments and must return a boolean as it's
7
7
  # return value is used by the checkout state_machine to determine
@@ -11,7 +11,7 @@ module Spree
11
11
  def total_available_store_credit
12
12
  return 0.0 unless user
13
13
 
14
- user.total_available_store_credit
14
+ user.total_available_store_credit(currency, store)
15
15
  end
16
16
 
17
17
  def could_use_store_credit?
@@ -2,6 +2,7 @@ require_dependency 'spree/order/checkout'
2
2
  require_dependency 'spree/order/currency_updater'
3
3
  require_dependency 'spree/order/payments'
4
4
  require_dependency 'spree/order/store_credit'
5
+ require_dependency 'spree/order/emails'
5
6
 
6
7
  module Spree
7
8
  class Order < Spree::Base
@@ -13,10 +14,15 @@ module Spree
13
14
  include Spree::Order::Payments
14
15
  include Spree::Order::StoreCredit
15
16
  include Spree::Order::AddressBook
17
+ include Spree::Order::Emails
16
18
  include Spree::Core::NumberGenerator.new(prefix: 'R')
17
19
  include Spree::Core::TokenGenerator
18
20
 
19
21
  include NumberAsParam
22
+ include SingleStoreResource
23
+ include MemoizedData
24
+
25
+ MEMOIZED_METHODS = %w(tax_zone)
20
26
 
21
27
  extend Spree::DisplayMoney
22
28
  money_methods :outstanding_balance, :item_total, :adjustment_total,
@@ -93,6 +99,7 @@ module Spree
93
99
  has_many :reimbursements, inverse_of: :order, class_name: 'Spree::Reimbursement'
94
100
  has_many :line_item_adjustments, through: :line_items, source: :adjustments
95
101
  has_many :inventory_units, inverse_of: :order, class_name: 'Spree::InventoryUnit'
102
+ has_many :return_items, through: :inventory_units, class_name: 'Spree::ReturnItem'
96
103
  has_many :variants, through: :line_items
97
104
  has_many :products, through: :variants
98
105
  has_many :refunds, through: :payments
@@ -121,6 +128,8 @@ module Spree
121
128
  # Needs to happen before save_permalink is called
122
129
  before_validation :ensure_store_presence
123
130
  before_validation :ensure_currency_presence
131
+ before_validation :uppercase_number
132
+
124
133
  before_validation :clone_billing_address, if: :use_billing?
125
134
  attr_accessor :use_billing
126
135
 
@@ -129,7 +138,9 @@ module Spree
129
138
  before_update :homogenize_line_item_currencies, if: :currency_changed?
130
139
 
131
140
  with_options presence: true do
132
- validates :number, length: { maximum: 32, allow_blank: true }, uniqueness: { allow_blank: true, case_sensitive: false }
141
+ # we want to have this case_sentive: true as changing it to false causes all SQL to use LOWER(slug)
142
+ # which is very costly and slow on large set of records
143
+ validates :number, length: { maximum: 32, allow_blank: true }, uniqueness: { allow_blank: true, case_sensitive: true }
133
144
  validates :email, length: { maximum: 254, allow_blank: true }, email: { allow_blank: true }, if: :require_email
134
145
  validates :item_count, numericality: { greater_than_or_equal_to: 0, less_than: 2**31, only_integer: true, allow_blank: true }
135
146
  validates :store
@@ -158,6 +169,8 @@ module Spree
158
169
  scope :complete, -> { where.not(completed_at: nil) }
159
170
  scope :incomplete, -> { where(completed_at: nil) }
160
171
  scope :not_canceled, -> { where.not(state: 'canceled') }
172
+ scope :with_deleted_bill_address, -> { joins(:bill_address).where.not(Address.table_name => { deleted_at: nil }) }
173
+ scope :with_deleted_ship_address, -> { joins(:ship_address).where.not(Address.table_name => { deleted_at: nil }) }
161
174
 
162
175
  # shows completed orders first, by their completed_at date, then uncompleted orders by their created_at
163
176
  scope :reverse_chronological, -> { order(Arel.sql('spree_orders.completed_at IS NULL'), completed_at: :desc, created_at: :desc) }
@@ -326,6 +339,10 @@ module Spree
326
339
  complete? || resumed? || awaiting_return? || returned?
327
340
  end
328
341
 
342
+ def uneditable?
343
+ complete? || canceled? || returned?
344
+ end
345
+
329
346
  def credit_cards
330
347
  credit_card_ids = payments.from_credit_card.pluck(:source_id).uniq
331
348
  CreditCard.where(id: credit_card_ids)
@@ -356,7 +373,6 @@ module Spree
356
373
  touch :completed_at
357
374
 
358
375
  deliver_order_confirmation_email unless confirmation_delivered?
359
-
360
376
  deliver_store_owner_order_notification_email if deliver_store_owner_order_notification_email?
361
377
 
362
378
  consider_risk
@@ -368,17 +384,16 @@ module Spree
368
384
  save!
369
385
  end
370
386
 
371
- def deliver_order_confirmation_email
372
- OrderMailer.confirm_email(id).deliver_later
373
- update_column(:confirmation_delivered, true)
374
- end
375
-
376
387
  # Helper methods for checkout steps
377
388
  def paid?
378
389
  payment_state == 'paid' || payment_state == 'credit_owed'
379
390
  end
380
391
 
381
392
  def available_payment_methods(store = nil)
393
+ if store.present?
394
+ ActiveSupport::Deprecation.warn('The `store` parameter is deprecated and will be removed in Spree 5. Order is already associated with Store')
395
+ end
396
+
382
397
  @available_payment_methods ||= collect_payment_methods(store)
383
398
  end
384
399
 
@@ -410,21 +425,15 @@ module Spree
410
425
  end
411
426
 
412
427
  def empty!
413
- if completed?
414
- raise Spree.t(:cannot_empty_completed_order)
415
- else
416
- line_items.destroy_all
417
- updater.update_item_count
418
- adjustments.destroy_all
419
- shipments.destroy_all
420
- state_changes.destroy_all
421
- order_promotions.destroy_all
428
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
429
+ `Order#empty!` is deprecated and will be removed in Spree 5.0.
430
+ Please use `Spree::Cart::Empty.call(order: order)` instead.
431
+ DEPRECATION
422
432
 
423
- update_totals
424
- persist_totals
425
- restart_checkout_flow
426
- self
427
- end
433
+ raise Spree.t(:cannot_empty_completed_order) if completed?
434
+
435
+ result = Spree::Dependencies.cart_empty_service.constantize.call(order: self)
436
+ result.value
428
437
  end
429
438
 
430
439
  def has_step?(step)
@@ -562,6 +571,10 @@ module Spree
562
571
  !approved?
563
572
  end
564
573
 
574
+ def can_be_destroyed?
575
+ !completed? && payments.completed.empty?
576
+ end
577
+
565
578
  def consider_risk
566
579
  considered_risky! if is_risky? && !approved?
567
580
  end
@@ -574,11 +587,6 @@ module Spree
574
587
  update_column(:considered_risky, false)
575
588
  end
576
589
 
577
- def reload(options = nil)
578
- remove_instance_variable(:@tax_zone) if defined?(@tax_zone)
579
- super
580
- end
581
-
582
590
  def tax_total
583
591
  included_tax_total + additional_tax_total
584
592
  end
@@ -617,12 +625,12 @@ module Spree
617
625
 
618
626
  def validate_payments_attributes(attributes)
619
627
  # Ensure the payment methods specified are allowed for this user
620
- payment_methods = Spree::PaymentMethod.where(id: available_payment_methods.map(&:id))
628
+ payment_method_ids = available_payment_methods.map(&:id)
629
+
621
630
  attributes.each do |payment_attributes|
622
- payment_method_id = payment_attributes[:payment_method_id]
631
+ payment_method_id = payment_attributes[:payment_method_id].to_i
623
632
 
624
- # raise RecordNotFound unless it is an allowed payment method
625
- payment_methods.find(payment_method_id) if payment_method_id
633
+ raise ActiveRecord::RecordNotFound unless payment_method_ids.include?(payment_method_id)
626
634
  end
627
635
  end
628
636
 
@@ -693,10 +701,6 @@ module Spree
693
701
  update_with_updater!
694
702
  end
695
703
 
696
- def send_cancel_email
697
- OrderMailer.cancel_email(id).deliver_later
698
- end
699
-
700
704
  def after_resume
701
705
  shipments.each(&:resume!)
702
706
  consider_risk
@@ -715,23 +719,20 @@ module Spree
715
719
  end
716
720
 
717
721
  def collect_payment_methods(store = nil)
718
- PaymentMethod.available_on_front_end.select { |pm| pm.available_for_order?(self) && pm.available_for_store?(store) }
722
+ if store.present?
723
+ ActiveSupport::Deprecation.warn('The `store` parameter is deprecated and will be removed in Spree 5. Order is already associated with Store')
724
+ end
725
+ store ||= self.store
726
+
727
+ store.payment_methods.available_on_front_end.select { |pm| pm.available_for_order?(self) }
719
728
  end
720
729
 
721
730
  def credit_card_nil_payment?(attributes)
722
731
  payments.store_credits.present? && attributes[:amount].to_f.zero?
723
732
  end
724
733
 
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)
734
+ def uppercase_number
735
+ number&.upcase!
735
736
  end
736
737
  end
737
738
  end
@@ -112,6 +112,13 @@ module Spree
112
112
  end
113
113
  end
114
114
 
115
+ def source
116
+ return super if payment_method.nil?
117
+ return super unless payment_method.source_required?
118
+
119
+ payment_method.payment_source_class.unscoped { super }
120
+ end
121
+
115
122
  def money
116
123
  Spree::Money.new(amount, currency: currency)
117
124
  end
@@ -3,6 +3,8 @@ module Spree
3
3
  acts_as_paranoid
4
4
  acts_as_list
5
5
 
6
+ include MultiStoreResource
7
+
6
8
  DISPLAY = [:both, :front_end, :back_end].freeze
7
9
 
8
10
  scope :active, -> { where(active: true).order(position: :asc) }
@@ -31,6 +33,8 @@ module Spree
31
33
  # e.g. CreditCard in the case of a the Gateway payment type
32
34
  # nil means the payment method doesn't require a source e.g. check
33
35
  def payment_source_class
36
+ return unless source_required?
37
+
34
38
  raise ::NotImplementedError, 'You must implement payment_source_class method for this gateway.'
35
39
  end
36
40
 
@@ -83,5 +87,17 @@ module Spree
83
87
 
84
88
  store_ids.include?(store.id)
85
89
  end
90
+
91
+ def public_preferences
92
+ public_preference_keys.each_with_object({}) do |key, hash|
93
+ hash[key] = preferences[key]
94
+ end
95
+ end
96
+
97
+ protected
98
+
99
+ def public_preference_keys
100
+ []
101
+ end
86
102
  end
87
103
  end
@@ -58,6 +58,11 @@ module Spree::Preferences::Preferable
58
58
  send self.class.preference_default_getter_method(name)
59
59
  end
60
60
 
61
+ def preference_deprecated(name)
62
+ has_preference! name
63
+ send(self.class.preference_deprecated_getter_method(name))
64
+ end
65
+
61
66
  def has_preference!(name)
62
67
  raise NoMethodError, "#{name} preference not defined" unless has_preference? name
63
68
  end
@@ -72,6 +77,13 @@ module Spree::Preferences::Preferable
72
77
  end
73
78
  end
74
79
 
80
+ def deprecated_preferences
81
+ defined_preferences.each_with_object([]) do |pref_name, array|
82
+ deprecated_message = preference_deprecated(pref_name)
83
+ array << { name: pref_name, message: deprecated_message } unless deprecated_message.nil?
84
+ end
85
+ end
86
+
75
87
  def default_preferences
76
88
  Hash[
77
89
  defined_preferences.map do |preference|
@@ -2,9 +2,10 @@ module Spree::Preferences
2
2
  module PreferableClassMethods
3
3
  def preference(name, type, *args)
4
4
  options = args.extract_options!
5
- options.assert_valid_keys(:default)
5
+ options.assert_valid_keys(:default, :deprecated)
6
6
  default = options[:default]
7
7
  default = -> { options[:default] } unless default.is_a?(Proc)
8
+ deprecated = options[:deprecated]
8
9
 
9
10
  # cache_key will be nil for new objects, then if we check if there
10
11
  # is a pending preference before going to default
@@ -29,6 +30,10 @@ module Spree::Preferences
29
30
  define_method preference_type_getter_method(name) do
30
31
  type
31
32
  end
33
+
34
+ define_method preference_deprecated_getter_method(name) do
35
+ deprecated
36
+ end
32
37
  end
33
38
 
34
39
  def preference_getter_method(name)
@@ -43,6 +48,10 @@ module Spree::Preferences
43
48
  "preferred_#{name}_default".to_sym
44
49
  end
45
50
 
51
+ def preference_deprecated_getter_method(name)
52
+ "preferred_#{name}_deprecated".to_sym
53
+ end
54
+
46
55
  def preference_type_getter_method(name)
47
56
  "preferred_#{name}_type".to_sym
48
57
  end
@@ -21,7 +21,13 @@
21
21
  module Spree
22
22
  class Product < Spree::Base
23
23
  extend FriendlyId
24
- include Spree::ProductScopes
24
+ include ProductScopes
25
+ include MultiStoreResource
26
+ include MemoizedData
27
+
28
+ MEMOIZED_METHODS = %w(total_on_hand taxonomy_ids taxon_and_ancestors category
29
+ default_variant_id tax_category default_variant
30
+ purchasable? in_stock? backorderable?)
25
31
 
26
32
  friendly_id :slug_candidates, use: :history
27
33
 
@@ -36,6 +42,8 @@ module Spree
36
42
  has_many :product_properties, dependent: :destroy, inverse_of: :product
37
43
  has_many :properties, through: :product_properties
38
44
 
45
+ has_many :menu_items, as: :linked_resource
46
+
39
47
  has_many :classifications, dependent: :delete_all, inverse_of: :product
40
48
  has_many :taxons, through: :classifications, before_remove: :remove_taxon
41
49
 
@@ -77,6 +85,9 @@ module Spree
77
85
  has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
78
86
  has_many :variant_images_without_master, -> { order(:position) }, source: :images, through: :variants
79
87
 
88
+ has_many :store_products, class_name: 'Spree::StoreProduct'
89
+ has_many :stores, through: :store_products, class_name: 'Spree::Store'
90
+
80
91
  after_create :add_associations_from_prototype
81
92
  after_create :build_variants_from_option_values_hash, if: :option_values_hash
82
93
 
@@ -90,10 +101,7 @@ module Spree
90
101
  after_save :reset_nested_changes
91
102
  after_touch :touch_taxons
92
103
 
93
- # reset cache on save inside trasaction and transaction commit
94
- after_save :reset_memoized_data
95
- after_commit :reset_memoized_data
96
-
104
+ before_validation :downcase_slug
97
105
  before_validation :normalize_slug, on: :update
98
106
  before_validation :validate_master
99
107
 
@@ -107,7 +115,7 @@ module Spree
107
115
  validates :price, if: :requires_price?
108
116
  end
109
117
 
110
- validates :slug, presence: true, uniqueness: { allow_blank: true, case_sensitive: false }
118
+ validates :slug, presence: true, uniqueness: { allow_blank: true, case_sensitive: true }
111
119
  validate :discontinue_on_must_be_later_than_available_on, if: -> { available_on && discontinue_on }
112
120
 
113
121
  attr_accessor :option_values_hash
@@ -122,7 +130,7 @@ module Spree
122
130
 
123
131
  [
124
132
  :sku, :price, :currency, :weight, :height, :width, :depth, :is_master,
125
- :cost_currency, :price_in, :amount_in, :cost_price, :compare_at_price
133
+ :cost_currency, :price_in, :amount_in, :cost_price, :compare_at_price, :compare_at_amount_in
126
134
  ].each do |method_name|
127
135
  delegate method_name, :"#{method_name}=", to: :find_or_build_master
128
136
  end
@@ -132,26 +140,19 @@ module Spree
132
140
 
133
141
  alias master_images images
134
142
 
135
- def reload
136
- %w(total_on_hand taxonomy_ids taxon_and_ancestors category category default_variant_id tax_category default_variant).each do |v|
137
- instance_variable_set(:"@#{v}", nil)
138
- end
139
- super
140
- end
141
-
142
143
  # Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
143
144
  def purchasable?
144
- variants_including_master.any?(&:purchasable?)
145
+ default_variant.purchasable? || variants.any?(&:purchasable?)
145
146
  end
146
147
 
147
148
  # Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
148
149
  def in_stock?
149
- variants_including_master.any?(&:in_stock?)
150
+ default_variant.in_stock? || variants.any?(&:in_stock?)
150
151
  end
151
152
 
152
153
  # Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
153
154
  def backorderable?
154
- variants_including_master.any?(&:backorderable?)
155
+ default_variant.backorderable? || variants.any?(&:backorderable?)
155
156
  end
156
157
 
157
158
  def find_or_build_master
@@ -173,8 +174,8 @@ module Spree
173
174
  # @return [Spree::Variant]
174
175
  def default_variant
175
176
  @default_variant ||= Rails.cache.fetch(default_variant_cache_key) do
176
- if Spree::Config[:track_inventory_levels] && variants.in_stock_or_backorderable.any?
177
- variants.in_stock_or_backorderable.first
177
+ if Spree::Config[:track_inventory_levels] && available_variant = variants.detect(&:purchasable?)
178
+ available_variant
178
179
  else
179
180
  has_variants? ? variants.first : master
180
181
  end
@@ -300,11 +301,13 @@ module Spree
300
301
  end
301
302
 
302
303
  def total_on_hand
303
- @total_on_hand ||= if any_variants_not_track_inventory?
304
- Float::INFINITY
305
- else
306
- stock_items.sum(:count_on_hand)
307
- end
304
+ @total_on_hand ||= Rails.cache.fetch(['product-total-on-hand', cache_key_with_version]) do
305
+ if any_variants_not_track_inventory?
306
+ Float::INFINITY
307
+ else
308
+ stock_items.sum(:count_on_hand)
309
+ end
310
+ end
308
311
  end
309
312
 
310
313
  # Master variant may be deleted (i.e. when the product is deleted)
@@ -322,6 +325,12 @@ module Spree
322
325
  @category ||= taxons.joins(:taxonomy).order(depth: :desc).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) })
323
326
  end
324
327
 
328
+ def taxons_for_store(store)
329
+ Rails.cache.fetch("#{cache_key_with_version}/taxons-per-store/#{store.id}") do
330
+ taxons.for_store(store)
331
+ end
332
+ end
333
+
325
334
  private
326
335
 
327
336
  def add_associations_from_prototype
@@ -481,12 +490,6 @@ module Spree
481
490
  end
482
491
  end
483
492
 
484
- def reset_memoized_data
485
- %w(total_on_hand taxonomy_ids taxon_and_ancestors category default_variant_id tax_category default_variant).each do |v|
486
- instance_variable_set(:"@#{v}", nil)
487
- end
488
- end
489
-
490
493
  def requires_price?
491
494
  Spree::Config[:require_master_price]
492
495
  end
@@ -494,5 +497,9 @@ module Spree
494
497
  def requires_shipping_category?
495
498
  true
496
499
  end
500
+
501
+ def downcase_slug
502
+ slug&.downcase!
503
+ end
497
504
  end
498
505
  end