spree_core 6.0.0.beta4 → 6.0.0.rc2

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 (575) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  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/search_provider/index_job.rb +4 -0
  10. data/app/jobs/spree/seller_payouts/sweep_seller_job.rb +2 -0
  11. data/app/jobs/spree/uploads/purge_unattached_job.rb +49 -0
  12. data/app/mailers/spree/admin_user_mailer.rb +4 -19
  13. data/app/mailers/spree/base_mailer.rb +97 -13
  14. data/app/mailers/spree/email_template_mailer.rb +27 -0
  15. data/app/mailers/spree/export_mailer.rb +3 -4
  16. data/app/mailers/spree/import_mailer.rb +3 -4
  17. data/app/mailers/spree/invitation_mailer.rb +24 -7
  18. data/app/mailers/spree/seller_user_mailer.rb +4 -16
  19. data/app/mailers/spree/webhook_mailer.rb +2 -2
  20. data/app/models/concerns/spree/acted_by.rb +1 -1
  21. data/app/models/concerns/spree/admin_user_methods.rb +15 -1
  22. data/app/models/concerns/spree/api_typed.rb +91 -0
  23. data/app/models/concerns/spree/calculated_adjustments.rb +41 -13
  24. data/app/models/concerns/spree/calculator/currency_amounts.rb +1 -1
  25. data/app/models/concerns/spree/calculator/tiers.rb +63 -0
  26. data/app/models/concerns/spree/canonical_decimals.rb +61 -0
  27. data/app/models/concerns/spree/customer_methods.rb +23 -18
  28. data/app/models/concerns/spree/derived_number.rb +11 -13
  29. data/app/models/concerns/spree/email_template_identity.rb +52 -0
  30. data/app/models/concerns/spree/parameterizable_name.rb +2 -0
  31. data/app/models/concerns/spree/payment_session_transitions.rb +8 -2
  32. data/app/models/concerns/spree/post_sale/taxation.rb +54 -0
  33. data/app/models/concerns/spree/post_sale/taxed_line.rb +51 -0
  34. data/app/models/concerns/spree/preference_schema/json_schema.rb +139 -0
  35. data/app/models/concerns/spree/preference_schema.rb +62 -32
  36. data/app/models/concerns/spree/product_scopes.rb +16 -2
  37. data/app/models/concerns/spree/provider_listing.rb +41 -0
  38. data/app/models/concerns/spree/publishable.rb +82 -14
  39. data/app/models/concerns/spree/purchase/addresses.rb +23 -10
  40. data/app/models/concerns/spree/purchase/currency.rb +1 -1
  41. data/app/models/concerns/spree/purchase/deprecated_aliases.rb +87 -0
  42. data/app/models/concerns/spree/purchase/gift_cards.rb +10 -4
  43. data/app/models/concerns/spree/purchase/locale.rb +1 -1
  44. data/app/models/concerns/spree/purchase/payment_processing.rb +8 -4
  45. data/app/models/concerns/spree/purchase/purchase_order.rb +9 -4
  46. data/app/models/concerns/spree/purchase/store_credits.rb +36 -1
  47. data/app/models/concerns/spree/purchase/totals.rb +49 -8
  48. data/app/models/concerns/spree/ransackable_attributes.rb +46 -0
  49. data/app/models/concerns/spree/receivable.rb +1 -1
  50. data/app/models/concerns/spree/searchable.rb +0 -4
  51. data/app/models/concerns/spree/secret_preferences.rb +59 -0
  52. data/app/models/concerns/spree/signed_id_attachments.rb +54 -0
  53. data/app/models/concerns/spree/single_store_resource.rb +1 -1
  54. data/app/models/concerns/spree/stores/email_branding.rb +32 -0
  55. data/app/models/concerns/spree/stores/markets.rb +5 -2
  56. data/app/models/concerns/spree/type_labels.rb +38 -0
  57. data/app/models/concerns/spree/typed_adjustment_line.rb +5 -6
  58. data/app/models/concerns/spree/typed_associations.rb +12 -18
  59. data/app/models/concerns/spree/vat_price_calculation.rb +5 -6
  60. data/app/models/spree/address.rb +12 -2
  61. data/app/models/spree/adjusters/largest_remainder.rb +14 -1
  62. data/app/models/spree/adjusters/promotion.rb +4 -19
  63. data/app/models/spree/allowed_origin.rb +3 -1
  64. data/app/models/spree/api_key.rb +5 -6
  65. data/app/models/spree/authentication/strategies/oidc_strategy.rb +5 -5
  66. data/app/models/spree/base.rb +99 -22
  67. data/app/models/spree/calculator/flat_percent_item_total.rb +2 -4
  68. data/app/models/spree/calculator/flat_rate.rb +3 -5
  69. data/app/models/spree/calculator/flexi_rate.rb +4 -6
  70. data/app/models/spree/calculator/percent_on_line_item.rb +2 -2
  71. data/app/models/spree/calculator/price_sack.rb +5 -7
  72. data/app/models/spree/calculator/shipping/digital_delivery.rb +3 -5
  73. data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +7 -7
  74. data/app/models/spree/calculator/shipping/flat_rate.rb +5 -7
  75. data/app/models/spree/calculator/shipping/flexi_rate.rb +4 -6
  76. data/app/models/spree/calculator/shipping/per_item.rb +3 -5
  77. data/app/models/spree/calculator/shipping/price_sack.rb +5 -7
  78. data/app/models/spree/calculator/tiered_flat_rate.rb +7 -24
  79. data/app/models/spree/calculator/tiered_percent.rb +7 -25
  80. data/app/models/spree/cart.rb +78 -18
  81. data/app/models/spree/catalog.rb +1 -0
  82. data/app/models/spree/catalog_price.rb +0 -7
  83. data/app/models/spree/catalog_price_tier.rb +0 -8
  84. data/app/models/spree/category.rb +3 -1
  85. data/app/models/spree/channel/gating.rb +3 -2
  86. data/app/models/spree/channel.rb +6 -4
  87. data/app/models/spree/claim.rb +22 -1
  88. data/app/models/spree/claim_line_item.rb +41 -6
  89. data/app/models/spree/collection.rb +2 -1
  90. data/app/models/spree/collection_rule.rb +5 -21
  91. data/app/models/spree/commission_line.rb +1 -1
  92. data/app/models/spree/commission_rate.rb +7 -4
  93. data/app/models/spree/commission_rate_value.rb +1 -1
  94. data/app/models/spree/commission_rule.rb +4 -11
  95. data/app/models/spree/commission_rules/category_rule.rb +2 -5
  96. data/app/models/spree/commission_rules/item_total_rule.rb +2 -2
  97. data/app/models/spree/commission_rules/product_rule.rb +1 -1
  98. data/app/models/spree/commission_rules/seller_rule.rb +2 -5
  99. data/app/models/spree/company.rb +1 -0
  100. data/app/models/spree/company_invitation.rb +1 -0
  101. data/app/models/spree/consent_record.rb +0 -1
  102. data/app/models/spree/credit_card.rb +1 -1
  103. data/app/models/spree/current.rb +23 -0
  104. data/app/models/spree/custom_field.rb +2 -2
  105. data/app/models/spree/custom_field_definition.rb +20 -35
  106. data/app/models/spree/custom_fields/boolean.rb +1 -1
  107. data/app/models/spree/custom_fields/json.rb +1 -1
  108. data/app/models/spree/customer_group.rb +1 -0
  109. data/app/models/spree/data_feed/google.rb +0 -2
  110. data/app/models/spree/data_request.rb +2 -1
  111. data/app/models/spree/delivery_method.rb +36 -14
  112. data/app/models/spree/delivery_method_rule.rb +4 -11
  113. data/app/models/spree/delivery_method_rules/channel_rule.rb +2 -5
  114. data/app/models/spree/delivery_method_rules/item_total_rule.rb +2 -2
  115. data/app/models/spree/delivery_profile.rb +1 -0
  116. data/app/models/spree/delivery_rate.rb +7 -8
  117. data/app/models/spree/delivery_rate_provider/base.rb +1 -0
  118. data/app/models/spree/delivery_zone.rb +1 -2
  119. data/app/models/spree/delivery_zone_member.rb +4 -4
  120. data/app/models/spree/digital_asset.rb +7 -0
  121. data/app/models/spree/digital_asset_provider/base.rb +2 -0
  122. data/app/models/spree/digital_link.rb +2 -5
  123. data/app/models/spree/discount.rb +1 -1
  124. data/app/models/spree/email_template.rb +25 -0
  125. data/app/models/spree/email_template_draft.rb +13 -0
  126. data/app/models/spree/email_template_revision.rb +17 -0
  127. data/app/models/spree/email_templates/entry.rb +118 -0
  128. data/app/models/spree/email_templates/sample_record.rb +16 -0
  129. data/app/models/spree/emails/branding.rb +80 -0
  130. data/app/models/spree/exchange.rb +16 -1
  131. data/app/models/spree/exchange_line_item.rb +121 -5
  132. data/app/models/spree/export.rb +0 -1
  133. data/app/models/spree/exports/products.rb +10 -1
  134. data/app/models/spree/exports/report.rb +3 -3
  135. data/app/models/spree/fee.rb +4 -2
  136. data/app/models/spree/file_upload.rb +155 -0
  137. data/app/models/spree/fulfillment.rb +66 -30
  138. data/app/models/spree/fulfillment_changer.rb +2 -2
  139. data/app/models/spree/fulfillment_group.rb +6 -1
  140. data/app/models/spree/fulfillment_item.rb +0 -4
  141. data/app/models/spree/fulfillment_provider/base.rb +1 -0
  142. data/app/models/spree/gateway/bogus.rb +6 -0
  143. data/app/models/spree/gateway/custom_payment_source_method.rb +5 -0
  144. data/app/models/spree/gateway.rb +6 -2
  145. data/app/models/spree/gift_card.rb +18 -8
  146. data/app/models/spree/gift_card_batch.rb +3 -5
  147. data/app/models/spree/import.rb +5 -7
  148. data/app/models/spree/import_mapping.rb +1 -2
  149. data/app/models/spree/import_row.rb +2 -2
  150. data/app/models/spree/import_schemas/products.rb +1 -0
  151. data/app/models/spree/integration.rb +9 -19
  152. data/app/models/spree/invitation.rb +5 -5
  153. data/app/models/spree/line_item.rb +15 -4
  154. data/app/models/spree/locale.rb +11 -8
  155. data/app/models/spree/market.rb +8 -2
  156. data/app/models/spree/media.rb +1 -9
  157. data/app/models/spree/newsletter_subscriber.rb +4 -0
  158. data/app/models/spree/option_type.rb +2 -1
  159. data/app/models/spree/option_value.rb +2 -1
  160. data/app/models/spree/order.rb +60 -142
  161. data/app/models/spree/order_group.rb +18 -4
  162. data/app/models/spree/order_inventory.rb +10 -5
  163. data/app/models/spree/order_promotion.rb +1 -1
  164. data/app/models/spree/order_routing/has_strategy_preference.rb +1 -1
  165. data/app/models/spree/order_routing/strategy/base.rb +4 -2
  166. data/app/models/spree/order_routing/strategy/rules.rb +1 -1
  167. data/app/models/spree/order_routing_rule.rb +6 -22
  168. data/app/models/spree/package_type.rb +2 -2
  169. data/app/models/spree/payment/gateway_options.rb +15 -53
  170. data/app/models/spree/payment/processing.rb +2 -4
  171. data/app/models/spree/payment.rb +21 -13
  172. data/app/models/spree/payment_method/check.rb +2 -0
  173. data/app/models/spree/payment_method/session_instrumentation.rb +1 -0
  174. data/app/models/spree/payment_method/store_credit.rb +15 -13
  175. data/app/models/spree/payment_method.rb +78 -6
  176. data/app/models/spree/payment_session.rb +5 -1
  177. data/app/models/spree/payment_setup_session.rb +1 -0
  178. data/app/models/spree/payout_provider/base.rb +3 -1
  179. data/app/models/spree/pickup_point_provider/base.rb +2 -0
  180. data/app/models/spree/policy.rb +1 -0
  181. data/app/models/spree/price.rb +17 -14
  182. data/app/models/spree/price_adjustment_tier.rb +4 -0
  183. data/app/models/spree/price_list.rb +14 -9
  184. data/app/models/spree/price_rules/channel_rule.rb +3 -6
  185. data/app/models/spree/price_rules/customer_group_rule.rb +3 -6
  186. data/app/models/spree/price_rules/market_rule.rb +2 -5
  187. data/app/models/spree/price_rules/user_rule.rb +1 -3
  188. data/app/models/spree/product/channels.rb +9 -2
  189. data/app/models/spree/product.rb +54 -30
  190. data/app/models/spree/product_submission.rb +0 -12
  191. data/app/models/spree/product_type.rb +1 -1
  192. data/app/models/spree/promotion/actions/create_line_items.rb +28 -18
  193. data/app/models/spree/promotion/rules/category.rb +1 -5
  194. data/app/models/spree/promotion/rules/channel.rb +2 -9
  195. data/app/models/spree/promotion/rules/country.rb +3 -8
  196. data/app/models/spree/promotion/rules/currency.rb +1 -5
  197. data/app/models/spree/promotion/rules/customer_group.rb +2 -9
  198. data/app/models/spree/promotion/rules/first_order.rb +0 -4
  199. data/app/models/spree/promotion/rules/item_total.rb +6 -10
  200. data/app/models/spree/promotion/rules/market.rb +2 -9
  201. data/app/models/spree/promotion/rules/one_use_per_user.rb +0 -4
  202. data/app/models/spree/promotion/rules/option_value.rb +2 -6
  203. data/app/models/spree/promotion/rules/product.rb +1 -5
  204. data/app/models/spree/promotion/rules/user.rb +0 -4
  205. data/app/models/spree/promotion/rules/user_logged_in.rb +0 -4
  206. data/app/models/spree/promotion.rb +36 -6
  207. data/app/models/spree/promotion_action.rb +7 -14
  208. data/app/models/spree/promotion_action_line_item.rb +1 -1
  209. data/app/models/spree/promotion_handler/coupon.rb +59 -27
  210. data/app/models/spree/promotion_rule.rb +7 -14
  211. data/app/models/spree/purchase_order.rb +3 -0
  212. data/app/models/spree/quantity_rule.rb +1 -1
  213. data/app/models/spree/refund.rb +41 -18
  214. data/app/models/spree/return.rb +31 -2
  215. data/app/models/spree/return_line_item.rb +65 -14
  216. data/app/models/spree/role.rb +7 -7
  217. data/app/models/spree/saved_report.rb +2 -1
  218. data/app/models/spree/search_provider/base.rb +4 -0
  219. data/app/models/spree/seller.rb +10 -2
  220. data/app/models/spree/seller_payout.rb +8 -0
  221. data/app/models/spree/seller_requirement.rb +5 -12
  222. data/app/models/spree/seller_requirement_custom_field.rb +1 -2
  223. data/app/models/spree/seller_requirement_submission.rb +3 -2
  224. data/app/models/spree/seller_requirements/accept_terms.rb +2 -3
  225. data/app/models/spree/seller_transfer.rb +6 -0
  226. data/app/models/spree/shipping_label.rb +2 -0
  227. data/app/models/spree/stock/availability_validator.rb +2 -2
  228. data/app/models/spree/stock/estimator.rb +1 -1
  229. data/app/models/spree/stock/inventory_unit_builder.rb +1 -1
  230. data/app/models/spree/stock/packer.rb +2 -2
  231. data/app/models/spree/stock/splitter/weight.rb +1 -1
  232. data/app/models/spree/stock_level/custom_events.rb +6 -0
  233. data/app/models/spree/stock_level.rb +3 -1
  234. data/app/models/spree/stock_location.rb +1 -0
  235. data/app/models/spree/stock_movement.rb +1 -1
  236. data/app/models/spree/stock_receipt_item.rb +1 -1
  237. data/app/models/spree/stock_reservation.rb +2 -2
  238. data/app/models/spree/stock_transfer.rb +6 -2
  239. data/app/models/spree/store.rb +70 -19
  240. data/app/models/spree/store_credit.rb +13 -13
  241. data/app/models/spree/store_credit_event.rb +5 -5
  242. data/app/models/spree/supplier.rb +1 -0
  243. data/app/models/spree/tax_category.rb +1 -0
  244. data/app/models/spree/tax_exemption_certificate.rb +3 -0
  245. data/app/models/spree/tax_identifier.rb +3 -1
  246. data/app/models/spree/tax_line.rb +53 -3
  247. data/app/models/spree/tax_provider/base.rb +71 -14
  248. data/app/models/spree/tax_provider/internal.rb +70 -41
  249. data/app/models/spree/tax_provider/recorded_share.rb +114 -0
  250. data/app/models/spree/tax_rate.rb +30 -8
  251. data/app/models/spree/taxon.rb +1 -1
  252. data/app/models/spree/taxonomy.rb +0 -1
  253. data/app/models/spree/update_status.rb +25 -0
  254. data/app/models/spree/variant.rb +10 -12
  255. data/app/models/spree/variant_media.rb +1 -1
  256. data/app/models/spree/webhook_delivery.rb +1 -0
  257. data/app/models/spree/webhook_endpoint.rb +46 -13
  258. data/app/models/spree/wishlist.rb +1 -6
  259. data/app/models/spree/wishlist_item/custom_events.rb +6 -0
  260. data/app/presenters/spree/csv/customer_presenter.rb +1 -1
  261. data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +1 -1
  262. data/app/presenters/spree/csv/order_line_item_presenter.rb +10 -6
  263. data/app/presenters/spree/csv/price_list_price_presenter.rb +3 -8
  264. data/app/presenters/spree/csv/product_variant_presenter.rb +59 -20
  265. data/app/presenters/spree/csv/purchase_order_item_presenter.rb +1 -3
  266. data/app/serializers/spree/emails/base_serializer.rb +14 -0
  267. data/app/serializers/spree/emails/export_serializer.rb +13 -0
  268. data/app/serializers/spree/emails/import_serializer.rb +19 -0
  269. data/app/serializers/spree/emails/invitation_serializer.rb +28 -0
  270. data/app/serializers/spree/emails/store_serializer.rb +31 -0
  271. data/app/serializers/spree/emails/user_serializer.rb +12 -0
  272. data/app/serializers/spree/emails/webhook_endpoint_serializer.rb +16 -0
  273. data/app/services/spree/carts/create.rb +8 -2
  274. data/app/services/spree/carts/destroy.rb +2 -2
  275. data/app/services/spree/carts/remove_out_of_stock_items.rb +2 -2
  276. data/app/services/spree/carts/split_by_seller.rb +1 -1
  277. data/app/services/spree/carts/update.rb +22 -8
  278. data/app/services/spree/catalogs/set_product_terms.rb +1 -1
  279. data/app/services/spree/categories/add_products.rb +13 -31
  280. data/app/services/spree/categories/remove_products.rb +12 -51
  281. data/app/services/spree/checkout/advance.rb +1 -4
  282. data/app/services/spree/collections/add_products.rb +10 -23
  283. data/app/services/spree/collections/remove_products.rb +7 -43
  284. data/app/services/spree/coupon_codes/bulk_generate.rb +8 -14
  285. data/app/services/spree/data_requests/create.rb +1 -1
  286. data/app/services/spree/deliveries/destroy.rb +2 -2
  287. data/app/services/spree/email_templates/check.rb +58 -0
  288. data/app/services/spree/email_templates/no_sample_record.rb +7 -0
  289. data/app/services/spree/email_templates/preview.rb +99 -0
  290. data/app/services/spree/emails/file_system.rb +23 -0
  291. data/app/services/spree/emails/filters.rb +84 -0
  292. data/app/services/spree/emails/liquid_context.rb +48 -0
  293. data/app/services/spree/emails/rendered_email.rb +14 -0
  294. data/app/services/spree/emails/renderer.rb +125 -0
  295. data/app/services/spree/emails/template.rb +51 -0
  296. data/app/services/spree/emails/template_data.rb +23 -0
  297. data/app/services/spree/emails/template_resolver.rb +109 -0
  298. data/app/services/spree/emails/text_converter.rb +72 -0
  299. data/app/services/spree/emails/translation_inliner.rb +134 -0
  300. data/app/services/spree/imports/row_processors/price_list_price.rb +10 -10
  301. data/app/services/spree/imports/row_processors/product_variant.rb +77 -34
  302. data/app/services/spree/imports/row_processors/purchase_order.rb +13 -13
  303. data/app/services/spree/locales.rb +43 -10
  304. data/app/services/spree/newsletter/subscribe.rb +8 -12
  305. data/app/services/spree/orders/build_fulfillments.rb +3 -2
  306. data/app/services/spree/orders/create.rb +5 -4
  307. data/app/services/spree/orders/discounts/create.rb +14 -11
  308. data/app/services/spree/orders/discounts/destroy.rb +1 -0
  309. data/app/services/spree/orders/discounts/update.rb +1 -0
  310. data/app/services/spree/orders/fees/create.rb +1 -0
  311. data/app/services/spree/orders/fees/destroy.rb +1 -0
  312. data/app/services/spree/orders/fees/update.rb +1 -0
  313. data/app/services/spree/orders/remove_line_item.rb +13 -3
  314. data/app/services/spree/orders/update.rb +10 -6
  315. data/app/services/spree/orders/update_item.rb +6 -3
  316. data/app/services/spree/orders/update_statuses.rb +3 -1
  317. data/app/services/spree/prices/bulk_upsert.rb +32 -25
  318. data/app/services/spree/product_memberships.rb +61 -0
  319. data/app/services/spree/returns/eligibility_validator.rb +1 -1
  320. data/app/services/spree/search_provider/custom_field_schema.rb +2 -2
  321. data/app/services/spree/seeds/commission_rates.rb +1 -1
  322. data/app/services/spree/seeds/digital_delivery.rb +1 -1
  323. data/app/services/spree/seeds/payment_methods.rb +2 -2
  324. data/app/services/spree/seeds/saved_reports.rb +3 -3
  325. data/app/services/spree/seeds/stores.rb +1 -1
  326. data/app/services/spree/sellers/requirements.rb +1 -2
  327. data/app/services/spree/shipping_labels/confirm_refund.rb +1 -1
  328. data/app/services/spree/shipping_labels/store_file.rb +3 -3
  329. data/app/services/spree/stock_levels/correct.rb +3 -3
  330. data/app/services/spree/stock_reservations/reserve.rb +2 -3
  331. data/app/services/spree/store_credits/apply.rb +15 -13
  332. data/app/services/spree/stores/provision_defaults.rb +23 -25
  333. data/app/services/spree/update_check.rb +160 -0
  334. data/app/services/spree/uploads/assign_stores.rb +92 -0
  335. data/app/subscribers/spree/seller_onboarding_subscriber.rb +1 -1
  336. data/app/validators/spree/attachment_content_type_validator.rb +19 -2
  337. data/app/validators/spree/locale_codes_validator.rb +22 -0
  338. data/app/views/layouts/spree/base_mailer.html.erb +2 -43
  339. data/app/views/layouts/spree/base_mailer.liquid +79 -0
  340. data/app/views/spree/admin_user_mailer/password_reset_email.liquid +14 -0
  341. data/app/views/spree/export_mailer/export_done.liquid +12 -0
  342. data/app/views/spree/import_mailer/import_done.liquid +15 -0
  343. data/app/views/spree/invitation_mailer/invitation_accepted.liquid +9 -0
  344. data/app/views/spree/invitation_mailer/invitation_email.liquid +13 -0
  345. data/app/views/spree/seller_user_mailer/password_reset_email.liquid +14 -0
  346. data/app/views/spree/shared/_mailer_button.html.erb +4 -5
  347. data/app/views/spree/shared/_mailer_hero.html.erb +6 -5
  348. data/app/views/spree/shared/_summary_row.liquid +8 -0
  349. data/app/views/spree/webhook_mailer/endpoint_disabled.liquid +21 -0
  350. data/app/workflows/spree/carts/add_item.rb +4 -4
  351. data/app/workflows/spree/carts/complete.rb +13 -3
  352. data/app/workflows/spree/carts/merge.rb +1 -1
  353. data/app/workflows/spree/carts/recalculate_totals.rb +5 -0
  354. data/app/workflows/spree/carts/upsert_items.rb +18 -9
  355. data/app/workflows/spree/claims/approve.rb +5 -22
  356. data/app/workflows/spree/claims/cancel.rb +5 -21
  357. data/app/workflows/spree/claims/create.rb +15 -0
  358. data/app/workflows/spree/claims/deny.rb +7 -0
  359. data/app/workflows/spree/claims/resolve.rb +34 -31
  360. data/app/workflows/spree/customers/anonymize.rb +3 -4
  361. data/app/workflows/spree/customers/create.rb +1 -1
  362. data/app/workflows/spree/data_requests/fulfill.rb +2 -2
  363. data/app/workflows/spree/deliveries/update_tracking.rb +1 -1
  364. data/app/workflows/spree/email_templates/discard_draft.rb +20 -0
  365. data/app/workflows/spree/email_templates/publish.rb +70 -0
  366. data/app/workflows/spree/email_templates/restore_revision.rb +33 -0
  367. data/app/workflows/spree/email_templates/revert.rb +29 -0
  368. data/app/workflows/spree/email_templates/save_draft.rb +85 -0
  369. data/app/workflows/spree/exchanges/approve.rb +5 -22
  370. data/app/workflows/spree/exchanges/cancel.rb +5 -21
  371. data/app/workflows/spree/exchanges/create.rb +6 -0
  372. data/app/workflows/spree/exchanges/fulfill.rb +75 -51
  373. data/app/workflows/spree/exchanges/receive.rb +6 -65
  374. data/app/workflows/spree/fulfillments/cancel.rb +1 -1
  375. data/app/workflows/spree/fulfillments/create.rb +53 -49
  376. data/app/workflows/spree/fulfillments/fulfill.rb +23 -27
  377. data/app/workflows/spree/fulfillments/mark_delivered.rb +1 -1
  378. data/app/workflows/spree/fulfillments/replacements.rb +59 -0
  379. data/app/workflows/spree/gift_cards/apply.rb +2 -2
  380. data/app/workflows/spree/orders/add_item.rb +5 -1
  381. data/app/workflows/spree/orders/cancel.rb +3 -3
  382. data/app/workflows/spree/orders/complete.rb +16 -8
  383. data/app/workflows/spree/payments/capture.rb +20 -5
  384. data/app/workflows/spree/payments/process.rb +5 -3
  385. data/app/workflows/spree/post_sale/approval.rb +35 -0
  386. data/app/workflows/spree/post_sale/cancellation.rb +44 -0
  387. data/app/workflows/spree/post_sale/receipt.rb +92 -0
  388. data/app/workflows/spree/price_lists/update.rb +4 -4
  389. data/app/workflows/spree/products/nested_attributes.rb +1 -1
  390. data/app/workflows/spree/purchase_orders/cancel.rb +1 -1
  391. data/app/workflows/spree/purchase_orders/close.rb +3 -31
  392. data/app/workflows/spree/purchase_orders/create.rb +3 -1
  393. data/app/workflows/spree/purchase_orders/mark_draft.rb +2 -2
  394. data/app/workflows/spree/purchase_orders/mark_ordered.rb +2 -2
  395. data/app/workflows/spree/purchase_orders/receive.rb +1 -1
  396. data/app/workflows/spree/purchase_orders/update.rb +5 -34
  397. data/app/workflows/spree/receivables/closing_short.rb +46 -0
  398. data/app/workflows/spree/receivables/draft_editing.rb +48 -0
  399. data/app/workflows/spree/refunds/create.rb +5 -2
  400. data/app/workflows/spree/refunds/order_payments.rb +14 -2
  401. data/app/workflows/spree/refunds/tax_credit.rb +67 -0
  402. data/app/workflows/spree/returns/approve.rb +5 -22
  403. data/app/workflows/spree/returns/cancel.rb +5 -22
  404. data/app/workflows/spree/returns/create.rb +8 -0
  405. data/app/workflows/spree/returns/receive.rb +5 -76
  406. data/app/workflows/spree/returns/refund.rb +31 -8
  407. data/app/workflows/spree/seller_requirement_submissions/create.rb +1 -2
  408. data/app/workflows/spree/seller_transfers/reverse.rb +28 -1
  409. data/app/workflows/spree/shipping_labels/purchase.rb +8 -8
  410. data/app/workflows/spree/shipping_labels/record.rb +7 -7
  411. data/app/workflows/spree/shipping_labels/refund.rb +2 -2
  412. data/app/workflows/spree/stock_receipts/recording.rb +4 -4
  413. data/app/workflows/spree/stock_transfers/cancel.rb +2 -2
  414. data/app/workflows/spree/stock_transfers/close.rb +3 -30
  415. data/app/workflows/spree/stock_transfers/create.rb +3 -1
  416. data/app/workflows/spree/stock_transfers/mark_draft.rb +1 -1
  417. data/app/workflows/spree/stock_transfers/mark_in_transit.rb +3 -3
  418. data/app/workflows/spree/stock_transfers/mark_ready.rb +2 -2
  419. data/app/workflows/spree/stock_transfers/receive.rb +1 -1
  420. data/app/workflows/spree/stock_transfers/update.rb +5 -33
  421. data/config/currency_exponents.json +180 -0
  422. data/config/i18n-tasks.yml +32 -18
  423. data/config/initializers/alba.rb +7 -0
  424. data/config/language_names.csv +264 -0
  425. data/config/locales/ar.yml +811 -0
  426. data/config/locales/be.yml +855 -0
  427. data/config/locales/bg.yml +723 -0
  428. data/config/locales/ca.yml +689 -0
  429. data/config/locales/content_locales.rb +9 -0
  430. data/config/locales/cs.yml +855 -0
  431. data/config/locales/da.yml +771 -0
  432. data/config/locales/de-CH.yml +248 -0
  433. data/config/locales/de.yml +835 -0
  434. data/config/locales/el.yml +769 -0
  435. data/config/locales/en.yml +47 -505
  436. data/config/locales/es-CL.yml +301 -0
  437. data/config/locales/es-EC.yml +186 -0
  438. data/config/locales/es-MX.yml +334 -0
  439. data/config/locales/es.yml +831 -0
  440. data/config/locales/et.yml +644 -0
  441. data/config/locales/fa.yml +709 -0
  442. data/config/locales/fi.yml +771 -0
  443. data/config/locales/fr.yml +830 -0
  444. data/config/locales/hu.yml +751 -0
  445. data/config/locales/id.yml +756 -0
  446. data/config/locales/it.yml +833 -0
  447. data/config/locales/ja.yml +726 -0
  448. data/config/locales/km.yml +759 -0
  449. data/config/locales/ko.yml +575 -0
  450. data/config/locales/ku.yml +753 -0
  451. data/config/locales/lt.yml +821 -0
  452. data/config/locales/lv.yml +685 -0
  453. data/config/locales/nb.yml +824 -0
  454. data/config/locales/ne.yml +823 -0
  455. data/config/locales/nl.yml +826 -0
  456. data/config/locales/pl.yml +835 -0
  457. data/config/locales/pt-BR.yml +547 -0
  458. data/config/locales/pt.yml +636 -0
  459. data/config/locales/ro.yml +750 -0
  460. data/config/locales/ru.yml +834 -0
  461. data/config/locales/sk.yml +680 -0
  462. data/config/locales/sl-SI.yml +600 -0
  463. data/config/locales/sv.yml +827 -0
  464. data/config/locales/th.yml +745 -0
  465. data/config/locales/tr.yml +777 -0
  466. data/config/locales/uk.yml +836 -0
  467. data/config/locales/vi.yml +768 -0
  468. data/config/locales/zh-CN.yml +786 -0
  469. data/config/locales/zh-TW.yml +834 -0
  470. data/db/migrate/20260925000001_add_replacement_to_spree_fulfillment_items.rb +5 -0
  471. data/db/migrate/20261001000001_add_post_sale_tax.rb +30 -0
  472. data/db/migrate/20261001000001_convert_preferences_to_json.rb +166 -0
  473. data/db/migrate/20261001000001_create_spree_email_templates.rb +52 -0
  474. data/db/migrate/20261009000001_change_money_columns_to_decimal_19_4.rb +116 -0
  475. data/db/migrate/20261010000001_add_store_id_to_active_storage_blobs.rb +12 -0
  476. data/lib/generators/spree/dummy/dummy_generator.rb +0 -9
  477. data/lib/generators/spree/dummy/templates/rails/test.rb +26 -0
  478. data/lib/spree/checkout/default_requirements.rb +37 -13
  479. data/lib/spree/core/configuration.rb +19 -1
  480. data/lib/spree/core/controller_helpers/store.rb +1 -1
  481. data/lib/spree/core/dependencies.rb +5 -4
  482. data/lib/spree/core/emails/escaped_output.rb +60 -0
  483. data/lib/spree/core/engine.rb +72 -165
  484. data/lib/spree/core/permissions/default_catalog.rb +5 -0
  485. data/lib/spree/core/preferences/invalid_preferences.rb +18 -0
  486. data/lib/spree/core/preferences/json_conversion.rb +186 -0
  487. data/lib/spree/core/preferences/masking.rb +55 -2
  488. data/lib/spree/core/preferences/preferable.rb +343 -103
  489. data/lib/spree/core/preferences/preferable_class_methods.rb +188 -136
  490. data/lib/spree/core/previews/import_preview.rb +10 -0
  491. data/lib/spree/core/ransack_configuration.rb +13 -2
  492. data/lib/spree/core/tax/provider_error.rb +37 -0
  493. data/lib/spree/core/version.rb +1 -1
  494. data/lib/spree/core.rb +91 -373
  495. data/lib/spree/emails/editable_templates.rb +82 -0
  496. data/lib/spree/events/catalog.rb +189 -0
  497. data/lib/spree/events.rb +21 -1
  498. data/lib/spree/hooks.rb +0 -17
  499. data/lib/spree/i18n.rb +32 -15
  500. data/lib/spree/iso_data.rb +7 -0
  501. data/lib/spree/localized_number.rb +6 -0
  502. data/lib/spree/migrations.rb +4 -1
  503. data/lib/spree/money.rb +196 -15
  504. data/lib/spree/reporting/adapters/base.rb +7 -6
  505. data/lib/spree/reporting/adapters/live.rb +6 -6
  506. data/lib/spree/reporting/default_vocabulary.rb +22 -10
  507. data/lib/spree/reporting/hydration.rb +1 -1
  508. data/lib/spree/reporting/query.rb +8 -0
  509. data/lib/spree/reporting/registry.rb +13 -0
  510. data/lib/spree/reporting/schema.rb +10 -10
  511. data/lib/spree/testing_support/editable_email_templates.rb +61 -0
  512. data/lib/spree/testing_support/emails.rb +22 -0
  513. data/lib/spree/testing_support/factories/cart_factory.rb +1 -1
  514. data/lib/spree/testing_support/factories/email_template_factory.rb +28 -0
  515. data/lib/spree/testing_support/factories/order_factory.rb +2 -2
  516. data/lib/spree/testing_support/factories/product_factory.rb +9 -0
  517. data/lib/spree/testing_support/factories/refund_factory.rb +1 -1
  518. data/lib/spree/testing_support/factories/stock_factory.rb +1 -1
  519. data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
  520. data/lib/spree/testing_support/i18n.rb +3 -94
  521. data/lib/spree/testing_support/lifecycle_events.rb +1 -1
  522. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  523. data/lib/spree/testing_support/preferences.rb +0 -5
  524. data/lib/spree/testing_support/store.rb +9 -1
  525. data/lib/spree/upgrades/5_6_to_6_0/manifest.yml +67 -1
  526. data/lib/spree/uploads.rb +101 -0
  527. data/lib/tasks/categories_and_collections.rake +3 -3
  528. data/lib/tasks/core.rake +6 -4
  529. data/lib/tasks/markets.rake +2 -1
  530. data/lib/tasks/media.rake +3 -3
  531. data/lib/tasks/migrate_users_to_customers.rake +23 -18
  532. data/lib/tasks/money.rake +46 -0
  533. data/lib/tasks/package_types.rake +1 -1
  534. data/lib/tasks/preferences_json.rake +101 -0
  535. data/lib/tasks/seller_sample_data.rake +2 -2
  536. data/lib/tasks/store_settings.rake +13 -6
  537. data/lib/tasks/typed_adjustments_migration.rake +1 -1
  538. data/lib/tasks/uploads.rake +19 -0
  539. data/spec/fixtures/mailer_views/custom_views_probe_mailer/welcome_email.html.erb +4 -0
  540. metadata +219 -46
  541. data/app/jobs/spree/products/touch_categories_job.rb +0 -15
  542. data/app/jobs/spree/products/touch_taxons_job.rb +0 -13
  543. data/app/models/acts_as_taggable_on/tag_decorator.rb +0 -10
  544. data/app/models/concerns/spree/has_image_alt_text.rb +0 -18
  545. data/app/models/spree/base_analytics_event_handler.rb +0 -54
  546. data/app/models/spree/invitations/store.rb +0 -6
  547. data/app/models/spree/preference.rb +0 -14
  548. data/app/models/spree/promotion_handler/page.rb +0 -25
  549. data/app/models/spree/promotion_handler/promotion_duplicator.rb +0 -60
  550. data/app/models/spree/stock/differentiator.rb +0 -45
  551. data/app/presenters/spree/filters/options_presenter.rb +0 -47
  552. data/app/services/spree/carts/empty.rb +0 -42
  553. data/app/services/spree/country_to_timezone.rb +0 -273
  554. data/app/services/spree/payments/create.rb +0 -92
  555. data/app/validators/spree/url_validator.rb +0 -23
  556. data/app/views/active_storage/blobs/_blob.html.erb +0 -14
  557. data/app/views/spree/admin_user_mailer/password_reset_email.html.erb +0 -8
  558. data/app/views/spree/export_mailer/export_done.html.erb +0 -7
  559. data/app/views/spree/import_mailer/import_done.html.erb +0 -12
  560. data/app/views/spree/invitation_mailer/invitation_accepted.html.erb +0 -4
  561. data/app/views/spree/invitation_mailer/invitation_email.html.erb +0 -12
  562. data/app/views/spree/seller_user_mailer/password_reset_email.html.erb +0 -8
  563. data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -19
  564. data/app/views/spree/shared/_base_mailer_header.html.erb +0 -8
  565. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -399
  566. data/app/views/spree/shared/_mailer_logo.html.erb +0 -41
  567. data/app/views/spree/shared/_purchased_items_styles.html.erb +0 -119
  568. data/app/views/spree/webhook_mailer/endpoint_disabled.html.erb +0 -51
  569. data/app/views/spree/webhook_mailer/endpoint_disabled.text.erb +0 -10
  570. data/app/workflows/spree/fulfillments/purchase_label.rb +0 -40
  571. data/app/workflows/spree/returns/purchase_label.rb +0 -32
  572. data/lib/spree/analytics.rb +0 -11
  573. data/lib/spree/core/preferences/scoped_store.rb +0 -34
  574. data/lib/spree/core/preferences/store.rb +0 -105
  575. data/lib/spree/translation_migrations.rb +0 -52
