spree_core 6.0.0.beta3 → 6.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 (495) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/helpers/spree/images_helper.rb +0 -57
  4. data/app/jobs/spree/base_job.rb +21 -0
  5. data/app/jobs/spree/carts/reap_expired_job.rb +2 -2
  6. data/app/jobs/spree/collections/regenerate_time_based_job.rb +6 -3
  7. data/app/jobs/spree/orders/finalize_stale_drafts_job.rb +8 -5
  8. data/app/jobs/spree/payments/cancel_unused_sessions_job.rb +61 -0
  9. data/app/jobs/spree/seller_payouts/sweep_seller_job.rb +2 -0
  10. data/app/mailers/spree/admin_user_mailer.rb +4 -19
  11. data/app/mailers/spree/base_mailer.rb +96 -13
  12. data/app/mailers/spree/email_template_mailer.rb +27 -0
  13. data/app/mailers/spree/export_mailer.rb +3 -4
  14. data/app/mailers/spree/import_mailer.rb +3 -4
  15. data/app/mailers/spree/invitation_mailer.rb +24 -7
  16. data/app/mailers/spree/seller_user_mailer.rb +4 -16
  17. data/app/mailers/spree/webhook_mailer.rb +2 -2
  18. data/app/models/concerns/spree/acted_by.rb +1 -1
  19. data/app/models/concerns/spree/admin_user_methods.rb +13 -1
  20. data/app/models/concerns/spree/api_typed.rb +91 -0
  21. data/app/models/concerns/spree/calculator/tiers.rb +76 -0
  22. data/app/models/concerns/spree/customer_methods.rb +15 -14
  23. data/app/models/concerns/spree/email_template_identity.rb +52 -0
  24. data/app/models/concerns/spree/parameterizable_name.rb +2 -0
  25. data/app/models/concerns/spree/payment_session_transitions.rb +8 -2
  26. data/app/models/concerns/spree/post_sale/taxation.rb +54 -0
  27. data/app/models/concerns/spree/post_sale/taxed_line.rb +51 -0
  28. data/app/models/concerns/spree/preference_schema.rb +4 -12
  29. data/app/models/concerns/spree/product_scopes.rb +11 -1
  30. data/app/models/concerns/spree/provider_listing.rb +41 -0
  31. data/app/models/concerns/spree/publishable.rb +82 -14
  32. data/app/models/concerns/spree/purchase/addresses.rb +23 -10
  33. data/app/models/concerns/spree/purchase/currency.rb +1 -1
  34. data/app/models/concerns/spree/purchase/deprecated_aliases.rb +87 -0
  35. data/app/models/concerns/spree/purchase/gift_cards.rb +10 -4
  36. data/app/models/concerns/spree/purchase/locale.rb +1 -1
  37. data/app/models/concerns/spree/purchase/payment_processing.rb +7 -3
  38. data/app/models/concerns/spree/purchase/purchase_order.rb +2 -2
  39. data/app/models/concerns/spree/purchase/totals.rb +49 -1
  40. data/app/models/concerns/spree/receivable.rb +1 -1
  41. data/app/models/concerns/spree/searchable.rb +0 -4
  42. data/app/models/concerns/spree/secret_preferences.rb +59 -0
  43. data/app/models/concerns/spree/single_store_resource.rb +1 -1
  44. data/app/models/concerns/spree/stores/email_branding.rb +31 -0
  45. data/app/models/concerns/spree/type_labels.rb +38 -0
  46. data/app/models/concerns/spree/typed_adjustment_line.rb +1 -1
  47. data/app/models/concerns/spree/typed_associations.rb +6 -0
  48. data/app/models/spree/address.rb +11 -1
  49. data/app/models/spree/adjusters/promotion.rb +1 -15
  50. data/app/models/spree/allowed_origin.rb +0 -1
  51. data/app/models/spree/api_key.rb +5 -6
  52. data/app/models/spree/authentication/strategies/oidc_strategy.rb +5 -5
  53. data/app/models/spree/base.rb +70 -22
  54. data/app/models/spree/calculator/flat_percent_item_total.rb +1 -3
  55. data/app/models/spree/calculator/flat_rate.rb +1 -3
  56. data/app/models/spree/calculator/flexi_rate.rb +1 -3
  57. data/app/models/spree/calculator/percent_on_line_item.rb +1 -1
  58. data/app/models/spree/calculator/price_sack.rb +1 -3
  59. data/app/models/spree/calculator/shipping/digital_delivery.rb +1 -3
  60. data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +1 -3
  61. data/app/models/spree/calculator/shipping/flat_rate.rb +1 -3
  62. data/app/models/spree/calculator/shipping/flexi_rate.rb +1 -3
  63. data/app/models/spree/calculator/shipping/per_item.rb +1 -3
  64. data/app/models/spree/calculator/shipping/price_sack.rb +1 -3
  65. data/app/models/spree/calculator/tiered_flat_rate.rb +6 -23
  66. data/app/models/spree/calculator/tiered_percent.rb +7 -25
  67. data/app/models/spree/cart.rb +78 -18
  68. data/app/models/spree/channel/gating.rb +1 -1
  69. data/app/models/spree/channel.rb +4 -4
  70. data/app/models/spree/claim.rb +21 -1
  71. data/app/models/spree/claim_line_item.rb +41 -6
  72. data/app/models/spree/collection.rb +0 -1
  73. data/app/models/spree/collection_rule.rb +5 -21
  74. data/app/models/spree/commission_line.rb +1 -1
  75. data/app/models/spree/commission_rate.rb +2 -3
  76. data/app/models/spree/commission_rate_value.rb +1 -1
  77. data/app/models/spree/commission_rule.rb +4 -11
  78. data/app/models/spree/commission_rules/product_rule.rb +1 -1
  79. data/app/models/spree/company_invitation.rb +1 -0
  80. data/app/models/spree/consent_record.rb +0 -1
  81. data/app/models/spree/credit_card.rb +1 -1
  82. data/app/models/spree/current.rb +23 -0
  83. data/app/models/spree/custom_field.rb +2 -2
  84. data/app/models/spree/custom_field_definition.rb +9 -23
  85. data/app/models/spree/custom_fields/boolean.rb +1 -1
  86. data/app/models/spree/custom_fields/json.rb +1 -1
  87. data/app/models/spree/data_feed/google.rb +0 -2
  88. data/app/models/spree/data_request.rb +1 -1
  89. data/app/models/spree/delivery_method.rb +30 -13
  90. data/app/models/spree/delivery_method_rule.rb +4 -11
  91. data/app/models/spree/delivery_rate.rb +4 -5
  92. data/app/models/spree/delivery_rate_provider/base.rb +1 -0
  93. data/app/models/spree/delivery_zone.rb +0 -1
  94. data/app/models/spree/delivery_zone_member.rb +4 -4
  95. data/app/models/spree/digital_asset.rb +7 -0
  96. data/app/models/spree/digital_asset_provider/base.rb +2 -0
  97. data/app/models/spree/digital_link.rb +2 -5
  98. data/app/models/spree/discount.rb +1 -1
  99. data/app/models/spree/email_template.rb +25 -0
  100. data/app/models/spree/email_template_draft.rb +13 -0
  101. data/app/models/spree/email_template_revision.rb +17 -0
  102. data/app/models/spree/email_templates/entry.rb +118 -0
  103. data/app/models/spree/email_templates/sample_record.rb +16 -0
  104. data/app/models/spree/emails/branding.rb +80 -0
  105. data/app/models/spree/exchange.rb +15 -1
  106. data/app/models/spree/exchange_line_item.rb +121 -5
  107. data/app/models/spree/export.rb +0 -1
  108. data/app/models/spree/exports/products.rb +10 -1
  109. data/app/models/spree/exports/report.rb +1 -1
  110. data/app/models/spree/fee.rb +4 -2
  111. data/app/models/spree/fulfillment.rb +53 -27
  112. data/app/models/spree/fulfillment_changer.rb +2 -2
  113. data/app/models/spree/fulfillment_item.rb +0 -4
  114. data/app/models/spree/fulfillment_provider/base.rb +1 -0
  115. data/app/models/spree/gateway/bogus.rb +4 -0
  116. data/app/models/spree/gateway/custom_payment_source_method.rb +5 -0
  117. data/app/models/spree/gateway.rb +5 -1
  118. data/app/models/spree/gift_card.rb +12 -1
  119. data/app/models/spree/gift_card_batch.rb +0 -1
  120. data/app/models/spree/import.rb +2 -7
  121. data/app/models/spree/import_mapping.rb +1 -2
  122. data/app/models/spree/import_row.rb +2 -2
  123. data/app/models/spree/import_schemas/products.rb +1 -0
  124. data/app/models/spree/integration.rb +8 -18
  125. data/app/models/spree/invitation.rb +5 -5
  126. data/app/models/spree/line_item.rb +13 -2
  127. data/app/models/spree/locale.rb +11 -8
  128. data/app/models/spree/market.rb +1 -0
  129. data/app/models/spree/newsletter_subscriber.rb +3 -0
  130. data/app/models/spree/order.rb +56 -138
  131. data/app/models/spree/order_group.rb +11 -2
  132. data/app/models/spree/order_inventory.rb +10 -5
  133. data/app/models/spree/order_promotion.rb +1 -1
  134. data/app/models/spree/order_routing/has_strategy_preference.rb +1 -1
  135. data/app/models/spree/order_routing/strategy/base.rb +4 -2
  136. data/app/models/spree/order_routing/strategy/rules.rb +1 -1
  137. data/app/models/spree/order_routing_rule.rb +6 -22
  138. data/app/models/spree/package_type.rb +1 -2
  139. data/app/models/spree/payment/gateway_options.rb +14 -52
  140. data/app/models/spree/payment/processing.rb +2 -4
  141. data/app/models/spree/payment.rb +20 -5
  142. data/app/models/spree/payment_method/session_instrumentation.rb +1 -0
  143. data/app/models/spree/payment_method/store_credit.rb +4 -4
  144. data/app/models/spree/payment_method.rb +36 -4
  145. data/app/models/spree/payment_session.rb +5 -1
  146. data/app/models/spree/payment_setup_session.rb +1 -0
  147. data/app/models/spree/payout_provider/base.rb +3 -1
  148. data/app/models/spree/pickup_point_provider/base.rb +2 -0
  149. data/app/models/spree/price_list.rb +1 -2
  150. data/app/models/spree/price_rules/channel_rule.rb +1 -1
  151. data/app/models/spree/price_rules/customer_group_rule.rb +1 -1
  152. data/app/models/spree/product.rb +31 -7
  153. data/app/models/spree/product_submission.rb +0 -12
  154. data/app/models/spree/product_type.rb +0 -1
  155. data/app/models/spree/promotion/actions/create_line_items.rb +27 -17
  156. data/app/models/spree/promotion/rules/category.rb +0 -4
  157. data/app/models/spree/promotion/rules/channel.rb +0 -4
  158. data/app/models/spree/promotion/rules/country.rb +0 -4
  159. data/app/models/spree/promotion/rules/currency.rb +0 -4
  160. data/app/models/spree/promotion/rules/customer_group.rb +0 -4
  161. data/app/models/spree/promotion/rules/first_order.rb +0 -4
  162. data/app/models/spree/promotion/rules/item_total.rb +4 -8
  163. data/app/models/spree/promotion/rules/market.rb +0 -4
  164. data/app/models/spree/promotion/rules/one_use_per_user.rb +0 -4
  165. data/app/models/spree/promotion/rules/option_value.rb +0 -3
  166. data/app/models/spree/promotion/rules/product.rb +0 -4
  167. data/app/models/spree/promotion/rules/user.rb +0 -4
  168. data/app/models/spree/promotion/rules/user_logged_in.rb +0 -4
  169. data/app/models/spree/promotion.rb +35 -6
  170. data/app/models/spree/promotion_action.rb +7 -14
  171. data/app/models/spree/promotion_action_line_item.rb +1 -1
  172. data/app/models/spree/promotion_handler/coupon.rb +59 -27
  173. data/app/models/spree/promotion_rule.rb +7 -14
  174. data/app/models/spree/purchase_order.rb +1 -0
  175. data/app/models/spree/quantity_rule.rb +1 -1
  176. data/app/models/spree/refund.rb +28 -3
  177. data/app/models/spree/return.rb +30 -2
  178. data/app/models/spree/return_line_item.rb +65 -14
  179. data/app/models/spree/role.rb +7 -7
  180. data/app/models/spree/saved_report.rb +1 -1
  181. data/app/models/spree/seller.rb +2 -1
  182. data/app/models/spree/seller_payout.rb +7 -0
  183. data/app/models/spree/seller_requirement.rb +4 -12
  184. data/app/models/spree/seller_requirement_custom_field.rb +1 -2
  185. data/app/models/spree/seller_requirement_submission.rb +2 -2
  186. data/app/models/spree/seller_requirements/accept_terms.rb +2 -3
  187. data/app/models/spree/seller_transfer.rb +5 -0
  188. data/app/models/spree/shipping_label.rb +1 -0
  189. data/app/models/spree/stock/availability_validator.rb +2 -2
  190. data/app/models/spree/stock/inventory_unit_builder.rb +1 -1
  191. data/app/models/spree/stock/packer.rb +2 -2
  192. data/app/models/spree/stock/splitter/weight.rb +1 -1
  193. data/app/models/spree/stock_level/custom_events.rb +6 -0
  194. data/app/models/spree/stock_level.rb +1 -1
  195. data/app/models/spree/stock_movement.rb +1 -1
  196. data/app/models/spree/stock_receipt_item.rb +1 -1
  197. data/app/models/spree/stock_reservation.rb +2 -2
  198. data/app/models/spree/stock_transfer.rb +4 -2
  199. data/app/models/spree/store.rb +33 -7
  200. data/app/models/spree/store_credit.rb +8 -9
  201. data/app/models/spree/store_credit_event.rb +5 -5
  202. data/app/models/spree/tax_exemption_certificate.rb +2 -0
  203. data/app/models/spree/tax_identifier.rb +3 -1
  204. data/app/models/spree/tax_line.rb +53 -3
  205. data/app/models/spree/tax_provider/base.rb +71 -14
  206. data/app/models/spree/tax_provider/internal.rb +59 -33
  207. data/app/models/spree/tax_provider/recorded_share.rb +114 -0
  208. data/app/models/spree/tax_rate.rb +1 -2
  209. data/app/models/spree/taxonomy.rb +0 -1
  210. data/app/models/spree/variant.rb +4 -3
  211. data/app/models/spree/variant_media.rb +1 -1
  212. data/app/models/spree/webhook_endpoint.rb +10 -13
  213. data/app/models/spree/wishlist.rb +1 -6
  214. data/app/models/spree/wishlist_item/custom_events.rb +6 -0
  215. data/app/presenters/spree/csv/customer_presenter.rb +1 -1
  216. data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +1 -1
  217. data/app/presenters/spree/csv/order_line_item_presenter.rb +1 -1
  218. data/app/presenters/spree/csv/product_variant_presenter.rb +42 -12
  219. data/app/serializers/spree/emails/base_serializer.rb +14 -0
  220. data/app/serializers/spree/emails/export_serializer.rb +13 -0
  221. data/app/serializers/spree/emails/import_serializer.rb +19 -0
  222. data/app/serializers/spree/emails/invitation_serializer.rb +28 -0
  223. data/app/serializers/spree/emails/store_serializer.rb +31 -0
  224. data/app/serializers/spree/emails/user_serializer.rb +12 -0
  225. data/app/serializers/spree/emails/webhook_endpoint_serializer.rb +16 -0
  226. data/app/services/spree/carts/create.rb +8 -2
  227. data/app/services/spree/carts/destroy.rb +2 -2
  228. data/app/services/spree/carts/remove_out_of_stock_items.rb +2 -2
  229. data/app/services/spree/carts/split_by_seller.rb +1 -1
  230. data/app/services/spree/carts/update.rb +19 -5
  231. data/app/services/spree/catalogs/set_product_terms.rb +1 -1
  232. data/app/services/spree/categories/add_products.rb +13 -31
  233. data/app/services/spree/categories/remove_products.rb +12 -51
  234. data/app/services/spree/checkout/advance.rb +1 -4
  235. data/app/services/spree/collections/add_products.rb +10 -23
  236. data/app/services/spree/collections/remove_products.rb +7 -43
  237. data/app/services/spree/coupon_codes/bulk_generate.rb +8 -14
  238. data/app/services/spree/data_requests/create.rb +1 -1
  239. data/app/services/spree/deliveries/destroy.rb +2 -2
  240. data/app/services/spree/email_templates/check.rb +58 -0
  241. data/app/services/spree/email_templates/no_sample_record.rb +7 -0
  242. data/app/services/spree/email_templates/preview.rb +99 -0
  243. data/app/services/spree/emails/file_system.rb +23 -0
  244. data/app/services/spree/emails/filters.rb +84 -0
  245. data/app/services/spree/emails/liquid_context.rb +48 -0
  246. data/app/services/spree/emails/rendered_email.rb +14 -0
  247. data/app/services/spree/emails/renderer.rb +125 -0
  248. data/app/services/spree/emails/template.rb +51 -0
  249. data/app/services/spree/emails/template_data.rb +23 -0
  250. data/app/services/spree/emails/template_resolver.rb +109 -0
  251. data/app/services/spree/emails/text_converter.rb +72 -0
  252. data/app/services/spree/emails/translation_inliner.rb +134 -0
  253. data/app/services/spree/imports/row_processors/price_list_price.rb +10 -10
  254. data/app/services/spree/imports/row_processors/product_variant.rb +65 -34
  255. data/app/services/spree/imports/row_processors/purchase_order.rb +13 -13
  256. data/app/services/spree/locales.rb +4 -5
  257. data/app/services/spree/newsletter/subscribe.rb +8 -12
  258. data/app/services/spree/orders/build_fulfillments.rb +3 -2
  259. data/app/services/spree/orders/create.rb +2 -1
  260. data/app/services/spree/orders/discounts/create.rb +7 -4
  261. data/app/services/spree/orders/discounts/destroy.rb +1 -0
  262. data/app/services/spree/orders/discounts/update.rb +1 -0
  263. data/app/services/spree/orders/fees/create.rb +1 -0
  264. data/app/services/spree/orders/fees/destroy.rb +1 -0
  265. data/app/services/spree/orders/fees/update.rb +1 -0
  266. data/app/services/spree/orders/remove_line_item.rb +13 -3
  267. data/app/services/spree/orders/update.rb +10 -6
  268. data/app/services/spree/orders/update_item.rb +6 -3
  269. data/app/services/spree/orders/update_statuses.rb +3 -1
  270. data/app/services/spree/product_memberships.rb +61 -0
  271. data/app/services/spree/returns/eligibility_validator.rb +1 -1
  272. data/app/services/spree/search_provider/custom_field_schema.rb +2 -2
  273. data/app/services/spree/seeds/commission_rates.rb +1 -1
  274. data/app/services/spree/seeds/digital_delivery.rb +1 -1
  275. data/app/services/spree/seeds/payment_methods.rb +2 -2
  276. data/app/services/spree/seeds/saved_reports.rb +3 -3
  277. data/app/services/spree/sellers/requirements.rb +1 -2
  278. data/app/services/spree/shipping_labels/confirm_refund.rb +1 -1
  279. data/app/services/spree/shipping_labels/store_file.rb +3 -3
  280. data/app/services/spree/stock_levels/correct.rb +3 -3
  281. data/app/services/spree/stock_reservations/reserve.rb +2 -3
  282. data/app/services/spree/store_credits/apply.rb +15 -13
  283. data/app/services/spree/stores/provision_defaults.rb +15 -14
  284. data/app/subscribers/spree/seller_onboarding_subscriber.rb +1 -1
  285. data/app/views/layouts/spree/base_mailer.html.erb +2 -43
  286. data/app/views/layouts/spree/base_mailer.liquid +79 -0
  287. data/app/views/spree/admin_user_mailer/password_reset_email.liquid +14 -0
  288. data/app/views/spree/export_mailer/export_done.liquid +12 -0
  289. data/app/views/spree/import_mailer/import_done.liquid +15 -0
  290. data/app/views/spree/invitation_mailer/invitation_accepted.liquid +9 -0
  291. data/app/views/spree/invitation_mailer/invitation_email.liquid +13 -0
  292. data/app/views/spree/seller_user_mailer/password_reset_email.liquid +14 -0
  293. data/app/views/spree/shared/_mailer_button.html.erb +4 -5
  294. data/app/views/spree/shared/_mailer_hero.html.erb +6 -5
  295. data/app/views/spree/shared/_summary_row.liquid +8 -0
  296. data/app/views/spree/webhook_mailer/endpoint_disabled.liquid +21 -0
  297. data/app/workflows/spree/carts/add_item.rb +4 -4
  298. data/app/workflows/spree/carts/complete.rb +13 -3
  299. data/app/workflows/spree/carts/merge.rb +1 -1
  300. data/app/workflows/spree/carts/recalculate_totals.rb +5 -0
  301. data/app/workflows/spree/carts/upsert_items.rb +18 -9
  302. data/app/workflows/spree/claims/approve.rb +5 -22
  303. data/app/workflows/spree/claims/cancel.rb +5 -21
  304. data/app/workflows/spree/claims/create.rb +15 -0
  305. data/app/workflows/spree/claims/deny.rb +7 -0
  306. data/app/workflows/spree/claims/resolve.rb +34 -31
  307. data/app/workflows/spree/customers/anonymize.rb +3 -4
  308. data/app/workflows/spree/customers/create.rb +1 -1
  309. data/app/workflows/spree/data_requests/fulfill.rb +2 -2
  310. data/app/workflows/spree/deliveries/update_tracking.rb +1 -1
  311. data/app/workflows/spree/email_templates/discard_draft.rb +20 -0
  312. data/app/workflows/spree/email_templates/publish.rb +70 -0
  313. data/app/workflows/spree/email_templates/restore_revision.rb +33 -0
  314. data/app/workflows/spree/email_templates/revert.rb +29 -0
  315. data/app/workflows/spree/email_templates/save_draft.rb +85 -0
  316. data/app/workflows/spree/exchanges/approve.rb +5 -22
  317. data/app/workflows/spree/exchanges/cancel.rb +5 -21
  318. data/app/workflows/spree/exchanges/create.rb +6 -0
  319. data/app/workflows/spree/exchanges/fulfill.rb +75 -51
  320. data/app/workflows/spree/exchanges/receive.rb +6 -65
  321. data/app/workflows/spree/fulfillments/cancel.rb +1 -1
  322. data/app/workflows/spree/fulfillments/create.rb +51 -47
  323. data/app/workflows/spree/fulfillments/fulfill.rb +23 -27
  324. data/app/workflows/spree/fulfillments/mark_delivered.rb +1 -1
  325. data/app/workflows/spree/fulfillments/replacements.rb +59 -0
  326. data/app/workflows/spree/gift_cards/apply.rb +2 -2
  327. data/app/workflows/spree/orders/add_item.rb +5 -1
  328. data/app/workflows/spree/orders/cancel.rb +3 -3
  329. data/app/workflows/spree/orders/complete.rb +16 -8
  330. data/app/workflows/spree/payments/process.rb +2 -2
  331. data/app/workflows/spree/post_sale/approval.rb +35 -0
  332. data/app/workflows/spree/post_sale/cancellation.rb +44 -0
  333. data/app/workflows/spree/post_sale/receipt.rb +92 -0
  334. data/app/workflows/spree/products/nested_attributes.rb +1 -1
  335. data/app/workflows/spree/purchase_orders/cancel.rb +1 -1
  336. data/app/workflows/spree/purchase_orders/close.rb +3 -31
  337. data/app/workflows/spree/purchase_orders/mark_draft.rb +2 -2
  338. data/app/workflows/spree/purchase_orders/mark_ordered.rb +2 -2
  339. data/app/workflows/spree/purchase_orders/receive.rb +1 -1
  340. data/app/workflows/spree/purchase_orders/update.rb +5 -34
  341. data/app/workflows/spree/receivables/closing_short.rb +46 -0
  342. data/app/workflows/spree/receivables/draft_editing.rb +48 -0
  343. data/app/workflows/spree/refunds/create.rb +5 -2
  344. data/app/workflows/spree/refunds/order_payments.rb +14 -2
  345. data/app/workflows/spree/refunds/tax_credit.rb +67 -0
  346. data/app/workflows/spree/returns/approve.rb +5 -22
  347. data/app/workflows/spree/returns/cancel.rb +5 -22
  348. data/app/workflows/spree/returns/create.rb +8 -0
  349. data/app/workflows/spree/returns/receive.rb +5 -76
  350. data/app/workflows/spree/returns/refund.rb +31 -8
  351. data/app/workflows/spree/seller_requirement_submissions/create.rb +1 -2
  352. data/app/workflows/spree/seller_transfers/reverse.rb +28 -1
  353. data/app/workflows/spree/shipping_labels/purchase.rb +8 -8
  354. data/app/workflows/spree/shipping_labels/record.rb +5 -5
  355. data/app/workflows/spree/shipping_labels/refund.rb +2 -2
  356. data/app/workflows/spree/stock_receipts/recording.rb +4 -4
  357. data/app/workflows/spree/stock_transfers/cancel.rb +2 -2
  358. data/app/workflows/spree/stock_transfers/close.rb +3 -30
  359. data/app/workflows/spree/stock_transfers/mark_draft.rb +1 -1
  360. data/app/workflows/spree/stock_transfers/mark_in_transit.rb +3 -3
  361. data/app/workflows/spree/stock_transfers/mark_ready.rb +2 -2
  362. data/app/workflows/spree/stock_transfers/receive.rb +1 -1
  363. data/app/workflows/spree/stock_transfers/update.rb +5 -33
  364. data/config/i18n-tasks.yml +32 -18
  365. data/config/initializers/alba.rb +7 -0
  366. data/config/language_names.csv +264 -0
  367. data/config/locales/ar.yml +811 -0
  368. data/config/locales/be.yml +855 -0
  369. data/config/locales/bg.yml +723 -0
  370. data/config/locales/ca.yml +689 -0
  371. data/config/locales/cs.yml +855 -0
  372. data/config/locales/da.yml +771 -0
  373. data/config/locales/de-CH.yml +248 -0
  374. data/config/locales/de.yml +835 -0
  375. data/config/locales/el.yml +769 -0
  376. data/config/locales/en.yml +37 -503
  377. data/config/locales/es-CL.yml +301 -0
  378. data/config/locales/es-EC.yml +186 -0
  379. data/config/locales/es-MX.yml +334 -0
  380. data/config/locales/es.yml +831 -0
  381. data/config/locales/et.yml +644 -0
  382. data/config/locales/fa.yml +709 -0
  383. data/config/locales/fi.yml +771 -0
  384. data/config/locales/fr.yml +830 -0
  385. data/config/locales/hu.yml +751 -0
  386. data/config/locales/id.yml +756 -0
  387. data/config/locales/it.yml +833 -0
  388. data/config/locales/ja.yml +726 -0
  389. data/config/locales/km.yml +759 -0
  390. data/config/locales/ko.yml +575 -0
  391. data/config/locales/ku.yml +753 -0
  392. data/config/locales/lt.yml +821 -0
  393. data/config/locales/lv.yml +685 -0
  394. data/config/locales/nb.yml +824 -0
  395. data/config/locales/ne.yml +823 -0
  396. data/config/locales/nl.yml +826 -0
  397. data/config/locales/pl.yml +835 -0
  398. data/config/locales/pt-BR.yml +547 -0
  399. data/config/locales/pt.yml +636 -0
  400. data/config/locales/ro.yml +750 -0
  401. data/config/locales/ru.yml +834 -0
  402. data/config/locales/sk.yml +680 -0
  403. data/config/locales/sl-SI.yml +600 -0
  404. data/config/locales/sv.yml +827 -0
  405. data/config/locales/th.yml +745 -0
  406. data/config/locales/tr.yml +777 -0
  407. data/config/locales/uk.yml +836 -0
  408. data/config/locales/vi.yml +768 -0
  409. data/config/locales/zh-CN.yml +786 -0
  410. data/config/locales/zh-TW.yml +834 -0
  411. data/db/migrate/20260925000001_add_replacement_to_spree_fulfillment_items.rb +5 -0
  412. data/db/migrate/20261001000001_add_post_sale_tax.rb +30 -0
  413. data/db/migrate/20261001000001_convert_preferences_to_json.rb +166 -0
  414. data/db/migrate/20261001000001_create_spree_email_templates.rb +52 -0
  415. data/lib/generators/spree/dummy/dummy_generator.rb +0 -9
  416. data/lib/generators/spree/dummy/templates/rails/test.rb +7 -0
  417. data/lib/spree/checkout/default_requirements.rb +37 -13
  418. data/lib/spree/core/configuration.rb +1 -1
  419. data/lib/spree/core/controller_helpers/store.rb +1 -1
  420. data/lib/spree/core/dependencies.rb +5 -4
  421. data/lib/spree/core/emails/escaped_output.rb +60 -0
  422. data/lib/spree/core/engine.rb +48 -167
  423. data/lib/spree/core/permissions/default_catalog.rb +5 -0
  424. data/lib/spree/core/preferences/json_conversion.rb +182 -0
  425. data/lib/spree/core/preferences/masking.rb +4 -1
  426. data/lib/spree/core/preferences/preferable.rb +137 -83
  427. data/lib/spree/core/preferences/preferable_class_methods.rb +81 -146
  428. data/lib/spree/core/previews/import_preview.rb +10 -0
  429. data/lib/spree/core/tax/provider_error.rb +37 -0
  430. data/lib/spree/core/version.rb +1 -1
  431. data/lib/spree/core.rb +85 -370
  432. data/lib/spree/emails/editable_templates.rb +82 -0
  433. data/lib/spree/events/catalog.rb +189 -0
  434. data/lib/spree/events.rb +21 -1
  435. data/lib/spree/hooks.rb +0 -17
  436. data/lib/spree/i18n.rb +32 -15
  437. data/lib/spree/reporting/adapters/live.rb +6 -6
  438. data/lib/spree/reporting/default_vocabulary.rb +22 -10
  439. data/lib/spree/reporting/hydration.rb +1 -1
  440. data/lib/spree/reporting/query.rb +8 -0
  441. data/lib/spree/reporting/schema.rb +10 -10
  442. data/lib/spree/testing_support/editable_email_templates.rb +61 -0
  443. data/lib/spree/testing_support/emails.rb +22 -0
  444. data/lib/spree/testing_support/factories/cart_factory.rb +1 -1
  445. data/lib/spree/testing_support/factories/email_template_factory.rb +28 -0
  446. data/lib/spree/testing_support/factories/order_factory.rb +2 -2
  447. data/lib/spree/testing_support/factories/refund_factory.rb +1 -1
  448. data/lib/spree/testing_support/factories/stock_factory.rb +1 -1
  449. data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
  450. data/lib/spree/testing_support/i18n.rb +3 -94
  451. data/lib/spree/testing_support/lifecycle_events.rb +1 -1
  452. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  453. data/lib/spree/testing_support/preferences.rb +0 -5
  454. data/lib/spree/testing_support/store.rb +9 -1
  455. data/lib/spree/upgrades/5_6_to_6_0/manifest.yml +45 -0
  456. data/lib/tasks/categories_and_collections.rake +3 -3
  457. data/lib/tasks/core.rake +6 -4
  458. data/lib/tasks/media.rake +3 -3
  459. data/lib/tasks/package_types.rake +1 -1
  460. data/lib/tasks/preferences_json.rake +101 -0
  461. data/spec/fixtures/mailer_views/custom_views_probe_mailer/welcome_email.html.erb +4 -0
  462. metadata +188 -44
  463. data/app/models/acts_as_taggable_on/tag_decorator.rb +0 -10
  464. data/app/models/concerns/spree/has_image_alt_text.rb +0 -18
  465. data/app/models/spree/base_analytics_event_handler.rb +0 -54
  466. data/app/models/spree/invitations/store.rb +0 -6
  467. data/app/models/spree/preference.rb +0 -14
  468. data/app/models/spree/promotion_handler/page.rb +0 -25
  469. data/app/models/spree/promotion_handler/promotion_duplicator.rb +0 -60
  470. data/app/models/spree/stock/differentiator.rb +0 -45
  471. data/app/presenters/spree/filters/options_presenter.rb +0 -47
  472. data/app/services/spree/carts/empty.rb +0 -42
  473. data/app/services/spree/country_to_timezone.rb +0 -273
  474. data/app/services/spree/payments/create.rb +0 -92
  475. data/app/validators/spree/url_validator.rb +0 -23
  476. data/app/views/active_storage/blobs/_blob.html.erb +0 -14
  477. data/app/views/spree/admin_user_mailer/password_reset_email.html.erb +0 -8
  478. data/app/views/spree/export_mailer/export_done.html.erb +0 -7
  479. data/app/views/spree/import_mailer/import_done.html.erb +0 -12
  480. data/app/views/spree/invitation_mailer/invitation_accepted.html.erb +0 -4
  481. data/app/views/spree/invitation_mailer/invitation_email.html.erb +0 -12
  482. data/app/views/spree/seller_user_mailer/password_reset_email.html.erb +0 -8
  483. data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -19
  484. data/app/views/spree/shared/_base_mailer_header.html.erb +0 -8
  485. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -399
  486. data/app/views/spree/shared/_mailer_logo.html.erb +0 -41
  487. data/app/views/spree/shared/_purchased_items_styles.html.erb +0 -119
  488. data/app/views/spree/webhook_mailer/endpoint_disabled.html.erb +0 -51
  489. data/app/views/spree/webhook_mailer/endpoint_disabled.text.erb +0 -10
  490. data/app/workflows/spree/fulfillments/purchase_label.rb +0 -40
  491. data/app/workflows/spree/returns/purchase_label.rb +0 -32
  492. data/lib/spree/analytics.rb +0 -11
  493. data/lib/spree/core/preferences/scoped_store.rb +0 -34
  494. data/lib/spree/core/preferences/store.rb +0 -105
  495. data/lib/spree/translation_migrations.rb +0 -52
