spree_core 4.10.1 → 5.0.0.rc1

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 (476) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/spree_core_manifest.js +4 -0
  3. data/app/assets/images/google_on_white_hdpi.png +0 -0
  4. data/app/controllers/spree/base_controller.rb +1 -4
  5. data/app/finders/spree/orders/find_complete.rb +14 -2
  6. data/app/finders/spree/products/find.rb +74 -23
  7. data/app/finders/spree/stores/find_current.rb +6 -2
  8. data/app/helpers/spree/addresses_helper.rb +106 -0
  9. data/app/helpers/spree/base_helper.rb +83 -55
  10. data/app/helpers/spree/currency_helper.rb +12 -0
  11. data/app/helpers/spree/images_helper.rb +18 -0
  12. data/app/helpers/spree/mail_helper.rb +24 -0
  13. data/app/helpers/spree/products_helper.rb +1 -20
  14. data/app/javascript/spree/core/controllers/address_autocomplete_controller.js +233 -0
  15. data/app/javascript/spree/core/controllers/address_form_controller.js +98 -0
  16. data/app/javascript/spree/core/controllers/enable_button_controller.js +29 -0
  17. data/app/javascript/spree/core/helpers/address_autocomplete/google_places_suggestions_provider.js +179 -0
  18. data/app/javascript/spree/core/helpers/debounce.js +9 -0
  19. data/app/javascript/spree/core/helpers/scroll_lock.js +25 -0
  20. data/app/jobs/spree/addresses/geocode_address_job.rb +31 -0
  21. data/app/jobs/spree/base_job.rb +1 -0
  22. data/app/jobs/spree/coupon_codes/bulk_generate_job.rb +17 -0
  23. data/app/jobs/spree/exports/generate_job.rb +12 -0
  24. data/app/jobs/spree/products/auto_match_taxons_job.rb +14 -0
  25. data/app/jobs/spree/products/touch_taxons_job.rb +12 -0
  26. data/app/jobs/spree/reports/generate_job.rb +12 -0
  27. data/app/jobs/spree/stock_locations/stock_items/create_job.rb +1 -1
  28. data/app/jobs/spree/themes/duplicate_components_job.rb +59 -0
  29. data/app/jobs/spree/themes/screenshot_job.rb +81 -0
  30. data/app/jobs/spree/variants/remove_from_incomplete_orders_job.rb +2 -0
  31. data/app/jobs/spree/variants/remove_line_item_job.rb +2 -0
  32. data/app/mailers/spree/base_mailer.rb +51 -0
  33. data/app/mailers/spree/export_mailer.rb +19 -0
  34. data/app/mailers/spree/report_mailer.rb +20 -0
  35. data/app/mailers/spree/test_mailer.rb +8 -0
  36. data/app/models/action_text/rich_text_decorator.rb +11 -0
  37. data/app/models/action_text/video_embed.rb +13 -0
  38. data/app/models/acts_as_taggable_on/tag_decorator.rb +10 -0
  39. data/app/models/concerns/spree/calculated_adjustments.rb +2 -0
  40. data/app/models/concerns/spree/display_on.rb +13 -0
  41. data/app/models/concerns/spree/has_one_link.rb +42 -0
  42. data/app/models/concerns/spree/has_page_links.rb +53 -0
  43. data/app/models/concerns/spree/metadata.rb +3 -7
  44. data/app/models/concerns/spree/multi_searchable.rb +21 -0
  45. data/app/models/concerns/spree/multi_store_resource.rb +9 -0
  46. data/app/models/concerns/spree/number_as_param.rb +4 -2
  47. data/app/models/concerns/spree/parameterizable_name.rb +21 -0
  48. data/app/models/concerns/spree/previewable.rb +17 -0
  49. data/app/models/concerns/spree/product_scopes.rb +7 -7
  50. data/app/models/concerns/spree/stores/setup.rb +52 -0
  51. data/app/models/concerns/spree/stores/socials.rb +68 -0
  52. data/app/models/concerns/spree/user_address.rb +4 -0
  53. data/app/models/concerns/spree/user_methods.rb +61 -11
  54. data/app/models/concerns/spree/user_reporting.rb +14 -6
  55. data/app/models/concerns/spree/user_roles.rb +1 -1
  56. data/app/models/spree/ability.rb +4 -2
  57. data/app/models/spree/address.rb +122 -28
  58. data/app/models/spree/adjustment.rb +4 -1
  59. data/app/models/spree/asset/support/active_storage.rb +1 -1
  60. data/app/models/spree/asset.rb +18 -6
  61. data/app/models/spree/base.rb +38 -7
  62. data/app/models/spree/base_analytics_event_handler.rb +49 -0
  63. data/app/models/spree/calculator.rb +1 -1
  64. data/app/models/spree/classification.rb +10 -1
  65. data/app/models/spree/country.rb +1 -1
  66. data/app/models/spree/coupon_code.rb +38 -0
  67. data/app/models/spree/credit_card.rb +4 -3
  68. data/app/models/spree/current.rb +9 -0
  69. data/app/models/spree/custom_domain.rb +53 -0
  70. data/app/models/spree/customer_return.rb +13 -1
  71. data/app/models/spree/data_feed.rb +1 -1
  72. data/app/models/spree/digital.rb +5 -6
  73. data/app/models/spree/digital_link.rb +11 -6
  74. data/app/models/spree/export.rb +172 -0
  75. data/app/models/spree/exports/orders.rb +23 -0
  76. data/app/models/spree/exports/products.rb +35 -0
  77. data/app/models/spree/gateway/bogus.rb +5 -0
  78. data/app/models/spree/gateway.rb +14 -4
  79. data/app/models/spree/gateway_customer.rb +13 -0
  80. data/app/models/spree/image/configuration/active_storage.rb +1 -1
  81. data/app/models/spree/inventory_unit.rb +1 -1
  82. data/app/models/spree/legacy_user.rb +3 -1
  83. data/app/models/spree/line_item.rb +37 -2
  84. data/app/models/spree/log_entry.rb +1 -1
  85. data/app/models/spree/option_type.rb +40 -6
  86. data/app/models/spree/option_type_prototype.rb +1 -1
  87. data/app/models/spree/option_value.rb +35 -5
  88. data/app/models/spree/option_value_variant.rb +2 -2
  89. data/app/models/spree/order/address_book.rb +34 -15
  90. data/app/models/spree/order/checkout.rb +12 -2
  91. data/app/models/spree/order/currency_updater.rb +1 -1
  92. data/app/models/spree/order/digital.rb +14 -3
  93. data/app/models/spree/order/emails.rb +1 -1
  94. data/app/models/spree/order/payments.rb +1 -13
  95. data/app/models/spree/order/store_credit.rb +17 -5
  96. data/app/models/spree/order/webhooks.rb +1 -1
  97. data/app/models/spree/order.rb +179 -49
  98. data/app/models/spree/order_promotion.rb +1 -1
  99. data/app/models/spree/order_updater.rb +9 -3
  100. data/app/models/spree/page.rb +184 -0
  101. data/app/models/spree/page_block.rb +69 -0
  102. data/app/models/spree/page_blocks/buttons.rb +29 -0
  103. data/app/models/spree/page_blocks/heading.rb +18 -0
  104. data/app/models/spree/page_blocks/image.rb +17 -0
  105. data/app/models/spree/page_blocks/link.rb +21 -0
  106. data/app/models/spree/page_blocks/mega_nav.rb +33 -0
  107. data/app/models/spree/page_blocks/mega_nav_with_subcategories.rb +32 -0
  108. data/app/models/spree/page_blocks/nav.rb +15 -0
  109. data/app/models/spree/page_blocks/newsletter_form.rb +18 -0
  110. data/app/models/spree/page_blocks/products/buy_buttons.rb +12 -0
  111. data/app/models/spree/page_blocks/products/price.rb +18 -0
  112. data/app/models/spree/page_blocks/products/quantity_selector.rb +12 -0
  113. data/app/models/spree/page_blocks/products/share.rb +8 -0
  114. data/app/models/spree/page_blocks/products/title.rb +15 -0
  115. data/app/models/spree/page_blocks/products/variant_picker.rb +9 -0
  116. data/app/models/spree/page_blocks/subheading.rb +17 -0
  117. data/app/models/spree/page_blocks/text.rb +16 -0
  118. data/app/models/spree/page_link.rb +59 -0
  119. data/app/models/spree/page_section.rb +215 -0
  120. data/app/models/spree/page_sections/announcement_bar.rb +30 -0
  121. data/app/models/spree/page_sections/collection_banner.rb +18 -0
  122. data/app/models/spree/page_sections/custom_code.rb +11 -0
  123. data/app/models/spree/page_sections/featured_posts.rb +43 -0
  124. data/app/models/spree/page_sections/featured_product.rb +46 -0
  125. data/app/models/spree/page_sections/featured_taxon.rb +88 -0
  126. data/app/models/spree/page_sections/featured_taxons.rb +45 -0
  127. data/app/models/spree/page_sections/footer.rb +94 -0
  128. data/app/models/spree/page_sections/header.rb +62 -0
  129. data/app/models/spree/page_sections/image_banner.rb +38 -0
  130. data/app/models/spree/page_sections/image_with_text.rb +48 -0
  131. data/app/models/spree/page_sections/main_password_footer.rb +18 -0
  132. data/app/models/spree/page_sections/main_password_header.rb +20 -0
  133. data/app/models/spree/page_sections/newsletter.rb +47 -0
  134. data/app/models/spree/page_sections/page_title.rb +19 -0
  135. data/app/models/spree/page_sections/post_details.rb +19 -0
  136. data/app/models/spree/page_sections/post_grid.rb +19 -0
  137. data/app/models/spree/page_sections/product_details.rb +16 -0
  138. data/app/models/spree/page_sections/product_grid.rb +13 -0
  139. data/app/models/spree/page_sections/related_products.rb +60 -0
  140. data/app/models/spree/page_sections/rich_text.rb +20 -0
  141. data/app/models/spree/page_sections/taxon_banner.rb +18 -0
  142. data/app/models/spree/page_sections/taxon_grid.rb +17 -0
  143. data/app/models/spree/page_sections/video.rb +99 -0
  144. data/app/models/spree/pages/account.rb +15 -0
  145. data/app/models/spree/pages/cart.rb +9 -0
  146. data/app/models/spree/pages/checkout.rb +9 -0
  147. data/app/models/spree/pages/custom.rb +34 -0
  148. data/app/models/spree/pages/homepage.rb +68 -0
  149. data/app/models/spree/pages/login.rb +15 -0
  150. data/app/models/spree/pages/password.rb +57 -0
  151. data/app/models/spree/pages/post.rb +27 -0
  152. data/app/models/spree/pages/post_list.rb +32 -0
  153. data/app/models/spree/pages/product_details.rb +29 -0
  154. data/app/models/spree/pages/search_results.rb +43 -0
  155. data/app/models/spree/pages/shop_all.rb +36 -0
  156. data/app/models/spree/pages/taxon.rb +29 -0
  157. data/app/models/spree/pages/taxon_list.rb +41 -0
  158. data/app/models/spree/pages/wishlist.rb +11 -0
  159. data/app/models/spree/payment/gateway_options.rb +13 -15
  160. data/app/models/spree/payment/processing.rb +1 -1
  161. data/app/models/spree/payment/webhooks.rb +1 -1
  162. data/app/models/spree/payment.rb +61 -12
  163. data/app/models/spree/payment_capture_event.rb +1 -1
  164. data/app/models/spree/payment_method/store_credit.rb +9 -1
  165. data/app/models/spree/payment_method.rb +26 -8
  166. data/app/models/spree/payment_source.rb +2 -2
  167. data/app/models/spree/post.rb +108 -0
  168. data/app/models/spree/post_category.rb +33 -0
  169. data/app/models/spree/preference.rb +1 -1
  170. data/app/models/spree/price.rb +10 -3
  171. data/app/models/spree/product/webhooks.rb +1 -1
  172. data/app/models/spree/product.rb +325 -54
  173. data/app/models/spree/product_option_type.rb +1 -1
  174. data/app/models/spree/product_promotion_rule.rb +1 -1
  175. data/app/models/spree/product_property.rb +4 -1
  176. data/app/models/spree/promotion/actions/create_line_items.rb +37 -2
  177. data/app/models/spree/promotion/rules/country.rb +22 -4
  178. data/app/models/spree/promotion/rules/currency.rb +21 -0
  179. data/app/models/spree/promotion/rules/item_total.rb +12 -3
  180. data/app/models/spree/promotion/rules/option_value.rb +5 -20
  181. data/app/models/spree/promotion/rules/product.rb +33 -1
  182. data/app/models/spree/promotion/rules/taxon.rb +31 -0
  183. data/app/models/spree/promotion/rules/user.rb +33 -4
  184. data/app/models/spree/promotion.rb +136 -15
  185. data/app/models/spree/promotion_action.rb +31 -1
  186. data/app/models/spree/promotion_action_line_item.rb +1 -1
  187. data/app/models/spree/promotion_category.rb +1 -1
  188. data/app/models/spree/promotion_handler/cart.rb +1 -1
  189. data/app/models/spree/promotion_handler/coupon.rb +46 -8
  190. data/app/models/spree/promotion_handler/free_shipping.rb +1 -1
  191. data/app/models/spree/promotion_handler/promotion_duplicator.rb +6 -5
  192. data/app/models/spree/promotion_rule.rb +23 -1
  193. data/app/models/spree/promotion_rule_taxon.rb +1 -1
  194. data/app/models/spree/promotion_rule_user.rb +1 -1
  195. data/app/models/spree/property.rb +11 -3
  196. data/app/models/spree/property_prototype.rb +1 -1
  197. data/app/models/spree/prototype.rb +1 -1
  198. data/app/models/spree/prototype_taxon.rb +1 -1
  199. data/app/models/spree/refund.rb +24 -4
  200. data/app/models/spree/refund_reason.rb +12 -2
  201. data/app/models/spree/reimbursement/credit.rb +1 -1
  202. data/app/models/spree/reimbursement/emails.rb +1 -1
  203. data/app/models/spree/reimbursement.rb +5 -3
  204. data/app/models/spree/reimbursement_type.rb +1 -1
  205. data/app/models/spree/report.rb +110 -0
  206. data/app/models/spree/report_line_item.rb +27 -0
  207. data/app/models/spree/report_line_items/products_performance.rb +76 -0
  208. data/app/models/spree/report_line_items/sales_total.rb +49 -0
  209. data/app/models/spree/reports/products_performance.rb +44 -0
  210. data/app/models/spree/reports/sales_total.rb +14 -0
  211. data/app/models/spree/return_authorization.rb +4 -1
  212. data/app/models/spree/return_authorization_reason.rb +1 -1
  213. data/app/models/spree/return_item.rb +2 -1
  214. data/app/models/spree/role.rb +5 -2
  215. data/app/models/spree/role_user.rb +2 -2
  216. data/app/models/spree/shipment/emails.rb +1 -1
  217. data/app/models/spree/shipment/webhooks.rb +1 -1
  218. data/app/models/spree/shipment.rb +14 -4
  219. data/app/models/spree/shipping_category.rb +1 -1
  220. data/app/models/spree/shipping_method.rb +48 -8
  221. data/app/models/spree/shipping_method_category.rb +1 -1
  222. data/app/models/spree/shipping_method_zone.rb +1 -1
  223. data/app/models/spree/shipping_rate.rb +21 -3
  224. data/app/models/spree/state.rb +1 -1
  225. data/app/models/spree/state_change.rb +1 -1
  226. data/app/models/spree/stock_item/webhooks.rb +1 -1
  227. data/app/models/spree/stock_item.rb +9 -6
  228. data/app/models/spree/stock_location.rb +35 -8
  229. data/app/models/spree/stock_movement/webhooks.rb +1 -1
  230. data/app/models/spree/stock_movement.rb +9 -3
  231. data/app/models/spree/stock_transfer.rb +41 -3
  232. data/app/models/spree/store.rb +345 -72
  233. data/app/models/spree/store_credit.rb +12 -4
  234. data/app/models/spree/store_credit_category.rb +1 -1
  235. data/app/models/spree/store_credit_event.rb +21 -1
  236. data/app/models/spree/store_credit_type.rb +1 -1
  237. data/app/models/spree/store_payment_method.rb +1 -1
  238. data/app/models/spree/store_product.rb +1 -1
  239. data/app/models/spree/store_promotion.rb +1 -1
  240. data/app/models/spree/tax_category.rb +15 -1
  241. data/app/models/spree/tax_rate.rb +1 -1
  242. data/app/models/spree/taxon.rb +210 -27
  243. data/app/models/spree/taxon_image/configuration/active_storage.rb +1 -1
  244. data/app/models/spree/taxon_rule.rb +25 -0
  245. data/app/models/spree/taxon_rules/available_on.rb +20 -0
  246. data/app/models/spree/taxon_rules/sale.rb +16 -0
  247. data/app/models/spree/taxon_rules/tag.rb +19 -0
  248. data/app/models/spree/taxonomy.rb +3 -2
  249. data/app/models/spree/theme.rb +200 -0
  250. data/app/models/spree/themes/default.rb +94 -0
  251. data/app/models/spree/variant/webhooks.rb +1 -1
  252. data/app/models/spree/variant.rb +211 -62
  253. data/app/models/spree/wished_item.rb +1 -1
  254. data/app/models/spree/wishlist.rb +1 -1
  255. data/app/models/spree/zone.rb +1 -1
  256. data/app/models/spree/zone_member.rb +1 -1
  257. data/app/presenters/spree/csv/order_line_item_presenter.rb +145 -0
  258. data/app/presenters/spree/csv/product_presenter.rb +63 -0
  259. data/app/presenters/spree/csv/product_variant_presenter.rb +130 -0
  260. data/app/services/spree/addresses/create.rb +31 -6
  261. data/app/services/spree/addresses/helper.rb +7 -4
  262. data/app/services/spree/addresses/update.rb +79 -12
  263. data/app/services/spree/cart/remove_out_of_stock_items.rb +56 -0
  264. data/app/services/spree/checkout/add_store_credit.rb +6 -1
  265. data/app/services/spree/checkout/advance.rb +44 -4
  266. data/app/services/spree/checkout/select_shipping_method.rb +2 -0
  267. data/app/services/spree/coupon_codes/bulk_generate.rb +37 -0
  268. data/app/services/spree/coupon_codes/coupon_codes_handler.rb +34 -0
  269. data/app/services/spree/orders/create_user_account.rb +70 -0
  270. data/app/services/spree/orders/update_contact_information.rb +19 -0
  271. data/app/services/spree/products/auto_match_taxons.rb +64 -0
  272. data/app/services/spree/products/duplicator.rb +121 -0
  273. data/app/services/spree/products/prepare_nested_attributes.rb +169 -0
  274. data/app/services/spree/seeds/admin_user.rb +22 -0
  275. data/app/services/spree/seeds/all.rb +1 -0
  276. data/app/services/spree/seeds/stores.rb +5 -10
  277. data/app/services/spree/seeds/zones.rb +2 -0
  278. data/app/services/spree/tags/bulk_add.rb +38 -0
  279. data/app/services/spree/tags/bulk_remove.rb +24 -0
  280. data/app/services/spree/taxons/add_products.rb +39 -0
  281. data/app/services/spree/taxons/regenerate_products.rb +53 -0
  282. data/app/services/spree/taxons/remove_products.rb +53 -0
  283. data/app/services/spree/taxons/touch_featured_sections.rb +21 -0
  284. data/app/services/spree/themes/duplicator.rb +40 -0
  285. data/app/services/spree/variants/remove_line_items.rb +1 -1
  286. data/app/sorters/spree/classifications/sort.rb +68 -0
  287. data/app/sorters/spree/products/sort.rb +2 -3
  288. data/app/views/action_text/video_embeds/_thumbnail.html.erb +1 -0
  289. data/app/views/action_text/video_embeds/_video_embed.html.erb +3 -0
  290. data/app/views/active_storage/blobs/_blob.html.erb +20 -0
  291. data/app/views/layouts/action_text/contents/_content.html.erb +3 -0
  292. data/app/views/layouts/spree/base_mailer.html.erb +46 -0
  293. data/app/views/spree/addresses/_form.html.erb +58 -0
  294. data/app/views/spree/addresses/_suggestions_box.erb +14 -0
  295. data/app/views/spree/export_mailer/export_done.html.erb +15 -0
  296. data/app/views/spree/report_mailer/report_done.html.erb +15 -0
  297. data/app/views/spree/shared/_base_mailer_footer.html.erb +12 -0
  298. data/app/views/spree/shared/_base_mailer_header.html.erb +6 -0
  299. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +456 -0
  300. data/app/views/spree/shared/_google_places_api_loader.html.erb +7 -0
  301. data/app/views/spree/shared/_mailer_line_item.html.erb +12 -0
  302. data/app/views/spree/shared/_mailer_logo.html.erb +41 -0
  303. data/app/views/spree/shared/_payment.html.erb +41 -0
  304. data/app/views/spree/test_mailer/test_email.html.erb +40 -0
  305. data/app/views/spree/test_mailer/test_email.text.erb +4 -0
  306. data/config/i18n-tasks.yml +178 -0
  307. data/config/importmap.rb +14 -0
  308. data/config/initializers/acts_as_taggable_on.rb +2 -0
  309. data/config/initializers/inflections.rb +2 -0
  310. data/config/initializers/mobility.rb +4 -0
  311. data/config/initializers/oembed.rb +1 -0
  312. data/config/locales/en.yml +823 -413
  313. data/config/routes.rb +6 -5
  314. data/db/migrate/20210914000000_spree_four_three.rb +0 -79
  315. data/db/migrate/20240913143518_change_default_value_of_spree_option_types_filterable.rb +5 -0
  316. data/db/migrate/20240914153106_add_display_on_to_spree_properties.rb +5 -0
  317. data/db/migrate/20240915144935_add_position_to_spree_properties.rb +6 -0
  318. data/db/migrate/20241004181911_create_spree_coupon_codes.rb +15 -0
  319. data/db/migrate/20241005093437_add_multi_code_to_spree_promotions.rb +14 -0
  320. data/db/migrate/20241014140140_translate_rich_texts.rb +17 -0
  321. data/db/migrate/20241030134309_create_spree_exports.rb +23 -0
  322. data/db/migrate/20241104083457_migrate_spree_promotion_rules_option_value_eligible_values.rb +16 -0
  323. data/db/migrate/20241123110646_add_estimated_transit_fields_to_spree_shipping_methods.rb +6 -0
  324. data/db/migrate/20241127193411_create_spree_taxon_rules.rb +13 -0
  325. data/db/migrate/20241127223627_add_rules_match_policy_and_sort_order_to_spree_taxons.rb +6 -0
  326. data/db/migrate/20241128103947_add_automatic_to_spree_taxons.rb +5 -0
  327. data/db/migrate/20241218183905_add_gateway_customer_profile_id_to_spree_payment_sources.rb +5 -0
  328. data/db/migrate/20250107220432_add_accept_marketing_and_signup_for_an_account_to_spree_orders.rb +6 -0
  329. data/db/migrate/20250110171203_add_quick_checkout_to_spree_addresses.rb +6 -0
  330. data/db/migrate/20250113180019_add_preferences_to_spree_stores.rb +5 -0
  331. data/db/migrate/20250114193857_add_metadata_to_spree_stores.rb +13 -0
  332. data/db/migrate/20250119165904_create_spree_custom_domains.rb +22 -0
  333. data/db/migrate/20250120094216_create_page_builder_models.rb +78 -0
  334. data/db/migrate/20250120152208_add_default_locale_to_action_text_rich_texts.rb +7 -0
  335. data/db/migrate/20250121160028_create_spree_posts_and_spree_post_categories.rb +33 -0
  336. data/db/migrate/20250122113708_add_first_and_last_name_to_spree_admin_class.rb +9 -0
  337. data/db/migrate/20250123135358_add_custom_code_fields_to_spree_store.rb +7 -0
  338. data/db/migrate/20250127083740_add_kind_to_spree_properties.rb +5 -0
  339. data/db/migrate/20250127112758_add_latitude_and_longitude_to_spree_addresses.rb +6 -0
  340. data/db/migrate/20250127151258_add_phone_to_spree_users.rb +5 -0
  341. data/db/migrate/20250204162453_create_spree_reports.rb +13 -0
  342. data/db/migrate/20250207084000_add_accepts_email_marketing_field_to_spree_users_table.rb +6 -0
  343. data/db/migrate/20250217171018_create_action_text_video_embeds.rb +11 -0
  344. data/db/migrate/20250304115943_add_performed_by_to_spree_reimbursements.rb +5 -0
  345. data/db/migrate/20250305121352_remove_page_builder_indices.rb +11 -0
  346. data/db/migrate/20250305121657_remove_spree_posts_indices.rb +7 -0
  347. data/db/migrate/20250311105934_create_spree_gateway_customers.rb +18 -0
  348. data/db/migrate/20250312202705_add_unique_index_on_promotion_rules_associations.rb +75 -0
  349. data/db/migrate/20250313104226_add_user_type_to_spree_role_users.rb +18 -0
  350. data/db/migrate/20250313175830_add_unique_index_on_promotion_action_line_items.rb +29 -0
  351. data/db/migrate/20250314144210_create_spree_taggings_and_spree_tags.rb +38 -0
  352. data/lib/generators/spree/authentication/custom/custom_generator.rb +49 -0
  353. data/lib/generators/spree/authentication/custom/templates/authentication_helpers.rb.tt +50 -0
  354. data/lib/generators/spree/authentication/devise/devise_generator.rb +57 -0
  355. data/lib/generators/spree/authentication/devise/templates/authentication_helpers.rb.tt +50 -0
  356. data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
  357. data/lib/generators/spree/dummy/templates/rails/database.yml +1 -0
  358. data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
  359. data/lib/generators/spree/install/install_generator.rb +21 -36
  360. data/lib/generators/spree/install/templates/config/initializers/spree.rb +40 -6
  361. data/lib/normalize_string.rb +18 -0
  362. data/lib/spree/analytics.rb +11 -0
  363. data/lib/spree/core/components.rb +1 -1
  364. data/lib/spree/core/configuration.rb +14 -11
  365. data/lib/spree/core/controller_helpers/auth.rb +0 -26
  366. data/lib/spree/core/controller_helpers/order.rb +77 -12
  367. data/lib/spree/core/controller_helpers/search.rb +2 -0
  368. data/lib/spree/core/controller_helpers/store.rb +0 -5
  369. data/lib/spree/core/controller_helpers/strong_parameters.rb +4 -0
  370. data/lib/spree/core/controller_helpers/turbo.rb +19 -0
  371. data/lib/spree/core/dependencies.rb +3 -5
  372. data/lib/spree/core/engine.rb +158 -7
  373. data/lib/spree/core/preferences/configuration.rb +2 -44
  374. data/lib/spree/core/preferences/preferable.rb +9 -0
  375. data/lib/spree/core/preferences/preferable_class_methods.rb +11 -1
  376. data/lib/spree/core/preferences/runtime_configuration.rb +13 -2
  377. data/lib/spree/core/search/base.rb +2 -0
  378. data/lib/spree/core/version.rb +1 -1
  379. data/lib/spree/core.rb +61 -11
  380. data/lib/spree/i18n.rb +5 -8
  381. data/lib/spree/migrations.rb +1 -1
  382. data/lib/spree/permitted_attributes.rb +24 -15
  383. data/lib/spree/testing_support/authorization_helpers.rb +9 -6
  384. data/lib/spree/testing_support/capybara_config.rb +11 -0
  385. data/lib/spree/testing_support/common_rake.rb +20 -12
  386. data/lib/spree/testing_support/factories/calculator_factory.rb +16 -0
  387. data/lib/spree/testing_support/factories/country_factory.rb +8 -0
  388. data/lib/spree/testing_support/factories/coupon_code_factory.rb +7 -0
  389. data/lib/spree/testing_support/factories/custom_domain_factory.rb +7 -0
  390. data/lib/spree/testing_support/factories/export_factory.rb +32 -0
  391. data/lib/spree/testing_support/factories/gateway_customer_factory.rb +7 -0
  392. data/lib/spree/testing_support/factories/order_factory.rb +14 -3
  393. data/lib/spree/testing_support/factories/page_block_factory.rb +21 -0
  394. data/lib/spree/testing_support/factories/page_factory.rb +33 -0
  395. data/lib/spree/testing_support/factories/page_link_factory.rb +7 -0
  396. data/lib/spree/testing_support/factories/page_section_factory.rb +24 -0
  397. data/lib/spree/testing_support/factories/payment_factory.rb +2 -2
  398. data/lib/spree/testing_support/factories/post_category_factory.rb +7 -0
  399. data/lib/spree/testing_support/factories/post_factory.rb +10 -0
  400. data/lib/spree/testing_support/factories/product_factory.rb +3 -8
  401. data/lib/spree/testing_support/factories/product_property_factory.rb +1 -1
  402. data/lib/spree/testing_support/factories/promotion_action_factory.rb +5 -0
  403. data/lib/spree/testing_support/factories/promotion_factory.rb +7 -9
  404. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +12 -0
  405. data/lib/spree/testing_support/factories/property_factory.rb +1 -1
  406. data/lib/spree/testing_support/factories/report_factory.rb +33 -0
  407. data/lib/spree/testing_support/factories/role_user_factory.rb +7 -0
  408. data/lib/spree/testing_support/factories/shipping_method_factory.rb +9 -0
  409. data/lib/spree/testing_support/factories/stock_transfer_factory.rb +5 -2
  410. data/lib/spree/testing_support/factories/store_factory.rb +6 -9
  411. data/lib/spree/testing_support/factories/taxon_factory.rb +13 -0
  412. data/lib/spree/testing_support/factories/taxon_rule_factory.rb +38 -0
  413. data/lib/spree/testing_support/factories/theme_factory.rb +14 -0
  414. data/lib/spree/testing_support/factories/user_factory.rb +13 -11
  415. data/lib/spree/testing_support/factories/variant_factory.rb +23 -5
  416. data/lib/spree/testing_support/jobs.rb +1 -7
  417. data/lib/spree/testing_support/metadata.rb +13 -1
  418. data/lib/spree/testing_support/order_walkthrough.rb +1 -7
  419. data/lib/spree/testing_support/preferences.rb +1 -4
  420. data/lib/spree/testing_support/store.rb +26 -0
  421. data/lib/spree_core.rb +1 -0
  422. data/vendor/javascript/@rails--request.js.js +4 -0
  423. data/vendor/javascript/@stimulus-components--auto-submit.js +4 -0
  424. data/vendor/javascript/stimulus-reveal-controller.js +4 -0
  425. data/vendor/javascript/tailwindcss-stimulus-components.js +4 -0
  426. metadata +340 -197
  427. data/Gemfile +0 -3
  428. data/app/finders/spree/cms_pages/find.rb +0 -41
  429. data/app/finders/spree/menus/find.rb +0 -11
  430. data/app/models/concerns/spree/display_link.rb +0 -30
  431. data/app/models/spree/cms/pages/feature_page.rb +0 -7
  432. data/app/models/spree/cms/pages/homepage.rb +0 -20
  433. data/app/models/spree/cms/pages/standard_page.rb +0 -4
  434. data/app/models/spree/cms/sections/featured_article.rb +0 -22
  435. data/app/models/spree/cms/sections/hero_image.rb +0 -38
  436. data/app/models/spree/cms/sections/image_gallery.rb +0 -97
  437. data/app/models/spree/cms/sections/product_carousel.rb +0 -14
  438. data/app/models/spree/cms/sections/rich_text_content.rb +0 -13
  439. data/app/models/spree/cms/sections/side_by_side_images.rb +0 -68
  440. data/app/models/spree/cms_page.rb +0 -70
  441. data/app/models/spree/cms_section.rb +0 -69
  442. data/app/models/spree/cms_section_image.rb +0 -9
  443. data/app/models/spree/cms_section_image_one.rb +0 -4
  444. data/app/models/spree/cms_section_image_three.rb +0 -4
  445. data/app/models/spree/cms_section_image_two.rb +0 -4
  446. data/app/models/spree/icon.rb +0 -7
  447. data/app/models/spree/linkable/homepage.rb +0 -3
  448. data/app/models/spree/linkable/uri.rb +0 -3
  449. data/app/models/spree/menu.rb +0 -66
  450. data/app/models/spree/menu_item.rb +0 -72
  451. data/brakeman.ignore +0 -328
  452. data/db/migrate/20211201202851_update_linkable_resource_types.rb +0 -10
  453. data/db/migrate/20220329113557_fix_cms_pages_unique_indexes.rb +0 -8
  454. data/lib/generators/spree/custom_authentication/custom_authentication_generator.rb +0 -23
  455. data/lib/generators/spree/custom_authentication/templates/authentication_helpers.rb.tt +0 -23
  456. data/lib/generators/spree/custom_user/custom_user_generator.rb +0 -46
  457. data/lib/generators/spree/custom_user/templates/current_user_helpers.rb.tt +0 -15
  458. data/lib/generators/spree/custom_user/templates/initializer.rb.tt +0 -1
  459. data/lib/generators/spree/custom_user/templates/migration.rb.tt +0 -7
  460. data/lib/generators/spree/dummy/templates/package.json +0 -12
  461. data/lib/spree/core/product_duplicator.rb +0 -85
  462. data/lib/spree/core/runtime_configuration.rb +0 -10
  463. data/lib/spree/testing_support/factories/cms_page_factory.rb +0 -20
  464. data/lib/spree/testing_support/factories/cms_section_factory.rb +0 -31
  465. data/lib/spree/testing_support/factories/icon_factory.rb +0 -9
  466. data/lib/spree/testing_support/factories/menu_factory.rb +0 -16
  467. data/lib/spree/testing_support/factories/menu_item_factory.rb +0 -10
  468. data/script/rails +0 -9
  469. data/spec/fixtures/favicon.ico +0 -0
  470. data/spec/fixtures/files/icon_256x256.gif +0 -0
  471. data/spec/fixtures/files/icon_256x256.png +0 -0
  472. data/spec/fixtures/files/icon_512x512.png +0 -0
  473. data/spec/fixtures/files/img_256x128.png +0 -0
  474. data/spec/fixtures/text-file.txt +0 -1
  475. data/spec/fixtures/thinking-cat.jpg +0 -0
  476. data/spree_core.gemspec +0 -62
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 918652467235e29f0c6defaeddbb7530e77c10f67f12abe2355b6e66c1401b86
4
- data.tar.gz: 685c2ec7206e68233b5811dc8f5ab3ab47029a3fd07431db724b79da47175fea
3
+ metadata.gz: 5b0801c23fbb8cd3771471358df47a3b16c62d063c6f2721ade347cfdc1f7f5c
4
+ data.tar.gz: 84049aed1f998d89471aac0d8b0d4614b301234b5e7cd7a032fe42cff50de4db
5
5
  SHA512:
