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
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class LineItem < Spree::Base
2
+ class LineItem < Spree.base_class
3
3
  include Spree::Metadata
4
4
  if defined?(Spree::Webhooks::HasWebhooks)
5
5
  include Spree::Webhooks::HasWebhooks
@@ -19,6 +19,7 @@ module Spree
19
19
 
20
20
  has_many :adjustments, as: :adjustable, dependent: :destroy
21
21
  has_many :inventory_units, inverse_of: :line_item
22
+ has_many :shipments, through: :inventory_units, source: :shipment
22
23
  has_many :digital_links, dependent: :destroy
23
24
 
24
25
  before_validation :copy_price
@@ -52,6 +53,8 @@ module Spree
52
53
  delegate :tax_zone, to: :order
53
54
  delegate :digital?, to: :variant
54
55
 
56
+ scope :with_digital_assets, -> { joins(:variant).merge(Spree::Variant.with_digital_assets) }
57
+
55
58
  attr_accessor :target_shipment
56
59
 
57
60
  self.whitelisted_ransackable_associations = %w[variant order tax_category]
@@ -82,7 +85,7 @@ module Spree
82
85
  extend DisplayMoney
83
86
  money_methods :amount, :subtotal, :discounted_amount, :final_amount, :total, :price,
84
87
  :adjustment_total, :additional_tax_total, :promo_total, :included_tax_total,
85
- :pre_tax_amount
88
+ :pre_tax_amount, :shipping_cost, :tax_total
86
89
 
87
90
  alias single_money display_price
88
91
  alias single_display_amount display_price
@@ -136,6 +139,27 @@ module Spree
136
139
  inventory_units.all?(&:shipped?)
137
140
  end
138
141
 
142
+ # Returns the shipping cost for the line item
143
+ #
144
+ # @return [BigDecimal]
145
+ def shipping_cost
146
+ shipments.sum do |shipment|
147
+ # Skip cancelled shipments
148
+ return BigDecimal('0') if shipment.canceled?
149
+
150
+ # Get all inventory units in this shipment for this line item
151
+ line_item_units = shipment.inventory_units.where(line_item_id: id).count
152
+
153
+ # Get total inventory units in this shipment
154
+ total_units = shipment.inventory_units.count
155
+
156
+ # Calculate proportional shipping cost
157
+ return BigDecimal('0') if total_units.zero? || line_item_units.zero? || shipment.cost.zero?
158
+
159
+ shipment.cost * (line_item_units.to_d / total_units)
160
+ end
161
+ end
162
+
139
163
  def options=(options = {})
140
164
  return unless options.present?
141
165
 
@@ -147,6 +171,17 @@ module Spree
147
171
  assign_attributes opts
148
172
  end
149
173
 
174
+ # Returns the maximum quantity that can be added to the line item
175
+ #
176
+ # @return [Integer]
177
+ def maximum_quantity
178
+ @maximum_quantity ||= variant.backorderable? ? Spree::DatabaseTypeUtilities.maximum_value_for(:integer) : variant.total_on_hand
179
+ end
180
+
181
+ def with_digital_assets?
182
+ variant.with_digital_assets?
183
+ end
184
+
150
185
  private
151
186
 
152
187
  def ensure_valid_quantity
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class LogEntry < Spree::Base
2
+ class LogEntry < Spree.base_class
3
3
  if defined?(Spree::Security::LogEntries)
4
4
  include Spree::Security::LogEntries
5
5
  end
@@ -1,5 +1,8 @@
1
1
  module Spree
2
- class OptionType < Spree::Base
2
+ class OptionType < Spree.base_class
3
+ COLOR_NAMES = %w[color colour].freeze
4
+
5
+ include Spree::ParameterizableName
3
6
  include Spree::UniqueName
4
7
  include Spree::Metadata
5
8
  include Spree::TranslatableResource
@@ -15,41 +18,72 @@ module Spree
15
18
  translates(*TRANSLATABLE_FIELDS, column_fallback: true)
16
19
  end
17
20
 
21
+ #
22
+ # Magic methods
23
+ #
24
+ self.whitelisted_ransackable_scopes = %w[search_by_name]
18
25
  acts_as_list