@@ -45,11 +45,15 @@ module Spree
45
45
  include Spree::Purchase::Validations
46
46
  include Spree::Purchase::Totals
47
47
  include Spree::Purchase::Lifecycle
48
+ include Spree::Purchase::DeprecatedAliases
48
49
  has_spree_number prefix: 'R'
49
50
 
50
51
  include Spree::NumberIdentifier
51
52
 
52
53
  publishes_lifecycle_events
54
+ publishes_events :approved, :canceled, :delivered, :fulfilled, :paid, :placed, :shipped,
55
+ :resend_confirmation_email, :resend_digital_links_email
56
+ publishes_event :completed, deprecated_alias_of: 'order.placed'
53
57
  include Spree::HasCustomFields
54
58
  include Spree::Metadata
55
59
  include Spree::HasExternalReferences
@@ -69,8 +73,6 @@ module Spree
69
73
  :payment_total, :amount_due, :fee_total,
70
74
  :commission_amount_total, :commission_tax_total, :commission_total
71
75
 
72
- alias display_ship_total display_delivery_total
73
- alias_attribute :ship_total, :delivery_total
74
76
 
75
77
  # Transient warnings populated by remove_out_of_stock_items! and ensure_available_delivery_rates
76
78
  attribute :warnings, default: -> { [] }