6
- metadata.gz: e4ab07e13870ed8a97caeb349f37d439090081ed7d693b76858bea8718f698d2546664315f2525c1134dfa7633c2068dd82d9bebc77a41e59f094deb4d7b54ee
7
- data.tar.gz: dacf561acf437770b5ad7291c5785a2eed28d53056a30b3eb6480146d862c6332b9849849344cc91e7c69b63cc77e73aeab373c0601ecc760eb2c46f9ed2322b
6
+ metadata.gz: f8b9420d3a8d33484b98801baf8b85262a1b0d28424a370df01a36161264df4a73d849f3570a9f4cd89f0047c77d1023eb4103800165cde57b99df915e468eed
7
+ data.tar.gz: 82c9c3467ba606290d40ebf8d45987ba02f4ddccfafc580664e9256152901bda9db582dc9806388cda0054fd4f589321b11230e22ab621aa5b45afc804277637
@@ -0,0 +1,4 @@
1
+ //= link_tree ../../javascript/spree/core/controllers .js
2
+ //= link_tree ../../javascript/spree/core/helpers .js
3
+ //= link_tree ../../../vendor/javascript .js
4
+ //= link_tree ../images
@@ -3,12 +3,9 @@ require_dependency 'spree/core/controller_helpers/strong_parameters'
3
3
 
