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,49 @@
1
+ module Spree
2
+ module ReportLineItems
3
+ class SalesTotal < Spree::ReportLineItem
4
+ attribute :date, :string
5
+ attribute :order, :string
6
+ attribute :product, :string
7
+ attribute :quantity, :integer
8
+ attribute :pre_tax_amount, :decimal
9
+ attribute :promo_total, :decimal
10
+ attribute :shipment_total, :decimal
11
+ attribute :tax_total, :decimal
12
+ attribute :total, :decimal
13
+
14
+ delegate :quantity, to: :record
15
+
16
+ def date
17
+ record.order.completed_at.strftime('%Y-%m-%d')
18
+ end
19
+
20
+ def order
21
+ record.order.number
22
+ end
23
+
24
+ def product
25
+ record.variant.descriptive_name
26
+ end
27
+
28
+ def total
29
+ Spree::Money.new(record.final_amount + record.shipping_cost, currency: record.currency)
30
+ end
31
+
32
+ def promo_total
33
+ record.display_promo_total
34
+ end
35
+
36
+ def pre_tax_amount
37
+ record.display_pre_tax_amount
38
+ end
39
+
40
+ def shipment_total
41
+ record.display_shipping_cost
42
+ end
43
+
44
+ def tax_total
45
+ record.display_tax_total
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,44 @@
1
+ module Spree
2
+ module Reports
3
+ class ProductsPerformance < Spree::Report
4
+ def line_items_scope
5
+ line_items_scope = Spree::LineItem.
6
+ select("
7
+ #{Spree::LineItem.table_name}.quantity as quantity,
8
+ #{Spree::LineItem.table_name}.pre_tax_amount as pre_tax_amount,
9
+ #{Spree::LineItem.table_name}.promo_total as promo_total,
10
+ #{Spree::LineItem.table_name}.included_tax_total + #{Spree::LineItem.table_name}.additional_tax_total AS tax_total,
11
+ #{Spree::LineItem.table_name}.pre_tax_amount + #{Spree::LineItem.table_name}.adjustment_total AS total,
12
+ #{Spree::Variant.table_name}.product_id AS product_id
13
+ ").
14
+ joins(:variant, :order).
15
+ where(
16
+ spree_line_items: {
17
+ currency: currency
18
+ },
19
+ spree_orders: {
20
+ completed_at: (date_from.to_time.beginning_of_day)..(date_to.to_time.end_of_day)
21
+ }
22
+ )
23
+
24
+ return Spree::Product.none if line_items_scope.empty?
25
+
26
+ line_items_sql = line_items_scope.to_sql
27
+
28
+ product_scope = store.products
29
+ product_scope = product_scope.where(vendor_id: vendor.id) if defined?(vendor) && vendor.present?
30
+
31
+ product_scope.includes(:taxons, :tax_category, variants: :prices, master: :prices).
32
+ joins("LEFT JOIN (#{line_items_sql}) AS line_items ON #{Spree::Product.table_name}.id = line_items.product_id").
33
+ select("
34
+ spree_products.*,
35
+ COALESCE(SUM(line_items.pre_tax_amount), 0.0) AS pre_tax_amount,
36
+ COALESCE(SUM(line_items.quantity), 0) AS quantity,
37
+ COALESCE(SUM(line_items.promo_total), 0.0) AS promo_total,
38
+ COALESCE(SUM(line_items.tax_total), 0.0) AS tax_total,
39
+ COALESCE(SUM(line_items.total), 0.0) AS total
40
+ ").group('spree_products.id')
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ module Reports
3
+ class SalesTotal < Spree::Report
4
+ def line_items_scope
5
+ store.line_items.where(
6
+ order: Spree::Order.complete.where(
7
+ currency: currency,
8
+ completed_at: (date_from.to_time.beginning_of_day)..(date_to.to_time.end_of_day)
9
+ )
10
+ ).includes(:order, variant: :product)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ReturnAuthorization < Spree::Base
2
+ class ReturnAuthorization < Spree.base_class
3
3
  include Spree::Core::NumberGenerator.new(prefix: 'RA', length: 9)
4
4
  include Spree::NumberIdentifier
5
5
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -14,6 +14,9 @@ module Spree
14
14
  has_many :customer_returns
15
15
  end
16
16
 
17
+ has_many :reimbursements, through: :customer_returns
18
+ has_many :refunds, through: :reimbursements
19
+
17
20
  belongs_to :stock_location
18
21
  belongs_to :reason, class_name: 'Spree::ReturnAuthorizationReason', foreign_key: :return_authorization_reason_id
19
22
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ReturnAuthorizationReason < Spree::Base
2
+ class ReturnAuthorizationReason < Spree.base_class
3
3
  include Spree::NamedType
4
4
 
5
5
  has_many :return_authorizations, dependent: :restrict_with_error
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ReturnItem < Spree::Base
2
+ class ReturnItem < Spree.base_class
3
3
  COMPLETED_RECEPTION_STATUSES = %w(received given_to_customer)
4
4
 
5
5
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -35,6 +35,7 @@ module Spree
35
35
  belongs_to :exchange_variant, class_name: 'Spree::Variant'
36
36
  belongs_to :preferred_reimbursement_type, class_name: 'Spree::ReimbursementType'
37
37
  belongs_to :override_reimbursement_type, class_name: 'Spree::ReimbursementType'
38
+ has_one :line_item, through: :inventory_unit
38
39
 
39
40
  validate :eligible_exchange_variant
40
41
  validate :belongs_to_same_customer_order
@@ -1,8 +1,11 @@
1
1
  module Spree
2
- class Role < Spree::Base
2
+ class Role < Spree.base_class
3
3
  include Spree::UniqueName
4
4
 
5
+ ADMIN_ROLE = 'admin'
6
+
5
7
  has_many :role_users, class_name: 'Spree::RoleUser', dependent: :destroy
6
- has_many :users, through: :role_users, class_name: "::#{Spree.user_class}"
8
+ has_many :users, through: :role_users, source: :user, source_type: Spree.user_class.to_s
9
+ has_many :admin_users, through: :role_users, source: :user, source_type: Spree.admin_user_class.to_s
7
10
  end
8
11
  end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
- class RoleUser < Spree::Base
2
+ class RoleUser < Spree.base_class
3
3
  belongs_to :role, class_name: 'Spree::Role'
4
- belongs_to :user, class_name: Spree.admin_user_class.to_s
4
+ belongs_to :user, polymorphic: true
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Shipment < Spree::Base
2
+ class Shipment < Spree.base_class
3
3
  module Emails
4
4
  def send_shipped_email
5
5
  # you can overwrite this method in your application / extension to send out the confirmation email
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Shipment < Spree::Base
2
+ class Shipment < Spree.base_class
3
3
  module Webhooks
4
4
  extend ActiveSupport::Concern
5
5
 
@@ -1,7 +1,7 @@
1
1
  require 'ostruct'
2
2
 
3
3
  module Spree
4
- class Shipment < Spree::Base
4
+ class Shipment < Spree.base_class
5
5
  include Spree::Core::NumberGenerator.new(prefix: 'H', length: 11)
6
6
  include Spree::NumberIdentifier
7
7
  include Spree::NumberAsParam
@@ -45,6 +45,7 @@ module Spree
45
45
  scope :pending, -> { with_state('pending') }
46
46
  scope :ready, -> { with_state('ready') }
47
47
  scope :shipped, -> { with_state('shipped') }
48
+ scope :ready_or_pending, -> { where(state: %w(ready pending)) }
48
49
  scope :trackable, -> { where("tracking IS NOT NULL AND tracking != ''") }
49
50
  scope :with_state, ->(*s) { where(state: s) }
50
51
  # sort by most recent shipped_at, falling back to created_at. add "id desc" to make specs that involve this scope more deterministic.
@@ -58,7 +59,8 @@ module Spree
58
59
  joins(:selected_shipping_rate).
59
60
  where(Spree::ShippingRate.arel_table[:shipping_method_id].not_eq(nil)).
60
61
  select(Spree::ShippingRate.arel_table[:shipping_method_id])
61
- }
62
+ }
63
+ scope :digital_delivery, -> { joins(:shipping_methods).merge(Spree::ShippingMethod.digital) }
62
64
 