@@ -84,7 +86,7 @@ module Spree
84
86
  Spree::Deprecation.warn('Spree::Order#remove_out_of_stock_items! is deprecated and will be removed in Spree 6.1. This method now works only on Spree::Cart objects')
85
87
 
86
88
  existing_warnings = warnings
87
- result = Spree::Carts::RemoveOutOfStockItems.call(cart: self)
89
+ result = Spree.cart_remove_out_of_stock_items_service.call(cart: self)
88
90
  return self unless result.success?
89
91
 
90
92
  order, _messages, new_warnings = result.value
@@ -140,24 +142,6 @@ module Spree
140
142
  Spree::Checkout::Registry.step_names_for(self).reject { |step| step == 'complete' }
141
143
  end
142
144
 
143
- # Standardized column names (renamed in 6.0); legacy readers stay as
144
- # aliases one release.
145
- alias_attribute :promo_total, :discount_total
146
- alias display_promo_total display_discount_total
147
- alias_attribute :item_count, :total_quantity
148
-
149
- # @deprecated The column is +customer_note+ since 6.0; removed in 6.1.
150
- def special_instructions
151
- Spree::Deprecation.warn('Spree::Order#special_instructions is deprecated and will be removed in Spree 6.1. Use #customer_note instead.')
152
- customer_note
153
- end
154
-
155
- # @deprecated See {#special_instructions}; removed in 6.1.
156
- def special_instructions=(value)
157
- Spree::Deprecation.warn('Spree::Order#special_instructions= is deprecated and will be removed in Spree 6.1. Use #customer_note= instead.')
158
- self.customer_note = value
159
- end
160
-
161
145
  # lock_version (renamed from state_lock_version) drives the API's manual
