spree_core 4.2.7 → 4.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) 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/address_book.rb +3 -5
  53. data/app/models/spree/order/currency_updater.rb +1 -1
  54. data/app/models/spree/order/emails.rb +32 -0
  55. data/app/models/spree/order/payments.rb +1 -1
  56. data/app/models/spree/order/store_credit.rb +1 -9
  57. data/app/models/spree/order.rb +46 -45
  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/rules/country.rb +1 -1
  65. data/app/models/spree/promotion/rules/first_order.rb +4 -3
  66. data/app/models/spree/promotion/rules/taxon.rb +10 -7
  67. data/app/models/spree/promotion.rb +6 -15
  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/components.rb +8 -0
  137. data/lib/spree/core/controller_helpers/auth.rb +7 -1
  138. data/lib/spree/core/controller_helpers/common.rb +1 -1
  139. data/lib/spree/core/controller_helpers/order.rb +4 -4
  140. data/lib/spree/core/controller_helpers/search.rb +1 -0
  141. data/lib/spree/core/controller_helpers/store.rb +10 -1
  142. data/lib/spree/core/engine.rb +6 -0
  143. data/lib/spree/core/importer/product.rb +3 -1
  144. data/lib/spree/core/product_duplicator.rb +1 -0
  145. data/lib/spree/core/search/base.rb +17 -22
  146. data/lib/spree/core/version.rb +1 -1
  147. data/lib/spree/core.rb +8 -4
  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 +207 -159
  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/order_contents.rb +0 -31
  203. data/app/models/spree/validations/db_maximum_length_validator.rb +0 -22
  204. data/app/views/layouts/spree/base_mailer.html.erb +0 -46
  205. data/app/views/spree/errors/forbidden.html.erb +0 -0
  206. data/app/views/spree/errors/unauthorized.html.erb +0 -0
  207. data/app/views/spree/order_mailer/cancel_email.html.erb +0 -24
  208. data/app/views/spree/order_mailer/cancel_email.text.erb +0 -38
  209. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -23
  210. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -39
  211. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +0 -23
  212. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +0 -38
  213. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -56
  214. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -24
  215. data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -12
  216. data/app/views/spree/shared/_base_mailer_header.html.erb +0 -13
  217. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -456
  218. data/app/views/spree/shared/_error_messages.html.erb +0 -11
  219. data/app/views/spree/shared/_mailer_line_item.html.erb +0 -16
  220. data/app/views/spree/shared/_paths.html.erb +0 -8
  221. data/app/views/spree/shared/_purchased_items_table.html.erb +0 -69
  222. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +0 -13
  223. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +0 -27
  224. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +0 -13
  225. data/app/views/spree/shared/purchased_items_table/_total.html.erb +0 -13
  226. data/app/views/spree/shipment_mailer/shipped_email.html.erb +0 -36
  227. data/app/views/spree/shipment_mailer/shipped_email.text.erb +0 -17
  228. data/app/views/spree/test_mailer/test_email.html.erb +0 -40
  229. data/app/views/spree/test_mailer/test_email.text.erb +0 -4
  230. data/config/initializers/assets.rb +0 -2
  231. data/config/initializers/premailer_assets.rb +0 -1
  232. data/config/initializers/premailer_rails.rb +0 -3
  233. data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +0 -10
  234. data/lib/generators/spree/dummy/templates/initializers/bullet.rb +0 -5
  235. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -15
  236. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -16
  237. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/backend/all.css +0 -16
  238. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -16
  239. data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +0 -23
  240. data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +0 -13
  241. data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +0 -5
  242. data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +0 -5
  243. data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +0 -11
  244. data/lib/tasks/email.rake +0 -10
  245. data/vendor/assets/javascripts/cleave.js +0 -1669
  246. data/vendor/assets/javascripts/fetch.umd.js +0 -531
  247. data/vendor/assets/javascripts/jquery.payment.js +0 -652
  248. data/vendor/assets/javascripts/jsuri.js +0 -458
  249. data/vendor/assets/javascripts/polyfill.min.js +0 -1
@@ -43,23 +43,23 @@ module Spree
43
43
  add_simple_scopes simple_scopes
44
44
 
45
45
  add_search_scope :ascend_by_master_price do
46
- joins(master: :default_price).order("#{price_table_name}.amount ASC")
46
+ order("#{price_table_name}.amount ASC")
47
47
  end
