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
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ module Products
3
+ class TouchTaxonsJob < ::Spree::BaseJob
4
+ queue_as Spree.queues.taxons
5
+
6
+ def perform(taxon_ids, taxonomy_ids)
7
+ Spree::Taxon.where(id: taxon_ids).update_all(updated_at: Time.current)
8
+ Spree::Taxonomy.where(id: taxonomy_ids).update_all(updated_at: Time.current)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ module Reports
3
+ class GenerateJob < Spree::BaseJob
4
+ queue_as Spree.queues.reports
5
+
6
+ def perform(report_id)
7
+ report = Spree::Report.find(report_id)
8
+ report.generate
9
+ end
10
+ end
11
+ end
12
+ end
@@ -2,7 +2,7 @@ module Spree
2
2
  module StockLocations
3
3
  module StockItems
4
4
  class CreateJob < Spree::BaseJob
5
- queue_as :spree_stock_location_stock_items
5
+ queue_as Spree.queues.stock_location_stock_items
6
6
 
7
7
  def perform(stock_location)
8
8
  Spree::StockLocations::StockItems::Create.call(stock_location: stock_location)
@@ -0,0 +1,59 @@
1
+ module Spree
2
+ module Themes
3
+ class DuplicateComponentsJob < Spree::BaseJob
4
+ queue_as Spree.queues.themes
5
+
6
+ # We need to duplicate:
7
+ # 1. Theme files + sections with pageable_type Spree::Theme.
8
+ # 2. Duplicate pages + sections.
9
+ # 3. Adjust linkable on page links for Spree::PageSection and Spree::PageBlock parents and Spree::Page linkable.
10
+
11
+ def perform(theme_id, duplicated_theme_id)
12
+ theme = Spree::Theme.find(theme_id)
13
+ duplicated_theme = Spree::Theme.find(duplicated_theme_id)
14
+
15
+ ApplicationRecord.transaction do
16
+ duplicated_pages = duplicate_pages(theme, duplicated_theme)
17
+
18
+ # Duplicated links on pages and blocks have references to pages from the previous theme
19
+ # We need to look for a duplicated page and update the link with it
20
+ duplicate_layout_sections(theme, duplicated_theme)
21
+ adjust_page_links(theme, duplicated_theme, duplicated_pages)
22
+
23
+ duplicated_theme.update!(ready: true)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def duplicate_layout_sections(theme, duplicated_theme)
30
+ theme.layout_sections.each { |section| section.deep_clone(duplicated_theme) }
31
+ end
32
+
33
+ def duplicate_pages(theme, duplicated_theme)
34
+ theme.pages.map { |page| page.duplicate(duplicated_theme) }
35
+ end
36
+
37
+ def adjust_page_links(theme, duplicated_theme, duplicated_pages)
38
+ page_sections = Spree::PageSection.where(pageable: duplicated_pages)
39
+ layout_sections = duplicated_theme.layout_sections
40
+ all_section_ids = page_sections.ids + layout_sections.ids
41
+
42
+ all_page_blocks = Spree::PageBlock.where(section_id: all_section_ids)
43
+
44
+ all_parent_ids = all_section_ids + all_page_blocks.ids
45
+ all_page_links = Spree::PageLink.
46
+ includes(:linkable, parent: :pageable).
47
+ where(linkable_type: 'Spree::Page').
48
+ where(parent_id: all_parent_ids, linkable_id: theme.pages)
49
+
50
+ all_page_links.each do |page_link|
51
+ linkable_type = page_link.linkable.type
52
+ duplicated_page = duplicated_theme.pages.find_by(type: linkable_type)
53
+
54
+ page_link.update!(linkable: duplicated_page)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,81 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+
4
+ module Spree
5
+ module Themes
6
+ class ScreenshotJob < Spree::BaseJob
7
+ queue_as Spree.queues.themes
8
+
9
+ BASE_SCREENSHOT_API_URL = 'https://shot.screenshotapi.net/v3/screenshot'.freeze
10
+ SCREENSHOT_OUTPUT = 'image'.freeze
11
+ SCREENSHOT_FILE_TYPE = 'png'.freeze
12
+
13
+ def perform(theme_id)
14
+ theme = Spree::Theme.find(theme_id)
15
+
16
+ Rails.logger.warn('Screenshot API token is missing') and return if screenshot_api_token.blank?
17
+
18
+ return if theme.screenshot.attached?
19
+
20
+ url = URI.encode_www_form_component("#{theme.store.url_or_custom_domain}?theme_id=#{theme_id}")
21
+ query_params = {
22
+ token: screenshot_api_token,
23
+ url: url,
24
+ output: SCREENSHOT_OUTPUT,
25
+ file_type: SCREENSHOT_FILE_TYPE,
26
+ retina: true,
27
+ enable_caching: true
28
+ }
29
+ query = "#{BASE_SCREENSHOT_API_URL}?#{query_params.to_query}"
30
+
31
+ # Send a GET request to the API
32
+ uri = URI.parse(query)
33
+ response = Net::HTTP.get_response(uri)
34
+
35
+ case response.code
36
+ when '301', '302'
37
+ redirect_uri = response['location']
38
+ redirect_uri = URI.parse(redirect_uri)
39
+ response = Net::HTTP.get_response(redirect_uri)
40
+ save_screenshot(theme, response)
41
+ when '200'
42
+ save_screenshot(theme, response)
43
+ else
44
+ Rails.error.report('Screenshot API returned non-200 status code')
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def screenshot_api_token
51
+ @screenshot_api_token ||= Spree.screenshot_api_token
52
+ end
53
+
54
+ def save_screenshot(theme, response)
55
+ temp_file_path = "theme-screenshot-#{theme.id}.png"
56
+
57
+ # Create a temporary file
58
+ File.open(temp_file_path, "wb") do |file|
59
+ file.write(response.body)
60
+ end
61
+
62
+ # Open the file for reading to attach it
63
+ file = File.open(temp_file_path, "rb")
64
+
65
+ # Attach the file
66
+ theme.screenshot.attach(
67
+ io: file,
68
+ filename: "theme-screenshot-#{theme.id}.#{SCREENSHOT_FILE_TYPE}",
69
+ content_type: "image/#{SCREENSHOT_FILE_TYPE}"
70
+ )
71
+ theme.save!
72
+
73
+ # Close the file before attempting to delete it
74
+ file.close
75
+
76
+ # Remove the temporary file
77
+ File.delete(temp_file_path) if File.exist?(temp_file_path)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Variants
3
3
  class RemoveFromIncompleteOrdersJob < Spree::BaseJob