162
146
  # optimistic concurrency (compare client-sent version, 409 on mismatch) —
163
147
  # Rails auto-locking must not raise on internal saves.
@@ -169,7 +153,7 @@ module Spree
169
153
  total item_total total_quantity considered_risky channel_id currency coupon_code customer_id seller_id
170
154
  order_group_id po_number
171
155
  ]
172
- self.whitelisted_ransackable_scopes = %w[complete incomplete refunded partially_refunded search multi_search]
156
+ self.whitelisted_ransackable_scopes = %w[complete incomplete refunded partially_refunded search]
173
157
  # A seller never sees the buyer's email, and a company member filtering the
174
158
  # company's orders must not learn a colleague's; the risk flag and coupon
175
159
  # are back-office data. `search` matches on the email too.
@@ -178,8 +162,8 @@ module Spree
178
162
  seller: %w[email considered_risky coupon_code]
179
163
  }
180
164
  self.private_ransackable_scopes = {
181
- store: %w[search multi_search],
182
- seller: %w[search multi_search]
165
+ store: %w[search],
166
+ seller: %w[search]
183
167
  }
184
168
 
185
169
  # Set to false on admin-initiated flows to suppress customer-facing emails.
@@ -209,14 +193,6 @@ module Spree
209
193
 
210
194
  ASSOCIATED_CUSTOMER_ATTRIBUTES = [:customer_id, :email, :bill_address_id, :ship_address_id]