63
65
  delegate :store, :currency, to: :order
64
66
  delegate :amount_in_cents, to: :display_cost
@@ -152,7 +154,7 @@ module Spree
152
154
  #
153
155
  # @return [Boolean]
154
156
  def shippable?
155
- can_ship? && tracked?
157
+ can_ship? && (tracked? || digital?)
156
158
  end
157
159
 
158
160
  # Returns true if not all of the shipment's line items are fully shipped
@@ -173,7 +175,7 @@ module Spree
173
175
  def determine_state(order)
174
176
  return 'canceled' if canceled? || order.canceled?
175
177
  return 'pending' unless order.can_ship?
176
- return 'pending' if inventory_units.any? &:backordered?
178
+ return 'pending' if inventory_units.any?(&:backordered?)
177
179
  return 'shipped' if shipped?
178
180
 
179
181
  order.paid? || Spree::Config[:auto_capture_on_dispatch] ? 'ready' : 'pending'
@@ -195,6 +197,10 @@ module Spree
195
197
  def free?
196
198
  return true if final_price == BigDecimal(0)
197
199
 
200
+ with_free_shipping_promotion?
201
+ end
202
+
203
+ def with_free_shipping_promotion?
198
204
  adjustments.promotion.any? { |p| p.source.type == 'Spree::Promotion::Actions::FreeShipping' }
