spree_core 4.2.5 → 4.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (248) 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 +55 -20
  10. data/app/finders/spree/stores/find_current.rb +24 -0
  11. data/app/helpers/spree/base_helper.rb +62 -2
  12. data/app/helpers/spree/locale_helper.rb +5 -1
  13. data/app/helpers/spree/products_helper.rb +7 -3
  14. data/app/models/concerns/spree/display_link.rb +42 -0
  15. data/app/models/concerns/spree/filter_param.rb +21 -0
  16. data/app/models/concerns/spree/memoized_data.rb +24 -0
  17. data/app/models/concerns/spree/multi_store_resource.rb +24 -0
  18. data/app/models/concerns/spree/product_scopes.rb +59 -8
  19. data/app/models/concerns/spree/single_store_resource.rb +9 -0
  20. data/app/models/concerns/spree/user_address.rb +19 -0
  21. data/app/models/concerns/spree/user_methods.rb +5 -4
  22. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  23. data/app/models/spree/ability.rb +3 -1
  24. data/app/models/spree/address.rb +27 -6
  25. data/app/models/spree/app_configuration.rb +8 -0
  26. data/app/models/spree/app_dependencies.rb +18 -6
  27. data/app/models/spree/base.rb +18 -0
  28. data/app/models/spree/classification.rb +3 -0
  29. data/app/models/spree/cms/pages/feature_page.rb +7 -0
  30. data/app/models/spree/cms/pages/homepage.rb +20 -0
  31. data/app/models/spree/cms/pages/standard_page.rb +4 -0
  32. data/app/models/spree/cms/sections/featured_article.rb +29 -0
  33. data/app/models/spree/cms/sections/hero_image.rb +47 -0
  34. data/app/models/spree/cms/sections/image_gallery.rb +103 -0
  35. data/app/models/spree/cms/sections/product_carousel.rb +14 -0
  36. data/app/models/spree/cms/sections/rich_text_content.rb +13 -0
  37. data/app/models/spree/cms/sections/side_by_side_images.rb +74 -0
  38. data/app/models/spree/cms_page.rb +66 -0
  39. data/app/models/spree/cms_section.rb +57 -0
  40. data/app/models/spree/country.rb +14 -6
  41. data/app/models/spree/credit_card.rb +2 -8
  42. data/app/models/spree/customer_return.rb +8 -2
  43. data/app/models/spree/icon.rb +9 -0
  44. data/app/models/spree/image/configuration/active_storage.rb +2 -0
  45. data/app/models/spree/inventory_unit.rb +1 -1
  46. data/app/models/spree/line_item.rb +1 -1
  47. data/app/models/spree/menu.rb +63 -0
  48. data/app/models/spree/menu_item.rb +76 -0
  49. data/app/models/spree/option_type.rb +1 -1
  50. data/app/models/spree/option_value.rb +11 -0
  51. data/app/models/spree/option_value_variant.rb +1 -1
  52. data/app/models/spree/order.rb +46 -45
  53. data/app/models/spree/order/address_book.rb +3 -5
  54. data/app/models/spree/order/currency_updater.rb +1 -1
  55. data/app/models/spree/order/emails.rb +32 -0
  56. data/app/models/spree/order/payments.rb +1 -1
  57. data/app/models/spree/order/store_credit.rb +1 -1
  58. data/app/models/spree/payment.rb +7 -0
  59. data/app/models/spree/payment_method.rb +4 -0
  60. data/app/models/spree/preferences/preferable.rb +12 -0
  61. data/app/models/spree/preferences/preferable_class_methods.rb +10 -1
  62. data/app/models/spree/product.rb +27 -22
  63. data/app/models/spree/product_property.rb +19 -4
  64. data/app/models/spree/promotion.rb +6 -15
  65. data/app/models/spree/promotion/rules/country.rb +1 -1
  66. data/app/models/spree/promotion/rules/first_order.rb +4 -3
  67. data/app/models/spree/promotion/rules/taxon.rb +10 -7
  68. data/app/models/spree/promotion_handler/cart.rb +7 -2
  69. data/app/models/spree/promotion_handler/coupon.rb +5 -4
  70. data/app/models/spree/promotion_handler/free_shipping.rb +5 -6
  71. data/app/models/spree/promotion_handler/page.rb +3 -2
  72. data/app/models/spree/promotion_handler/promotion_duplicator.rb +1 -0
  73. data/app/models/spree/promotion_rule.rb +2 -0
  74. data/app/models/spree/property.rb +27 -0
  75. data/app/models/spree/reimbursement.rb +3 -1
  76. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +2 -1
  77. data/app/models/spree/shipment_handler.rb +4 -2
  78. data/app/models/spree/stock/quantifier.rb +6 -6
  79. data/app/models/spree/store.rb +90 -7
  80. data/app/models/spree/store_credit.rb +7 -3
  81. data/app/models/spree/store_credit_event.rb +2 -2
  82. data/app/models/spree/store_payment_method.rb +11 -0
  83. data/app/models/spree/store_product.rb +11 -0
  84. data/app/models/spree/store_promotion.rb +11 -0
  85. data/app/models/spree/taxon.rb +21 -1
  86. data/app/models/spree/taxon_image/configuration/active_storage.rb +2 -0
  87. data/app/models/spree/taxonomy.rb +3 -1
  88. data/app/models/spree/variant.rb +13 -4
  89. data/app/presenters/spree/filters/options_presenter.rb +27 -0
  90. data/app/presenters/spree/filters/price_presenter.rb +22 -0
  91. data/app/presenters/spree/filters/price_range_presenter.rb +29 -0
  92. data/app/presenters/spree/filters/properties_presenter.rb +23 -0
  93. data/app/presenters/spree/filters/property_presenter.rb +22 -0
  94. data/app/presenters/spree/filters/quantified_price_range_presenter.rb +44 -0
  95. data/app/services/spree/account/addresses/create.rb +1 -0
  96. data/app/services/spree/account/addresses/helper.rb +6 -0
  97. data/app/services/spree/account/addresses/update.rb +9 -3
  98. data/app/services/spree/account/create.rb +17 -0
  99. data/app/services/spree/account/update.rb +15 -0
  100. data/app/services/spree/build_localized_redirect_url.rb +1 -1
  101. data/app/services/spree/cart/create.rb +5 -3
  102. data/app/services/spree/cart/destroy.rb +40 -0
  103. data/app/services/spree/cart/empty.rb +36 -0
  104. data/app/services/spree/cart/estimate_shipping_rates.rb +3 -3
  105. data/app/services/spree/checkout/add_store_credit.rb +1 -1
  106. data/app/services/spree/classifications/reposition.rb +18 -0
  107. data/app/services/spree/credit_cards/destroy.rb +41 -0
  108. data/app/validators/db_maximum_length_validator.rb +5 -0
  109. data/app/validators/email_validator.rb +3 -1
  110. data/app/views/spree/shared/_purchased_items_table.text.erb +25 -0
  111. data/config/initializers/active_storage.rb +2 -0
  112. data/config/locales/en.yml +166 -2
  113. data/config/routes.rb +0 -5
  114. data/db/migrate/20201023152810_add_filterable_to_spree_properties.rb +8 -0
  115. data/db/migrate/20210407200948_create_spree_menus.rb +16 -0
  116. data/db/migrate/20210408092939_create_spree_menu_items.rb +31 -0
  117. data/db/migrate/20210504163720_add_filter_param_to_spree_product_properties.rb +8 -0
  118. data/db/migrate/20210505114659_add_filter_param_to_spree_properties.rb +8 -0
  119. data/db/migrate/20210512191732_create_spree_cms_pages.rb +24 -0
  120. data/db/migrate/20210514204251_create_spree_cms_sections.rb +22 -0
  121. data/db/migrate/20210527094055_create_spree_products_stores.rb +29 -0
  122. data/db/migrate/20210608045519_ensure_store_default_country_is_set.rb +5 -0
  123. data/db/migrate/20210702112334_add_missing_timestamp_columns.rb +46 -0
  124. data/db/migrate/20210713131614_add_unique_index_on_property_id_and_product_id_to_product_properties.rb +29 -0
  125. data/db/migrate/20210715091956_add_store_id_to_spree_store_credits.rb +10 -0
  126. data/db/migrate/20210716093151_add_store_id_to_spree_taxonomies.rb +11 -0
  127. data/db/migrate/20210716104141_add_index_on_name_parent_id_and_taxonomy_id_on_spree_taxons.rb +31 -0
  128. data/db/migrate/20210721120857_add_index_on_permalink_parent_id_and_taxonomy_id_on_spree_taxons.rb +31 -0
  129. data/db/migrate/20210721125657_create_spree_promotions_stores.rb +29 -0
  130. data/db/migrate/20210722090705_add_store_id_to_spree_customer_returns.rb +11 -0
  131. data/db/migrate/20210726065456_change_integer_id_columns_into_bigint.rb +305 -0
  132. data/db/migrate/20210730154425_fix_promotion_code_and_path_unique_indexes.rb +9 -0
  133. data/lib/generators/spree/dummy/dummy_generator.rb +11 -6
  134. data/lib/generators/spree/dummy_model/templates/model.rb.tt +1 -1
  135. data/lib/generators/spree/install/install_generator.rb +12 -24
  136. data/lib/spree/core.rb +8 -4
  137. data/lib/spree/core/components.rb +8 -0
  138. data/lib/spree/core/controller_helpers/auth.rb +7 -1
  139. data/lib/spree/core/controller_helpers/common.rb +1 -1
  140. data/lib/spree/core/controller_helpers/order.rb +4 -4
  141. data/lib/spree/core/controller_helpers/search.rb +1 -0
  142. data/lib/spree/core/controller_helpers/store.rb +10 -1
  143. data/lib/spree/core/engine.rb +6 -0
  144. data/lib/spree/core/importer/product.rb +3 -1
  145. data/lib/spree/core/product_duplicator.rb +1 -0
  146. data/lib/spree/core/search/base.rb +17 -22
  147. data/lib/spree/core/version.rb +1 -1
  148. data/lib/spree/i18n.rb +1 -1
  149. data/lib/spree/money.rb +2 -1
  150. data/lib/spree/permitted_attributes.rb +14 -3
  151. data/lib/spree/testing_support/authorization_helpers.rb +6 -3
  152. data/lib/spree/testing_support/capybara_config.rb +3 -1
  153. data/lib/spree/testing_support/common_rake.rb +17 -4
  154. data/lib/spree/testing_support/extension_rake.rb +2 -2
  155. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  156. data/lib/spree/testing_support/factories/classification_factory.rb +8 -0
  157. data/lib/spree/testing_support/factories/cms_page_factory.rb +20 -0
  158. data/lib/spree/testing_support/factories/cms_section_factory.rb +31 -0
  159. data/lib/spree/testing_support/factories/customer_return_factory.rb +24 -17
  160. data/lib/spree/testing_support/factories/icon_factory.rb +7 -0
  161. data/lib/spree/testing_support/factories/line_item_factory.rb +6 -2
  162. data/lib/spree/testing_support/factories/menu_factory.rb +16 -0
  163. data/lib/spree/testing_support/factories/menu_item_factory.rb +10 -0
  164. data/lib/spree/testing_support/factories/options_factory.rb +5 -0
  165. data/lib/spree/testing_support/factories/order_factory.rb +11 -2
  166. data/lib/spree/testing_support/factories/payment_method_factory.rb +6 -2
  167. data/lib/spree/testing_support/factories/product_factory.rb +11 -1
  168. data/lib/spree/testing_support/factories/product_property_factory.rb +1 -1
  169. data/lib/spree/testing_support/factories/promotion_factory.rb +18 -9
  170. data/lib/spree/testing_support/factories/property_factory.rb +22 -0
  171. data/lib/spree/testing_support/factories/stock_location_factory.rb +5 -4
  172. data/lib/spree/testing_support/factories/store_credit_factory.rb +1 -0
  173. data/lib/spree/testing_support/factories/store_factory.rb +11 -0
  174. data/lib/spree/testing_support/factories/taxon_factory.rb +3 -1
  175. data/lib/spree/testing_support/factories/taxon_image_factory.rb +7 -0
  176. data/lib/spree/testing_support/factories/taxonomy_factory.rb +1 -0
  177. data/lib/spree/testing_support/factories/user_factory.rb +7 -2
  178. data/lib/spree/testing_support/factories/variant_factory.rb +2 -2
  179. data/lib/spree/testing_support/flatpickr_capybara.rb +58 -35
  180. data/lib/spree/testing_support/order_walkthrough.rb +9 -9
  181. data/lib/tasks/core.rake +1 -1
  182. data/spec/fixtures/favicon.ico +0 -0
  183. data/spec/fixtures/files/icon_256x256.gif +0 -0
  184. data/spec/fixtures/files/icon_256x256.png +0 -0
  185. data/spec/fixtures/files/icon_512x512.png +0 -0
  186. data/spec/fixtures/files/img_256x128.png +0 -0
  187. data/spree_core.gemspec +11 -10
  188. metadata +206 -157
  189. data/app/assets/images/logo/spree_50.png +0 -0
  190. data/app/assets/images/noimage/large.png +0 -0
  191. data/app/assets/images/noimage/mini.png +0 -0
  192. data/app/assets/images/noimage/product.png +0 -0
  193. data/app/assets/images/noimage/small.png +0 -0
  194. data/app/assets/javascripts/spree.js +0 -78
  195. data/app/controllers/spree/errors_controller.rb +0 -11
  196. data/app/helpers/spree/mail_helper.rb +0 -29
  197. data/app/mailers/spree/base_mailer.rb +0 -46
  198. data/app/mailers/spree/order_mailer.rb +0 -26
  199. data/app/mailers/spree/reimbursement_mailer.rb +0 -12
  200. data/app/mailers/spree/shipment_mailer.rb +0 -12
  201. data/app/mailers/spree/test_mailer.rb +0 -8
  202. data/app/models/spree/validations/db_maximum_length_validator.rb +0 -22
  203. data/app/views/layouts/spree/base_mailer.html.erb +0 -46
  204. data/app/views/spree/errors/forbidden.html.erb +0 -0
  205. data/app/views/spree/errors/unauthorized.html.erb +0 -0
  206. data/app/views/spree/order_mailer/cancel_email.html.erb +0 -24
  207. data/app/views/spree/order_mailer/cancel_email.text.erb +0 -38
  208. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -23
  209. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -39
  210. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +0 -23
  211. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +0 -38
  212. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -56
  213. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -24
  214. data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -12
  215. data/app/views/spree/shared/_base_mailer_header.html.erb +0 -13
  216. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -456
  217. data/app/views/spree/shared/_error_messages.html.erb +0 -11
  218. data/app/views/spree/shared/_mailer_line_item.html.erb +0 -16
  219. data/app/views/spree/shared/_paths.html.erb +0 -8
  220. data/app/views/spree/shared/_purchased_items_table.html.erb +0 -69
  221. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +0 -13
  222. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +0 -27
  223. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +0 -13
  224. data/app/views/spree/shared/purchased_items_table/_total.html.erb +0 -13
  225. data/app/views/spree/shipment_mailer/shipped_email.html.erb +0 -36
  226. data/app/views/spree/shipment_mailer/shipped_email.text.erb +0 -17
  227. data/app/views/spree/test_mailer/test_email.html.erb +0 -40
  228. data/app/views/spree/test_mailer/test_email.text.erb +0 -4
  229. data/config/initializers/assets.rb +0 -2
  230. data/config/initializers/premailer_assets.rb +0 -1
  231. data/config/initializers/premailer_rails.rb +0 -3
  232. data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +0 -10
  233. data/lib/generators/spree/dummy/templates/initializers/bullet.rb +0 -5
  234. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -15
  235. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -16
  236. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/backend/all.css +0 -16
  237. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -16
  238. data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +0 -23
  239. data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +0 -13
  240. data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +0 -5
  241. data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +0 -5
  242. data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +0 -11
  243. data/lib/tasks/email.rake +0 -10
  244. data/vendor/assets/javascripts/cleave.js +0 -1669
  245. data/vendor/assets/javascripts/fetch.umd.js +0 -531
  246. data/vendor/assets/javascripts/jquery.payment.js +0 -652
  247. data/vendor/assets/javascripts/jsuri.js +0 -458
  248. data/vendor/assets/javascripts/polyfill.min.js +0 -1
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class OptionValueVariant < Spree::Base
3
3
  belongs_to :option_value, class_name: 'Spree::OptionValue'