48
48
 
49
49
  add_search_scope :descend_by_master_price do
50
- joins(master: :default_price).order("#{price_table_name}.amount DESC")
50
+ order("#{price_table_name}.amount DESC")
51
51
  end
52
52
 
53
53
  add_search_scope :price_between do |low, high|
54
- joins(master: :default_price).where(Price.table_name => { amount: low..high })
54
+ where(Price.table_name => { amount: low..high })
55
55
  end
56
56
 
57
57
  add_search_scope :master_price_lte do |price|
58
- joins(master: :default_price).where("#{price_table_name}.amount <= ?", price)
58
+ where("#{price_table_name}.amount <= ?", price)
59
59
  end
60
60
 
61
61
  add_search_scope :master_price_gte do |price|
62
- joins(master: :default_price).where("#{price_table_name}.amount >= ?", price)
62
+ where("#{price_table_name}.amount >= ?", price)
63
63
  end
64
64
 
65
65
  # This scope selects products in taxon AND all its descendants
@@ -94,6 +94,19 @@ module Spree
94
94
  taxons.first ? prepare_taxon_conditions(taxons) : where(nil)
95
95
  end
96
96
 
97
+ add_search_scope :ascend_by_taxons_min_position do |taxon_ids|
98
+ joins(:classifications).
99
+ where(Classification.table_name => { taxon_id: taxon_ids }).
100
+ select(
101
+ [
102
+ "#{Product.table_name}.*",
103
+ "MIN(#{Classification.table_name}.position) AS min_position"
104
+ ].join(', ')
105
+ ).
106
+ group(:id).
107
+ order(min_position: :asc)
108
+ end
109
+
97
110
  # a scope that finds all products having property specified by name, object or id
98
111
  add_search_scope :with_property do |property|
99
112
  joins(:properties).where(property_conditions(property))
@@ -107,6 +120,12 @@ module Spree
107
120
  where(property_conditions(property))
108
121
  end
109
122
 
123
+ add_search_scope :with_property_values do |property_filter_param, property_values|
124
+ joins(product_properties: :property).
125
+ where(Property.table_name => { filter_param: property_filter_param }).
126
+ where(ProductProperty.table_name => { filter_param: property_values.map(&:parameterize) })
127
+ end
128
+
110
129
  add_search_scope :with_option do |option|
111
130
  option_types = OptionType.table_name
112
131
  conditions = case option
@@ -198,18 +217,50 @@ module Spree
198
217
  end
199
218
  end
200
219
  search_scopes << :not_discontinued
220
+
221
+ def self.with_currency(currency)
222
+ joins(variants_including_master: :prices).
223
+ where(Price.table_name => { currency: currency.upcase }).
224
+ where.not(Price.table_name => { amount: nil }).
225
+ distinct
226
+ end
227
+ search_scopes << :with_currency
228
+
201
229
  # Can't use add_search_scope for this as it needs a default argument
202
- def self.available(available_on = nil, _currency = nil)
230
+ def self.available(available_on = nil, currency = nil)
203
231
  available_on ||= Time.current
204
- not_discontinued.joins(master: :prices).where("#{Product.quoted_table_name}.available_on <= ?", available_on)
232
+
233
+ scope = not_discontinued.where("#{Product.quoted_table_name}.available_on <= ?", available_on)
234
+
235
+ unless Spree::Config.show_products_without_price
236
+ currency ||= Spree::Config[:currency]
237
+ scope = scope.with_currency(currency)
238
+ end
239
+
240
+ scope
205
241
  end
206
242
  search_scopes << :available
207
243
 
208
244
  def self.active(currency = nil)
209
- available(nil, currency&.upcase)
245
+ available(nil, currency)
210
246
  end
211
247
  search_scopes << :active
212
248
 
249
+ def self.for_filters(currency, taxon: nil)
250
+ scope = active(currency)
251
+ scope = scope.in_taxon(taxon) if taxon.present?
252
+ scope
253
+ end
254
+ search_scopes << :for_filters
255
+
256
+ def self.for_user(user = nil)
257
+ if user.try(:has_spree_role?, 'admin')
258
+ with_deleted
259
+ else
260
+ not_deleted.not_discontinued.where("#{Product.quoted_table_name}.available_on <= ?", Time.current)
261
+ end
262
+ end
263
+
213
264
  add_search_scope :taxons_name_eq do |name|