211
195
 
212
- # @deprecated Use {Spree::Purchase::PaymentProcessing#payment_methods};
213
- # removed in 6.1.
214
- def collect_frontend_payment_methods
215
- Spree::Deprecation.warn('Spree::Order#collect_frontend_payment_methods is deprecated and will be removed in Spree 6.1. Use #payment_methods instead.')
216
- payment_methods
217
- end
218
-
219
- include Spree::DeprecatedCustomerAlias
220
196
 
221
197
  belongs_to :customer, class_name: "::#{Spree.customer_class}", optional: true, autosave: true
222
198
  # The cart this order was completed from (unique — the completion
@@ -261,7 +237,10 @@ module Spree
261
237
 
262
238
  # Typed adjustment rows owned by this order (line-, fulfillment- and
263
239
  # order-level). See docs/plans/6.0-6.1-split-adjustments.md.
264
- has_many :tax_lines, class_name: 'Spree::TaxLine', dependent: :destroy, inverse_of: :order
240
+ # Sale rows only: the order's totals are re-summed from this association,
241
+ # and tax given back on a return, claim or exchange is not tax charged.
242
+ has_many :tax_lines, -> { sale }, class_name: 'Spree::TaxLine', dependent: :destroy, inverse_of: :order
243
+ has_many :post_sale_tax_lines, -> { post_sale }, class_name: 'Spree::TaxLine', dependent: :destroy
265
244
  # delete, not destroy: the snapshot is readonly once written, and destroy
266
245
  # refuses readonly records. It has no dependents of its own.
267
246
  has_one :tax_identifier, class_name: 'Spree::TaxIdentifier', as: :owner,
@@ -296,8 +275,6 @@ module Spree
296
275
  # Legacy names — removed in 6.1 (real names: fulfillments, delivery_total,
297
276
  # fulfillment_status since 6.0)
298
277
  has_many :shipments, class_name: 'Spree::Fulfillment', inverse_of: :order, deprecated: true
299
- alias_attribute :shipment_total, :delivery_total
300
- alias display_shipment_total display_delivery_total
301
278
  alias_attribute :shipment_state, :fulfillment_status
302
279
  # Deprecated alias — the column is payment_status since 6.0; remove in 6.1.
303
280
  alias_attribute :payment_state, :payment_status
@@ -382,9 +359,6 @@ module Spree
382
359
  left_joins(:bill_address).where(arel_table[:email].lower.eq(query.downcase)).or(where(conditions.reduce(:or)))
383
360
  end
384
361
 