4
- belongs_to :variant, class_name: 'Spree::Variant'
4
+ belongs_to :variant, touch: true, class_name: 'Spree::Variant'
5
5
 
6
6
  validates :option_value, :variant, presence: true
7
7
  validates :option_value_id, uniqueness: { scope: :variant_id }
@@ -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
@@ -2,7 +2,7 @@
2
2
  module Spree
3
3
  class Order < Spree::Base
4
4
  module AddressBook
5
- extend ActiveSupport::Concern
5
+ extend ActiveSupport::Concern # FIXME: this module is not required to be a concern
6
6
 
7
7
  def clone_shipping_address
8
8
  if ship_address
@@ -22,7 +22,6 @@ module Spree
22
22
  address = Spree::Address.find_by(id: id)
23
23
  if address && address.user_id == user_id
24
24
  self['bill_address_id'] = address.id
25
- user.update_attribute(:bill_address_id, address.id)
26
25
  bill_address.reload
27
26
  else
28
27
  self['bill_address_id'] = nil
@@ -31,14 +30,13 @@ module Spree
31
30
 
32
31
  def bill_address_attributes=(attributes)
33
32
  self.bill_address = update_or_create_address(attributes)
34
- user.bill_address = bill_address if user
33
+ user.bill_address = bill_address if user && user.bill_address.nil?
35
34
  end