@@ -3,7 +3,11 @@ module Spree
3
3
  #
4
4
  # Named for {Spree::LineItem}, which it mirrors: `quantity` is what the
5
5
  # customer said was coming, `received_quantity` what the warehouse counted.
6
+ # Like a line item it carries its worth before tax in `pre_tax_amount` and
7
+ # the tax on it beside that, both for the announced quantity.
6
8
  class ReturnLineItem < Spree.base_class
9
+ include Spree::PostSale::TaxedLine
10
+
7
11
  has_prefix_id :rli
8
12
 
9
13
  belongs_to :return, class_name: 'Spree::Return', inverse_of: :return_line_items
@@ -19,31 +23,80 @@ module Spree
19
23
 
20
24
  delegate :order, :currency, to: :return
21
25
 
22
- # What this line refunds. Once the warehouse has counted, only the units
23
- # that arrived are paid for — a customer who announced three and sent two
24
- # is owed two — and before the count there is nothing to go on but the
25
- # announced quantity.
26
+ extend Spree::DisplayMoney
27
+ money_methods :pre_tax_amount, :included_tax_total, :additional_tax_total, :tax_total,
28
+ :refund_amount, :refund_tax_amount
29
+
30
+ # What this line refunds, tax included. Once the warehouse has counted,
31
+ # only the units that arrived are paid for — a customer who announced
32
+ # three and sent two is owed two — and before the count there is nothing
33
+ # to go on but the announced quantity.
26
34
  #