19
26
  auto_strip_attributes :name, :presentation
20
27
 
28
+ #
29
+ # Associations
21
30
  with_options dependent: :destroy, inverse_of: :option_type do
22
31
  has_many :option_values, -> { order(:position) }
23
32
  has_many :product_option_types
24
33
  end
25
-
26
34
  has_many :products, through: :product_option_types
27
-
28
35
  has_many :option_type_prototypes, class_name: 'Spree::OptionTypePrototype'
29
36
  has_many :prototypes, through: :option_type_prototypes, class_name: 'Spree::Prototype'
30
37
 
38
+ #
39
+ # Validations
40
+ #
31
41
  validates :presentation, presence: true
32
42
 
43
+ #
44
+ # Scopes
45
+ #
33
46
  default_scope { order(:position) }
34
-
47
+ scope :colors, -> { where(name: COLOR_NAMES) }
35
48
  scope :filterable, -> { where(filterable: true) }
36
49
 
50
+ if defined?(PgSearch)
51
+ # full text search
52
+ include PgSearch::Model
53
+ pg_search_scope :search_by_name, against: %i[name presentation]
54
+ else
55
+ scope :search_by_name, ->(query) { where('name LIKE ?', "%#{query}%") }
56
+ end
57
+
58
+ #
59
+ # Attributes
60
+ #
37
61
  accepts_nested_attributes_for :option_values, reject_if: ->(ov) { ov[:name].blank? || ov[:presentation].blank? }, allow_destroy: true
38
62
 
63
+ #
64
+ # Callbacks
65
+ #
39
66
  after_touch :touch_all_products
67
+ after_update :touch_all_products, if: -> { saved_changes.key?(:presentation) }
68
+ after_destroy :touch_all_products
40
69
 
70
+ # legacy, name itself is now parameterized before saving
41
71
  def filter_param
42
72
  name.parameterize
43
73
  end
44
74
 
45
75
  def self.color
46
- find_by(name: 'color')
76
+ colors.first
77
+ end
78
+
79
+ def color?
80
+ name.in?(COLOR_NAMES)
47
81
  end
48
82
 
49
83
  private
50
84
 
51
85
  def touch_all_products
52
- products.update_all(updated_at: Time.current)
86
+ products.touch_all
53
87
  end
54
88
  end
55
89
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class OptionTypePrototype < Spree::Base
2
+ class OptionTypePrototype < Spree.base_class
3
3
  belongs_to :option_type, class_name: 'Spree::OptionType'
4
4
  belongs_to :prototype, class_name: 'Spree::Prototype'
5
5
 
@@ -1,5 +1,6 @@
1
1
  module Spree
2
- class OptionValue < Spree::Base
2
+ class OptionValue < Spree.base_class
3
+ include Spree::ParameterizableName
3
4
  include Spree::Metadata
4
5
  include Spree::TranslatableResource
5
6
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -14,19 +15,32 @@ module Spree
14
15
  translates(*TRANSLATABLE_FIELDS, column_fallback: true)
15
16
  end
16
17
 
17
- belongs_to :option_type, class_name: 'Spree::OptionType', touch: true, inverse_of: :option_values
18
-
18
+ #
19
+ # Magic methods
20
+ #
19
21
  acts_as_list scope: :option_type
20
22
  auto_strip_attributes :name, :presentation
23
+ self.whitelisted_ransackable_attributes = ['presentation']
21
24
 
25
+ #
26
+ # Associations
27
+ #
28
+ belongs_to :option_type, class_name: 'Spree::OptionType', touch: true, inverse_of: :option_values
22
29
  has_many :option_value_variants, class_name: 'Spree::OptionValueVariant'
23
30
  has_many :variants, through: :option_value_variants, class_name: 'Spree::Variant'
31
+ has_many :products, through: :variants, class_name: 'Spree::Product'
24
32
 
33
+ #
34
+ # Validations
35
+ #
25
36
  with_options presence: true do
26
37
  validates :name, uniqueness: { scope: :option_type_id, case_sensitive: false }
27
38
  validates :presentation
28
39
  end
29
40
 