4
4
  class Spree::BaseController < ApplicationController
5
5
  include Spree::Core::ControllerHelpers::Auth
6
- include Spree::Core::ControllerHelpers::Common
7
- include Spree::Core::ControllerHelpers::Search
8
6
  include Spree::Core::ControllerHelpers::Store
9
7
  include Spree::Core::ControllerHelpers::StrongParameters
10
8
  include Spree::Core::ControllerHelpers::Locale
11
9
  include Spree::Core::ControllerHelpers::Currency
12
-
13
- respond_to :html
10
+ include Spree::Core::ControllerHelpers::Turbo
14
11
  end
@@ -3,13 +3,14 @@ module Spree
3
3
  class FindComplete
4
4
  include Spree::Orders::FinderHelper
5
5
 
6
- attr_reader :user, :number, :token, :store
6
+ attr_reader :user, :number, :token, :store, :email
7
7
 
8
- def initialize(user: nil, number: nil, token: nil, store: nil)
8
+ def initialize(user: nil, number: nil, token: nil, store: nil, email: nil)
9
9
  @user = user
10
10
  @number = number
11
11
  @token = token
12
12
  @store = store
13
+ @email = email
13
14
  end
14
15
 
15
16
  def execute
@@ -17,6 +18,7 @@ module Spree
17
18
  orders = by_number(orders)