27
35
  # Rounded to the currency, because this is the ceiling a refund is checked
28
36
  # against as well as the figure the dialog offers: a third of $29.99 taken
29
37
  # three times is not $29.99 until it is.
30
38
  #
39
+ # A line opened before returns carried tax holds the price it was opened
40
+ # with in `pre_tax_amount` and no tax, so it refunds exactly what it did.
41
+ #
31
42
  # @return [BigDecimal]
32
43
  def refund_amount
33
- return pre_tax_amount unless self.return.counted?
34
- return 0.to_d if quantity.to_i.zero?
44
+ counted_share(total)
45
+ end
35
46
 
36
- Spree::Money::Rounding.to_currency(
37
- (pre_tax_amount / quantity) * received_quantity.to_i, currency
38
- )
47
+ # @return [BigDecimal] the tax inside {#refund_amount}
48
+ def refund_tax_amount
49
+ counted_share(tax_total)
50
+ end
51
+
52
+ # @return [BigDecimal] the announced units, tax included
53
+ def total
54
+ pre_tax_amount + tax_total
55
+ end
56
+
57
+ def tax_total
58
+ included_tax_total + additional_tax_total
59
+ end
60
+
61
+ # The units this line gives back: none once the return is canceled, what
62
+ # arrived once the warehouse has counted, what was announced before.
63
+ #
64
+ # @return [Integer]
65
+ def credited_quantity
66
+ return 0 if self.return.canceled?
67
+
68
+ self.return.counted? ? received_quantity.to_i : quantity.to_i
69
+ end
70
+
71
+ # @return [BigDecimal] what the credited units are worth, tax included
72
+ def credited_worth
73
+ refund_amount
39
74
  end