214
265
  group('spree_products.id').joins(:taxons).where(Taxon.arel_table[:name].eq(name))
215
266
  end
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module SingleStoreResource
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ scope :for_store, ->(store) { where(store_id: store.id) }
7
+ end
8
+ end
9
+ end
@@ -16,7 +16,12 @@ module Spree
16
16
  has_many :addresses, -> { where(deleted_at: nil).order('updated_at DESC') },
17
17
  class_name: 'Spree::Address', foreign_key: :user_id
18
18
 
19
+ validate :address_not_associated_with_other_user, :address_not_deprecated_in_completed_order
20
+
19
21
  def persist_order_address(order)
22
+ # FIXME: we should check if the User's address is associated with country accepted by Store
23
+ # if not we should try to find an address with valid country in User's address book
24
+ # or we should call `build_bill_address`
20
25
  b_address = bill_address || build_bill_address
21
26
  b_address.attributes = order.bill_address.value_attributes
22
27
  b_address.save
@@ -30,6 +35,20 @@ module Spree
30
35
  update(ship_address_id: s_address.id)
31
36
  end
32
37
  end
38
+
39
+ private
40
+
41
+ def address_not_associated_with_other_user
42
+ errors.add(:bill_address_id, :belongs_to_other_user) if bill_address&.user_id && self != bill_address&.user
43
+ errors.add(:ship_address_id, :belongs_to_other_user) if ship_address&.user_id && self != ship_address&.user
44
+ end
45
+
46
+ def address_not_deprecated_in_completed_order
47
+ errors.add(:bill_address_id, :deprecated_in_completed_order) if
48
+ orders.complete.with_deleted_bill_address.where(bill_address: bill_address_id).any?
49
+ errors.add(:ship_address_id, :deprecated_in_completed_order) if
50
+ orders.complete.with_deleted_ship_address.where(ship_address: ship_address_id).any?
51
+ end
33
52
  end
34
53
  end
35
54
  end
@@ -27,7 +27,7 @@ module Spree
27
27
  belongs_to :ship_address, class_name: 'Spree::Address', optional: true
28
28
  belongs_to :bill_address, class_name: 'Spree::Address', optional: true
29
29
 
30
- self.whitelisted_ransackable_associations = %w[bill_address ship_address]
30
+ self.whitelisted_ransackable_associations = %w[bill_address ship_address addresses]
31
31
  self.whitelisted_ransackable_attributes = %w[id email]
32
32
 
33
33
  def self.with_email(query)
@@ -59,9 +59,10 @@ module Spree
59
59
  first
60
60
  end
61
61
 
62
- def total_available_store_credit(currency = nil)
63
- currency ||= Spree::Config[:currency]
64
- store_credits.where(currency: currency).reload.to_a.sum(&:amount_remaining)
62
+ def total_available_store_credit(currency = nil, store = nil)
63
+ store ||= Store.default
64
+ currency ||= store.default_currency
65
+ store_credits.for_store(store).where(currency: currency).reload.to_a.sum(&:amount_remaining)
65
66
  end
66
67
 
67
68
  private
@@ -9,7 +9,7 @@ module Spree
9
9
  end
10
10
 
11
11
  def payment_sources
12
- credit_cards.with_payment_profile.not_expired.where(payment_method: Spree::PaymentMethod.active)
12
+ credit_cards.with_payment_profile.not_expired.where(payment_method: Spree::PaymentMethod.active).not_removed
13
13
  end
14
14
 
15
15
  def drop_payment_source(source)
@@ -61,6 +61,8 @@ module Spree
61
61
 
62
62
  def apply_user_permissions(user)
63
63
  can :read, ::Spree::Country
64
+ can :read, ::Spree::Menu
65
+ can :read, ::Spree::CmsPage
64
66
  can :read, ::Spree::OptionType
65
67
  can :read, ::Spree::OptionValue
66
68
  can :create, ::Spree::Order
@@ -71,7 +73,7 @@ module Spree
71
73
  !order.completed? && (order.user == user || order.token && token == order.token)
72
74
  end
73
75
  can :manage, ::Spree::Address, user_id: user.id
74
- can :read, ::Spree::CreditCard, user_id: user.id
76
+ can [:read, :destroy], ::Spree::CreditCard, user_id: user.id
75
77
  can :read, ::Spree::Product
76
78
  can :read, ::Spree::ProductProperty