18
19
  orders = by_token(orders)
19
20
  orders = by_store(orders)
21
+ orders = by_email(orders)
20
22
 
21
23
  orders
22
24
  end
@@ -43,6 +45,10 @@ module Spree
43
45
  store.present?
44
46
  end
45
47
 
48
+ def email?
49
+ email.present?
50
+ end
51
+
46
52
  def by_user(orders)
47
53
  return orders unless user?
48
54
 
@@ -66,6 +72,12 @@ module Spree
66
72
 
67
73
  orders.where(store: store)
68
74
  end
75
+
76
+ def by_email(orders)
77
+ return orders unless email?
78
+
79
+ orders.where(email: email.strip.downcase)
80
+ end
69
81
  end
70
82
  end
71
83
  end
@@ -1,21 +1,14 @@
1
1
  module Spree
2
2
  module Products
3
3
  class Find
4
- def initialize(scope:, params:, current_currency: nil)
5
- @scope = scope
6
-
7
- if current_currency.present?
8
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
9
- `current_currency` param is deprecated and will be removed in Spree 5.
10
- Please pass `:currency` in `params` hash instead.
11
- DEPRECATION
12
- end
13
-
4
+ def initialize(scope:, params:)
5
+ @scope = scope
6
+ @query = params[:q].presence&.strip
14
7
  @ids = String(params.dig(:filter, :ids)).split(',')