40
75
 
41
- def display_pre_tax_amount
42
- Spree::Money.new(pre_tax_amount, currency: currency)
76
+ # Copies the credit rows written at opening onto the line. The before-tax
77
+ # figure is what was paid after discounts less the tax inside it, so the
78
+ # three columns add up to the cent.
79
+ #
80
+ # @return [void]
81
+ def fold_tax_lines!
82
+ included, additional = tax_totals_from(tax_lines.credits.reload)
83
+
84
+ update_columns(
85
+ pre_tax_amount: default_pre_tax_amount - included,
86
+ included_tax_total: included,
87
+ additional_tax_total: additional
88
+ )
43
89
  end
44
90
 
45
91
  private
46
92
 
93
+ def counted_share(value)
94
+ return value unless self.return.counted?
95
+ return 0.to_d if quantity.to_i.zero?
96
+
97
+ Spree::Money::Rounding.to_currency((value / quantity) * received_quantity.to_i, currency)
98
+ end
99
+
47
100
  # The refundable amount defaults to this item's share of what the
48
101
  # customer actually paid for the line, after discounts — refunding the
49
102
  # list price would give back more than was taken.
@@ -53,9 +106,7 @@ module Spree
53
106
  end
54
107
 
55
108
  def default_pre_tax_amount