4
+ queue_as Spree.queues.variants
5
+
4
6
  def perform(variant)
5
7
  Spree::Variants::RemoveLineItems.call(variant: variant)
6
8
  end
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Variants
3
3
  class RemoveLineItemJob < Spree::BaseJob
4
+ queue_as Spree.queues.variants
5
+
4
6
  def perform(line_item:)
5
7
  Spree::Dependencies.cart_remove_line_item_service.constantize.call(order: line_item.order, line_item: line_item)
6
8
  end
@@ -0,0 +1,51 @@
1
+ module Spree
2
+ class BaseMailer < ActionMailer::Base
3
+ helper Spree::MailHelper
4
+
5
+ def current_store
6
+ @current_store ||= @order&.store.presence || Spree::Store.current || Spree::Store.default
7
+ end
8
+
9
+ helper_method :current_store
10
+
11
+ def from_address
12
+ current_store.mail_from_address
13
+ end
14
+
15
+ def reply_to_address
16
+ current_store.mail_from_address
17
+ end
18
+
19
+ def money(amount, currency = nil)
20
+ currency ||= current_store.default_currency
21
+ Spree::Money.new(amount, currency: currency).to_s
22
+ end
23
+ helper_method :money
24
+
25
+ def frontend_available?
26
+ Spree::Core::Engine.frontend_available?
27
+ end
28
+ helper_method :frontend_available?
29
+
30
+ def mail(headers = {}, &block)
31
+ ensure_default_action_mailer_url_host(headers[:store_url])
32
+ set_email_locale
33
+ super if Spree::Config[:send_core_emails]
34
+ end
35
+
36
+ private
37
+
38
+ # this ensures that ActionMailer::Base.default_url_options[:host] is always set
39
+ # this is only a fail-safe solution if developer didn't set this in environment files
40
+ # http://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views
41
+ def ensure_default_action_mailer_url_host(store_url = nil)
42
+ ActionMailer::Base.default_url_options ||= {}
43
+ ActionMailer::Base.default_url_options[:host] ||= store_url.presence || current_store.url
44
+ end
45
+
46
+ def set_email_locale
47
+ locale = @order&.store&.default_locale || current_store&.default_locale
48
+ I18n.locale = locale if locale.present?
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ class ExportMailer < Spree::BaseMailer
3
+ def export_done(export)
4
+ @export = export
5
+
6
+ mail(
7
+ to: @export.user.email,
8
+ subject: Spree.t('export_mailer.export_done.subject', export_number: @export.number).to_s,
9
+ from: from_address,
10
+ reply_to: reply_to_address,
11
+ store_url: current_store.url
12
+ )
13
+ end
14
+
15
+ def current_store
16
+ @current_store ||= @export.store
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module Spree
2
+ class ReportMailer < BaseMailer
3
+ def report_done(report)
4
+ @report = report
5
+
6
+ mail(
7
+ to: @report.user.email,
8
+ subject: Spree.t('report_mailer.report_done.subject', report_name: @report.human_name).to_s,
9
+ from: from_address,
10
+ reply_to: reply_to_address
11
+ )
12
+ end
13
+
14
+ private
15
+
16
+ def current_store
17
+ @current_store ||= @report.store
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module Spree
2
+ class TestMailer < BaseMailer
3
+ def test_email(email)
4
+ subject = "#{Spree::Store.default.name} #{Spree.t('test_mailer.test_email.subject')}"
5
+ mail(to: email, from: from_address, reply_to: reply_to_address, subject: subject)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module ActionText
2
+ module RichTextDecorator
3
+ def page_builder_url
4
+ return unless Spree::Core::Engine.routes.url_helpers.respond_to?(:policy_path)
5
+
6
+ Spree::Core::Engine.routes.url_helpers.policy_path(name.gsub(/customer_/, ''))
7
+ end
8
+ end
9
+
10
+ ActionText::RichText.include(RichTextDecorator)
11
+ end
@@ -0,0 +1,13 @@
1
+ module ActionText
2
+ class VideoEmbed < ApplicationRecord
3
+ include ActionText::Attachable
4
+
5
+ validates :url, :raw_html, :thumbnail_url, presence: true
6
+
7
+ # `to_partial_path` for the storefront render is by default "action_text/video_embeds/video_embed"
8
+
9
+ def to_trix_content_attachment_partial_path
10
+ 'action_text/video_embeds/thumbnail'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module ActsAsTaggableOn
2
+ module TagDecorator
3
+ def self.prepended(base)
4
+ base.include ::Spree::RansackableAttributes
5
+ base.whitelisted_ransackable_attributes = %w[id name]
6
+ end
7
+ end
8
+
9
+ Tag.prepend(TagDecorator)
10
+ end
@@ -8,6 +8,8 @@ module Spree
8
8
  validates :calculator, presence: true