15
8
  @skus = String(params.dig(:filter, :skus)).split(',')
16
9
  @store = params[:store] || Spree::Store.default
17
10
  @price = map_prices(String(params.dig(:filter, :price)).split(','))
18
- @currency = current_currency || params.dig(:filter, :currency) || params[:currency]
11
+ @currency = params.dig(:filter, :currency) || params[:currency] || Spree::Store.default.default_currency
19
12
  @taxons = taxon_ids(params.dig(:filter, :taxons))
20
13
  @concat_taxons = taxon_ids(params.dig(:filter, :concat_taxons))
21
14
  @name = params.dig(:filter, :name)
@@ -28,11 +21,21 @@ module Spree
28
21
  @in_stock = params.dig(:filter, :in_stock)
29
22
  @backorderable = params.dig(:filter, :backorderable)
30
23
  @purchasable = params.dig(:filter, :purchasable)
24
+ @out_of_stock = params.dig(:filter, :out_of_stock).to_b
25
+ @tags = params.dig(:filter, :tags).to_s.split(',').compact_blank
26
+ @vendor_ids = params.dig(:filter, :vendor_ids)&.split(',')&.compact_blank || []
27
+
28
+ if @purchasable.present? && @out_of_stock.present?
29
+ @purchasable = false
30
+ @out_of_stock = false
31
+ end
31
32
  end