56
- return 0 if line_item.nil? || line_item.quantity.to_i.zero?
57
-
58
- (line_item.amount / line_item.quantity) * quantity.to_i
109
+ line_item&.discounted_amount_for(quantity) || 0
59
110
  end
60
111
  end
61
112
  end
@@ -150,7 +150,7 @@ module Spree
150
150
 
151
151
  def permissions_must_be_known
152
152
  unknown = permissions - Spree.permissions.catalog_keys
153
- errors.add(:permissions, :role_permissions_unknown, message: Spree.t(:role_permissions_unknown, keys: unknown.join(', '))) if unknown.any?
153
+ errors.add(:permissions, :role_permissions_unknown, message: I18n.t('spree.role_permissions_unknown', keys: unknown.join(', '))) if unknown.any?
154
154
  end
155
155
 
156
156
  # Every role is bounded by the catalog: only resources registered as
@@ -164,26 +164,26 @@ module Spree
164
164
  return if ungrantable.none?
165
165
 
166
166
  errors.add(
167
- :permissions, :role_permissions_not_grantable_for_audience, message: Spree.t(:role_permissions_not_grantable_for_audience, audience: audience, keys: ungrantable.join(', '))
167
+ :permissions, :role_permissions_not_grantable_for_audience, message: I18n.t('spree.role_permissions_not_grantable_for_audience', audience: audience, keys: ungrantable.join(', '))
168
168
  )