385
- # Backward compatibility alias — remove in Spree 6.0
386
- def self.multi_search(query) = search(query)
387
-
388
362
  # Find an order by prefixed ID first, falling back to number, then integer id for backwards compatibility
389
363
  # @param param [String] the prefixed ID, number, or integer id to search for
390
364
  # @return [Spree::Order, nil] the found order or nil
@@ -447,11 +421,6 @@ module Spree
447
421
  end
448
422
 
449
423
 
450
- # @deprecated Use {#fulfillment_discount}; removed in 6.1.
451
- def shipping_discount
452
- Spree::Deprecation.warn('Spree::Order#shipping_discount is deprecated and will be removed in Spree 6.1. Use #fulfillment_discount instead.')
453
- fulfillment_discount
454
- end
455
424
 
456
425
 
457
426
 
@@ -651,12 +620,6 @@ module Spree
651
620
  Spree.order_update_statuses_service.call(order: self)
652
621
  end
653
622
 
654
- # @deprecated Use {#recalculate_totals!}; removed in 6.1.
655
- def update_with_updater!
656
- Spree::Deprecation.warn('Spree::Order#update_with_updater! is deprecated and will be removed in Spree 6.1. Use #recalculate_totals! instead.')
657
- recalculate_totals!
658
- end
659
-
660
623
  # @deprecated Use {Spree::Carts::Merge}; removed in 6.1.
661
624
  def merger
662
625
  @merger ||= Spree::OrderMerger.new(self)
@@ -684,12 +647,6 @@ module Spree
684
647
  Spree.cart_associate_service.call(guest_cart: self, customer: customer, override_email: override_email)
685
648
  end
686
649
 
687
- # @deprecated Use {#associate_customer!}; removed in 6.1.
688
- def associate_user!(user, override_email = true)
689
- Spree::Deprecation.warn('Spree::Order#associate_user! is deprecated and will be removed in Spree 6.1. Use #associate_customer! instead.')
690
- associate_customer!(user, override_email)
691
- end
692
-
693
650
  def disassociate_customer!
694
651
  nullified_attributes = ASSOCIATED_CUSTOMER_ATTRIBUTES.index_with(nil)
695
652
 
@@ -730,18 +687,31 @@ module Spree
730
687
  end
731
688
  end
732
689
 
733
- # Refunds are already netted out of payment_total by
734
- # Spree::Carts::RecalculateTotals, so returns and claims need no separate
735
- # term here — the legacy reimbursement payout was the only one that sat
736
- # outside that sum.
690
+ # Refunds are netted out of payment_total by Spree::Carts::RecalculateTotals,
691
+ # which is right for money handed back for nothing. A refund for goods that
692
+ # came back on a return, claim or exchange also settles what the customer
693
+ # owed for them, so it is added back here — the job the legacy
694
+ # reimbursement total did. Without it every refunded return read as a
695
+ # balance due, and the payment dialog offered to charge it again.
737
696
  def outstanding_balance
738
697
  if canceled?
739
698
  -1 * payment_total
740
699
  else
741
- total - payment_total
700
+ total - payment_total - returned_items_refund_total
742
701
  end
743
702
  end
744
703
 
704
+ # What refunds for returns, claims and exchanges have given back. Read off
705
+ # loaded refunds when a list preloaded them, as {#refunds_total} is, since
706
+ # every order serializer asks for it.
707
+ #
708
+ # @return [BigDecimal]
709
+ def returned_items_refund_total
710
+ return refunds.select(&:for_returned_items?).sum(0.to_d, &:amount) if refunds.loaded?
711
+
712
+ refunds.for_returned_items.sum(:amount)
713
+ end
714
+
745
715
 
746
716
  # The payments that settle this order.
747
717
  #
@@ -866,12 +836,6 @@ module Spree
866
836
 
867
837
 
868
838
 
869
- def available_payment_methods(store = nil)
870
- Spree::Deprecation.warn('`Order#available_payment_methods` is deprecated and will be removed in Spree 6.1. Use `payment_methods` instead.')
871
-
872
- @available_payment_methods ||= collect_payment_methods(store)
873
- end
874
-
875
839
  def insufficient_stock_lines
876
840
  line_items.select(&:insufficient_stock?)
877
841
  end
@@ -885,7 +849,7 @@ module Spree
885
849
  def ensure_line_item_variants_are_not_discontinued
886
850
  Spree::Deprecation.warn('Spree::Order#ensure_line_item_variants_are_not_discontinued is deprecated and will be removed in Spree 6.1. Completion validation lives in Spree::Checkout::Requirements.')
887
851
  if line_items.any? { |li| !li.variant || li.variant.discontinued? }
888
- errors.add(:base, :discontinued_variants_present, message: Spree.t(:discontinued_variants_present))
852
+ errors.add(:base, :discontinued_variants_present, message: I18n.t('spree.discontinued_variants_present'))
889
853
  false
890
854
  else
891
855
  true
@@ -898,7 +862,7 @@ module Spree
898
862
  def ensure_line_items_are_in_stock
899
863
  Spree::Deprecation.warn('Spree::Order#ensure_line_items_are_in_stock is deprecated and will be removed in Spree 6.1. Completion validation lives in Spree::Checkout::Requirements.')
900
864
  if insufficient_stock_lines.present?
901
- errors.add(:base, :insufficient_stock_lines_present, message: Spree.t(:insufficient_stock_lines_present))
865
+ errors.add(:base, :insufficient_stock_lines_present, message: I18n.t('spree.insufficient_stock_lines_present'))
902
866
  false
903
867
  else
904
868
  true
@@ -941,7 +905,15 @@ module Spree
941
905
  fully_fulfilled?
942
906
  end
943
907
 
944
- def rebuild_fulfillments!
908
+ # @param keep_selection [Boolean] false when the destination changed, so
909
+ # the new proposals start from the default rate
910
+ def rebuild_fulfillments!(keep_selection: true)
911
+ # A placed order's delivery was charged at placement; re-pricing it
912
+ # belongs to the post-placement edit path, not to a rebuild.
913
+ unless completed?
914
+ previous_selections = keep_selection ? fulfillments.selected_rates_by_stock_location : {}
915
+ end
916
+
945
917
  discounts.for_fulfillments.delete_all
946
918
  tax_lines.for_fulfillments.delete_all
947
919
  fees.for_fulfillments.delete_all
@@ -956,34 +928,13 @@ module Spree
956
928
  fulfillment_items.on_hand_or_backordered.delete_all
957
929
 
958
930
  self.fulfillments = order_routing_strategy.for_allocation.map do |package|
959
- package.to_fulfillment.tap { |fulfillment| fulfillment.address_id = ship_address_id }
931
+ package.to_fulfillment.tap do |fulfillment|
932
+ fulfillment.address_id = ship_address_id
933
+ fulfillment.carry_over_selection(previous_selections.fetch(fulfillment.stock_location_id, [])) if previous_selections
934
+ end
960
935
  end
961
936
  end
962
937
 
963
- # @deprecated Use {#rebuild_fulfillments!}; removed in 6.1.
964
- def create_proposed_fulfillments
965
- Spree::Deprecation.warn('Spree::Order#create_proposed_fulfillments is deprecated and will be removed in Spree 6.1. Use #rebuild_fulfillments! instead.')
966
- rebuild_fulfillments!
967
- end
968
-
969
- # @deprecated Use {#rebuild_fulfillments!}; removed in 6.1.
970
- def create_proposed_shipments
971
- Spree::Deprecation.warn('Spree::Order#create_proposed_shipments is deprecated and will be removed in Spree 6.1. Use #rebuild_fulfillments! instead.')
972
- rebuild_fulfillments!
973
- end
974
-
975
- # @deprecated Use {#delivery_step_required?}; removed in 6.1.
976
- def delivery_required?
977
- Spree::Deprecation.warn('Spree::Order#delivery_required? is deprecated and will be removed in Spree 6.1. Use #delivery_step_required? (delivery-step applicability) or #shipping_address_required? (address collection) instead.')
978
- delivery_step_required?
979
- end
980
-
981
- # @deprecated Use {#shipping_address_required?}; removed in 6.1.
982
- def requires_ship_address?
983
- Spree::Deprecation.warn('Spree::Order#requires_ship_address? is deprecated and will be removed in Spree 6.1. Use #shipping_address_required? instead.')
984
- shipping_address_required?
985
- end
986
-
987
938
  # Resolves the routing strategy from the channel override first, then the