32
33
 
33
34
  def execute
34
35
  products = by_ids(scope)
35
36
  products = by_skus(products)
37
+ products = by_query(products)
38
+ products = include_discontinued(products)
36
39
  products = by_price(products)
37
40
  products = by_currency(products)
38
41
  products = by_taxons(products)
@@ -41,12 +44,14 @@ module Spree
41
44
  products = by_options(products)
42
45
  products = by_option_value_ids(products)
43
46
  products = by_properties(products)
47
+ products = by_tags(products)
44
48
  products = include_deleted(products)
45
- products = include_discontinued(products)
46
49
  products = show_only_stock(products)
47
50
  products = show_only_backorderable(products)
48
51
  products = show_only_purchasable(products)
52
+ products = show_only_out_of_stock(products)
49
53
  products = ordered(products)
54
+ products = by_vendor_ids(products)
50
55
 
51
56
  products.distinct
52
57
  end
@@ -54,7 +59,12 @@ module Spree
54
59
  private
55
60
 
56
61
  attr_reader :ids, :skus, :price, :currency, :taxons, :concat_taxons, :name, :options, :option_value_ids, :scope,
57
- :sort_by, :deleted, :discontinued, :properties, :store, :in_stock, :backorderable, :purchasable
62
+ :sort_by, :deleted, :discontinued, :properties, :store, :in_stock, :backorderable, :purchasable, :tags,
63
+ :query, :vendor_ids, :out_of_stock
64
+
65
+ def query?
66
+ query.present?
67
+ end
58
68
 
59
69
  def ids?
60
70
  ids.present?
@@ -100,6 +110,16 @@ module Spree
100
110
  properties.present? && properties.values.reject(&:empty?).present?
101
111
  end
102
112
 
113
+ def vendor_ids?
114
+ vendor_ids.present?
115
+ end
116
+
117
+ def by_query(products)
118
+ return products unless query?
119
+
120
+ products.multi_search(query)
121
+ end
122
+
103
123
  def by_ids(products)
104
124
  return products unless ids?
105
125
 
@@ -155,7 +175,9 @@ module Spree
155
175
  def by_options(products)
156
176
  return products unless options?
157
177
 
158
- products_ids = options.map { |key, value| products.with_option_value(key, value)&.ids }.compact.uniq
178
+ products_for_options = query? ? products.unscope(:order) : products
179
+
180
+ products_ids = options.map { |key, value| products_for_options.with_option_value(key, value)&.ids }.compact.uniq
159
181
  products.where(id: products_ids.reduce(&:intersection))
160
182
  end
161
183
 
@@ -194,6 +216,16 @@ module Spree
194
216
  products.where(id: product_ids)
195
217
  end
196
218
 
219
+ def by_tags(products)
220
+ return products if tags.empty?
221
+
222
+ products.tagged_with(tags, any: true)
223
+ end
224
+
225
+ def by_vendor_ids(products)
226
+ products
227
+ end
228
+
197
229
  def option_types_count(option_value_ids)
198
230
  Spree::OptionValue.
199
231
  where(id: option_value_ids).
@@ -205,7 +237,7 @@ module Spree
205
237
  return products unless sort_by?
206
238
 
207
239
  case sort_by
208
- when 'default'
240
+ when 'default', 'manual'
209
241
  if taxons?
210
242
  products.ascend_by_taxons_min_position(taxons)
211
243
  else
@@ -214,17 +246,23 @@ module Spree
214
246
  when 'name-a-z'
215
247
  # workaround for Mobility issue #596 - explicitly select fields to avoid error when selecting distinct
216
248
  products.i18n.
217
- select("#{Product.table_name}.*").select(:name).order(name: :asc)
249
+ select("#{Spree::Product.table_name}.*").select(:name).order(name: :asc)
218
250
  when 'name-z-a'
219
251
  # workaround for Mobility issue #596
220
252
  products.i18n.
221
- select("#{Product.table_name}.*").select(:name).order(name: :desc)
253
+ select("#{Spree::Product.table_name}.*").select(:name).order(name: :desc)
222
254
  when 'newest-first'
223
255
  products.order(available_on: :desc)
256
+ when 'oldest-first'
257
+ products.order(available_on: :asc)
224
258
  when 'price-high-to-low'
225
- order_by_price(products, :descend_by_master_price)
259
+ order_by_price(products, :desc)
226
260
  when 'price-low-to-high'
227
- order_by_price(products, :ascend_by_master_price)
261
+ order_by_price(products, :asc)
262
+ when 'best-selling'
263
+ order_by_best_selling(products)
264
+ else
265
+ products
228
266
  end
229
267
  end
230
268
 
@@ -254,6 +292,12 @@ module Spree
254
292
  products.in_stock_or_backorderable
255
293
  end
256
294
 
295
+ def show_only_out_of_stock(products)
296
+ return products unless out_of_stock.present?
297
+
298
+ products.out_of_stock
299
+ end
300
+
257
301
  def map_prices(prices)
258
302
  prices.map do |price|
259
303
  price == 'Infinity' ? BigDecimal::INFINITY : price.to_f
@@ -267,11 +311,18 @@ module Spree
267
311
  taxons.map(&:cached_self_and_descendants_ids).flatten.compact.uniq.map(&:to_s)
268
312
  end
269
313
 
270
- def order_by_price(scope, order_type)
314
+ def order_by_price(scope, sort_order)
271
315
  scope.
272
- select("#{Product.table_name}.*, #{Spree::Price.table_name}.amount").
273
- reorder('').
274
- send(order_type)
316
+ joins(variants_including_master: :prices).
317
+ select("#{Spree::Product.table_name}.* , min(#{Spree::Price.table_name}.amount)").
318
+ where(Spree::Price.table_name => { currency: currency }).
319
+ where.not(Spree::Price.table_name => { amount: nil }).
320
+ order("min(#{Spree::Price.table_name}.amount) #{sort_order}").
321
+ group("#{Spree::Product.table_name}.id")
322
+ end
323
+
324
+ def order_by_best_selling(scope)
325
+ scope.by_best_selling(:desc)
275
326
  end
276
327
  end
277
328
  end
@@ -7,7 +7,11 @@ module Spree
7
7
  end
8
8
 
9
9
  def execute
10
- by_url(scope) || scope.default
10
+ store = by_url(scope) || scope.default
11
+ return if store.nil?
12
+
13
+ Spree::Current.store = store
14
+ store
11
15
  end
12
16
 
13
17
  protected
@@ -17,7 +21,7 @@ module Spree
17
21
  def by_url(scope)
18
22
  return if url.blank?
19
23
 
20
- scope.by_url(url).first
24
+ scope.by_custom_domain(url).or(scope.by_url(url)).first
21
25
  end
22
26
  end
23
27
  end