199
205
  end
200
206
 
@@ -223,6 +229,10 @@ module Spree
223
229
  inventory_units.includes(:line_item).map(&:line_item).uniq
224
230
  end
225
231
 
232
+ def digital?
233
+ shipping_method&.calculator&.is_a?(Spree::Calculator::Shipping::DigitalDelivery)
234
+ end
235
+
226
236
  ManifestItem = Struct.new(:line_item, :variant, :quantity, :states)
227
237
 
228
238
  def manifest
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ShippingCategory < Spree::Base
2
+ class ShippingCategory < Spree.base_class
3
3
  include Spree::UniqueName
4
4
  if defined?(Spree::Webhooks::HasWebhooks)
5
5
  include Spree::Webhooks::HasWebhooks
@@ -1,8 +1,9 @@
1
1
  module Spree
2
- class ShippingMethod < Spree::Base
2
+ class ShippingMethod < Spree.base_class
3
3
  acts_as_paranoid
4
4
  include Spree::CalculatedAdjustments
5
5
  include Spree::Metadata
6
+ include Spree::DisplayOn
6
7
  if defined?(Spree::Webhooks::HasWebhooks)
7
8
  include Spree::Webhooks::HasWebhooks
8
9
  end
@@ -10,7 +11,7 @@ module Spree
10
11
  include Spree::VendorConcern
11
12
  end
12
13
 
13
- DISPLAY = [:both, :front_end, :back_end]
14
+ extend Spree::DisplayMoney
14
15
 
15
16
  # Used for #refresh_rates
16
17
  DISPLAY_ON_FRONT_END = 1
@@ -18,8 +19,6 @@ module Spree
18
19
 
19
20
  default_scope { where(deleted_at: nil) }
20
21
 
21
- scope :with_calculator, ->(calculator) { joins(:calculator).where(calculator: { type: calculator.to_s }) }
22
-
23
22
  has_many :shipping_method_categories, dependent: :destroy