77
79
  can :read, ::Spree::Property
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Address < Spree::Base
3
- require 'twitter_cldr'
3
+ require 'validates_zipcode'
4
4
 
5
5
  if Rails::VERSION::STRING >= '6.1'
6
6
  serialize :preferences, Hash, default: {}
@@ -55,13 +55,21 @@ module Spree
55
55
  alias_attribute :first_name, :firstname
56
56
  alias_attribute :last_name, :lastname
57
57
 
58
- self.whitelisted_ransackable_attributes = %w[firstname lastname company]
58
+ self.whitelisted_ransackable_attributes = ADDRESS_FIELDS
59
+ self.whitelisted_ransackable_associations = %w[country state user]
59
60
 
60
61
  def self.build_default
62
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
63
+ `Address#build_default` is deprecated and will be removed in Spree 5.0.
64
+ Please use standard rails `Address.new(country: current_store.default_country)`
65
+ DEPRECATION
61
66
  new(country: Spree::Country.default)
62
67
  end
63
68
 
64
69
  def self.default(user = nil, kind = 'bill')
70
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
71
+ `Address#default` is deprecated and will be removed in Spree 5.0.
72
+ DEPRECATION
65
73
  if user && user_address = user.public_send(:"#{kind}_address")
66
74
  user_address.clone
67
75
  else
@@ -157,6 +165,7 @@ module Spree
157
165
  super
158
166
  else
159
167
  update_column :deleted_at, Time.current
168
+ assign_new_default_address_to_user
160
169
  end
161
170
  end
162
171
 
@@ -214,11 +223,23 @@ module Spree
214
223
  end
215
224
 
216
225
  def postal_code_validate
217
- return if country.blank? || country.iso.blank? || !require_zipcode?
218
- return unless TwitterCldr::Shared::PostalCodes.territories.include?(country.iso.downcase.to_sym)
226
+ return if country.blank? || country_iso.blank? || !require_zipcode? || zipcode.blank?
227
+ return unless ::ValidatesZipcode::CldrRegexpCollection::ZIPCODES_REGEX.keys.include?(country_iso.upcase.to_sym)
219
228
 
220
- postal_code = TwitterCldr::Shared::PostalCodes.for_territory(country.iso)
221
- errors.add(:zipcode, :invalid) unless postal_code.valid?(zipcode.to_s.strip)
229
+ formatted_zip = ::ValidatesZipcode::Formatter.new(
230
+ zipcode: zipcode.to_s.strip,
231
+ country_alpha2: country_iso.upcase
232
+ ).format
233
+
234
+ errors.add(:zipcode, :invalid) unless ::ValidatesZipcode.valid?(formatted_zip, country_iso.upcase)
235
+ end
236
+
237
+ def assign_new_default_address_to_user
238
+ return unless user
239
+
240
+ user.bill_address = user.addresses.last if user.bill_address == self
241
+ user.ship_address = user.addresses.last if user.ship_address == self
242
+ user.save!
222
243
  end
223
244
  end
224
245
  end
@@ -45,6 +45,7 @@ module Spree
45
45
  preference :currency, :string, default: 'USD'
46
46
  preference :default_country_id, :integer
47
47
  preference :disable_sku_validation, :boolean, default: false # when turned off disables the built-in SKU uniqueness validation
48
+ preference :disable_store_presence_validation, :boolean, default: false # when turned off disables Store presence validation for Products and Payment Methods
48
49
  preference :expedited_exchanges, :boolean, default: false # NOTE this requires payment profiles to be supported on your gateway of choice as well as a delayed job handler to be configured with activejob. kicks off an exchange shipment upon return authorization save. charge customer if they do not return items within timely manner.
49
50
  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
51
  preference :layout, :string, default: 'spree/layouts/spree_application'
@@ -52,6 +53,7 @@ module Spree
52
53
  preference :mailer_logo, :string, default: 'logo/spree_50.png'
53
54
  preference :max_level_in_taxons_menu, :integer, default: 1 # maximum nesting level in taxons menu
54
55
  preference :products_per_page, :integer, default: 12
56
+ preference :product_wysiwyg_editor_enabled, :boolean, default: true
55
57
  preference :require_master_price, :boolean, default: true
56
58
  preference :restock_inventory, :boolean, default: true # Determines if a return item is restocked automatically once it has been received
57
59
  preference :return_eligibility_number_of_days, :integer, default: 365