9
9
  delegate :compute, to: :calculator
10
10
 
11
+ scope :with_calculator, ->(calculator) { joins(:calculator).where(calculator: { type: calculator.to_s }) }
12
+
11
13
  def self.calculators
12
14
  spree_calculators.send model_name_without_spree_namespace
13
15
  end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ module DisplayOn
3
+ extend ActiveSupport::Concern
4
+
5
+ DISPLAY = [:both, :front_end, :back_end].freeze
6
+
7
+ included do
8
+ scope :available, -> { where(display_on: [:both]) }
9
+ scope :available_on_front_end, -> { where(display_on: [:front_end, :both]) }
10
+ scope :available_on_back_end, -> { where(display_on: [:back_end, :both]) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ module HasOneLink
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_one :link, ->(ps) { ps.links }, class_name: 'Spree::PageLink', as: :parent, dependent: :destroy, inverse_of: :parent
7
+ accepts_nested_attributes_for :link
8
+
9
+ def allowed_linkable_types
10
+ [
11
+ [Spree.t(:page), 'Spree::Page'],
12
+ [Spree.t(:product), 'Spree::Product'],
13
+ [Spree.t(:post), 'Spree::Post'],
14
+ [Spree.t(:taxon), 'Spree::Taxon'],
15
+ [Spree.t(:policy), 'ActionText::RichText'],
16
+ [Spree.t(:url), nil]
17
+ ]
18
+ end
19
+
20
+ def default_linkable_type
21
+ 'Spree::Page'
22
+ end
23
+
24
+ def default_linkable_resource
25
+ @default_linkable_resource ||= theme_or_parent.pages.find_by(type: 'Spree::Pages::Homepage')
26
+ end
27
+
28
+ def default_links
29
+ @default_links.presence || [
30
+ Spree::PageLink.new(
31
+ label: Spree.t(:shop_all),
32
+ linkable: theme_or_parent.pages.find_by(type: 'Spree::Pages::ShopAll')
33
+ )
34
+ ]
35
+ end
36
+
37
+ def theme_or_parent
38
+ theme.preview? ? theme.parent : theme
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ module Spree
2
+ module HasPageLinks
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :links, -> { order(:position).includes(:linkable) }, class_name: 'Spree::PageLink', as: :parent, dependent: :destroy, inverse_of: :parent
7
+ alias page_links links
8
+
9
+ after_create :create_default_links, unless: :do_not_create_links
10
+
11
+ attribute :do_not_create_links, :boolean, default: false
12
+ attr_accessor :default_links
13
+
14
+ def allowed_linkable_types
15
+ [
16
+ [Spree.t(:page), 'Spree::Page'],
17
+ [Spree.t(:product), 'Spree::Product'],
18
+ [Spree.t(:post), 'Spree::Post'],
19
+ [Spree.t(:taxon), 'Spree::Taxon'],
20
+ [Spree.t(:policy), 'ActionText::RichText'],
21
+ [Spree.t(:url), nil]
22
+ ]
23
+ end
24
+
25
+ def default_linkable_type
26
+ 'Spree::Page'
27
+ end
28
+
29
+ def theme_or_parent
30
+ theme.preview? ? theme.parent : theme
31
+ end
32
+
33
+ def default_linkable_resource
34
+ @default_linkable_resource ||= theme_or_parent.pages.find_by(type: 'Spree::Pages::Homepage')
35
+ end
36
+
37
+ def default_links
38
+ @default_links.presence || []
39
+ end
40
+
41
+ def links_available?
42
+ true
43
+ end
44
+
45
+ def create_default_links
46
+ default_links.each do |link|
47
+ link.parent = self
48
+ link.save!
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -5,13 +5,9 @@ module Spree
5
5
  included do
6
6
  attribute :public_metadata, default: {}
7
7
  attribute :private_metadata, default: {}
8
- if Rails::VERSION::STRING >= '7.1.0'
9
- serialize :public_metadata, coder: HashSerializer
10
- serialize :private_metadata, coder: HashSerializer
11
- else
12
- serialize :public_metadata, HashSerializer
13
- serialize :private_metadata, HashSerializer
14
- end
8
+
9
+ serialize :public_metadata, coder: HashSerializer
10
+ serialize :private_metadata, coder: HashSerializer
15
11
  end
16
12
 
17
13
  # https://nandovieira.com/using-postgresql-and-jsonb-with-ruby-on-rails
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ module MultiSearchable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def self.sanitize_query_for_multi_search(query)
7
+ ActiveRecord::Base.sanitize_sql_like(query.to_s.downcase.strip)
8
+ end
9
+
10
+ def self.multi_search_condition(model_class, attribute, query)
11
+ encrypted_attributes = model_class.encrypted_attributes.presence || []
12
+
13
+ if encrypted_attributes.include?(attribute.to_sym)
14
+ model_class.arel_table[attribute.to_sym].eq(query)
15
+ else
16
+ model_class.arel_table[attribute.to_sym].lower.matches("%#{query}%")
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -5,6 +5,8 @@ module Spree
5
5
  included do
6
6
  scope :for_store, ->(store) { joins(:stores).where(Store.table_name => { id: store.id }) }
7
7
 
8
+ before_validation :set_default_store, if: :new_record?
9
+
8
10
  validate :must_have_one_store, unless: :disable_store_presence_validation?
9
11
  end
10
12
 
@@ -16,6 +18,13 @@ module Spree
16
18
  errors.add(:stores, Spree.t(:must_have_one_store))
17
19
  end
18
20
 
21
+ def set_default_store
22
+ return if disable_store_presence_validation?
23
+ return if stores.any?
24
+
25
+ stores << Spree::Store.default
26
+ end
27
+
19
28
  # this can be overridden on model basis
20
29
  def disable_store_presence_validation?
21
30
  Spree::Config[:disable_store_presence_validation]
@@ -2,8 +2,10 @@ module Spree
2
2
  module NumberAsParam
3
3
  extend ActiveSupport::Concern
4
4
 
5
- def to_param
6
- number.presence.to_s
5
+ included do
6
+ extend FriendlyId
7
+
8
+ friendly_id :number
7
9
  end
8
10
  end
9
11
  end
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ module ParameterizableName
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ #
7
+ # Callbacks
8
+ #
9
+ before_validation :set_name_from_presentation, if: -> { name.blank? }
10
+ before_validation :normalize_name
11
+
12
+ def set_name_from_presentation
13
+ self.name = presentation
14
+ end
15
+
16
+ def normalize_name
17
+ self.name = name.to_s.parameterize.strip
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ module Previewable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |base|
6
+ belongs_to :parent, class_name: base.name, optional: true, foreign_key: :parent_id
7
+ has_many :previews, class_name: base.name, dependent: :destroy_async, foreign_key: :parent_id
8
+
9
+ scope :without_previews, -> { where(parent_id: nil) }
10
+ scope :only_previews, -> { where.not(parent_id: nil) }
11
+ end
12
+
13
+ def preview?
14
+ parent.present?
15
+ end
16
+ end
17
+ end
@@ -246,7 +246,7 @@ module Spree
246
246
 
247
247
  def self.not_discontinued(only_not_discontinued = true)
248
248
  if only_not_discontinued != '0' && only_not_discontinued
249
- where.not(status: 'archived')
249
+ where(discontinue_on: [nil, Time.current..])
250
250
  else
251
251
  all
252
252
  end
@@ -263,11 +263,11 @@ module Spree
263
263
 
264
264
  # Can't use add_search_scope for this as it needs a default argument
265
265
  def self.available(available_on = nil, currency = nil)
266
- if available_on
267
- scope = not_discontinued.where("#{Product.quoted_table_name}.available_on <= ?", available_on)
268
- else
269
- scope = where(status: 'active')
270
- end
266
+ scope = if available_on
267
+ not_discontinued.where("#{Product.quoted_table_name}.available_on <= ?", available_on)
268
+ else
269
+ not_discontinued.where(status: 'active')
270
+ end
271
271
 
272
272
  unless Spree::Config.show_products_without_price
273
273
  currency ||= Spree::Store.default.default_currency
@@ -305,7 +305,7 @@ module Spree
305
305
  # .search_by_name
306
306
  if defined?(PgSearch)
307
307
  include PgSearch::Model
308
- pg_search_scope :search_by_name, against: :name, using: { tsearch: { any_word: true, prefix: true } }
308
+ pg_search_scope :search_by_name, against: { name: 'A', meta_title: 'B' }, using: { tsearch: { any_word: true, prefix: true } }
309
309
  else
310
310
  def self.search_by_name(query)
311
311
  i18n { name.lower.matches("%#{query.downcase}%") }
@@ -0,0 +1,52 @@
1
+ module Spree
2
+ module Stores
3
+ module Setup
4
+ extend ActiveSupport::Concern
5
+
6
+ def setup_task_done?(task)
7
+ case task
8
+ when :setup_payment_method
9
+ payment_method_setup?
10
+ when :setup_taxes_collection
11
+ Spree::TaxRate.any?
12
+ when :add_products
13
+ products.any?
14
+ when :set_customer_support_email
15
+ customer_support_email.present?
16
+ end
17
+ end
18
+
19
+ def setup_tasks_total
20
+ @setup_tasks_total = setup_tasks_list.count
21
+ end
22
+
23
+ def setup_tasks_list
24
+ return [] if deleted?
25
+
26
+ @setup_tasks_list = []
27
+ @setup_tasks_list << :setup_payment_method
28
+ @setup_tasks_list << :add_products
29
+ @setup_tasks_list << :set_customer_support_email
30
+ @setup_tasks_list << :setup_taxes_collection
31
+
32
+ @setup_tasks_list
33
+ end
34
+
35
+ def setup_tasks_done
36
+ @setup_tasks_done = setup_tasks_list.select { |task| setup_task_done?(task) }.count
37
+ end
38
+
39
+ def setup_completed?
40
+ @setup_completed ||= setup_tasks_done == setup_tasks_total
41
+ end
42
+
43
+ def setup_percentage
44
+ @setup_percentage ||= (setup_tasks_done / setup_tasks_total.to_f * 100).to_i
45
+ end
46
+
47
+ def payment_method_setup?
48
+ payment_methods.active.where.not(type: Spree::PaymentMethod::StoreCredit.to_s).any?
49
+ end
50
+ end
51
+ end
52
+ end