41
+ #
42
+ # Scopes
43
+ #
30
44
  scope :filterable, lambda {
31
45
  joins(:option_type).
32
46
  where(OptionType.table_name => { filterable: true }).
@@ -38,16 +52,32 @@ module Spree
38
52
  where(Variant.table_name => { product_id: products.map(&:id) })
39
53
  }
40
54
 
55
+ #
56
+ # Callbacks
57
+ #
41
58
  after_touch :touch_all_variants
59
+ after_update :touch_all_products, if: -> { saved_changes.key?(:presentation) }
60
+ after_touch :touch_all_products
42
61
 
43
62
  delegate :name, :presentation, to: :option_type, prefix: true, allow_nil: true
44
63
 
45
- self.whitelisted_ransackable_attributes = ['presentation']
64
+ def self.to_tom_select_json
65
+ all.pluck(:id, :presentation).map do |id, presentation|
66
+ {
67
+ id: id,
68
+ name: presentation
69
+ }
70
+ end
71
+ end
46
72
 
47
73
  private
48
74
 
49
75
  def touch_all_variants
50
- variants.update_all(updated_at: Time.current)
76
+ variants.touch_all
77
+ end
78
+
79
+ def touch_all_products
80
+ products.touch_all
51
81
  end
52
82
  end
53
83
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class OptionValueVariant < Spree::Base
2
+ class OptionValueVariant < Spree.base_class
3
3
  belongs_to :option_value, class_name: 'Spree::OptionValue'
4
4
  belongs_to :variant, touch: true, class_name: 'Spree::Variant'
5
5
 
@@ -7,7 +7,7 @@ module Spree
7
7
  validates :option_value_id, uniqueness: { scope: :variant_id }
8
8
 
9
9
  scope :for_option_types, lambda { |option_types|
10
- joins(:option_value).merge(Spree::OptionValue.where(option_types: option_types))
10
+ joins(:option_value).merge(Spree::OptionValue.where(option_type: option_types))
11
11
  }
12
12
  end
13
13
  end
@@ -1,20 +1,15 @@
1
- # https://github.com/spree-contrib/spree_address_book/blob/master/app/models/spree/order_decorator.rb
2
1
  module Spree
3
- class Order < Spree::Base
2
+ class Order < Spree.base_class
4
3
  module AddressBook
5
- extend ActiveSupport::Concern # FIXME: this module is not required to be a concern
6
-
7
4
  def clone_shipping_address
8
- if ship_address
9
- self.bill_address = ship_address
10
- end
5
+ self.bill_address = ship_address if ship_address
6
+ user.bill_address = ship_address if should_assign_user_default_address?(ship_address)
11
7
  true
12
8
  end
13
9
 
14
10
  def clone_billing_address
15
- if bill_address
16
- self.ship_address = bill_address
17
- end
11
+ self.ship_address = bill_address if bill_address
12
+ user.ship_address = bill_address if should_assign_user_default_address?(bill_address)
18
13
  true
19
14
  end
20
15
 
@@ -30,7 +25,7 @@ module Spree
30
25
 
31
26
  def bill_address_attributes=(attributes)
32
27
  self.bill_address = update_or_create_address(attributes)
33
- user.bill_address = bill_address if user && user.bill_address.nil?
28
+ user.bill_address = bill_address if should_assign_user_default_address?(bill_address)
34
29
  end
35
30
 
36
31
  def ship_address_id=(id)
@@ -45,7 +40,8 @@ module Spree
45
40
 
46
41
  def ship_address_attributes=(attributes)
47
42
  self.ship_address = update_or_create_address(attributes)
48
- user.ship_address = ship_address if user && user.ship_address.nil?
43
+ user.ship_address = ship_address if should_assign_user_default_address?(ship_address)
44
+ self.ship_address = nil if quick_checkout_address?(attributes[:quick_checkout]) && !ship_address.persisted?
49
45
  end
50
46
 
51
47
  private
@@ -53,10 +49,10 @@ module Spree
53
49
  def update_or_create_address(attributes = {})
54
50
  return if attributes.blank?
55
51
 
56
- attributes.transform_values! { |v| v == '' ? nil : v }
52
+ attributes.transform_values!(&:presence)
57
53
  attributes = attributes.to_h.symbolize_keys