@@ -62,6 +64,7 @@ module Spree
62
64
  preference :show_products_without_price, :boolean, default: false
63
65
  preference :show_raw_product_description, :boolean, default: false
64
66
  preference :tax_using_ship_address, :boolean, default: true
67
+ preference :taxon_wysiwyg_editor_enabled, :boolean, default: true
65
68
  preference :track_inventory_levels, :boolean, default: true # Determines whether to track on_hand values for variants / products.
66
69
 
67
70
  # Store credits configurations
@@ -76,6 +79,11 @@ module Spree
76
79
  @searcher_class ||= Spree::Core::Search::Base
77
80
  end
78
81
 
82
+ # Sets the path used for products, taxons and pages.
83
+ preference :storefront_products_path, :string, default: 'products'
84
+ preference :storefront_taxons_path, :string, default: 't'
85
+ preference :storefront_pages_path, :string, default: 'pages'
86
+
79
87
  attr_writer :searcher_class
80
88
  end
81
89
  end
@@ -6,14 +6,14 @@ module Spree
6
6
  :ability_class,
7
7
  :cart_create_service, :cart_add_item_service, :cart_remove_item_service,
8
8
  :cart_remove_line_item_service, :cart_set_item_quantity_service, :cart_recalculate_service,
9
- :cart_update_service, :checkout_next_service, :checkout_advance_service, :checkout_update_service,
10
- :checkout_complete_service, :checkout_add_store_credit_service,
11
- :checkout_remove_store_credit_service, :checkout_get_shipping_rates_service,
12
- :coupon_handler, :country_finder, :current_order_finder, :credit_card_finder,
9
+ :cms_page_finder, :cart_update_service, :checkout_next_service, :checkout_advance_service, :checkout_update_service,
10
+ :checkout_complete_service, :checkout_add_store_credit_service, :checkout_remove_store_credit_service, :checkout_get_shipping_rates_service,
11
+ :coupon_handler, :menu_finder, :country_finder, :current_order_finder, :credit_card_finder,
13
12
  :completed_order_finder, :order_sorter, :cart_compare_line_items_service, :collection_paginator, :products_sorter,
14
13
  :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,
16
- :collection_sorter, :error_handler
14
+ :account_create_address_service, :account_update_address_service, :account_create_service, :account_update_service,
15
+ :address_finder, :collection_sorter, :error_handler, :current_store_finder, :cart_empty_service, :cart_destroy_service,
16
+ :classification_reposition_service, :credit_cards_destroy_service
17
17
  ].freeze
18
18
 
19
19
  attr_accessor *INJECTION_POINTS
@@ -41,6 +41,8 @@ module Spree
41
41
  @cart_remove_line_item_service = 'Spree::Cart::RemoveLineItem'
42
42
  @cart_set_item_quantity_service = 'Spree::Cart::SetQuantity'
43
43
  @cart_estimate_shipping_rates_service = 'Spree::Cart::EstimateShippingRates'
44
+ @cart_empty_service = 'Spree::Cart::Empty'
45
+ @cart_destroy_service = 'Spree::Cart::Destroy'
44
46
 
45
47
  # checkout
46
48
  @checkout_next_service = 'Spree::Checkout::Next'
@@ -64,16 +66,26 @@ module Spree
64
66
  @coupon_handler = 'Spree::PromotionHandler::Coupon'
65
67
 
66
68
  # account
69
+ @account_create_service = 'Spree::Account::Create'
70
+ @account_update_service = 'Spree::Account::Update'
67
71
  @account_create_address_service = 'Spree::Account::Addresses::Create'
68
72
  @account_update_address_service = 'Spree::Account::Addresses::Update'
69
73
 
74
+ # credit cards
75
+ @credit_cards_destroy_service = 'Spree::CreditCards::Destroy'
76
+
77
+ @classification_reposition_service = 'Spree::Classifications::Reposition'
78
+
70
79
  @error_handler = 'Spree::ErrorReporter'
71
80
  end
72
81
 
73
82
  def set_default_finders
74
83
  @address_finder = 'Spree::Addresses::Find'
75
84
  @country_finder = 'Spree::Countries::Find'
85
+ @cms_page_finder = 'Spree::CmsPages::Find'
86
+ @menu_finder = 'Spree::Menus::Find'
76
87
  @current_order_finder = 'Spree::Orders::FindCurrent'