988
939
  # store default. Only a registered Spree::OrderRouting::Strategy::Base
989
940
  # subclass is used; any other value (an unregistered/typo'd class, or a
@@ -1053,23 +1004,17 @@ module Spree
1053
1004
  ::Spree::PromotionHandler::Cart.new(self).activate
1054
1005
  end
1055
1006
 
1056
- # Drops stale fulfillments so they are rebuilt from current items.
1007
+ # Rebuilds stale fulfillments from the current items, keeping the chosen
1008
+ # rates. The first ones are Spree::Orders::BuildFulfillments' to build.
1057
1009
  def ensure_updated_fulfillments
1058
1010
  if fulfillments.any? && !completed?
1059
- fulfillments.destroy_all
1060
- update_column(:delivery_total, 0)
1011
+ rebuild_fulfillments!
1061
1012
 
1062
- # Manually publish update event since update_column bypasses callbacks
1013
+ # Nothing here saves the order, so its update event is published by hand.
1063
1014
  publish_event('order.updated')
1064
1015
  end
1065
1016
  end
1066
1017
 
1067
- # @deprecated Use {#ensure_updated_fulfillments}; removed in 6.1.
1068
- def ensure_updated_shipments
1069
- Spree::Deprecation.warn('Spree::Order#ensure_updated_fulfillments is deprecated and will be removed in Spree 6.1. Use #ensure_updated_fulfillments instead.')
1070
- ensure_updated_fulfillments
1071
- end
1072
-
1073
1018
  # Re-quotes every fulfillment for the given audience.
1074
1019
  #
1075
1020
  # @param audience [Symbol] {Spree::DeliveryMethod::STOREFRONT} (default)
@@ -1085,11 +1030,6 @@ module Spree
1085
1030
  refresh_delivery_rates(audience)
1086
1031
  end
1087
1032
 
1088
- def set_shipments_cost
1089
- Spree::Deprecation.warn('Spree::Order#set_shipments_cost is deprecated and will be removed in Spree 6.1l. Please use set_fulfillments_cost instead')
1090
- set_fulfillments_cost
1091
- end
1092
-
1093
1033
  def set_fulfillments_cost
1094
1034
  fulfillments.each(&:update_amounts)
1095
1035
  recalculate_totals!
@@ -1249,11 +1189,6 @@ module Spree
1249
1189
  csv_lines
1250
1190
  end
1251
1191
 
1252
- def all_line_items
1253
- Spree::Deprecation.warn('Spree::Order#all_line_items is deprecated and will be removed in Spree 6.1. Please use Spree::Order#line_items instead')
1254
- line_items
1255
- end
1256
-
1257
1192
  private
1258
1193
 
1259
1194
  # An order placed in a split checkout owns no payments, so its money is
@@ -1274,14 +1209,14 @@ module Spree
1274
1209
  def ensure_can_be_deleted
1275
1210
  return true if can_be_deleted?
1276
1211
 
1277
- errors.add(:base, :order_cannot_be_deleted, message: Spree.t(:order_cannot_be_deleted))
1212
+ errors.add(:base, :order_cannot_be_deleted, message: I18n.t('spree.order_cannot_be_deleted'))
1278
1213
  throw :abort
1279
1214
  end
1280
1215
 
1281
1216
  def valid_order_routing_strategy_class(klass_name)
1282
1217
  return if klass_name.blank?
1283
1218
 
1284
- klass = Spree.order_routing.strategies.find { |strategy| strategy.to_s == klass_name.to_s }
1219
+ klass = Spree::ApiTyped.registered_class(Spree.order_routing.strategies, klass_name)
1285
1220
  return klass if klass
1286
1221
 
1287
1222
  Rails.logger.warn(
@@ -1303,7 +1238,7 @@ module Spree
1303
1238
 
1304
1239
  def ensure_line_items_present
1305
1240
  unless line_items.present?
1306
- errors.add(:base, :there_are_no_items_for_this_order, message: Spree.t(:there_are_no_items_for_this_order)) && (return false)
1241
+ errors.add(:base, :there_are_no_items_for_this_order, message: I18n.t('spree.there_are_no_items_for_this_order')) && (return false)
1307
1242
  end
1308
1243
  end
1309
1244
 
@@ -1320,43 +1255,26 @@ module Spree
1320
1255
  if undeliverable_line_items.present?
1321
1256
  product_names = undeliverable_line_items.map(&:name).to_sentence
1322
1257
  errors.add(:base, :products_cannot_be_shipped, product_names: product_names,
1323
- message: Spree.t(:products_cannot_be_shipped, product_names: product_names))
1258
+ message: I18n.t('spree.products_cannot_be_shipped', product_names: product_names))
1324
1259
  self.warnings |= undeliverable_line_items.map do |line_item|
1325
1260
  {
1326
1261
  code: 'delivery_unavailable',
1327
- message: Spree.t('cart_line_item.delivery_unavailable', li_name: line_item.name),
1262
+ message: I18n.t('spree.cart_line_item.delivery_unavailable', li_name: line_item.name),
1328
1263
  line_item_id: line_item.prefixed_id,
1329
1264
  variant_id: line_item.variant&.prefixed_id
1330
1265
  }
1331
1266
  end
1332
1267
  else
1333
- errors.add(:base, :items_cannot_be_shipped, message: Spree.t(:items_cannot_be_shipped))
1334
- self.warnings |= [{ code: 'delivery_unavailable', message: Spree.t(:items_cannot_be_shipped) }]
1268
+ errors.add(:base, :items_cannot_be_shipped, message: I18n.t('spree.items_cannot_be_shipped'))
1269
+ self.warnings |= [{ code: 'delivery_unavailable', message: I18n.t('spree.items_cannot_be_shipped') }]
1335
1270
  end
1336
1271
 
1337
1272
  false
1338
1273
  end
1339
1274
  end
1340
1275
 
1341
- def collect_payment_methods
1342
- Spree::Deprecation.warn('`Order#collect_payment_methods` is deprecated and will be removed in Spree 6.1. Use `payment_methods` instead.')
1343
-
1344
- store.payment_methods.active.storefront_visible.select { |pm| pm.available_for_order?(self) }
1345
- end
1346
-
1347
1276
  def credit_card_nil_payment?(attributes)
1348
1277
  payments.store_credits.present? && attributes[:amount].to_f.zero?
1349
1278
  end
1350
-
1351
- def recalculate_store_credit_payment
1352
- recalculate_totals! if using_store_credit?
1353
-
1354
- if gift_card.present?
1355
- recalculate_gift_card
1356
- elsif using_store_credit?
1357
- Spree.store_credit_apply_service.call(order: self)
1358
- end
1359
- end
1360
-
1361
1279
  end
1362
1280
  end
@@ -39,11 +39,11 @@ module Spree
39
39
  has_spree_number prefix: 'R', key: :order
40
40
 
41
41
  publishes_lifecycle_events
42
+ publishes_events :completed, :resend_confirmation_email
42
43
 
43
44
  #
44
45
  # Associations
45
46
  #
46
- belongs_to :store, class_name: 'Spree::Store'
47
47
  belongs_to :customer, class_name: "::#{Spree.customer_class}", optional: true
48
48
  # The cart this group was completed from — unique, and the replay key that
49
49
  # makes a retried completion return this group instead of building another.
@@ -255,9 +255,18 @@ module Spree
255
255
  association(:orders).reset
256
256
  end
257
257
 
258
+ # Refunds for goods that came back settle what was owed for them, as on
259
+ # {Spree::Order#outstanding_balance}, so they do not count as uncollected.
260
+ #
258
261
  # @return [BigDecimal] still to collect across the whole checkout
259
262
  def outstanding_balance
260
- total - payment_total
263
+ total - payment_total - returned_items_refund_total
264
+ end
265
+
266
+ # @return [BigDecimal] what refunds for returns, claims and exchanges on
267
+ # this checkout's payments have given back
268
+ def returned_items_refund_total
269
+ Spree::Refund.for_returned_items.where(payment_id: payments.completed.select(:id)).sum(:amount)
261
270
  end
262
271
 
263
272
  # @return [Boolean]
@@ -26,7 +26,10 @@ module Spree
26
26
  def verify(shipment = nil, is_updated: false, removing: false)
27
27
  return unless order.completed? || shipment.present?
28
28
 