169
169
  end
170
170
 
171
171
  # Re-pointing the resource would move every existing assignment to another
172
172
  # panel — and, for a store, to another tenant.
173
173
  def resource_immutable
174
- errors.add(:resource, :role_resource_immutable, message: Spree.t(:role_resource_immutable))
174
+ errors.add(:resource, :role_resource_immutable, message: I18n.t('spree.role_resource_immutable'))
175
175
  end
176
176
 
177
177
  def name_immutable
178
- errors.add(:name, :role_immutable, message: Spree.t(:role_immutable)) unless mutable_was_and_not_admin?
178
+ errors.add(:name, :role_immutable, message: I18n.t('spree.role_immutable')) unless mutable_was_and_not_admin?
179
179
  end
180
180
 
181
181
  def permissions_immutable
182
- errors.add(:permissions, :role_immutable, message: Spree.t(:role_immutable)) unless mutable_was_and_not_admin?
182
+ errors.add(:permissions, :role_immutable, message: I18n.t('spree.role_immutable')) unless mutable_was_and_not_admin?
183
183
  end
184
184
 
185
185
  def description_immutable
186
- errors.add(:description, :role_immutable, message: Spree.t(:role_immutable)) unless mutable_was_and_not_admin?
186
+ errors.add(:description, :role_immutable, message: I18n.t('spree.role_immutable')) unless mutable_was_and_not_admin?
187
187
  end
188
188
 
189
189
  # Guards compare against the persisted `mutable` so flipping it in the same
@@ -197,7 +197,7 @@ module Spree
197
197
  def ensure_can_be_deleted
198
198
  return true if can_be_deleted?
199
199
 
200
- errors.add(:base, :role_cannot_be_deleted, message: Spree.t(:role_cannot_be_deleted))
200
+ errors.add(:base, :role_cannot_be_deleted, message: I18n.t('spree.role_cannot_be_deleted'))
201
201
  throw :abort
202
202
  end
203
203
  end
@@ -23,9 +23,10 @@ module Spree
23
23
  scope :seeded, -> { where(seeded: true) }
24
24
 
25
25
  self.whitelisted_ransackable_attributes = %w[name seeded created_at updated_at]
26
+ search_by :name
26
27
 
27
28
  def event_serializer_class
28
- 'Spree::Api::V3::Admin::SavedReportSerializer'.safe_constantize
29
+ 'Spree::Api::V3::SavedReportEventSerializer'.safe_constantize
29
30
  end
30
31
 
31
32
  # The stored query, normalized against the registry.
@@ -1,6 +1,10 @@
1
1
  module Spree
2
2
  module SearchProvider
3
3
  class Base
4
+ # Sort keys a provider accepts beyond the product's sortable
5
+ # attributes. `price` also sorts descending as `-price`.
6
+ SORT_FIELDS = %w[price best_selling manual].freeze
7
+
4
8
  attr_reader :store
5
9
 
6
10
  # Whether this provider requires background indexing jobs.
@@ -25,6 +25,8 @@ module Spree
25
25
  MEMOIZED_METHODS = %w[onboarding_requirements onboarding_progress products_count returns_location].freeze
26
26
 
27
27
  publishes_lifecycle_events
28
+ publishes_events :approved, :invited, :onboarding_reopened, :onboarding_started, :rejected,
29
+ :submitted_for_review, :suspended
28
30
 
29
31
  # Where a seller is in its life on the marketplace. Transitions belong to
30
32
  # workflows (Spree::Sellers::Approve and friends) rather than a state
@@ -39,6 +41,12 @@ module Spree
39
41
  has_status :pending, :invited, :canceled, :onboarding, :ready_for_review,
40
42
  :approved, :rejected, :suspended, default: :pending
41
43
 
44
+ # The storefront lists approved sellers only, and a seller's contact
45
+ # address is back-office data.
46
+ self.whitelisted_ransackable_attributes = %w[status contact_email]
47
+ search_by :name
48
+ self.private_ransackable_attributes = { store: %w[status contact_email], seller: %w[status contact_email] }
49
+
42
50
  # Who remits consumer tax on this seller's sales. `seller` means they are
43
51
  # merchant of record; `platform` is the marketplace-facilitator case, and
44
52
  # only Enterprise decides a seller belongs there — core just reads it.
@@ -62,7 +70,6 @@ module Spree
62
70
  #
63
71
  # Associations
64
72
  #