@@ -0,0 +1,106 @@
1
+ # https://github.com/spree-contrib/spree_address_book/blob/master/app/helpers/spree/addresses_helper.rb
2
+ module Spree
3
+ module AddressesHelper
4
+ def address_field(form, method, address_id = 'b', required = false, text_field_attributes: {}, &handler)
5
+ content_tag :div, id: [address_id, method].join, class: 'mb-4' do
6
+ if handler
7
+ yield
8
+ else
9
+ method_name = I18n.t("activerecord.attributes.spree/address.#{method}")
10
+ form.label(method, method_name, class: 'block text-xs text-neutral-600 mb-1') +
11
+ form.text_field(method,
12
+ class: ['text-input w-full'].compact,
13
+ placeholder: method_name,
14
+ required: required,
15
+ aria: { label: method_name },
16
+ **text_field_attributes)
17
+
18
+ end
19
+ end
20
+ end
21
+
22
+ def address_zipcode(form, country, address_id = 'b')
23
+ method_name = Spree.t(:zipcode)
24
+ form.label(:zipcode, method_name, id: address_id + '_zipcode_label', class: 'block text-xs text-neutral-600 mb-1') +
25
+ form.text_field(:zipcode,
26
+ class: 'text-input h-full',
27
+ placeholder: method_name,
28
+ required: country&.zipcode_required?,
29
+ data: { 'address-form-target': 'zipcode', address_autocomplete_target: 'zipcode' },
30
+ aria: { label: Spree.t(:zipcode) })
31
+ end
32
+
33
+ def address_state(form, country, address_id = 'b')
34
+ country ||= address_default_country
35
+ states_required = country.states_required?
36
+ have_states = states_required && country.states.any?
37
+ state_elements = [
38
+ form.label(Spree.t(:state).downcase,
39
+ Spree.t(:state),
40
+ class: [have_states ? 'state-select-label' : nil, ' block text-xs text-neutral-600 mb-1'].compact,
41
+ id: address_id + '_state_label',
42
+ data: { 'address-form-target': 'stateLabel' }) +
43
+ form.collection_select(:state_id, checkout_zone_applicable_states_for(country).sort_by(&:name),
44
+ :id, :name,
45
+ { prompt: Spree.t(:state) },
46
+ class: 'select-input min-w-full max-w-full',
47
+ data: { 'address-form-target': 'state', address_autocomplete_target: 'state' },
48
+ required: have_states && states_required,
49
+ aria: { label: Spree.t(:state) }) +
50
+ form.text_field(:state_name,
51
+ class: 'ml-3 text-input',
52
+ aria: { label: Spree.t(:state) },
53
+ required: !have_states && states_required,
54
+ data: { 'address-form-target': 'stateName' },
55
+ placeholder: Spree.t(:state))
56
+ ].join.tr('"', "'").delete("\n")
57
+
58
+ content_tag :span, class: 'w-full state-select max-w-full' do
59
+ state_elements.html_safe
60
+ end
61
+ end
62
+
63
+ def available_states
64
+ @available_states ||= Rails.cache.fetch(['available-states-v2', current_store.cache_key_with_version]) do
65
+ Spree::State.where(country_id: available_countries).pluck(:country_id, :id, :abbr, :name)
66
+ end
67
+ end
68
+
69
+ def current_store_countries_with_states_ids
70
+ @current_store_countries_with_states_ids ||= current_store.countries_available_for_checkout.where(states_required: true).includes(:states).each_with_object([]) do |country, memo|
71
+ memo << current_store.states_available_for_checkout(country)
72
+ end.flatten.pluck(:country_id)
73
+ end
74
+
75
+ def current_store_countries_without_states_ids
76
+ @current_store_countries_without_states_ids ||= current_store.countries_available_for_checkout.where(states_required: false).ids
77
+ end
78
+
79
+ def current_store_supported_countries_ids
80
+ @current_store_supported_countries_ids ||= Rails.cache.fetch(['current_store_supported_countries_ids', current_store]) do
81
+ (current_store_countries_with_states_ids + current_store_countries_without_states_ids).uniq
82
+ end
83
+ end
84
+
85
+ def user_available_addresses
86
+ return [] unless try_spree_current_user
87
+
88
+ @user_available_addresses ||= begin
89
+ try_spree_current_user.
90
+ addresses.
91
+ includes(:country, :state).
92
+ not_quick_checkout.
93
+ where(country_id: current_store_supported_countries_ids).
94
+ includes(:user)
95
+ end
96
+ end
97
+
98
+ def checkout_zone_applicable_states_for(country)
99
+ current_store.states_available_for_checkout(country)
100
+ end
101
+
102
+ def address_default_country
103
+ @address_default_country ||= current_store.default_country
104
+ end
105
+ end
106
+ end
@@ -54,27 +54,6 @@ module Spree
54
54
  end
55
55
  end
56
56
 
57
- def logo(image_path = nil, options = {})
58
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
59
- `BaseHelper#logo` is deprecated and will be removed in Spree 5.0.
60
- Please use `FrontendHelper#logo` instead
61
- DEPRECATION
62
-
63
- image_path ||= if current_store.logo.attached? && current_store.logo.variable?
64
- main_app.cdn_image_url(current_store.logo.variant(resize_to_limit: [244, 104]))
65
- elsif current_store.logo.attached? && current_store.logo.image?
66
- main_app.cdn_image_url(current_store.logo)
67
- else
68
- 'logo/spree_50.png'
69
- end
70
-
71
- path = spree.respond_to?(:root_path) ? spree.root_path : main_app.root_path
72
-
73
- link_to path, 'aria-label': current_store.name, method: options[:method] do
74
- image_tag image_path, alt: current_store.name, title: current_store.name
75
- end
76
- end
77
-
78
57
  def spree_favicon_path
79
58
  if current_store.favicon.present?
80
59
  main_app.cdn_image_url(current_store.favicon)
@@ -127,7 +106,7 @@ module Spree
127
106
  description: [object.name, current_store.meta_description].reject(&:blank?).join(', '))
128
107
  else
129
108
  meta.reverse_merge!(keywords: (current_store.meta_keywords || current_store.seo_title),
130
- description: (current_store.homepage(I18n.locale)&.seo_meta_description || current_store.seo_meta_description))
109
+ description: current_store.seo_meta_description)
131
110
  end
132
111
  end
133
112
  meta
@@ -157,12 +136,22 @@ module Spree
157
136
  def pretty_time(time)
158
137
  return '' if time.blank?
159
138
 
139
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
140
+ `BaseHelper#pretty_time` is deprecated and will be removed in Spree 6.0.
141
+ Please add `local_time` gem to your Gemfile and use `local_time(time)` instead
142
+ DEPRECATION
143
+
160
144
  [I18n.l(time.to_date, format: :long), time.strftime('%l:%M %p %Z')].join(' ')
161
145
  end
162
146
 
163
147
  def pretty_date(date)
164
148
  return '' if date.blank?
165
149
 
150
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
151
+ `BaseHelper#pretty_date` is deprecated and will be removed in Spree 6.0.
152
+ Please add `local_time` gem to your Gemfile and use `local_date(date)` instead
153
+ DEPRECATION
154
+
166
155
  [I18n.l(date.to_date, format: :long)].join(' ')
167
156
  end
168
157
 
@@ -175,9 +164,17 @@ module Spree
175
164
  end
176
165
 
177
166
  def spree_storefront_resource_url(resource, options = {})
178
- if defined?(locale_param) && locale_param.present?
179
- options.merge!(locale: locale_param)
180
- end
167
+ options.merge!(locale: locale_param) if defined?(locale_param) && locale_param.present?
168
+
169
+ store = options[:store] || current_store
170
+
171
+ base_url = if options[:relative]
172
+ ''
173
+ elsif store.formatted_custom_domain.blank?
174
+ store.formatted_url
175
+ else
176
+ store.formatted_custom_domain
177
+ end
181
178
 
182
179
  localize = if options[:locale].present?
183
180
  "/#{options[:locale]}"
@@ -186,47 +183,66 @@ module Spree
186
183
  end