58
54
 
59
- default_address_scope = user ? user.addresses : ::Spree::Address
55
+ default_address_scope = user ? user.addresses : ::Spree::Address.where(user_id: nil)
60
56
  default_address = default_address_scope.find_by(id: attributes[:id])
61
57
 
62
58
  if default_address&.editable?
@@ -65,7 +61,30 @@ module Spree
65
61
  return default_address
66
62
  end
67
63
 
68
- ::Spree::Address.find_or_create_by(attributes.except(:id, :updated_at, :created_at))
64
+ attributes = attributes.except(:id, :updated_at, :created_at)
65
+ attributes[:user_id] = user&.id
66
+
67
+ existing_address = find_existing_address(attributes)
68
+ return existing_address if existing_address
69
+
70
+ ::Spree::Address.create(attributes)
71
+ end
72
+
73
+ def find_existing_address(attributes)
74
+ address_attributes = attributes.except(:state_name)
75
+ state_name = attributes[:state_name]
76
+
77
+ scope = Spree::Address.not_deleted.where(address_attributes)
78
+ scope = scope.by_state_name_or_abbr(state_name) if state_name.present?
79
+ scope.first
80
+ end
81
+
82
+ def quick_checkout_address?(quick_checkout_param)
83
+ quick_checkout_param.present? ? quick_checkout_param.to_b : false
84
+ end
85
+
86
+ def should_assign_user_default_address?(address)
87
+ user.present? && address.present? && address.valid? && address.user == user && !address.quick_checkout?
69
88
  end
70
89
  end
71
90
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module Checkout
4
4
  def self.included(klass)
5
5
  klass.class_eval do
@@ -85,9 +85,10 @@ module Spree
85
85
  end
86
86
 
87
87
  before_transition to: :complete do |order|
88
- order.create_digital_links if order.some_digital?
88
+ order.create_digital_links if order.with_digital_assets?
89
89
  end
90
90
 
91
+ after_transition to: :complete, do: :create_user_record
91
92
  after_transition to: :complete, do: :persist_user_credit_card
92
93
  before_transition to: :payment, do: :set_shipments_cost
93
94
  before_transition to: :payment, do: :create_tax_charge!
@@ -108,6 +109,7 @@ module Spree
108
109
  before_transition to: :delivery, do: :create_shipment_tax_charge!
109
110
  before_transition from: :delivery, do: :apply_free_shipping_promotions
110
111
  before_transition to: :delivery, do: :apply_unassigned_promotions
112
+ after_transition to: :delivery, do: :go_to_payment_if_fully_digital!
111
113
  end
112
114
 
113
115
  before_transition to: :resumed, do: :ensure_line_item_variants_are_not_discontinued
@@ -115,6 +117,7 @@ module Spree
115
117
  before_transition to: :resumed, do: proc { |order| order.state_machine_resumed = true }
116
118
 
117
119
  after_transition to: :complete, do: :finalize!
120
+ after_transition to: :complete, do: :use_all_coupon_codes
118
121
  after_transition to: :resumed, do: :after_resume
119
122
  after_transition to: :canceled, do: :after_cancel
120
123
 
@@ -269,6 +272,13 @@ module Spree
269
272
  end
270
273
  end
271
274
 
275
+ def create_user_record
276
+ return if user.present?
277
+ return unless signup_for_an_account?
278
+
279
+ Spree::Orders::CreateUserAccount.call(order: self, accepts_email_marketing: accept_marketing?)
280
+ end
281
+
272
282
  def persist_user_credit_card
273
283
  return unless !temporary_credit_card && user_id && valid_credit_cards.present?
274
284
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module CurrencyUpdater
4
4
  extend ActiveSupport::Concern # FIXME: this module is not required to be a concern
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module Digital
4
4
  def digital?
5
5
  if line_items.empty?
@@ -13,8 +13,12 @@ module Spree
13
13
  line_items.any?(&:digital?)
14
14
  end
15
15
 
16
+ def with_digital_assets?
17
+ line_items.any?(&:with_digital_assets?)
18
+ end
19
+
16
20
  def digital_line_items
17
- line_items.select(&:digital?)
21
+ line_items.with_digital_assets.distinct
18
22
  end