65
- belongs_to :store, class_name: 'Spree::Store'
66
73
  # The address knows it is a seller's from its owner, so it is read back
67
74
  # with the business rules — no personal name insisted on, the company line
68
75
  # required. Not `dependent: :destroy`: a seller is paranoid, so destroy is
@@ -195,6 +202,7 @@ module Spree
195
202
  has_one_attached :logo, service: Spree.public_storage_service_name
196
203
  has_one_attached :square_logo, service: Spree.public_storage_service_name
197
204
  has_one_attached :cover_photo, service: Spree.public_storage_service_name
205
+ signed_id_attachments :logo, :square_logo, :cover_photo
198
206
 
199
207
  #
200
208
  # Validations
@@ -339,7 +347,7 @@ module Spree
339
347
  # A seller keeps no clock of their own: a date means whatever the
340
348
  # marketplace says it means, so their panel reads timestamps in the
341
349
  # store's zone rather than in whichever one their browser sits in.
342
- delegate :preferred_timezone, to: :store, allow_nil: true
350
+ delegate :preferred_timezone, :timezone, to: :store, allow_nil: true
343
351
 
344
352
  # Sellers holding an account with one provider, for the reverse lookup a
345
353
  # provider webhook does — it knows the account, not the seller.
@@ -16,6 +16,8 @@ module Spree
16
16
  # and leaves the operator to pay by bank, while a provider like Stripe
17
17
  # Connect performs the transfer itself.
18
18
  class SellerPayout < Spree.base_class
19
+ publishes_event :completed
20
+
19
21
  has_prefix_id :vpo
20
22
 
21
23
  include Spree::Metadata
@@ -58,6 +60,12 @@ module Spree
58
60
  scope :owed, -> { where(status: %w[pending processing]) }
59
61
 
60
62
  self.whitelisted_ransackable_attributes = %w[amount currency status provider reference period_start period_end created_at seller_id]
63
+ search_by :reference
64
+ # Filtered by the provider's API shorthand (`system`); the column holds
65
+ # its class name.
66
+ ransacker :provider, formatter: ->(value) { Spree::ApiTyped.class_name_for(Spree.payout_providers, value) } do |parent|
67
+ parent.table[:provider]
68
+ end
61
69
  # No `transfers`: they lead on to the order and its buyer, which a
62
70
  # payouts-only caller may not read.
63
71
  self.whitelisted_ransackable_associations = %w[seller]
@@ -16,8 +16,12 @@ module Spree
16
16
  include Spree::HasListPosition
17
17
  include Spree::PreferenceSchema
18
18
  include Spree::Metadata
19
+ include Spree::TypeLabels
20
+
21
+ self.type_labels_scope = 'spree.seller_requirement_types'
19
22
 
20
23
  has_prefix_id :selreq
24
+ search_by :name
21
25
 
22
26
  acts_as_list scope: :store
23
27
 
@@ -87,16 +91,6 @@ module Spree
87
91
  end
88
92
  end
89
93
 
90
- # @return [String] the localized name of the kind, used by operator pickers
91
- def self.human_name
92
- Spree.t("seller_requirement_types.#{api_type}.name", default: api_type.titleize)
93
- end
94
-
95
- # @return [String] the localized description of the kind
96
- def self.human_description
97
- Spree.t("seller_requirement_types.#{api_type}.description", default: '')
98
- end
99
-
100
94
  # Whether the operator may configure this kind more than once per store.
101
95
  # True for the kinds whose meaning comes from the operator's own copy.
102
96
  #
@@ -266,8 +260,7 @@ module Spree
266
260
  return if Spree.seller_requirements.any? { |kind| kind.to_s == type }
267
261
 
268
262
  errors.add(
269
- :type, :invalid_seller_requirement, message: Spree.t(:invalid_seller_requirement, scope: [:errors, :messages],
270
- default: 'is not a registered seller requirement')
263
+ :type, :invalid_seller_requirement, message: I18n.t('spree.errors.messages.invalid_seller_requirement')
271
264
  )
272
265
  end
273
266
  end
@@ -22,8 +22,7 @@ module Spree
22
22
  return if custom_field_definition.resource_type == Spree::Seller.to_s
23
23
 
24
24
  errors.add(:custom_field_definition, :invalid,
25
- message: Spree.t('seller_requirements.custom_field_not_for_sellers',
26
- default: 'must be a custom field defined for sellers'))
25
+ message: I18n.t('spree.seller_requirements.custom_field_not_for_sellers'))
27
26
  end
28
27
 
29
28
  # Both sides are store-owned, so a marketplace can only ask its sellers
@@ -16,6 +16,7 @@ module Spree
16
16
  has_prefix_id :selsub
17
17
 
18
18
  publishes_lifecycle_events
19
+ publishes_events :accepted, :created, :rejected, :waived
19
20
 
20
21
  # `waived` is the operator excusing one seller from something the store
21
22
  # asks of everyone — a requirement they have already satisfied off the
@@ -37,6 +38,7 @@ module Spree
37
38
  # Private, and served only through the admin and seller branches: these
38
39
  # are business registrations and identity documents.
39
40
  has_one_attached :file, service: Spree.private_storage_service_name
41
+ signed_id_attachments :file
40
42
 
41
43
  #
42
44
  # Validations
@@ -84,8 +86,7 @@ module Spree
84
86
  return if seller.nil? || requirement.nil?
85
87
  return if seller.store_id == requirement.store_id
86
88
 
87
- errors.add(:requirement, :seller_requirement_store_mismatch, message: Spree.t('errors.messages.seller_requirement_store_mismatch',
88
- default: 'must belong to the same store as the seller'))
89
+ errors.add(:requirement, :seller_requirement_store_mismatch, message: I18n.t('spree.errors.messages.seller_requirement_store_mismatch'))
89
90
  end
90
91
  end
91
92
  end
@@ -90,14 +90,13 @@ module Spree
90
90
  # On the preference rather than :base, so the operator's form marks the
91
91
  # field they got wrong instead of only showing a summary line.
92
92
  errors.add(:preferred_terms_effective_from, :invalid_terms_effective_from,
93
- message: Spree.t('seller_requirements.invalid_terms_effective_from',
94
- default: 'Terms effective from is not a date'))
93
+ message: I18n.t('spree.seller_requirements.invalid_terms_effective_from'))
95
94
  end
96
95
 
97
96
  def store_terms_body
98
97
  return if store.nil?
99
98
 
100
- store.policies.with_matching_name(Spree.t(:terms_of_service)).detect(&:with_body?)&.body
99
+ store.policies.with_matching_name(I18n.t('spree.terms_of_service')).detect(&:with_body?)&.body
101
100
  end
102
101
  end
103
102
  end
@@ -112,6 +112,12 @@ module Spree
112
112
  end
113
113
 
114
114
  self.whitelisted_ransackable_attributes = %w[amount currency kind status provider reference created_at seller_id order_id payout_id]
115
+ search_by :reference
116
+ # Filtered by the provider's API shorthand (`system`); the column holds
117
+ # its class name.
118
+ ransacker :provider, formatter: ->(value) { Spree::ApiTyped.class_name_for(Spree.payout_providers, value) } do |parent|
119
+ parent.table[:provider]
120
+ end
115
121
  # No `order`: filtering through it reaches the buyer's email and address,
116
122
  # which a payouts-only caller may not read. `order_id` covers the lookup.
117
123
  self.whitelisted_ransackable_associations = %w[seller payout refund]
@@ -20,6 +20,7 @@ module Spree
20
20
  include Spree::Metadata
21
21
 
22
22
  publishes_lifecycle_events
23
+ publishes_events :purchased, :refunded
23
24
 
24
25
  has_status :purchased, :refund_requested, :refunded, default: :purchased
25
26
 
@@ -38,6 +39,7 @@ module Spree
38
39
  # merchant's account details, and is served only through an
39
40
  # authenticated, streamed download.
40
41
  has_one_attached :file, service: Spree.private_storage_service_name
42
+ signed_id_attachments :file
41
43
 
42
44
  validates :source, inclusion: { in: SOURCES }
43
45
  validates :owner_type, inclusion: { in: OWNER_TYPES }
@@ -17,11 +17,11 @@ module Spree
17
17
  if variant.available? || variant.preorder?
18
18
  line_item.errors.add(:quantity,
19
19
  :selected_quantity_not_available,
20
- message: Spree.t(:selected_quantity_not_available, item: display_name.inspect))
20
+ message: I18n.t('spree.selected_quantity_not_available', item: display_name.inspect))
21
21
  else