88
+ @current_store_finder = 'Spree::Stores::FindCurrent'
77
89
  @completed_order_finder = 'Spree::Orders::FindComplete'
78
90
  @credit_card_finder = 'Spree::CreditCards::Find'
79
91
  @products_finder = 'Spree::Products::Find'
@@ -22,6 +22,16 @@ class Spree::Base < ApplicationRecord
22
22
  false
23
23
  end
24
24
 
25
+ def self.for_store(store)
26
+ plural_model_name = model_name.plural.gsub(/spree_/, '').to_sym
27
+
28
+ if store.respond_to?(plural_model_name)
29
+ store.send(plural_model_name)
30
+ else
31
+ self
32
+ end
33
+ end
34
+
25
35
  def self.spree_base_scopes
26
36
  where(nil)
27
37
  end
@@ -30,4 +40,12 @@ class Spree::Base < ApplicationRecord
30
40
  def self.has_many_inversing
31
41
  false
32
42
  end
43
+
44
+ def self.json_api_columns
45
+ column_names.reject { |c| c.match(/_id$|id|preferences|(.*)password|(.*)token|(.*)api_key/) }
46
+ end
47
+
48
+ def self.json_api_type
49
+ to_s.demodulize.underscore
50
+ end
33
51
  end
@@ -9,7 +9,10 @@ module Spree
9
9
  end
10
10
 
11
11
  validates :taxon, :product, presence: true
12
+ validates :position, numericality: { only_integer: true, allow_blank: true, allow_nil: true }
12
13
  # For #3494
13
14
  validates :taxon_id, uniqueness: { scope: :product_id, message: :already_linked, allow_blank: true }
15
+
16
+ self.whitelisted_ransackable_attributes = ['taxon_id', 'product_id']
14
17
  end
15
18
  end