36
35
 
37
36
  def ship_address_id=(id)
38
37
  address = Spree::Address.find_by(id: id)
39
38
  if address && address.user_id == user_id
40
39
  self['ship_address_id'] = address.id
41
- user.update_attribute(:ship_address_id, address.id)
42
40
  ship_address.reload
43
41
  else
44
42
  self['ship_address_id'] = nil
@@ -47,7 +45,7 @@ module Spree
47
45
 
48
46
  def ship_address_attributes=(attributes)
49
47
  self.ship_address = update_or_create_address(attributes)
50
- user.ship_address = ship_address if user
48
+ user.ship_address = ship_address if user && user.ship_address.nil?
51
49
  end
52
50
 
53
51
  private
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Order < Spree::Base
3
3
  module CurrencyUpdater
4
- extend ActiveSupport::Concern
4
+ extend ActiveSupport::Concern # FIXME: this module is not required to be a concern
5
5
 
6
6
  included do
7
7
  def homogenize_line_item_currencies
@@ -0,0 +1,32 @@
1
+ module Spree
2
+ class Order < Spree::Base
3
+ module Emails
4
+ extend ActiveSupport::Concern
5
+
6
+ def deliver_order_confirmation_email
7
+ # you can overwrite this method in your application / extension to send out the confirmation email
8
+ # or use `spree_emails` gem
9
+ # YourEmailVendor.deliver_order_confirmation_email(id) # `id` = ID of the Order being sent, you can also pass the entire Order object using `self`
10
+ # update_column(:confirmation_delivered, true) # if you would like to mark that the email was sent
11
+ end
12
+
13
+ # If you would like to also send confirmation email to store owner(s)
14
+ def deliver_store_owner_order_notification_email?
15
+ false
16
+ end
17
+
18
+ def deliver_store_owner_order_notification_email
19
+ # you can overwrite this method in your application / extension to send out the confirmation email
20
+ # or use `spree_emails` gem
21
+ # YourEmailVendor.deliver_store_owner_notification_email(id) # `id` = ID of the Order being sent, you can also pass the entire Order object using `self`
22
+ # update_column(:store_owner_notification_delivered, true) # if you would like to mark that the email was sent
23
+ end
24
+
25
+ def send_cancel_email
26
+ # you can overwrite this method in your application / extension to send out the confirmation email
27
+ # or use `spree_emails` gem
28
+ # YourEmailVendor.deliver_cancel_email(id) # `id` = ID of the Order being sent, you can also pass the entire Order object using `self`
29
+ end
30
+ end
31
+ end
32
+ end
@@ -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?
@@ -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
 
@@ -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,13 +140,6 @@ 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
145
  variants_including_master.any?(&:purchasable?)
@@ -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
@@ -322,6 +323,12 @@ module Spree
322
323
  @category ||= taxons.joins(:taxonomy).order(depth: :desc).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) })
323
324
  end
324
325
 
326
+ def taxons_for_store(store)
327
+ Rails.cache.fetch("#{cache_key_with_version}/taxons-per-store/#{store.id}") do
328
+ taxons.for_store(store)
329
+ end
330
+ end
331
+
325
332
  private
326
333
 
327
334
  def add_associations_from_prototype
@@ -481,12 +488,6 @@ module Spree
481
488
  end
482
489
  end
483
490
 
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
491
  def requires_price?
491
492
  Spree::Config[:require_master_price]
492
493
  end
@@ -494,5 +495,9 @@ module Spree
494
495
  def requires_shipping_category?
495
496
  true
496
497
  end
498
+
499
+ def downcase_slug
500
+ slug&.downcase!
501
+ end
497
502
  end
498
503
  end