22
22
  line_item.errors.add(:base,
23
23
  :only_active_products_can_be_added_to_cart,
24
- message: Spree.t(:only_active_products_can_be_added_to_cart))
24
+ message: I18n.t('spree.only_active_products_can_be_added_to_cart'))
25
25
  end
26
26
  end
27
27
 
@@ -121,7 +121,7 @@ module Spree
121
121
 
122
122
  percent = service_row&.markup_percent || delivery_method.markup_percent || 0
123
123
  flat = service_row&.markup_flat || delivery_method.markup_flat || 0
124
- (cost * (1 + (percent / 100)) + flat).round(2)
124
+ Spree::Money::Rounding.to_currency(cost * (1 + (percent / 100)) + flat, currency)
125
125
  end
126
126
 
127
127
  # Display name for provider-priced rates: the merchant's label override,
@@ -14,7 +14,7 @@ module Spree
14
14
  @order.line_items.map do |line_item|
15
15
  # They go through multiple splits, avoid loading the
16
16
  # association to order until needed.
17
- Spree::InventoryUnit.new(
17
+ Spree::FulfillmentItem.new(
18
18
  pending: true,
19
19
  line_item_id: line_item.id,
20
20
  variant_id: line_item.variant_id,
@@ -35,8 +35,8 @@ module Spree
35
35
  next unless stock_location.stocks? variant
36
36
 
37
37
  on_hand, backordered = stock_location.fill_status(variant, unit.quantity)
38
- package.add(InventoryUnit.split(unit, backordered), :backordered) if backordered.positive?
39
- package.add(InventoryUnit.split(unit, on_hand), :on_hand) if on_hand.positive?
38
+ package.add(FulfillmentItem.split(unit, backordered), :backordered) if backordered.positive?
39
+ package.add(FulfillmentItem.split(unit, on_hand), :on_hand) if on_hand.positive?
40
40
  else
41
41
  package.add unit
42
42
  end
@@ -73,7 +73,7 @@ module Spree
73
73
  per_content_max_quantity = 1 if per_content_max_quantity.zero?
74
74
  content_items = [content_item]
75
75
  while content_item.quantity > per_content_max_quantity
76
- split_inventory = InventoryUnit.split(content_item.inventory_unit, per_content_max_quantity)
76
+ split_inventory = FulfillmentItem.split(content_item.inventory_unit, per_content_max_quantity)
77
77
  content_items << ContentItem.new(split_inventory, content_item.state)
78
78
  end
79
79
  content_items
@@ -17,6 +17,12 @@ module Spree
17
17
  LEGACY_EVENT_PREFIX = 'stock_item'
18
18
  LEGACY_EVENT_SUFFIXES = %w[created updated deleted].freeze
19
19
 
20
+ def self.included(base)
21
+ LEGACY_EVENT_SUFFIXES.each do |suffix|
22
+ base.publishes_event("#{LEGACY_EVENT_PREFIX}.#{suffix}", deprecated_alias_of: "#{base.event_prefix}.#{suffix}")
23
+ end
24
+ end
25
+
20
26
  # Wraps publishing rather than the three callbacks that call it, so the
21
27
  # decisions Publishable makes — whether events are enabled at all,
22
28
  # whether a touch-only update is worth announcing — are made once and the
@@ -38,7 +38,9 @@ module Spree
38
38
 
39
39
  self.whitelisted_ransackable_attributes = %w[count_on_hand allocated_count reserved_count incoming_count
40
40
  stock_location_id variant_id]
41
+ search_by :variant_sku, :variant_product_name
41
42
  self.whitelisted_ransackable_scopes = %w[with_stock_status]
43
+ self.ransackable_scope_types = { 'with_stock_status' => { list: 'text' } }
42
44
  self.whitelisted_ransackable_associations = %w[variant stock_location]
43
45
 
44
46
  scope :with_active_stock_location, -> { joins(:stock_location).merge(Spree::StockLocation.active) }
@@ -100,7 +102,7 @@ module Spree
100
102
  }
101
103
 
102
104
  def backordered_inventory_units
103
- Spree::InventoryUnit.backordered_for_stock_level(self)
105
+ Spree::FulfillmentItem.backordered_for_stock_level(self)
104
106
  end
105
107
 
106
108
  # @api private
@@ -50,6 +50,7 @@ module Spree
50
50
  country_code state_code created_at updated_at
51
51
  seller_id
52
52
  ]
53
+ search_by :name
53
54
  self.whitelisted_ransackable_associations = %w[seller]
54
55
 
55
56
  scope :active, -> { where(active: true) }
@@ -114,7 +114,7 @@ module Spree
114
114
  return default_adjustment_reason if reason.blank?
115
115
  return reason.to_s unless ADJUSTMENT_REASONS.include?(reason.to_s)
116
116
 
117
- Spree.t("stock_movement.reasons.#{reason}", locale: :en)
117
+ I18n.t("spree.stock_movement.reasons.#{reason}", locale: :en)
118
118
  end
119
119
 
120
120
  # A movement is an immutable audit row: once written, nothing may rewrite
@@ -29,7 +29,7 @@ module Spree
29
29
  def counts_something
30
30
  return if quantity_counted.positive?
31
31
 
32
- errors.add(:base, :nothing_counted, message: Spree.t('stock_receipt.errors.nothing_counted'))
32
+ errors.add(:base, :nothing_counted, message: I18n.t('spree.stock_receipt.errors.nothing_counted'))
33
33
  end
34
34
  end
35
35
  end
@@ -127,7 +127,7 @@ module Spree
127
127
  end
128
128
 
129
129
  def exactly_one_owner
130
- 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?
130
+ 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?
131
131
  end
132
132
 
133
133
  # Only a quantity change moves units between counters, so re-pointing a
@@ -135,7 +135,7 @@ module Spree
135
135
  # missing from the new. A hold that belongs elsewhere is released and
136
136
  # taken again, never moved.
137
137
  def stock_level_unchanged
138
- errors.add(:stock_level_id, :immutable, message: Spree.t('errors.messages.stock_level_immutable')) if stock_level_id_changed?
138
+ errors.add(:stock_level_id, :immutable, message: I18n.t('spree.errors.messages.stock_level_immutable')) if stock_level_id_changed?
139
139
  end
140
140
  end
141
141
  end
@@ -36,6 +36,8 @@ module Spree
36
36
  acts_as_paranoid
37
37
 
38
38
  publishes_lifecycle_events
39
+ publishes_events :canceled, :draft, :partially_received, :over_received, :ready_to_ship,
40
+ :received, :shipped
39
41
 
40
42
  has_status :draft, :ready_to_ship, :in_transit, :partially_received, :received, :over_received, :canceled,
41
43
  default: :draft
@@ -64,7 +66,9 @@ module Spree
64
66
  self.whitelisted_ransackable_attributes = %w[number status reference source_location_id
65
67
  destination_location_id shipped_at received_at
66
68
  closed_short_at created_at]
69
+ search_by :number, :reference
67
70
  self.whitelisted_ransackable_scopes = %w[open closed]
71
+ self.ransackable_scope_types = %w[open closed].index_with('boolean')
68
72
  self.whitelisted_ransackable_associations = %w[source_location destination_location items]
69
73
 
70
74
  # Whether the merchant may still edit the lines. Once the box is sealed and
@@ -97,7 +101,7 @@ module Spree
97
101
  return if source_location_id.blank? || destination_location_id.blank?
98
102
  return if source_location_id != destination_location_id
99
103
 
100
- errors.add(:source_location, :same_location, message: Spree.t('stock_transfer.errors.same_location'))
104
+ errors.add(:source_location, :same_location, message: I18n.t('spree.stock_transfer.errors.same_location'))
101
105
  end
102
106
 
103
107
  # A transfer moves a merchant's own stock between their own warehouses. Two
@@ -108,7 +112,7 @@ module Spree
108
112
  return if source_location.store_id == destination_location.store_id
109
113
 
110
114
  errors.add(:destination_location, :must_belong_to_same_store,
111
- message: Spree.t('stock_transfer.errors.locations_in_different_stores'))
115
+ message: I18n.t('spree.stock_transfer.errors.locations_in_different_stores'))
112
116
  end
113
117
  end
114
118
  end