24
23
  has_many :shipping_categories, through: :shipping_method_categories
25
24
  has_many :shipping_rates, inverse_of: :shipping_method
@@ -32,12 +31,21 @@ module Spree
32
31
  belongs_to :tax_category, -> { with_deleted }, class_name: 'Spree::TaxCategory', optional: true
33
32
 
34
33
  validates :name, :display_on, presence: true
35
-
34
+ validates :estimated_transit_business_days_min, numericality: { greater_than_or_equal_to: 1 }, allow_nil: true
35
+ validates :estimated_transit_business_days_max, numericality: { greater_than_or_equal_to: 1 }, allow_nil: true
36
36
  validate :at_least_one_shipping_category
37
37
 
38
- scope :available, -> { where(display_on: [:both]) }
39
- scope :available_on_front_end, -> { where(display_on: [:front_end, :both]) }
40
- scope :available_on_back_end, -> { where(display_on: [:back_end, :both]) }
38
+ scope :digital, lambda {
39
+ joins(:calculator).where(spree_calculators: { type: Spree::Calculator::Shipping::DigitalDelivery.to_s })
40
+ }
41
+
42
+ if defined?(PgSearch)
43
+ # full text search
44
+ include PgSearch::Model
45
+ pg_search_scope :search_by_name, against: %i[name]
46
+ else
47
+ scope :search_by_name, ->(query) { where('name LIKE ?', "%#{query}%") }
48
+ end
41
49
 
42
50
  def include?(address)
43
51
  return false unless address
@@ -79,6 +87,38 @@ module Spree
79
87
  (backend? && display_filter == DISPLAY_ON_BACK_END)
80
88
  end
81
89
 
90
+ def delivery_range
91
+ return unless estimated_transit_business_days_min || estimated_transit_business_days_max
92
+
93
+ if estimated_transit_business_days_min == estimated_transit_business_days_max
94
+ estimated_transit_business_days_min.to_s
95
+ else
96
+ "#{estimated_transit_business_days_min}-#{estimated_transit_business_days_max}"
97
+ end
98
+ end
99
+
100
+ def display_estimated_price
101
+ return unless calculator
102
+
103
+ @display_estimated_price ||= begin
104
+ calculator.description + ': ' +
105
+
106
+ if calculator.is_a?(Spree::Calculator::Shipping::FlatRate)
107
+ if calculator.preferred_amount == 0
108
+ Spree.t(:free)
109
+ else
110
+ Spree::Money.new(calculator.preferred_amount, { currency: calculator.preferred_currency }).to_s
111
+ end
112
+ elsif calculator.is_a?(Spree::Calculator::Shipping::FlexiRate)
113
+ Spree::Money.new(calculator.preferred_first_item, { currency: calculator.preferred_currency }).to_s
114
+ elsif calculator.is_a?(Spree::Calculator::Shipping::FlatPercentItemTotal)
115
+ ActionController::Base.helpers.number_to_percentage(calculator.preferred_flat_percent, precision: 2)
116
+ else
117
+ ''
118
+ end
119
+ end
120
+ end
121
+
82
122
  private
83
123
 
84
124
  # Some shipping methods are only meant to be set via backend
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ShippingMethodCategory < Spree::Base
2
+ class ShippingMethodCategory < Spree.base_class
3
3
  belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
4
4
  belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories
5
5
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ShippingMethodZone < Spree::Base
2
+ class ShippingMethodZone < Spree.base_class
3
3
  belongs_to :shipping_method, -> { with_deleted }, inverse_of: :shipping_method_zones, class_name: 'Spree::ShippingMethod'
4
4
  belongs_to :zone, inverse_of: :shipping_method_zones, class_name: 'Spree::Zone'
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ShippingRate < Spree::Base
2
+ class ShippingRate < Spree.base_class
3
3
  belongs_to :shipment, class_name: 'Spree::Shipment'