187
184
 
188
185
  if resource.instance_of?(Spree::Product)
189
- "#{current_store.formatted_url + localize}/#{Spree::Config[:storefront_products_path]}/#{resource.slug}"
190
- elsif resource.instance_of?(Spree::Taxon)
191
- "#{current_store.formatted_url + localize}/#{Spree::Config[:storefront_taxons_path]}/#{resource.permalink}"
192
- elsif resource.instance_of?(Spree::Cms::Pages::FeaturePage) || resource.instance_of?(Spree::Cms::Pages::StandardPage)
193
- "#{current_store.formatted_url + localize}/#{Spree::Config[:storefront_pages_path]}/#{resource.slug}"
186
+ preview_id = ("preview_id=#{options[:preview_id]}" if options[:preview_id].present?)
187
+
188
+ variant_id = ("variant_id=#{options[:variant_id]}" if options[:variant_id].present?)
189
+
190
+ params = [preview_id, variant_id].compact_blank.join('&')
191
+ params = "?#{params}" if params.present?
192
+
193
+ "#{base_url + localize}/products/#{resource.slug}#{params}"
194
+ elsif resource.is_a?(Post)
195
+ preview_id = options[:preview_id].present? ? "?preview_id=#{options[:preview_id]}" : ''
196
+ "#{base_url + localize}/posts/#{resource.slug}#{preview_id}"
197
+ elsif resource.is_a?(Spree::Taxon)
198
+ "#{base_url + localize}/t/#{resource.permalink}"
199
+ elsif resource.is_a?(Spree::Page) || resource.is_a?(ActionText::RichText)
200
+ "#{base_url + localize}#{resource.page_builder_url}"
201
+ elsif resource.is_a?(Spree::PageLink)
202
+ resource.linkable_url
194
203
  elsif localize.blank?
195
- current_store.formatted_url
204
+ base_url
196
205
  else
197
- current_store.formatted_url + localize
206
+ base_url + localize
198
207
  end
199
208
  end
200
209
 
201
210
  # we should always try to render image of the default variant
202
211
  # same as it's done on PDP
203
212
  def default_image_for_product(product)
204
- if product.images.any?
205
- product.images.first
206
- elsif product.default_variant.images.any?
207
- product.default_variant.images.first
208
- elsif product.variant_images.any?
209
- product.variant_images.first
210
- end
213
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
214
+ `BaseHelper#default_image_for_product` is deprecated and will be removed in Spree 6.0.
215
+ Please use `product.default_image` instead
216
+ DEPRECATION
217
+
218
+ product.default_image
211
219
  end
212
220
 
213
221
  def default_image_for_product_or_variant(product_or_variant)
214
- Rails.cache.fetch("spree/default-image/#{product_or_variant.cache_key_with_version}") do
215
- if product_or_variant.is_a?(Spree::Product)
216
- default_image_for_product(product_or_variant)
217
- elsif product_or_variant.is_a?(Spree::Variant)
218
- if product_or_variant.images.any?
219
- product_or_variant.images.first
220
- else
221
- default_image_for_product(product_or_variant.product)
222
- end
223
- end
224
- end
222
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
223
+ `BaseHelper#default_image_for_product_or_variant` is deprecated and will be removed in Spree 6.0.
224
+ Please use `product_or_variant.default_image` instead
225
+ DEPRECATION
226
+
227
+ product_or_variant.default_image
225
228
  end
226
229
 
227
230
  def base_cache_key
228
- [I18n.locale, current_currency, defined?(try_spree_current_user) && try_spree_current_user.present?,
229
- defined?(try_spree_current_user) && try_spree_current_user.try(:has_spree_role?, 'admin')]
231
+ Spree::Deprecation.warn('`base_cache_key` is deprecated and will be removed in Spree 6. Please use `spree_base_cache_key` instead')
232
+ spree_base_cache_key
233
+ end
234
+
235
+ def spree_base_cache_key
236
+ [
237
+ I18n.locale,
238
+ (current_currency if defined?(current_currency)),
239
+ defined?(try_spree_current_user) && try_spree_current_user.present?,
240
+ defined?(try_spree_current_user) && try_spree_current_user.try(:has_spree_role?, 'admin')
241
+ ].compact
242
+ end
243
+
244
+ def spree_base_cache_scope
245
+ ->(record = nil) { [*spree_base_cache_key, record].compact_blank }
230
246
  end
231
247
 
232
248
  def maximum_quantity
@@ -248,7 +264,9 @@ module Spree
248
264
  img = if image_path.present?
249
265
  create_product_image_tag image_path, product, options, style
250
266
  else
251
- inline_svg_tag 'noimage/backend-missing-image.svg', class: 'noimage', size: '60%*60%'
267
+ width = style.to_s.split('x').first.to_i
268
+ height = style.to_s.split('x').last.to_i
269
+ content_tag(:div, width: width, height: height, style: "background-color: #f0f0f0;")
252
270
  end
253
271
 
254
272
  content_tag(:div, img, class: "admin-product-image-container #{style}-img")
@@ -257,8 +275,9 @@ module Spree
257
275
 
258
276
  # Returns style of image or nil
259
277
  def image_style_from_method_name(method_name)
260
- if method_name.to_s.match(/_image$/) && style = method_name.to_s.sub(/_image$/, '')
261
- style if style.in? Spree::Image.styles.with_indifferent_access
278
+ style = method_name.to_s.sub(/_image$/, '')
279
+ if method_name.to_s.match(/_image$/) && Spree::Image.styles.keys.map(&:to_s).include?(style)
280
+ style
262
281
  end
263
282
  end
264
283
 
@@ -268,5 +287,14 @@ module Spree
268
287
 
269
288
  tag('meta', name: 'robots', content: current_store.seo_robots)
270
289
  end
290
+
291
+ def legal_policy(policy)
292
+ current_store.send("customer_#{policy}")&.body&.html_safe
293
+ end
294
+
295
+ I18N_PLURAL_MANY_COUNT = 2.1
296
+ def plural_resource_name(resource_class)
297
+ resource_class.model_name.human(count: I18N_PLURAL_MANY_COUNT)
298
+ end
271
299
  end
272
300
  end
@@ -30,5 +30,17 @@ module Spree
30
30
 
31
31
  [label, currency]
32
32
  end
33
+
34
+ def preferred_currencies
35
+ @preferred_currencies ||= current_store.supported_currencies_list
36
+ end
37
+
38
+ def preferred_currencies_select_options
39
+ preferred_currencies.map { |currency| ["#{currency.name} - #{currency.iso_code}", currency] }
40
+ end
41
+
42
+ def currency_money(currency = current_currency)
43
+ ::Money::Currency.find(currency)
44
+ end
33
45
  end
34
46
  end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ module ImagesHelper
3
+ # convert images to webp with some sane optimization defaults
4
+ def spree_image_variant_options(options = {})
5
+ {
6
+ saver: {
7
+ strip: true,
8
+ quality: 75,
9
+ lossless: false,
10
+ alpha_q: 85,
11
+ reduction_effort: 6,
12
+ smart_subsample: true
13
+ },
14
+ format: :webp
15
+ }.merge(options)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module Spree
2
+ module MailHelper
3
+ include BaseHelper
4
+
5
+ def variant_image_url(variant)
6
+ image = default_image_for_product_or_variant(variant)
7
+ image ? main_app.cdn_image_url(image.url(:small)) : image_url('noimage/small.png')
8
+ end
9
+
10
+ def name_for(order)
11
+ order.name || Spree.t('customer')
12
+ end
13
+
14
+ def store_logo
15
+ @store_logo ||= current_store&.mailer_logo || current_store&.logo
16
+ end
17
+
18
+ def logo_path
19
+ return main_app.cdn_image_url(store_logo.variant(resize_to_limit: [244, 104])) if store_logo&.variable?
20
+
21
+ return main_app.cdn_image_url(store_logo) if store_logo&.image?
22
+ end
23
+ end
24
+ end