29
- units_count = fulfillment_items.reload.sum(&:quantity)
29
+ # A replacement sent by an exchange or claim stands in for a unit the
30
+ # quantity already paid for, so only a line being destroyed counts it.
31
+ units = fulfillment_items.reload
32
+ units_count = (removing ? units : units.reject(&:replacement?)).sum(&:quantity)
30
33
  line_item_changed = is_updated ? !line_item.saved_changes? : !line_item.changed?
31
34
 
32
35
  if removing
@@ -67,12 +70,12 @@ module Spree
67
70
 
68
71
  def remove_all_units(quantity, target_fulfillment = nil)
69
72
  if target_fulfillment.present?
70
- remove_from_shipment(target_fulfillment, quantity)
73
+ remove_from_shipment(target_fulfillment, quantity, include_replacements: true)
71
74
  else
72
75
  order.fulfillments.each do |shipment|
73
76
  break if quantity.zero?
74
77
 
75
- quantity -= remove_from_shipment(shipment, quantity)
78
+ quantity -= remove_from_shipment(shipment, quantity, include_replacements: true)
76
79
  end
77
80
  end
78
81
  end
@@ -120,10 +123,12 @@ module Spree
120
123
  quantity
121
124
  end
122
125
 
123
- def remove_from_shipment(shipment, quantity)
126
+ def remove_from_shipment(shipment, quantity, include_replacements: false)
124
127
  return 0 if quantity.zero? || shipment.fulfilled?
125
128
 
126
- shipment_units = shipment.inventory_units_for_item(line_item, variant).reject(&:shipped?).sort_by(&:status)
129
+ shipment_units = shipment.inventory_units_for_item(line_item, variant).reject do |unit|
130
+ unit.shipped? || (unit.replacement? && !include_replacements)
131
+ end.sort_by(&:status)
127
132
 
128
133
  removed_quantity = 0
129
134
  removed_backordered = 0
@@ -41,7 +41,7 @@ module Spree
41
41
  private
42
42
 
43
43
  def exactly_one_owner
44
- errors.add(:base, :exactly_one_of_cart_or_order, message: Spree.t('errors.messages.exactly_one_of_cart_or_order')) unless [order, cart].compact.one?
44
+ errors.add(:base, :exactly_one_of_cart_or_order, message: I18n.t('spree.errors.messages.exactly_one_of_cart_or_order')) unless [order, cart].compact.one?
45
45
  end
46
46
  end
47
47
  end
@@ -19,7 +19,7 @@ module Spree
19
19
  return if Spree.order_routing.strategies.any? { |strategy| strategy.to_s == value.to_s }
20
20
 
21
21
  errors.add(
22
- :preferred_order_routing_strategy, :invalid_order_routing_strategy, message: Spree.t(:invalid_order_routing_strategy, scope: [:errors, :messages], default: 'is not a registered order routing strategy')
22
+ :preferred_order_routing_strategy, :invalid_order_routing_strategy, message: I18n.t('spree.errors.messages.invalid_order_routing_strategy')
23
23
  )
24
24
  end
25
25
  end
@@ -10,6 +10,8 @@ module Spree
10
10
  # Selected per Order via Spree::Order#order_routing_strategy.
11
11
  # See docs/plans/6.0-order-routing.md.
12
12
  class Base
13
+ extend Spree::ApiTyped
14
+
13
15
  attr_reader :order
14
16
 
15
17
  # Human label for admin strategy pickers. Override in a subclass or add
@@ -17,7 +19,7 @@ module Spree
17
19
  #
18
20
  # @return [String]
19
21
  def self.display_name
20
- Spree.t(name.demodulize.underscore, scope: 'order_routing.strategies', default: name.demodulize.titleize)
22
+ I18n.t("spree.order_routing.strategies.#{name.demodulize.underscore}", default: name.demodulize.titleize)
21
23
  end
22
24
 
23
25
  def initialize(order:)
@@ -29,7 +31,7 @@ module Spree
29
31
  raise NotImplementedError, "#{self.class} must implement #for_allocation"
30
32
  end
31
33
 
32
- # @param fulfillment [Spree::Shipment]
34
+ # @param fulfillment [Spree::Fulfillment]
33
35
  def for_sale(fulfillment:)
34
36
  raise NotImplementedError, "#{self.class} must implement #for_sale"
35
37
  end
@@ -23,7 +23,7 @@ module Spree
23
23
  estimate_rates(packages)
24
24
  end
25
25
 
26
- # Stock decrement / restock today happens via Spree::Shipment's state
26
+ # Stock decrement / restock today happens via Spree::Fulfillment's state
27
27
  # machine (after_ship / after_cancel). The strategy methods below are
28
28
  # part of the contract for the future reservation + typed-movement
29
29
  # phase — see 6.0-stock-reservations.md and 6.0-typed-stock-movements.md.
@@ -14,6 +14,10 @@ module Spree
14
14
  #
15
15
  # See docs/plans/6.0-order-routing.md.
16
16
  class OrderRoutingRule < Spree.base_class
17
+ include Spree::TypeLabels
18
+
19
+ self.type_labels_scope = 'spree.order_routing_rule_types'
20
+
17
21
  self.table_name = 'spree_order_routing_rules'
18
22
 
19
23
  # `rank` is integer (lower = better) when the rule has an opinion,
@@ -25,7 +29,6 @@ module Spree
25
29
  include Spree::SingleStoreResource
26
30
  include Spree::HasListPosition
27
31
 
28
- belongs_to :store, class_name: 'Spree::Store'
29
32
  belongs_to :channel, class_name: 'Spree::Channel'
30
33
 
31
34
  attribute :active, :boolean, default: true
@@ -51,25 +54,6 @@ module Spree
51
54
 
52
55
  validate :type_must_be_registered
53
56
 
54
- # @return [String] localized display name for the rule kind, used by admin pickers
55
- def self.human_name
56
- Spree.t("order_routing_rule_types.#{api_type}.name", default: api_type.titleize)
57
- end
58
-
59
- # @return [String] localized description for the rule kind
60
- def self.human_description
61
- Spree.t("order_routing_rule_types.#{api_type}.description", default: '')
62
- end
63
-
64
- # Feeds the `description` field of `subclasses_with_preference_schema`
65
- # (the `/types` discovery payload), which only reads `.description`.
66
- def self.description
67
- human_description
68
- end
69
-
70
- def human_name = self.class.human_name
71
- def human_description = self.class.human_description
72
-
73
57
  # Subclasses override. Returns an Array<LocationRanking> — one per location,
74
58
  # with rank=nil to abstain.
75
59
  #
@@ -95,14 +79,14 @@ module Spree
95
79
  return if type.blank?
96
80
  return if Spree.order_routing.rules.any? { |rule| rule.to_s == type }
97
81
 
98
- errors.add(:type, :invalid_order_routing_rule, message: Spree.t(:invalid_order_routing_rule, scope: [:errors, :messages], default: 'is not a registered order routing rule'))
82
+ errors.add(:type, :invalid_order_routing_rule, message: I18n.t('spree.errors.messages.invalid_order_routing_rule'))
99
83
  end
100
84
 
101
85
  def channel_belongs_to_store
102
86
  return if channel.nil? || store_id.nil?
103
87
  return if channel.store_id == store_id
104
88
 
105
- errors.add(:channel, :channel_store_mismatch, message: Spree.t('errors.messages.channel_store_mismatch'))
89
+ errors.add(:channel, :channel_store_mismatch, message: I18n.t('spree.errors.messages.channel_store_mismatch'))
106
90
  end
107
91
  end
108
92
  end
@@ -18,7 +18,6 @@ module Spree
18
18
  include Spree::SingleStoreResource
19
19
  include Spree::Metadata
20
20
 
21
- belongs_to :store, class_name: 'Spree::Store'
22
21
 
23
22
  # Whose packaging this is. Nil is the marketplace's own row — the shared
24
23
  # vocabulary every seller may pack into — and a seller's rows are theirs
@@ -150,7 +149,7 @@ module Spree
150
149
  return unless default?
151
150
  return if destroyed_by_association.present?
152
151
 
153
- errors.add(:base, Spree.t('errors.messages.cannot_delete_default_package_type'))
152
+ errors.add(:base, I18n.t('spree.errors.messages.cannot_delete_default_package_type'))
154
153
  throw(:abort)
155
154
  end
156
155