19
23
 
20
24
  def digital_links
@@ -22,12 +26,19 @@ module Spree
22
26
  end
23
27
 
24
28
  def create_digital_links
25
- digital_line_items.each do |line_item|
29
+ digital_line_items.includes(variant: :digitals).each do |line_item|
26
30
  line_item.variant.digitals.each do |digital|
27
31
  line_item.digital_links.create!(digital: digital)
28
32
  end
29
33
  end
30
34
  end
35
+
36
+ def go_to_payment_if_fully_digital!
37
+ return unless digital?
38
+ return unless delivery?
39
+
40
+ next!
41
+ end
31
42
  end
32
43
  end
33
44
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module Emails
4
4
  extend ActiveSupport::Concern
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module Payments
4
4
  extend ActiveSupport::Concern # FIXME: this module is not required to be a concern
5
5
  included do
@@ -51,23 +51,11 @@ module Spree
51
51
  break if payment_total >= total
52
52
 
53
53
  payment.public_send(method)
54
-
55
- if payment.completed? && payment_total != total_without_pending_store_credits
56
- self.payment_total += payment.amount
57
- end
58
54
  end
59
55
  rescue Core::GatewayError => e
60
56
  result = !!Spree::Config[:allow_checkout_on_gateway_error]
61
57
  errors.add(:base, e.message) && (return result)
62
58
  end
63
-
64
- # Pending store credits are not added to `self.payment_total`.
65
- # It can cause a situation where the amount of the credit card payment reduced with store credits
66
- # may be added twice to `self.payment_total` causing wrong `order.outstanding_balance`
67
- # calculations and thus an incorrect payment state.
68
- def total_without_pending_store_credits
69
- total - payments.map { |p| p.amount if p.source.is_a?(Spree::StoreCredit) && p.pending? }.sum(&:to_f)
70
- end
71
59
  end
72
60
  end
73
61
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module StoreCredit
4
4
  def add_store_credit_payments(amount = nil)
5
5
  Spree::Dependencies.checkout_add_store_credit_service.constantize.call(order: self, amount: amount)
@@ -10,9 +10,7 @@ module Spree
10
10
  end
11
11
 
12
12
  def covered_by_store_credit?
13
- return false unless user
14
-
15
- user.total_available_store_credit >= total
13
+ user.present? && total_applied_store_credit.positive? && total_applied_store_credit >= total
16
14
  end
17
15
  alias covered_by_store_credit covered_by_store_credit?
18
16
 
@@ -22,6 +20,12 @@ module Spree
22
20
  user.total_available_store_credit(currency, store)
23
21
  end
24
22
 
23
+ def available_store_credits
24
+ return Spree::StoreCredit.none if user.nil?
25
+
26
+ user.store_credits.for_store(store).where(currency: currency).available.sort_by(&:amount_remaining).reverse
27
+ end
28
+
25
29
  def could_use_store_credit?
26
30
  return false if Spree::PaymentMethod::StoreCredit.available.empty?
27
31
 
@@ -32,11 +36,15 @@ module Spree
32
36
  total - total_applicable_store_credit
33
37
  end
34
38
 
39
+ def total_minus_store_credits
40
+ total - total_applied_store_credit
41
+ end
42
+
35
43
  def total_applicable_store_credit
36
44
  if payment? || confirm? || complete?
37
45
  total_applied_store_credit
38
46
  else
39
- [total, (user.try(:total_available_store_credit) || 0.0)].min
47
+ [total, user.try(:total_available_store_credit) || 0.0].min
40
48
  end
41
49
  end
42
50
 
@@ -67,6 +75,10 @@ module Spree
67
75
  def display_store_credit_remaining_after_capture
68
76
  Spree::Money.new(total_available_store_credit - total_applicable_store_credit, currency: currency)
69
77
  end
78
+
79
+ def display_total_minus_store_credits
80
+ Spree::Money.new(total_minus_store_credits, currency: currency)
81
+ end
70
82
  end
71
83
  end
72
84
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < Spree::Base
2
+ class Order < Spree.base_class
3
3
  module Webhooks
4
4
  extend ActiveSupport::Concern
5
5