4
4
  belongs_to :tax_rate, -> { with_deleted }, class_name: 'Spree::TaxRate'
5
5
  belongs_to :shipping_method, -> { with_deleted }, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
@@ -7,7 +7,7 @@ module Spree
7
7
 
8
8
  money_methods :base_price, :final_price, :tax_amount
9
9
 
10
- delegate :order, :currency, :free?, to: :shipment
10
+ delegate :order, :currency, :free?, :with_free_shipping_promotion?, to: :shipment
11
11
  delegate :name, to: :shipping_method
12
12
  delegate :code, to: :shipping_method, prefix: true
13
13
 
@@ -34,13 +34,31 @@ module Spree
34
34
  # returns base price - any available discounts for this Shipment
35
35
  # useful when you want to present a list of available shipping rates
36
36
  def final_price
37
- if free? || cost < -discount_amount
37
+ if with_free_shipping_promotion? || cost < -discount_amount
38
38
  BigDecimal(0)
39
39
  else
40
40
  cost + discount_amount
41
41
  end
42
42
  end
43
43
 
44
+ # Returns the delivery range for the shipping method
45
+ #
46
+ # @return [String]
47
+ def delivery_range
48
+ return unless shipping_method.delivery_range
49
+
50
+ shipping_method.delivery_range
51
+ end
52
+
53
+ # Returns the display delivery range for the shipping method
54
+ #
55
+ # @return [String]
56
+ def display_delivery_range
57
+ return unless delivery_range
58
+
59
+ Spree.t(:display_delivery_range, delivery_range: delivery_range)
60
+ end
61
+
44
62
  private
45
63
 
46
64
  def discount_amount
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class State < Spree::Base
2
+ class State < Spree.base_class
3
3
  belongs_to :country, class_name: 'Spree::Country'
4
4
  has_many :addresses, dependent: :restrict_with_error
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class StateChange < Spree::Base
2
+ class StateChange < Spree.base_class
3
3
  belongs_to :user, class_name: "::#{Spree.user_class}", optional: true
4
4
  belongs_to :stateful, polymorphic: true
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class StockItem < Spree::Base
2
+ class StockItem < Spree.base_class
3
3
  module Webhooks
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class StockItem < Spree::Base
2
+ class StockItem < Spree.base_class
3
3
  acts_as_paranoid
4
4
 
5
5
  include Spree::Metadata
@@ -93,12 +93,15 @@ module Spree
93
93
  end
94
94
 
95
95
  def conditional_variant_touch
96
- # the variant_id changes from nil when a new stock location is added
97
- stock_changed = (saved_change_to_count_on_hand? &&
98
- saved_change_to_count_on_hand.any?(&:zero?)) ||
99
- saved_change_to_variant_id?
96
+ variant.touch if !Spree::Config.binary_inventory_cache || stock_changed?
97
+ end
100
98
 
101
- variant.touch if !Spree::Config.binary_inventory_cache || stock_changed
99
+ def stock_changed?
100
+ # the variant_id changes from nil when a new stock location is added
101
+ (
102
+ saved_change_to_count_on_hand? &&
103
+ saved_change_to_count_on_hand.any?(&:zero?)
104
+ ) || saved_change_to_variant_id?
102
105
  end
103
106
  end
104
107
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class StockLocation < Spree::Base
2
+ class StockLocation < Spree.base_class
3
3
  include Spree::UniqueName
4
4
  if defined?(Spree::Webhooks::HasWebhooks)
5
5
  include Spree::Webhooks::HasWebhooks
@@ -28,6 +28,9 @@ module Spree
28
28
  after_save :ensure_one_default
29
29
  after_update :conditional_touch_records
30
30
 
31
+ delegate :name, :iso3, :iso, :iso_name, to: :country, prefix: true
32
+ delegate :show_company_address_field?, to: :address
33
+
31
34
  def state_text
32
35
  state.try(:abbr) || state.try(:name) || state_name