@@ -0,0 +1,7 @@
1
+ module Spree::Cms::Pages
2
+ class FeaturePage < Spree::CmsPage
3
+ def sections?
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ module Spree::Cms::Pages
2
+ class Homepage < Spree::CmsPage
3
+ before_create :empty_slug
4
+ after_save :empty_slug
5
+
6
+ def sections?
7
+ true
8
+ end
9
+
10
+ def seo_meta_description
11
+ meta_description if meta_description.present?
12
+ end
13
+
14
+ private
15
+
16
+ def empty_slug
17
+ self.slug = nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module Spree::Cms::Pages
2
+ class StandardPage < Spree::CmsPage
3
+ end
4
+ end
@@ -0,0 +1,29 @@
1
+ module Spree::Cms::Sections
2
+ class FeaturedArticle < Spree::CmsSection
3
+ before_save :reset_link_attributes
4
+ after_initialize :default_values
5
+
6
+ store :content, accessors: [:title, :subtitle, :button_text, :rte_content], coder: JSON
7
+ store :settings, accessors: [:gutters], coder: JSON
8
+
9
+ LINKED_RESOURCE_TYPE = ['Spree::Taxon', 'Spree::Product', 'Spree::CmsPage']
10
+
11
+ def gutters?
12
+ gutters == 'Gutters'
13
+ end
14
+
15
+ private
16
+
17
+ def reset_link_attributes
18
+ if linked_resource_type_changed?
19
+ self.linked_resource_id = nil
20
+ end
21
+ end
22
+
23
+ def default_values
24
+ self.gutters ||= 'No Gutters'
25
+ self.fit ||= 'Screen'
26
+ self.linked_resource_type ||= 'Spree::Taxon'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ module Spree::Cms::Sections
2
+ class HeroImage < Spree::CmsSection
3
+ before_save :reset_link_attributes
4
+ after_initialize :default_values
5
+
6
+ store :content, accessors: [:title, :button_text], coder: JSON
7
+ store :settings, accessors: [:gutters], coder: JSON
8
+
9
+ LINKED_RESOURCE_TYPE = ['Spree::Taxon', 'Spree::Product', 'Spree::CmsPage']
10
+
11
+ def gutters?
12
+ gutters == 'Gutters'
13
+ end
14
+
15
+ def img_one_sm(dimensions = '600x250>')
16
+ super
17
+ end
18
+
19
+ def img_one_md(dimensions = '1200x500>')
20
+ super
21
+ end
22
+
23
+ def img_one_lg(dimensions = '2400x1000>')
24
+ super
25
+ end
26
+
27
+ def img_one_xl(dimensions = '4800x2000>')
28
+ super
29
+ end
30
+
31
+ private
32
+
33
+ def reset_link_attributes
34
+ if linked_resource_type_changed?
35
+ return if linked_resource_id_was.nil?
36
+
37
+ self.linked_resource_id = nil
38
+ end
39
+ end
40
+
41
+ def default_values
42
+ self.gutters ||= 'No Gutters'
43
+ self.fit ||= 'Screen'
44
+ self.linked_resource_type ||= 'Spree::Taxon'
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,103 @@
1
+ module Spree::Cms::Sections
2
+ class ImageGallery < Spree::CmsSection
3
+ after_initialize :default_values
4
+ before_save :reset_link_attributes
5
+
6
+ LINKED_RESOURCE_TYPE = if Rails::VERSION::STRING < '6.0'
7
+ ['Spree::Taxon'].freeze
8
+ else
9
+ ['Spree::Taxon', 'Spree::Product'].freeze
10
+ end
11
+
12
+ LAYOUT_OPTIONS = ['Default', 'Reversed'].freeze
13
+ LABEL_OPTIONS = ['Show', 'Hide'].freeze
14
+
15
+ store :content, accessors: [:link_type_one, :link_one, :title_one,
16
+ :link_type_two, :link_two, :title_two,
17
+ :link_type_three, :link_three, :title_three], coder: JSON
18
+
19
+ store :settings, accessors: [:layout_style, :display_labels], coder: JSON
20
+
21
+ #
22
+ # img_one sizing
23
+ def img_one_md(dimensions = '270x195>')
24
+ super
25
+ end
26
+
27
+ def img_one_lg(dimensions = '540x390>')
28
+ super
29
+ end
30
+
31
+ def img_one_xl(dimensions = '1080x780>')
32
+ super
33
+ end
34
+
35
+ #
36
+ # img_two sizing
37
+ def img_two_md(dimensions = '270x400>')
38
+ super
39
+ end
40
+
41
+ def img_two_lg(dimensions = '540x800>')
42
+ super
43
+ end
44
+
45
+ def img_two_xl(dimensions = '1080x1600>')
46
+ super
47
+ end
48
+
49
+ #
50
+ # img_three sizing
51
+ def img_three_md(dimensions = '270x195>')
52
+ super
53
+ end
54
+
55
+ def img_three_lg(dimensions = '540x390>')
56
+ super
57
+ end
58
+
59
+ def img_three_xl(dimensions = '1080x780>')
60
+ super
61
+ end
62
+
63
+ def default_layout?
64
+ layout_style == 'Default'
65
+ end
66
+
67
+ def show_labels?
68
+ display_labels == 'Show'
69
+ end
70
+
71
+ private
72
+
73
+ def reset_link_attributes
74
+ return if Rails::VERSION::STRING < '6.0'
75
+
76
+ if link_type_one_changed?
77
+ return if link_type_one_was.nil?
78
+
79
+ self.link_one = nil
80
+ end
81
+
82
+ if link_type_two_changed?
83
+ return if link_type_two_was.nil?
84
+
85
+ self.link_two = nil
86
+ end
87
+
88
+ if link_type_three_changed?
89
+ return if link_type_three_was.nil?
90
+
91
+ self.link_three = nil
92
+ end
93
+ end
94
+
95
+ def default_values
96
+ self.layout_style ||= 'Default'
97
+ self.fit ||= 'Container'
98
+ self.link_type_one ||= 'Spree::Taxon'
99
+ self.link_type_two ||= 'Spree::Taxon'
100
+ self.link_type_three ||= 'Spree::Taxon'
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,14 @@
1
+ module Spree::Cms::Sections
2
+ class ProductCarousel < Spree::CmsSection
3
+ after_initialize :default_values
4
+
5
+ LINKED_RESOURCE_TYPE = ['Spree::Taxon']
6
+
7
+ private
8
+
9
+ def default_values
10
+ self.fit ||= 'Screen'
11
+ self.linked_resource_type ||= 'Spree::Taxon'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Spree::Cms::Sections
2
+ class RichTextContent < Spree::CmsSection
3
+ after_initialize :default_values
4
+
5
+ store :content, accessors: [:rte_content], coder: JSON
6
+
7
+ private
8
+
9
+ def default_values
10
+ self.fit ||= 'Container'
11
+ end
12
+ end
13
+ end