33
36
  end
@@ -86,8 +89,8 @@ module Spree
86
89
  stock_item(variant).try(:backorderable?)
87
90
  end
88
91
 
89
- def restock(variant, quantity, originator = nil)
90
- move(variant, quantity, originator)
92
+ def restock(variant, quantity, originator = nil, persist: true)
93
+ move(variant, quantity, originator, persist: persist)
91
94
  end
92
95
 
93
96
  def restock_backordered(variant, quantity, _originator = nil)
@@ -98,13 +101,18 @@ module Spree
98
101
  )
99
102
  end
100
103
 
101
- def unstock(variant, quantity, originator = nil)
102
- move(variant, -quantity, originator)
104
+ def unstock(variant, quantity, originator = nil, persist: true)
105
+ move(variant, -quantity, originator, persist: persist)
103
106
  end
104
107
 
105
- def move(variant, quantity, originator = nil)
106
- stock_item_or_create(variant).stock_movements.create!(quantity: quantity,
107
- originator: originator)
108
+ def move(variant, quantity, originator = nil, persist: true)
109
+ stock_item = stock_item_or_create(variant)
110
+
111
+ if persist
112
+ stock_item.stock_movements.create!(quantity: quantity, originator: originator)
113
+ else
114
+ originator.stock_movements << stock_item.stock_movements.build(quantity: quantity)
115
+ end
108
116
  end
109
117
 
110
118
  def fill_status(variant, quantity)
@@ -137,6 +145,24 @@ module Spree
137
145
  )
138
146
  end
139
147
 
148
+ # needed for address form
149
+ def require_name?
150
+ false
151
+ end
152
+
153
+ # needed for address form
154
+ def require_company?
155
+ false
156
+ end
157
+
158
+ def require_phone?
159
+ false
160
+ end
161
+
162
+ def display_name
163
+ @display_name ||= [admin_name, name].delete_if(&:blank?).join(' / ')
164
+ end
165
+
140
166
  private
141
167
 
142
168
  def create_stock_items
@@ -146,6 +172,7 @@ module Spree
146
172
  def ensure_one_default
147
173
  if default
148
174
  StockLocation.where(default: true).where.not(id: id).update_all(default: false)
175
+ StockLocation.where.not(id: id).update_all(updated_at: Time.current)
149
176
  end
150
177
  end
151
178
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class StockMovement < Spree::Base
2
+ class StockMovement < Spree.base_class
3
3
  module Webhooks
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class StockMovement < Spree::Base
2
+ class StockMovement < Spree.base_class
3
3
  QUANTITY_LIMITS = {
4
4
  max: 2**31 - 1,
5
5
  min: -2**31
@@ -15,7 +15,7 @@ module Spree
15
15
  with_options presence: true do
16
16
  validates :stock_item
17
17
  validates :quantity, numericality: {
18
- greater_than_or_equal_to: QUANTITY_LIMITS[:min],
18
+ greater_than_or_equal_to: :min_quantity,
19
19
  less_than_or_equal_to: QUANTITY_LIMITS[:max],
20
20
  only_integer: true
21
21
  }
@@ -23,7 +23,7 @@ module Spree
23
23
 
24
24
  scope :recent, -> { order(created_at: :desc) }
25
25
 
26
- delegate :variant, to: :stock_item
26
+ delegate :variant, :variant_id, to: :stock_item, allow_nil: true
27
27
  delegate :product, to: :variant
28
28
 
29
29
  self.whitelisted_ransackable_attributes = ['quantity']
@@ -39,5 +39,11 @@ module Spree
39
39
 
40
40
  stock_item.adjust_count_on_hand quantity
41
41
  end
42
+
43
+ def min_quantity
44
+ return QUANTITY_LIMITS[:min] if stock_item.nil? || stock_item.backorderable?
45
+
46
+ -stock_item.count_on_hand
47
+ end
42
48
  end
43
49
  end