spree_core 5.6.1 → 6.0.0.beta1

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 (1588) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +30 -0
  3. data/README.md +2 -3
  4. data/app/finders/spree/line_items/find_by_variant.rb +5 -3
  5. data/app/finders/spree/sellers/panel_url.rb +47 -0
  6. data/app/finders/spree/stores/dashboard_url.rb +76 -0
  7. data/app/helpers/spree/images_helper.rb +1 -1
  8. data/app/jobs/spree/carts/reap_expired_job.rb +43 -0
  9. data/app/jobs/spree/collections/regenerate_time_based_job.rb +18 -0
  10. data/app/jobs/spree/data_requests/process_job.rb +42 -0
  11. data/app/jobs/spree/events/subscriber_job.rb +1 -1
  12. data/app/jobs/spree/images/migrate_product_media_job.rb +80 -0
  13. data/app/jobs/spree/images/save_from_url_job.rb +70 -13
  14. data/app/jobs/spree/imports/create_categories_job.rb +23 -14
  15. data/app/jobs/spree/imports/create_rows_job.rb +3 -62
  16. data/app/jobs/spree/imports/process_group_job.rb +1 -1
  17. data/app/jobs/spree/imports/process_job.rb +164 -0
  18. data/app/jobs/spree/imports/process_rows_job.rb +4 -71
  19. data/app/jobs/spree/orders/finalize_stale_drafts_job.rb +29 -0
  20. data/app/jobs/spree/payments/handle_webhook_job.rb +1 -1
  21. data/app/jobs/spree/price_lists/sync_currencies_job.rb +42 -0
  22. data/app/jobs/spree/product_types/apply_to_products_job.rb +74 -0
  23. data/app/jobs/spree/products/auto_match_collections_job.rb +14 -0
  24. data/app/jobs/spree/products/auto_match_taxons_job.rb +6 -7
  25. data/app/jobs/spree/products/refresh_metrics_job.rb +1 -1
  26. data/app/jobs/spree/products/touch_categories_job.rb +15 -0
  27. data/app/jobs/spree/products/touch_taxons_job.rb +7 -6
  28. data/app/jobs/spree/seller_payouts/sweep_due_job.rb +57 -0
  29. data/app/jobs/spree/seller_payouts/sweep_seller_job.rb +70 -0
  30. data/app/jobs/spree/seller_transfers/execute_pending_due_job.rb +56 -0
  31. data/app/jobs/spree/seller_transfers/execute_pending_job.rb +52 -0
  32. data/app/jobs/spree/shipping_labels/store_file_job.rb +17 -0
  33. data/app/jobs/spree/stock_locations/stock_items/create_job.rb +7 -5
  34. data/app/jobs/spree/stock_locations/stock_levels/create_job.rb +13 -0
  35. data/app/jobs/spree/stock_reservations/expire_job.rb +1 -1
  36. data/app/jobs/spree/tax_identifiers/validate_job.rb +14 -0
  37. data/app/jobs/spree/variants/remove_line_item_job.rb +29 -1
  38. data/app/mailers/spree/admin_user_mailer.rb +6 -35
  39. data/app/mailers/spree/base_mailer.rb +1 -20
  40. data/app/mailers/spree/invitation_mailer.rb +1 -1
  41. data/app/mailers/spree/seller_user_mailer.rb +47 -0
  42. data/app/models/concerns/spree/account_lockout.rb +38 -0
  43. data/app/models/concerns/spree/admin_user_methods.rb +14 -34
  44. data/app/models/concerns/spree/calculated_adjustments.rb +8 -14
  45. data/app/models/concerns/spree/calculator/currency_amounts.rb +43 -0
  46. data/app/models/concerns/spree/capture_method.rb +33 -0
  47. data/app/models/concerns/spree/custom_field_filterable.rb +163 -0
  48. data/app/models/concerns/spree/customer_methods.rb +421 -0
  49. data/app/models/concerns/spree/deprecated_customer_alias.rb +22 -0
  50. data/app/models/concerns/spree/derived_number.rb +66 -0
  51. data/app/models/concerns/spree/has_address_book.rb +89 -0
  52. data/app/models/concerns/spree/has_custom_fields.rb +360 -0
  53. data/app/models/concerns/spree/has_external_references.rb +95 -0
  54. data/app/models/concerns/spree/has_iso_geography.rb +71 -0
  55. data/app/models/concerns/spree/has_library_media.rb +94 -0
  56. data/app/models/concerns/spree/has_list_position.rb +15 -0
  57. data/app/models/concerns/spree/has_number.rb +139 -0
  58. data/app/models/concerns/spree/has_status.rb +76 -0
  59. data/app/models/concerns/spree/has_tracking_carrier.rb +18 -0
  60. data/app/models/concerns/spree/instruments_gateway_calls.rb +20 -0
  61. data/app/models/concerns/spree/integration_backed_provider.rb +89 -0
  62. data/app/models/concerns/spree/integrations_concern.rb +15 -2
  63. data/app/models/concerns/spree/label_translatable.rb +37 -0
  64. data/app/models/concerns/spree/marketplace/order_group.rb +35 -0
  65. data/app/models/concerns/spree/metadata.rb +18 -22
  66. data/app/models/concerns/spree/named_type.rb +11 -1
  67. data/app/models/concerns/spree/parameterizable_name.rb +5 -5
  68. data/app/models/concerns/spree/password_policy.rb +37 -0
  69. data/app/models/concerns/spree/payment_session_transitions.rb +93 -0
  70. data/app/models/concerns/spree/payment_source_concern.rb +1 -1
  71. data/app/models/concerns/spree/personal_data_matching.rb +120 -0
  72. data/app/models/concerns/spree/preference_schema.rb +120 -19
  73. data/app/models/concerns/spree/prefixed_id.rb +25 -3
  74. data/app/models/concerns/spree/presentation_translatable.rb +4 -37
  75. data/app/models/concerns/spree/product_scopes.rb +51 -191
  76. data/app/models/concerns/spree/provider_failure_policy.rb +44 -0
  77. data/app/models/concerns/spree/publishable.rb +7 -7
  78. data/app/models/concerns/spree/purchase/addresses.rb +258 -0
  79. data/app/models/concerns/spree/purchase/channel.rb +19 -0
  80. data/app/models/concerns/spree/purchase/checkout_steps.rb +68 -0
  81. data/app/models/concerns/spree/purchase/company.rb +96 -0
  82. data/app/models/concerns/spree/purchase/currency.rb +29 -0
  83. data/app/models/concerns/spree/purchase/digital_items.rb +60 -0
  84. data/app/models/concerns/spree/purchase/freight.rb +52 -0
  85. data/app/models/concerns/spree/purchase/gift_cards.rb +70 -0
  86. data/app/models/concerns/spree/purchase/lifecycle.rb +53 -0
  87. data/app/models/concerns/spree/purchase/line_item_currencies.rb +38 -0
  88. data/app/models/concerns/spree/purchase/line_item_lookup.rb +25 -0
  89. data/app/models/concerns/spree/purchase/locale.rb +30 -0
  90. data/app/models/concerns/spree/purchase/market.rb +29 -0
  91. data/app/models/concerns/spree/purchase/payment_processing.rb +93 -0
  92. data/app/models/concerns/spree/purchase/purchase_order.rb +94 -0
  93. data/app/models/concerns/spree/purchase/quantity_rules.rb +136 -0
  94. data/app/models/concerns/spree/purchase/store_credits.rb +100 -0
  95. data/app/models/concerns/spree/purchase/taxation.rb +146 -0
  96. data/app/models/concerns/spree/purchase/totals.rb +116 -0
  97. data/app/models/concerns/spree/purchase/validations.rb +45 -0
  98. data/app/models/concerns/spree/receivable.rb +103 -0
  99. data/app/models/concerns/spree/receivable_item.rb +78 -0
  100. data/app/models/concerns/spree/refund_methods.rb +19 -0
  101. data/app/models/concerns/spree/sanitizable_rich_text.rb +109 -0
  102. data/app/models/concerns/spree/search_indexable.rb +5 -2
  103. data/app/models/concerns/spree/single_store_resource.rb +3 -1
  104. data/app/models/concerns/spree/store_data_sources.rb +75 -0
  105. data/app/models/concerns/spree/store_preferences.rb +49 -0
  106. data/app/models/concerns/spree/stores/markets.rb +75 -28
  107. data/app/models/concerns/spree/stores/setup.rb +10 -0
  108. data/app/models/concerns/spree/translatable_resource.rb +25 -6
  109. data/app/models/concerns/spree/typed_adjustment_line.rb +55 -0
  110. data/app/models/concerns/spree/user_address.rb +13 -3
  111. data/app/models/concerns/spree/user_management.rb +18 -6
  112. data/app/models/concerns/spree/user_methods.rb +5 -330
  113. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  114. data/app/models/concerns/spree/user_roles.rb +18 -11
  115. data/app/models/concerns/spree/validates_store_uniqueness.rb +53 -0
  116. data/app/models/concerns/spree/vat_price_calculation.rb +58 -6
  117. data/app/models/concerns/spree/webhook_payload_redaction.rb +1 -1
  118. data/app/models/spree/ability.rb +147 -43
  119. data/app/models/spree/address.rb +387 -118
  120. data/app/models/spree/adjusters/base.rb +26 -0
  121. data/app/models/spree/adjusters/largest_remainder.rb +24 -0
  122. data/app/models/spree/adjusters/promotion.rb +253 -0
  123. data/app/models/spree/admin_user.rb +26 -0
  124. data/app/models/spree/allowed_origin.rb +1 -1
  125. data/app/models/spree/api_key.rb +29 -28
  126. data/app/models/spree/asset.rb +14 -211
  127. data/app/models/spree/authentication/strategies/base_strategy.rb +54 -3
  128. data/app/models/spree/authentication/strategies/email_password_strategy.rb +11 -3
  129. data/app/models/spree/authentication/strategies/oidc_strategy.rb +330 -0
  130. data/app/models/spree/authentication/strategy_registry.rb +83 -0
  131. data/app/models/spree/base.rb +83 -12
  132. data/app/models/spree/base_analytics_event_handler.rb +1 -1
  133. data/app/models/spree/calculator/shipping/digital_delivery.rb +5 -2
  134. data/app/models/spree/calculator/shipping/flat_rate.rb +10 -5
  135. data/app/models/spree/calculator/shipping/flexi_rate.rb +6 -0
  136. data/app/models/spree/calculator/shipping/per_item.rb +8 -3
  137. data/app/models/spree/calculator/shipping/price_sack.rb +6 -0
  138. data/app/models/spree/calculator/tiered_flat_rate.rb +5 -1
  139. data/app/models/spree/calculator.rb +10 -0
  140. data/app/models/spree/cart.rb +285 -0
  141. data/app/models/spree/carts/item_warning.rb +28 -0
  142. data/app/models/spree/carts/resolved_item.rb +37 -0
  143. data/app/models/spree/catalog.rb +466 -0
  144. data/app/models/spree/catalog_assignment.rb +41 -0
  145. data/app/models/spree/catalog_order_minimum.rb +26 -0
  146. data/app/models/spree/catalog_price.rb +100 -0
  147. data/app/models/spree/catalog_price_tier.rb +36 -0
  148. data/app/models/spree/catalog_product.rb +23 -0
  149. data/app/models/spree/catalog_quantity_rule.rb +46 -0
  150. data/app/models/spree/catalogs/product_term.rb +43 -0
  151. data/app/models/spree/category.rb +430 -12
  152. data/app/models/spree/channel/gating.rb +1 -2
  153. data/app/models/spree/channel.rb +38 -4
  154. data/app/models/spree/channel_stock_location.rb +8 -0
  155. data/app/models/spree/checkout/default_requirements.rb +105 -22
  156. data/app/models/spree/checkout/registry.rb +64 -12
  157. data/app/models/spree/checkout/requirement.rb +9 -9
  158. data/app/models/spree/checkout/requirements.rb +25 -20
  159. data/app/models/spree/checkout/step.rb +12 -12
  160. data/app/models/spree/claim.rb +68 -0
  161. data/app/models/spree/claim_line_item.rb +46 -0
  162. data/app/models/spree/claim_reason.rb +24 -0
  163. data/app/models/spree/classification.rb +7 -49
  164. data/app/models/spree/collection.rb +269 -0
  165. data/app/models/spree/collection_rule.rb +58 -0
  166. data/app/models/spree/collection_rules/available_on.rb +21 -0
  167. data/app/models/spree/collection_rules/sale.rb +18 -0
  168. data/app/models/spree/collection_rules/tag.rb +21 -0
  169. data/app/models/spree/commission_line.rb +85 -0
  170. data/app/models/spree/commission_rate.rb +370 -0
  171. data/app/models/spree/commission_rate_value.rb +47 -0
  172. data/app/models/spree/commission_rule.rb +77 -0
  173. data/app/models/spree/commission_rule_product.rb +19 -0
  174. data/app/models/spree/commission_rules/category_rule.rb +33 -0
  175. data/app/models/spree/commission_rules/item_total_rule.rb +31 -0
  176. data/app/models/spree/commission_rules/product_rule.rb +55 -0
  177. data/app/models/spree/commission_rules/seller_rule.rb +33 -0
  178. data/app/models/spree/commission_tax.rb +51 -0
  179. data/app/models/spree/commissions/context.rb +71 -0
  180. data/app/models/spree/company.rb +347 -0
  181. data/app/models/spree/company_invitation.rb +81 -0
  182. data/app/models/spree/company_membership.rb +25 -0
  183. data/app/models/spree/consent_record.rb +125 -0
  184. data/app/models/spree/country.rb +128 -52
  185. data/app/models/spree/coupon_code.rb +18 -5
  186. data/app/models/spree/credit_card.rb +10 -9
  187. data/app/models/spree/current.rb +124 -18
  188. data/app/models/spree/custom_field.rb +160 -7
  189. data/app/models/spree/custom_field_definition/search_capabilities.rb +98 -0
  190. data/app/models/spree/custom_field_definition.rb +219 -5
  191. data/app/models/spree/custom_fields/boolean.rb +15 -0
  192. data/app/models/spree/custom_fields/json.rb +38 -0
  193. data/app/models/spree/custom_fields/long_text.rb +11 -0
  194. data/app/models/spree/custom_fields/number.rb +23 -0
  195. data/app/models/spree/custom_fields/rich_text.rb +23 -0
  196. data/app/models/spree/custom_fields/short_text.rb +15 -0
  197. data/app/models/spree/customer.rb +34 -0
  198. data/app/models/spree/customer_group.rb +12 -12
  199. data/app/models/spree/customer_group_user.rb +6 -4
  200. data/app/models/spree/data_feed.rb +1 -1
  201. data/app/models/spree/data_request.rb +98 -0
  202. data/app/models/spree/delivery.rb +169 -0
  203. data/app/models/spree/delivery_method.rb +566 -0
  204. data/app/models/spree/delivery_method_rule.rb +55 -0
  205. data/app/models/spree/delivery_method_rule_product.rb +8 -0
  206. data/app/models/spree/delivery_method_rules/channel_rule.rb +41 -0
  207. data/app/models/spree/delivery_method_rules/company_rule.rb +24 -0
  208. data/app/models/spree/delivery_method_rules/excluded_products_rule.rb +48 -0
  209. data/app/models/spree/delivery_method_rules/item_total_rule.rb +19 -0
  210. data/app/models/spree/delivery_method_rules/volume_rule.rb +35 -0
  211. data/app/models/spree/delivery_method_rules/weight_rule.rb +19 -0
  212. data/app/models/spree/delivery_method_service.rb +24 -0
  213. data/app/models/spree/delivery_method_stock_location.rb +11 -0
  214. data/app/models/spree/delivery_origin_group.rb +73 -0
  215. data/app/models/spree/delivery_origin_group_location.rb +9 -0
  216. data/app/models/spree/delivery_profile.rb +141 -0
  217. data/app/models/spree/delivery_profiles/digital.rb +20 -0
  218. data/app/models/spree/delivery_profiles/shipping.rb +12 -0
  219. data/app/models/spree/delivery_rate.rb +164 -0
  220. data/app/models/spree/delivery_rate_provider/base.rb +120 -0
  221. data/app/models/spree/delivery_rate_provider/estimate.rb +44 -0
  222. data/app/models/spree/delivery_rate_provider/freight.rb +41 -0
  223. data/app/models/spree/delivery_rate_provider/internal.rb +28 -0
  224. data/app/models/spree/delivery_rate_provider/service_catalog.rb +48 -0
  225. data/app/models/spree/delivery_zone.rb +64 -0
  226. data/app/models/spree/delivery_zone_member.rb +98 -0
  227. data/app/models/spree/digital.rb +12 -16
  228. data/app/models/spree/digital_asset.rb +144 -0
  229. data/app/models/spree/digital_asset_provider/base.rb +95 -0
  230. data/app/models/spree/digital_asset_provider/file.rb +20 -0
  231. data/app/models/spree/digital_delivery.rb +28 -0
  232. data/app/models/spree/digital_link.rb +31 -11
  233. data/app/models/spree/discount.rb +51 -0
  234. data/app/models/spree/event.rb +6 -6
  235. data/app/models/spree/exchange.rb +49 -44
  236. data/app/models/spree/exchange_line_item.rb +52 -0
  237. data/app/models/spree/export.rb +128 -21
  238. data/app/models/spree/exports/customers.rb +2 -2
  239. data/app/models/spree/exports/gift_cards.rb +2 -2
  240. data/app/models/spree/exports/newsletter_subscribers.rb +2 -2
  241. data/app/models/spree/exports/orders.rb +35 -5
  242. data/app/models/spree/exports/price_list_prices.rb +107 -0
  243. data/app/models/spree/exports/products.rb +4 -4
  244. data/app/models/spree/exports/purchase_orders.rb +39 -0
  245. data/app/models/spree/exports/report.rb +95 -0
  246. data/app/models/spree/external_reference.rb +77 -0
  247. data/app/models/spree/external_video.rb +117 -0
  248. data/app/models/spree/fee.rb +40 -0
  249. data/app/models/spree/freight_summary/line.rb +257 -0
  250. data/app/models/spree/freight_summary.rb +180 -0
  251. data/app/models/spree/fulfillment/custom_events.rb +96 -0
  252. data/app/models/spree/fulfillment.rb +973 -0
  253. data/app/models/spree/fulfillment_changer.rb +170 -0
  254. data/app/models/spree/fulfillment_item.rb +148 -0
  255. data/app/models/spree/fulfillment_provider/base.rb +130 -0
  256. data/app/models/spree/fulfillment_provider/digital.rb +44 -0
  257. data/app/models/spree/fulfillment_provider/manual.rb +15 -0
  258. data/app/models/spree/fulfillment_provider/pickup.rb +38 -0
  259. data/app/models/spree/fulfillment_provider/pickup_point.rb +24 -0
  260. data/app/models/spree/fulfilment_changer.rb +3 -164
  261. data/app/models/spree/gateway/bogus.rb +5 -4
  262. data/app/models/spree/gateway/custom_payment_source_method.rb +5 -5
  263. data/app/models/spree/gateway.rb +2 -2
  264. data/app/models/spree/gateway_customer.rb +12 -4
  265. data/app/models/spree/gift_card.rb +140 -48
  266. data/app/models/spree/gift_card_batch.rb +2 -2
  267. data/app/models/spree/import.rb +136 -98
  268. data/app/models/spree/import_mapping.rb +1 -1
  269. data/app/models/spree/import_row.rb +35 -31
  270. data/app/models/spree/import_schemas/price_list_prices.rb +13 -0
  271. data/app/models/spree/import_schemas/products.rb +8 -1
  272. data/app/models/spree/import_schemas/purchase_orders.rb +19 -0
  273. data/app/models/spree/imports/price_list_prices.rb +72 -0
  274. data/app/models/spree/imports/purchase_orders.rb +28 -0
  275. data/app/models/spree/integration.rb +128 -5
  276. data/app/models/spree/inventory_provider/base.rb +30 -0
  277. data/app/models/spree/inventory_provider/internal.rb +22 -0
  278. data/app/models/spree/inventory_unit.rb +3 -139
  279. data/app/models/spree/invitation.rb +53 -47
  280. data/app/models/spree/label_purchase.rb +29 -0
  281. data/app/models/spree/line_item.rb +239 -105
  282. data/app/models/spree/market.rb +106 -15
  283. data/app/models/spree/market_country.rb +10 -5
  284. data/app/models/spree/media.rb +497 -0
  285. data/app/models/spree/media_usage_reference.rb +27 -0
  286. data/app/models/spree/metafield.rb +14 -102
  287. data/app/models/spree/metafield_definition.rb +11 -128
  288. data/app/models/spree/metafields.rb +32 -0
  289. data/app/models/spree/newsletter_subscriber.rb +10 -9
  290. data/app/models/spree/number_generators/base.rb +56 -0
  291. data/app/models/spree/number_generators/random.rb +23 -0
  292. data/app/models/spree/number_generators/sequential.rb +88 -0
  293. data/app/models/spree/number_sequence.rb +86 -0
  294. data/app/models/spree/option_type.rb +18 -32
  295. data/app/models/spree/option_type_product_type.rb +8 -0
  296. data/app/models/spree/option_value.rb +19 -13
  297. data/app/models/spree/option_value_variant.rb +0 -1
  298. data/app/models/spree/order.rb +628 -571
  299. data/app/models/spree/order_cancellation_reason.rb +25 -0
  300. data/app/models/spree/order_group.rb +244 -0
  301. data/app/models/spree/order_inventory.rb +42 -33
  302. data/app/models/spree/order_merger.rb +11 -6
  303. data/app/models/spree/order_promotion.rb +32 -6
  304. data/app/models/spree/order_routing/has_strategy_preference.rb +1 -2
  305. data/app/models/spree/order_routing/rules/minimize_splits.rb +6 -6
  306. data/app/models/spree/order_routing/strategy/rules.rb +12 -8
  307. data/app/models/spree/order_routing_rule.rb +5 -15
  308. data/app/models/spree/order_updater.rb +131 -163
  309. data/app/models/spree/package_type.rb +191 -0
  310. data/app/models/spree/payment/custom_events.rb +52 -5
  311. data/app/models/spree/payment/gateway_options.rb +20 -5
  312. data/app/models/spree/payment/processing.rb +95 -116
  313. data/app/models/spree/payment.rb +299 -123
  314. data/app/models/spree/payment_method/check.rb +4 -3
  315. data/app/models/spree/payment_method/session_instrumentation.rb +34 -0
  316. data/app/models/spree/payment_method/store_credit.rb +4 -2
  317. data/app/models/spree/payment_method.rb +106 -9
  318. data/app/models/spree/payment_session.rb +150 -53
  319. data/app/models/spree/payment_setup_session.rb +4 -37
  320. data/app/models/spree/payment_source.rb +5 -4
  321. data/app/models/spree/payment_split.rb +90 -0
  322. data/app/models/spree/payout_provider/base.rb +218 -0
  323. data/app/models/spree/payout_provider/system.rb +36 -0
  324. data/app/models/spree/permission_sets.rb +17 -0
  325. data/app/models/spree/pickup_point_option.rb +28 -0
  326. data/app/models/spree/pickup_point_provider/base.rb +24 -0
  327. data/app/models/spree/policy.rb +12 -11
  328. data/app/models/spree/price.rb +91 -5
  329. data/app/models/spree/price_adjustment_tier.rb +63 -0
  330. data/app/models/spree/price_history.rb +1 -1
  331. data/app/models/spree/price_list.rb +266 -142
  332. data/app/models/spree/price_rule.rb +51 -7
  333. data/app/models/spree/price_rules/channel_rule.rb +3 -0
  334. data/app/models/spree/price_rules/customer_group_rule.rb +10 -1
  335. data/app/models/spree/price_rules/market_rule.rb +6 -0
  336. data/app/models/spree/price_rules/user_rule.rb +12 -3
  337. data/app/models/spree/price_rules/volume_rule.rb +6 -0
  338. data/app/models/spree/price_rules/zone_rule.rb +5 -13
  339. data/app/models/spree/pricing_provider/base.rb +51 -0
  340. data/app/models/spree/pricing_provider/internal.rb +255 -0
  341. data/app/models/spree/pricing_provider.rb +28 -0
  342. data/app/models/spree/product.rb +528 -544
  343. data/app/models/spree/product_category.rb +65 -0
  344. data/app/models/spree/product_collection.rb +20 -0
  345. data/app/models/spree/product_option_type.rb +0 -1
  346. data/app/models/spree/product_promotion_rule.rb +0 -1
  347. data/app/models/spree/product_publication.rb +0 -1
  348. data/app/models/spree/product_submission.rb +72 -0
  349. data/app/models/spree/product_type.rb +116 -0
  350. data/app/models/spree/product_type_category.rb +8 -0
  351. data/app/models/spree/product_type_custom_field_definition.rb +39 -0
  352. data/app/models/spree/promotion/actions/create_adjustment.rb +9 -7
  353. data/app/models/spree/promotion/actions/create_item_adjustments.rb +11 -16
  354. data/app/models/spree/promotion/actions/create_line_items.rb +19 -8
  355. data/app/models/spree/promotion/actions/free_shipping.rb +12 -18
  356. data/app/models/spree/promotion/rules/category.rb +181 -0
  357. data/app/models/spree/promotion/rules/channel.rb +3 -3
  358. data/app/models/spree/promotion/rules/country.rb +43 -17
  359. data/app/models/spree/promotion/rules/currency.rb +2 -2
  360. data/app/models/spree/promotion/rules/customer_group.rb +13 -5
  361. data/app/models/spree/promotion/rules/first_order.rb +3 -3
  362. data/app/models/spree/promotion/rules/item_total.rb +2 -2
  363. data/app/models/spree/promotion/rules/market.rb +3 -3
  364. data/app/models/spree/promotion/rules/one_use_per_user.rb +4 -4
  365. data/app/models/spree/promotion/rules/option_value.rb +34 -11
  366. data/app/models/spree/promotion/rules/product.rb +3 -5
  367. data/app/models/spree/promotion/rules/taxon.rb +10 -131
  368. data/app/models/spree/promotion/rules/user.rb +14 -22
  369. data/app/models/spree/promotion/rules/user_logged_in.rb +3 -3
  370. data/app/models/spree/promotion.rb +59 -21
  371. data/app/models/spree/promotion_action.rb +52 -11
  372. data/app/models/spree/promotion_action_line_item.rb +1 -1
  373. data/app/models/spree/promotion_handler/coupon.rb +44 -16
  374. data/app/models/spree/promotion_handler/free_shipping.rb +1 -1
  375. data/app/models/spree/promotion_handler/promotion_duplicator.rb +1 -1
  376. data/app/models/spree/promotion_rule.rb +2 -9
  377. data/app/models/spree/promotion_rule_category.rb +22 -0
  378. data/app/models/spree/promotion_rule_taxon.rb +7 -6
  379. data/app/models/spree/promotion_rule_user.rb +2 -2
  380. data/app/models/spree/prototype.rb +3 -13
  381. data/app/models/spree/purchase_order.rb +95 -0
  382. data/app/models/spree/purchase_order_item.rb +40 -0
  383. data/app/models/spree/quantity_rule.rb +114 -0
  384. data/app/models/spree/refresh_token.rb +20 -2
  385. data/app/models/spree/refund.rb +94 -41
  386. data/app/models/spree/refund_reason.rb +32 -11
  387. data/app/models/spree/return.rb +150 -0
  388. data/app/models/spree/return_authorization_reason.rb +11 -6
  389. data/app/models/spree/return_line_item.rb +42 -0
  390. data/app/models/spree/return_reason.rb +26 -0
  391. data/app/models/spree/rich_text_sanitizer.rb +99 -0
  392. data/app/models/spree/role.rb +179 -4
  393. data/app/models/spree/role_user.rb +5 -21
  394. data/app/models/spree/saved_report.rb +56 -0
  395. data/app/models/spree/search_provider/base.rb +8 -2
  396. data/app/models/spree/search_provider/database.rb +73 -22
  397. data/app/models/spree/search_provider.rb +29 -0
  398. data/app/models/spree/seller.rb +475 -0
  399. data/app/models/spree/seller_balance.rb +86 -0
  400. data/app/models/spree/seller_payout.rb +116 -0
  401. data/app/models/spree/seller_requirement.rb +274 -0
  402. data/app/models/spree/seller_requirement_custom_field.rb +38 -0
  403. data/app/models/spree/seller_requirement_status.rb +144 -0
  404. data/app/models/spree/seller_requirement_submission.rb +91 -0
  405. data/app/models/spree/seller_requirements/accept_terms.rb +104 -0
  406. data/app/models/spree/seller_requirements/attestation.rb +22 -0
  407. data/app/models/spree/seller_requirements/billing_address.rb +13 -0
  408. data/app/models/spree/seller_requirements/complete_profile.rb +26 -0
  409. data/app/models/spree/seller_requirements/delivery_method.rb +20 -0
  410. data/app/models/spree/seller_requirements/document.rb +62 -0
  411. data/app/models/spree/seller_requirements/minimum_products.rb +20 -0
  412. data/app/models/spree/seller_requirements/operator_review.rb +23 -0
  413. data/app/models/spree/seller_requirements/package_type.rb +40 -0
  414. data/app/models/spree/seller_requirements/payout_account.rb +55 -0
  415. data/app/models/spree/seller_requirements/policy.rb +43 -0
  416. data/app/models/spree/seller_requirements/required_custom_fields.rb +56 -0
  417. data/app/models/spree/seller_requirements/returns_address.rb +19 -0
  418. data/app/models/spree/seller_transfer.rb +166 -0
  419. data/app/models/spree/setup_tasks.rb +3 -6
  420. data/app/models/spree/shipment.rb +3 -560
  421. data/app/models/spree/shipping_calculator.rb +7 -0
  422. data/app/models/spree/shipping_document.rb +32 -0
  423. data/app/models/spree/shipping_label.rb +146 -0
  424. data/app/models/spree/shipping_method.rb +3 -146
  425. data/app/models/spree/shipping_rate.rb +3 -97
  426. data/app/models/spree/state.rb +57 -23
  427. data/app/models/spree/stock/availability_validator.rb +1 -1
  428. data/app/models/spree/stock/content_item.rb +1 -0
  429. data/app/models/spree/stock/coordinator.rb +69 -9
  430. data/app/models/spree/stock/estimator.rb +198 -33
  431. data/app/models/spree/stock/inventory_unit_builder.rb +6 -1
  432. data/app/models/spree/stock/package.rb +145 -14
  433. data/app/models/spree/stock/packer.rb +20 -3
  434. data/app/models/spree/stock/prioritizer.rb +27 -4
  435. data/app/models/spree/stock/quantifier.rb +63 -38
  436. data/app/models/spree/stock/splitter/base.rb +3 -1
  437. data/app/models/spree/stock/splitter/delivery_profile.rb +41 -0
  438. data/app/models/spree/stock_item.rb +3 -147
  439. data/app/models/spree/stock_level/custom_events.rb +48 -0
  440. data/app/models/spree/stock_level.rb +305 -0
  441. data/app/models/spree/stock_location.rb +165 -87
  442. data/app/models/spree/stock_movement/custom_events.rb +1 -1
  443. data/app/models/spree/stock_movement.rb +166 -22
  444. data/app/models/spree/stock_receipt.rb +56 -0
  445. data/app/models/spree/stock_receipt_item.rb +35 -0
  446. data/app/models/spree/stock_reservation.rb +114 -11
  447. data/app/models/spree/stock_transfer.rb +84 -59
  448. data/app/models/spree/stock_transfer_item.rb +25 -0
  449. data/app/models/spree/store.rb +427 -107
  450. data/app/models/spree/store_credit.rb +88 -21
  451. data/app/models/spree/store_credit_category.rb +21 -28
  452. data/app/models/spree/store_credit_event.rb +1 -1
  453. data/app/models/spree/store_credit_type.rb +10 -2
  454. data/app/models/spree/store_payment_method.rb +0 -1
  455. data/app/models/spree/store_product.rb +2 -2
  456. data/app/models/spree/store_promotion.rb +0 -1
  457. data/app/models/spree/storefront/access_denied.rb +22 -0
  458. data/app/models/spree/storefront/access_policy.rb +180 -0
  459. data/app/models/spree/subscriber.rb +6 -6
  460. data/app/models/spree/supplier.rb +76 -0
  461. data/app/models/spree/tax_category.rb +15 -5
  462. data/app/models/spree/tax_exemption/item_override.rb +22 -0
  463. data/app/models/spree/tax_exemption.rb +81 -0
  464. data/app/models/spree/tax_exemption_certificate.rb +95 -0
  465. data/app/models/spree/tax_identifier.rb +209 -0
  466. data/app/models/spree/tax_identifiers/validation_result.rb +41 -0
  467. data/app/models/spree/tax_identifiers/validator/base.rb +53 -0
  468. data/app/models/spree/tax_identifiers/validator/eu_vat.rb +76 -0
  469. data/app/models/spree/tax_line.rb +79 -0
  470. data/app/models/spree/tax_provider/base.rb +150 -0
  471. data/app/models/spree/tax_provider/internal.rb +227 -0
  472. data/app/models/spree/tax_rate.rb +63 -100
  473. data/app/models/spree/taxon.rb +13 -514
  474. data/app/models/spree/taxon_rule.rb +8 -9
  475. data/app/models/spree/taxonomy.rb +8 -42
  476. data/app/models/spree/user_identity.rb +2 -2
  477. data/app/models/spree/variant.rb +629 -150
  478. data/app/models/spree/variant_media.rb +6 -7
  479. data/app/models/spree/webhook_endpoint.rb +2 -1
  480. data/app/models/spree/wished_item.rb +3 -31
  481. data/app/models/spree/wishlist.rb +17 -10
  482. data/app/models/spree/wishlist_item/custom_events.rb +42 -0
  483. data/app/models/spree/wishlist_item.rb +37 -0
  484. data/app/models/spree/zone.rb +24 -182
  485. data/app/models/spree/zone_member.rb +5 -8
  486. data/app/presenters/spree/csv/custom_fields_helper.rb +25 -0
  487. data/app/presenters/spree/csv/customer_presenter.rb +7 -6
  488. data/app/presenters/spree/csv/gift_card_presenter.rb +9 -8
  489. data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +7 -6
  490. data/app/presenters/spree/csv/order_line_item_presenter.rb +53 -21
  491. data/app/presenters/spree/csv/price_list_price_presenter.rb +41 -0
  492. data/app/presenters/spree/csv/product_variant_presenter.rb +22 -21
  493. data/app/presenters/spree/csv/purchase_order_item_presenter.rb +50 -0
  494. data/app/presenters/spree/data_feeds/google_presenter.rb +24 -10
  495. data/app/presenters/spree/filters/options_presenter.rb +2 -2
  496. data/app/services/spree/addresses/create.rb +70 -27
  497. data/app/services/spree/addresses/helper.rb +17 -54
  498. data/app/services/spree/addresses/update.rb +53 -31
  499. data/app/services/spree/carts/associate.rb +46 -0
  500. data/app/services/spree/carts/check_availability.rb +72 -0
  501. data/app/services/spree/carts/create.rb +7 -1
  502. data/app/services/spree/carts/destroy.rb +71 -0
  503. data/app/services/spree/carts/empty.rb +42 -0
  504. data/app/services/spree/carts/partition_by_seller.rb +71 -0
  505. data/app/services/spree/carts/price_items.rb +119 -0
  506. data/app/services/spree/carts/remove_item.rb +42 -0
  507. data/app/services/spree/carts/remove_line_item.rb +42 -0
  508. data/app/services/spree/carts/remove_out_of_stock_items.rb +104 -0
  509. data/app/services/spree/carts/set_quantity.rb +39 -0
  510. data/app/services/spree/carts/split_by_seller.rb +475 -0
  511. data/app/services/spree/carts/update.rb +157 -51
  512. data/app/services/spree/catalogs/resolve_prices.rb +192 -0
  513. data/app/services/spree/catalogs/resolve_quantity_rules.rb +115 -0
  514. data/app/services/spree/catalogs/set_assignments.rb +59 -0
  515. data/app/services/spree/catalogs/set_order_minimums.rb +44 -0
  516. data/app/services/spree/catalogs/set_product_terms.rb +83 -0
  517. data/app/services/spree/categories/add_products.rb +51 -0
  518. data/app/services/spree/categories/remove_products.rb +72 -0
  519. data/app/services/spree/checkout/add_store_credit.rb +11 -79
  520. data/app/services/spree/checkout/advance.rb +38 -38
  521. data/app/services/spree/checkout/remove_store_credit.rb +7 -12
  522. data/app/services/spree/collections/add_products.rb +42 -0
  523. data/app/services/spree/collections/regenerate_products.rb +67 -0
  524. data/app/services/spree/collections/remove_products.rb +65 -0
  525. data/app/services/spree/commissions/calculate_line.rb +132 -0
  526. data/app/services/spree/commissions/commission_order.rb +185 -0
  527. data/app/services/spree/commissions/resolve_rate.rb +114 -0
  528. data/app/services/spree/commissions/resolve_tax_rate.rb +78 -0
  529. data/app/services/spree/companies/add_member.rb +38 -0
  530. data/app/services/spree/company_invitations/accept.rb +60 -0
  531. data/app/services/spree/coupon_codes/coupon_codes_handler.rb +14 -2
  532. data/app/services/spree/customers/data_export.rb +372 -0
  533. data/app/services/spree/data_requests/create.rb +77 -0
  534. data/app/services/spree/deliveries/create.rb +56 -0
  535. data/app/services/spree/deliveries/destroy.rb +39 -0
  536. data/app/services/spree/deliveries/upsert_primary.rb +43 -0
  537. data/app/services/spree/fulfillments/recalculate_delivery.rb +62 -0
  538. data/app/services/spree/fulfillments/stand_down_provider.rb +47 -0
  539. data/app/services/spree/imports/row_processors/customer.rb +8 -8
  540. data/app/services/spree/imports/row_processors/price_list_price.rb +164 -0
  541. data/app/services/spree/imports/row_processors/product_variant.rb +193 -57
  542. data/app/services/spree/imports/row_processors/purchase_order.rb +157 -0
  543. data/app/services/spree/media/destroy.rb +88 -0
  544. data/app/services/spree/media/usage.rb +175 -0
  545. data/app/services/spree/newsletter/link_user.rb +4 -3
  546. data/app/services/spree/newsletter/subscribe.rb +3 -3
  547. data/app/services/spree/newsletter/verify.rb +6 -2
  548. data/app/services/spree/order_groups/allocate_payments.rb +101 -0
  549. data/app/services/spree/orders/approve.rb +9 -23
  550. data/app/services/spree/orders/build_fulfillments.rb +29 -0
  551. data/app/services/spree/orders/create.rb +38 -17
  552. data/app/services/spree/orders/create_from_cart.rb +88 -0
  553. data/app/services/spree/orders/create_user_account.rb +14 -67
  554. data/app/services/spree/orders/discounts/create.rb +84 -0
  555. data/app/services/spree/orders/discounts/destroy.rb +25 -0
  556. data/app/services/spree/orders/discounts/update.rb +29 -0
  557. data/app/services/spree/orders/fees/create.rb +28 -0
  558. data/app/services/spree/orders/fees/destroy.rb +22 -0
  559. data/app/services/spree/orders/fees/update.rb +25 -0
  560. data/app/services/spree/orders/remove_item.rb +13 -0
  561. data/app/services/spree/orders/remove_line_item.rb +13 -0
  562. data/app/services/spree/orders/update.rb +56 -11
  563. data/app/services/spree/orders/update_item.rb +105 -0
  564. data/app/services/spree/orders/update_statuses.rb +109 -0
  565. data/app/services/spree/payments/create.rb +31 -5
  566. data/app/services/spree/prices/bulk_upsert.rb +156 -30
  567. data/app/services/spree/product_submissions/close.rb +46 -0
  568. data/app/services/spree/product_types/apply_to_products.rb +167 -0
  569. data/app/services/spree/products/auto_match_collections.rb +75 -0
  570. data/app/services/spree/products/auto_match_taxons.rb +7 -54
  571. data/app/services/spree/products/duplicator.rb +16 -22
  572. data/app/services/spree/products/for_context.rb +54 -0
  573. data/app/services/spree/products/select_buy_box.rb +98 -0
  574. data/app/services/spree/purchases/amount_due_at_checkout.rb +33 -0
  575. data/app/services/spree/returns/eligibility_validator.rb +53 -0
  576. data/app/services/spree/sample_data/helper.rb +3 -3
  577. data/app/services/spree/sample_data/import_builder.rb +8 -4
  578. data/app/services/spree/sample_data/import_runner.rb +7 -4
  579. data/app/services/spree/sample_data/loader.rb +15 -6
  580. data/app/services/spree/search_provider/custom_field_schema.rb +153 -0
  581. data/app/services/spree/seeds/admin_user.rb +72 -12
  582. data/app/services/spree/seeds/all.rb +24 -13
  583. data/app/services/spree/seeds/commission_rates.rb +53 -0
  584. data/app/services/spree/seeds/digital_delivery.rb +18 -8
  585. data/app/services/spree/seeds/product_types.rb +23 -0
  586. data/app/services/spree/seeds/returns_environment.rb +44 -16
  587. data/app/services/spree/seeds/roles.rb +6 -1
  588. data/app/services/spree/seeds/saved_reports.rb +107 -0
  589. data/app/services/spree/seeds/seller_requirements.rb +19 -0
  590. data/app/services/spree/seeds/stores.rb +1 -1
  591. data/app/services/spree/seeds/tax_categories.rb +9 -2
  592. data/app/services/spree/sellers/requirements.rb +129 -0
  593. data/app/services/spree/shipments/update.rb +4 -33
  594. data/app/services/spree/shipping_labels/confirm_refund.rb +47 -0
  595. data/app/services/spree/shipping_labels/store_file.rb +68 -0
  596. data/app/services/spree/stock_levels/bulk_upsert.rb +67 -0
  597. data/app/services/spree/stock_levels/correct.rb +69 -0
  598. data/app/services/spree/stock_levels/recount.rb +103 -0
  599. data/app/services/spree/stock_locations/stock_items/create.rb +8 -13
  600. data/app/services/spree/stock_locations/stock_levels/create.rb +25 -0
  601. data/app/services/spree/stock_reservations/extend.rb +9 -5
  602. data/app/services/spree/stock_reservations/release.rb +4 -3
  603. data/app/services/spree/stock_reservations/reserve.rb +43 -32
  604. data/app/services/spree/store_credits/apply.rb +93 -0
  605. data/app/services/spree/store_credits/remove.rb +17 -0
  606. data/app/services/spree/stores/provision_defaults.rb +269 -0
  607. data/app/services/spree/tax/resolve_exemptions.rb +44 -0
  608. data/app/services/spree/tax/unusable_exemption_error.rb +8 -0
  609. data/app/services/spree/tax_identifiers/validate.rb +77 -0
  610. data/app/services/spree/taxons/add_products.rb +6 -39
  611. data/app/services/spree/taxons/regenerate_products.rb +8 -53
  612. data/app/services/spree/taxons/remove_products.rb +6 -60
  613. data/app/services/spree/variants/remove_line_items.rb +6 -1
  614. data/app/subscribers/spree/event_log_subscriber.rb +1 -1
  615. data/app/subscribers/spree/order_commission_subscriber.rb +23 -0
  616. data/app/subscribers/spree/order_placed_subscriber.rb +58 -0
  617. data/app/subscribers/spree/order_status_subscriber.rb +82 -0
  618. data/app/subscribers/spree/payment_split_subscriber.rb +71 -0
  619. data/app/subscribers/spree/product_metrics_subscriber.rb +2 -2
  620. data/app/subscribers/spree/seller_onboarding_subscriber.rb +32 -0
  621. data/app/subscribers/spree/seller_transfer_reversal_subscriber.rb +26 -0
  622. data/app/subscribers/spree/seller_transfer_subscriber.rb +26 -0
  623. data/app/subscribers/spree/seller_user_email_subscriber.rb +27 -0
  624. data/app/subscribers/spree/tax_identifier_validation_subscriber.rb +26 -0
  625. data/app/validators/spree/addresses/phone_validator.rb +2 -2
  626. data/app/validators/spree/attachment_content_type_validator.rb +183 -0
  627. data/app/validators/spree/password_length_validator.rb +23 -0
  628. data/app/views/spree/seller_user_mailer/password_reset_email.html.erb +8 -0
  629. data/app/views/spree/shared/_purchased_items_styles.html.erb +7 -0
  630. data/app/workflows/spree/carts/add_item.rb +234 -0
  631. data/app/workflows/spree/carts/complete.rb +516 -0
  632. data/app/workflows/spree/carts/merge.rb +90 -0
  633. data/app/workflows/spree/carts/recalculate.rb +54 -0
  634. data/app/workflows/spree/carts/recalculate_totals.rb +233 -0
  635. data/app/workflows/spree/carts/upsert_items.rb +368 -0
  636. data/app/workflows/spree/catalogs/activate.rb +51 -0
  637. data/app/workflows/spree/catalogs/create.rb +83 -0
  638. data/app/workflows/spree/catalogs/deactivate.rb +35 -0
  639. data/app/workflows/spree/catalogs/set_price_list.rb +130 -0
  640. data/app/workflows/spree/catalogs/update.rb +85 -0
  641. data/app/workflows/spree/claims/approve.rb +38 -0
  642. data/app/workflows/spree/claims/cancel.rb +37 -0
  643. data/app/workflows/spree/claims/create.rb +82 -0
  644. data/app/workflows/spree/claims/deny.rb +35 -0
  645. data/app/workflows/spree/claims/resolve.rb +166 -0
  646. data/app/workflows/spree/customers/anonymize.rb +502 -0
  647. data/app/workflows/spree/customers/create.rb +247 -0
  648. data/app/workflows/spree/data_requests/fulfill.rb +165 -0
  649. data/app/workflows/spree/deliveries/update_tracking.rb +96 -0
  650. data/app/workflows/spree/exchanges/approve.rb +38 -0
  651. data/app/workflows/spree/exchanges/cancel.rb +40 -0
  652. data/app/workflows/spree/exchanges/create.rb +90 -0
  653. data/app/workflows/spree/exchanges/fulfill.rb +146 -0
  654. data/app/workflows/spree/exchanges/receive.rb +86 -0
  655. data/app/workflows/spree/fulfillments/cancel.rb +87 -0
  656. data/app/workflows/spree/fulfillments/create.rb +346 -0
  657. data/app/workflows/spree/fulfillments/fulfill.rb +354 -0
  658. data/app/workflows/spree/fulfillments/mark_delivered.rb +67 -0
  659. data/app/workflows/spree/fulfillments/purchase_label.rb +40 -0
  660. data/app/workflows/spree/fulfillments/update.rb +123 -0
  661. data/app/workflows/spree/gift_cards/apply.rb +235 -0
  662. data/app/workflows/spree/gift_cards/cancel.rb +43 -0
  663. data/app/workflows/spree/gift_cards/redeem.rb +59 -0
  664. data/app/workflows/spree/gift_cards/remove.rb +78 -0
  665. data/app/workflows/spree/imports/complete.rb +45 -0
  666. data/app/workflows/spree/imports/complete_mapping.rb +50 -0
  667. data/app/workflows/spree/imports/retry_failed_rows.rb +46 -0
  668. data/app/workflows/spree/imports/start_mapping.rb +48 -0
  669. data/app/workflows/spree/imports/start_processing.rb +36 -0
  670. data/app/workflows/spree/invitations/accept.rb +50 -0
  671. data/app/workflows/spree/orders/add_item.rb +12 -0
  672. data/app/workflows/spree/orders/cancel.rb +260 -0
  673. data/app/workflows/spree/orders/complete.rb +169 -0
  674. data/app/workflows/spree/orders/recalculate.rb +11 -0
  675. data/app/workflows/spree/orders/recalculate_totals.rb +12 -0
  676. data/app/workflows/spree/orders/upsert_items.rb +28 -0
  677. data/app/workflows/spree/payment_sessions/complete.rb +44 -0
  678. data/app/workflows/spree/payments/capture.rb +109 -0
  679. data/app/workflows/spree/payments/handle_webhook.rb +100 -0
  680. data/app/workflows/spree/payments/process.rb +73 -0
  681. data/app/workflows/spree/payments/void.rb +72 -0
  682. data/app/workflows/spree/price_lists/activate.rb +49 -0
  683. data/app/workflows/spree/price_lists/create.rb +57 -0
  684. data/app/workflows/spree/price_lists/deactivate.rb +30 -0
  685. data/app/workflows/spree/price_lists/update.rb +117 -0
  686. data/app/workflows/spree/products/activate.rb +33 -0
  687. data/app/workflows/spree/products/approve.rb +52 -0
  688. data/app/workflows/spree/products/archive.rb +44 -0
  689. data/app/workflows/spree/products/create.rb +82 -0
  690. data/app/workflows/spree/products/destroy.rb +35 -0
  691. data/app/workflows/spree/products/draft.rb +49 -0
  692. data/app/workflows/spree/products/nested_attributes.rb +242 -0
  693. data/app/workflows/spree/products/propose.rb +62 -0
  694. data/app/workflows/spree/products/reject.rb +54 -0
  695. data/app/workflows/spree/products/update.rb +83 -0
  696. data/app/workflows/spree/purchase_orders/cancel.rb +57 -0
  697. data/app/workflows/spree/purchase_orders/close.rb +57 -0
  698. data/app/workflows/spree/purchase_orders/create.rb +68 -0
  699. data/app/workflows/spree/purchase_orders/mark_draft.rb +49 -0
  700. data/app/workflows/spree/purchase_orders/mark_ordered.rb +50 -0
  701. data/app/workflows/spree/purchase_orders/receive.rb +65 -0
  702. data/app/workflows/spree/purchase_orders/update.rb +56 -0
  703. data/app/workflows/spree/receivables/incoming_counter.rb +50 -0
  704. data/app/workflows/spree/refunds/create.rb +136 -0
  705. data/app/workflows/spree/refunds/order_payments.rb +129 -0
  706. data/app/workflows/spree/returns/approve.rb +47 -0
  707. data/app/workflows/spree/returns/cancel.rb +52 -0
  708. data/app/workflows/spree/returns/create.rb +135 -0
  709. data/app/workflows/spree/returns/purchase_label.rb +32 -0
  710. data/app/workflows/spree/returns/receive.rb +94 -0
  711. data/app/workflows/spree/returns/refund.rb +134 -0
  712. data/app/workflows/spree/seller_payouts/complete.rb +80 -0
  713. data/app/workflows/spree/seller_payouts/sweep.rb +192 -0
  714. data/app/workflows/spree/seller_requirement_submissions/accept.rb +40 -0
  715. data/app/workflows/spree/seller_requirement_submissions/create.rb +104 -0
  716. data/app/workflows/spree/seller_requirement_submissions/reject.rb +45 -0
  717. data/app/workflows/spree/seller_requirement_submissions/reviewable.rb +19 -0
  718. data/app/workflows/spree/seller_requirement_submissions/waive.rb +64 -0
  719. data/app/workflows/spree/seller_transfers/create.rb +131 -0
  720. data/app/workflows/spree/seller_transfers/reverse.rb +241 -0
  721. data/app/workflows/spree/sellers/approve.rb +88 -0
  722. data/app/workflows/spree/sellers/create.rb +72 -0
  723. data/app/workflows/spree/sellers/invite.rb +61 -0
  724. data/app/workflows/spree/sellers/reject.rb +52 -0
  725. data/app/workflows/spree/sellers/reopen_onboarding.rb +55 -0
  726. data/app/workflows/spree/sellers/start_onboarding.rb +46 -0
  727. data/app/workflows/spree/sellers/submit_for_review.rb +76 -0
  728. data/app/workflows/spree/sellers/suspend.rb +55 -0
  729. data/app/workflows/spree/shipping_labels/purchase.rb +154 -0
  730. data/app/workflows/spree/shipping_labels/record.rb +102 -0
  731. data/app/workflows/spree/shipping_labels/refund.rb +77 -0
  732. data/app/workflows/spree/stock_receipts/recording.rb +165 -0
  733. data/app/workflows/spree/stock_transfers/cancel.rb +103 -0
  734. data/app/workflows/spree/stock_transfers/close.rb +56 -0
  735. data/app/workflows/spree/stock_transfers/create.rb +63 -0
  736. data/app/workflows/spree/stock_transfers/mark_draft.rb +41 -0
  737. data/app/workflows/spree/stock_transfers/mark_in_transit.rb +91 -0
  738. data/app/workflows/spree/stock_transfers/mark_ready.rb +36 -0
  739. data/app/workflows/spree/stock_transfers/receive.rb +62 -0
  740. data/app/workflows/spree/stock_transfers/update.rb +55 -0
  741. data/app/workflows/spree/tax_exemption_certificates/verify.rb +48 -0
  742. data/app/workflows/spree/variants/create.rb +66 -0
  743. data/app/workflows/spree/variants/nested_attributes.rb +90 -0
  744. data/app/workflows/spree/variants/update.rb +55 -0
  745. data/config/brakeman.ignore +79 -79
  746. data/config/i18n-tasks.yml +4 -3
  747. data/config/initializers/mobility.rb +0 -4
  748. data/config/initializers/spree_store_setup_tasks.rb +4 -0
  749. data/config/locales/en.yml +951 -189
  750. data/config/routes.rb +11 -4
  751. data/db/migrate/20220201103922_add_first_name_and_last_name_to_spree_users.rb +7 -5
  752. data/db/migrate/20221215151408_add_selected_locale_to_spree_users.rb +6 -4
  753. data/db/migrate/20250127151258_add_phone_to_spree_users.rb +3 -1
  754. data/db/migrate/20250207084000_add_accepts_email_marketing_field_to_spree_users_table.rb +4 -2
  755. data/db/migrate/20250410061306_create_spree_invitations.rb +1 -1
  756. data/db/migrate/20250605131334_add_missing_fields_to_users.rb +24 -20
  757. data/db/migrate/20260315100000_add_product_media_support.rb +4 -1
  758. data/db/migrate/20260613000001_add_store_id_to_spree_role_users.rb +6 -3
  759. data/db/migrate/20260630000001_add_default_variant_id_to_spree_products.rb +9 -0
  760. data/db/migrate/20260708160054_create_spree_collections.rb +69 -0
  761. data/db/migrate/20260710000001_rename_taxons_to_categories.rb +28 -0
  762. data/db/migrate/20260727000001_add_unique_country_abbr_index_to_spree_states.rb +27 -4
  763. data/db/migrate/20260728000000_create_spree_customers_and_admin_users.rb +59 -0
  764. data/db/migrate/20260728000001_rename_prototypes_to_product_types.rb +59 -0
  765. data/db/migrate/20260728000002_create_spree_delivery_zones.rb +29 -0
  766. data/db/migrate/20260728000003_create_spree_carts.rb +58 -0
  767. data/db/migrate/20260728000003_rename_user_id_to_customer_id.rb +30 -0
  768. data/db/migrate/20260728000004_rename_shipping_to_fulfillment_and_delivery.rb +83 -0
  769. data/db/migrate/20260728000005_add_fulfillment_type_columns.rb +33 -0
  770. data/db/migrate/20260729000001_create_typed_adjustment_tables.rb +87 -0
  771. data/db/migrate/20260729100001_add_checkout_columns_to_spree_carts.rb +15 -0
  772. data/db/migrate/20260729100002_relax_owner_null_constraints.rb +7 -0
  773. data/db/migrate/20260729120001_rename_order_totals_to_standard_names.rb +7 -0
  774. data/db/migrate/20260729130001_create_spree_delivery_method_rules.rb +19 -0
  775. data/db/migrate/20260729140001_add_coupon_code_to_spree_orders.rb +6 -0
  776. data/db/migrate/20260729150001_add_store_to_delivery_methods_and_stock_locations.rb +6 -0
  777. data/db/migrate/20260802190001_create_spree_returns.rb +49 -0
  778. data/db/migrate/20260802210001_create_spree_exchanges_and_claims.rb +80 -0
  779. data/db/migrate/20260805100001_rename_return_authorization_reasons_to_return_reasons.rb +109 -0
  780. data/db/migrate/20260806000001_add_store_id_to_spree_tax_rates_and_categories.rb +16 -0
  781. data/db/migrate/20260806000001_create_spree_delivery_method_rule_products.rb +22 -0
  782. data/db/migrate/20260806000002_add_treatment_columns_to_spree_tax_lines.rb +19 -0
  783. data/db/migrate/20260806000003_create_spree_tax_identifiers.rb +41 -0
  784. data/db/migrate/20260806000004_add_tax_provider_to_spree_markets.rb +9 -0
  785. data/db/migrate/20260806000005_add_country_and_state_to_spree_tax_rates.rb +20 -0
  786. data/db/migrate/20260806100001_create_spree_product_type_custom_field_definitions.rb +17 -0
  787. data/db/migrate/20260806120001_add_rate_provider_to_delivery_methods.rb +7 -0
  788. data/db/migrate/20260806120002_add_carrier_columns_to_delivery_rates.rb +13 -0
  789. data/db/migrate/20260806130001_add_unique_store_type_index_to_spree_integrations.rb +9 -0
  790. data/db/migrate/20260807000001_add_permissions_to_spree_roles.rb +14 -0
  791. data/db/migrate/20260807000001_create_spree_companies.rb +66 -0
  792. data/db/migrate/20260807000003_create_spree_tax_exemption_certificates.rb +31 -0
  793. data/db/migrate/20260807120001_remove_claim_type_from_spree_claims.rb +5 -0
  794. data/db/migrate/20260807130001_add_country_state_codes_to_consumers.rb +28 -0
  795. data/db/migrate/20260807150001_reindex_spree_categories_by_store.rb +42 -0
  796. data/db/migrate/20260809000001_rename_metafields_to_custom_fields.rb +126 -0
  797. data/db/migrate/20260809100001_support_multi_rate_delivery_methods.rb +35 -0
  798. data/db/migrate/20260809120001_consolidate_metadata_columns.rb +120 -0
  799. data/db/migrate/20260809150001_promote_shipping_categories_to_delivery_profiles.rb +153 -0
  800. data/db/migrate/20260809170001_create_spree_channel_stock_locations.rb +17 -0
  801. data/db/migrate/20260809200001_add_rich_text_columns_for_action_text_removal.rb +11 -0
  802. data/db/migrate/20260810000001_rename_digitals_to_digital_assets.rb +38 -0
  803. data/db/migrate/20260811000001_add_delivery_tracking_to_fulfillments.rb +17 -0
  804. data/db/migrate/20260812000001_add_provider_type_to_spree_digital_assets.rb +7 -0
  805. data/db/migrate/20260812000002_add_metadata_to_spree_digital_assets.rb +11 -0
  806. data/db/migrate/20260813000001_create_spree_number_sequences.rb +13 -0
  807. data/db/migrate/20260813120001_add_setup_token_to_spree_stores.rb +11 -0
  808. data/db/migrate/20260813130001_add_capture_method_to_payment_methods.rb +17 -0
  809. data/db/migrate/20260813130001_add_unique_indexes_to_spree_data_feeds.rb +10 -0
  810. data/db/migrate/20260814000001_add_customs_fields_to_spree_variants.rb +7 -0
  811. data/db/migrate/20260814000001_rename_stock_items_to_stock_levels.rb +72 -0
  812. data/db/migrate/20260814000002_add_typed_stock_movements.rb +25 -0
  813. data/db/migrate/20260815000001_add_audience_to_spree_refresh_tokens.rb +14 -0
  814. data/db/migrate/20260815000002_add_resource_to_spree_roles.rb +190 -0
  815. data/db/migrate/20260816000001_create_spree_sellers.rb +59 -0
  816. data/db/migrate/20260816000002_add_seller_to_spree_products.rb +10 -0
  817. data/db/migrate/20260816210001_create_spree_commission_rates.rb +229 -0
  818. data/db/migrate/20260816210002_create_spree_commission_lines.rb +72 -0
  819. data/db/migrate/20260817000001_add_seller_to_spree_line_items.rb +15 -0
  820. data/db/migrate/20260817000002_add_seller_and_delivery_profile_to_spree_variants.rb +17 -0
  821. data/db/migrate/20260818000001_create_spree_external_references.rb +33 -0
  822. data/db/migrate/20260818000001_create_spree_seller_requirements.rb +60 -0
  823. data/db/migrate/20260818000001_rename_spree_payments_state_to_status.rb +5 -0
  824. data/db/migrate/20260818000002_add_price_source_to_spree_line_items.rb +9 -0
  825. data/db/migrate/20260818090001_rename_assets_to_media.rb +10 -0
  826. data/db/migrate/20260819000001_create_spree_seller_requirement_custom_fields.rb +15 -0
  827. data/db/migrate/20260819000001_replace_payment_method_display_on_with_storefront_visible.rb +25 -0
  828. data/db/migrate/20260819000002_rename_spree_gift_cards_state_to_status.rb +5 -0
  829. data/db/migrate/20260820000001_add_seller_business_identity_and_stock_locations.rb +17 -0
  830. data/db/migrate/20260820000001_create_spree_order_groups.rb +33 -0
  831. data/db/migrate/20260820000002_add_order_group_to_spree_orders_and_payments.rb +14 -0
  832. data/db/migrate/20260820000003_create_spree_payment_splits.rb +21 -0
  833. data/db/migrate/20260820000004_add_order_to_spree_refunds.rb +32 -0
  834. data/db/migrate/20260821000001_add_claimed_amount_to_spree_payment_splits.rb +14 -0
  835. data/db/migrate/20260822000001_create_spree_seller_transfers.rb +94 -0
  836. data/db/migrate/20260822000002_create_spree_seller_payouts.rb +48 -0
  837. data/db/migrate/20260822000003_add_payout_account_to_spree_sellers.rb +11 -0
  838. data/db/migrate/20260824000001_add_store_to_spree_media.rb +16 -0
  839. data/db/migrate/20260825000001_create_spree_catalogs.rb +40 -0
  840. data/db/migrate/20260826000001_add_owner_to_spree_addresses.rb +30 -0
  841. data/db/migrate/20260826000002_create_spree_product_submissions.rb +28 -0
  842. data/db/migrate/20260827000001_add_seller_to_spree_exports.rb +5 -0
  843. data/db/migrate/20260828100001_unify_import_and_export_tenancy.rb +79 -0
  844. data/db/migrate/20260830000001_add_catalog_to_spree_price_lists.rb +47 -0
  845. data/db/migrate/20260830000002_add_po_number_to_purchases.rb +16 -0
  846. data/db/migrate/20260830000002_add_price_adjustment_to_spree_price_lists.rb +14 -0
  847. data/db/migrate/20260831000001_add_description_to_spree_catalogs.rb +7 -0
  848. data/db/migrate/20260831000002_add_quantity_rules_to_spree_variants.rb +18 -0
  849. data/db/migrate/20260831000003_create_spree_catalog_terms.rb +35 -0
  850. data/db/migrate/20260831100001_create_spree_package_types.rb +38 -0
  851. data/db/migrate/20260831100002_add_carton_details_to_spree_variants.rb +10 -0
  852. data/db/migrate/20260831100003_add_unpriced_to_spree_delivery_rates.rb +8 -0
  853. data/db/migrate/20260901000001_add_seller_to_spree_delivery_methods.rb +11 -0
  854. data/db/migrate/20260902000001_add_store_and_filter_key_to_custom_field_definitions.rb +143 -0
  855. data/db/migrate/20260902000002_add_eu_legal_compliance.rb +68 -0
  856. data/db/migrate/20260902000002_replace_order_cancellation_tables_with_cancel_columns.rb +88 -0
  857. data/db/migrate/20260902100001_rename_wished_items_to_wishlist_items.rb +8 -0
  858. data/db/migrate/20260902100002_rename_promo_total_to_discount_total.rb +9 -0
  859. data/db/migrate/20260902100003_rename_address_name_and_postal_code_columns.rb +24 -0
  860. data/db/migrate/20260902100004_rename_option_presentation_to_label.rb +13 -0
  861. data/db/migrate/20260903000001_create_spree_shipping_labels_and_deliveries.rb +73 -0
  862. data/db/migrate/20260903120000_create_spree_saved_reports.rb +57 -0
  863. data/db/migrate/20260904000001_add_returns_enabled_to_stock_locations.rb +14 -0
  864. data/db/migrate/20260906000001_add_commission_total_to_orders.rb +22 -0
  865. data/db/migrate/20260907000001_add_inventory_operations.rb +113 -0
  866. data/db/migrate/20260907000001_add_min_quantity_to_spree_prices.rb +28 -0
  867. data/db/migrate/20260907000002_create_spree_price_adjustment_tiers.rb +19 -0
  868. data/db/migrate/20260908000001_add_seller_to_spree_package_types.rb +78 -0
  869. data/db/migrate/20260910000001_add_stock_receipts.rb +44 -0
  870. data/db/migrate/20260910000002_add_counters_to_spree_stock_levels.rb +6 -0
  871. data/db/migrate/20260910120000_index_reporting_time_columns.rb +12 -0
  872. data/db/migrate/20260912120000_index_reporting_lifetime_and_promotion_columns.rb +19 -0
  873. data/db/migrate/20260914000001_add_settlement_to_spree_seller_transfers.rb +18 -0
  874. data/db/migrate/20260914230000_add_store_to_spree_option_types.rb +46 -0
  875. data/db/sample_data/collections.rb +58 -0
  876. data/db/sample_data/custom_field_definitions.rb +9 -0
  877. data/db/sample_data/digital_products.rb +26 -0
  878. data/db/sample_data/fulfillment.rb +88 -0
  879. data/db/sample_data/options.rb +25 -1
  880. data/db/sample_data/orders.rb +53 -30
  881. data/db/sample_data/payment_methods.rb +2 -2
  882. data/db/sample_data/price_list_prices.csv +25 -0
  883. data/db/sample_data/product_type_categories.rb +27 -0
  884. data/db/sample_data/product_types.rb +83 -0
  885. data/db/sample_data/products.csv +39 -38
  886. data/db/sample_data/wholesale.rb +42 -3
  887. data/lib/generators/spree/api_resource/api_resource_generator.rb +1 -1
  888. data/lib/generators/spree/authentication/dummy/templates/create_spree_admin_users.rb.tt +1 -0
  889. data/lib/generators/spree/controller_decorator/controller_decorator_generator.rb +4 -4
  890. data/lib/generators/spree/dummy/dummy_generator.rb +5 -12
  891. data/lib/generators/spree/dummy/templates/rails/test.rb +5 -0
  892. data/lib/generators/spree/model/model_generator.rb +6 -6
  893. data/lib/generators/spree/model/templates/model.rb.tt +7 -3
  894. data/lib/spree/category_permalink_deduplicator.rb +328 -0
  895. data/lib/spree/core/configuration.rb +96 -47
  896. data/lib/spree/core/controller_helpers/store.rb +8 -9
  897. data/lib/spree/core/dependencies.rb +324 -71
  898. data/lib/spree/core/dependencies_helper.rb +4 -0
  899. data/lib/spree/core/engine.rb +333 -75
  900. data/lib/spree/core/number_generator.rb +37 -33
  901. data/lib/spree/core/permission_configuration.rb +183 -91
  902. data/lib/spree/core/permissions/default_catalog.rb +236 -0
  903. data/lib/spree/core/permissions/entry.rb +15 -0
  904. data/lib/spree/core/permissions/scope.rb +76 -0
  905. data/lib/spree/core/preferences/masking.rb +24 -2
  906. data/lib/spree/core/preferences/preferable.rb +52 -2
  907. data/lib/spree/core/preferences/preferable_class_methods.rb +41 -2
  908. data/lib/spree/core/preferences/runtime_configuration.rb +68 -9
  909. data/lib/spree/core/previews/admin_user_preview.rb +0 -8
  910. data/lib/spree/core/previews/invitation_preview.rb +1 -1
  911. data/lib/spree/core/previews/preview_data.rb +2 -2
  912. data/lib/spree/core/previews/seller_user_preview.rb +14 -0
  913. data/lib/spree/core/pricing/context.rb +28 -8
  914. data/lib/spree/core/pricing/price_resolution.rb +150 -0
  915. data/lib/spree/core/pricing/resolver.rb +17 -107
  916. data/lib/spree/core/ransack_configuration.rb +3 -3
  917. data/lib/spree/core/routes.rb +4 -6
  918. data/lib/spree/core/version.rb +1 -1
  919. data/lib/spree/core.rb +422 -62
  920. data/lib/spree/events/adapters/base.rb +42 -15
  921. data/lib/spree/hooks.rb +146 -0
  922. data/lib/spree/iso_data.rb +188 -0
  923. data/lib/spree/measurement.rb +113 -0
  924. data/lib/spree/money.rb +70 -0
  925. data/lib/spree/number_generators/registry.rb +80 -0
  926. data/lib/spree/reporting/adapters/base.rb +71 -0
  927. data/lib/spree/reporting/adapters/live.rb +677 -0
  928. data/lib/spree/reporting/counter_result.rb +19 -0
  929. data/lib/spree/reporting/counters.rb +33 -0
  930. data/lib/spree/reporting/default_vocabulary.rb +705 -0
  931. data/lib/spree/reporting/hydration.rb +64 -0
  932. data/lib/spree/reporting/query.rb +487 -0
  933. data/lib/spree/reporting/registry.rb +294 -0
  934. data/lib/spree/reporting/result.rb +10 -0
  935. data/lib/spree/reporting/schema.rb +124 -0
  936. data/lib/spree/reporting.rb +49 -0
  937. data/lib/spree/service_module.rb +6 -0
  938. data/lib/spree/store_scope_guard.rb +180 -0
  939. data/lib/spree/testing_support/action_text.rb +33 -0
  940. data/lib/spree/testing_support/common_rake.rb +4 -66
  941. data/lib/spree/testing_support/country_pool.rb +50 -0
  942. data/lib/spree/testing_support/extension_rake.rb +2 -6
  943. data/lib/spree/testing_support/factories/address_factory.rb +45 -15
  944. data/lib/spree/testing_support/factories/api_key_factory.rb +1 -1
  945. data/lib/spree/testing_support/factories/calculator_factory.rb +0 -3
  946. data/lib/spree/testing_support/factories/cart_factory.rb +60 -0
  947. data/lib/spree/testing_support/factories/catalog_factory.rb +37 -0
  948. data/lib/spree/testing_support/factories/category_factory.rb +21 -0
  949. data/lib/spree/testing_support/factories/claim_factory.rb +33 -0
  950. data/lib/spree/testing_support/factories/classification_factory.rb +3 -2
  951. data/lib/spree/testing_support/factories/collection_factory.rb +25 -0
  952. data/lib/spree/testing_support/factories/collection_rule_factory.rb +47 -0
  953. data/lib/spree/testing_support/factories/commission_rate_factory.rb +75 -0
  954. data/lib/spree/testing_support/factories/company_factory.rb +31 -0
  955. data/lib/spree/testing_support/factories/consent_record_factory.rb +10 -0
  956. data/lib/spree/testing_support/factories/country_factory.rb +28 -9
  957. data/lib/spree/testing_support/factories/custom_field_definition_factory.rb +79 -0
  958. data/lib/spree/testing_support/factories/custom_field_factory.rb +64 -0
  959. data/lib/spree/testing_support/factories/customer_group_user_factory.rb +1 -1
  960. data/lib/spree/testing_support/factories/data_request_factory.rb +17 -0
  961. data/lib/spree/testing_support/factories/delivery_factory.rb +13 -0
  962. data/lib/spree/testing_support/factories/delivery_method_factory.rb +47 -0
  963. data/lib/spree/testing_support/factories/delivery_origin_group_factory.rb +5 -0
  964. data/lib/spree/testing_support/factories/delivery_profile_factory.rb +9 -0
  965. data/lib/spree/testing_support/factories/delivery_rate_factory.rb +7 -0
  966. data/lib/spree/testing_support/factories/delivery_zone_factory.rb +34 -0
  967. data/lib/spree/testing_support/factories/digital_asset_factory.rb +13 -0
  968. data/lib/spree/testing_support/factories/digital_link_factory.rb +1 -1
  969. data/lib/spree/testing_support/factories/discount_factory.rb +9 -0
  970. data/lib/spree/testing_support/factories/exchange_factory.rb +50 -0
  971. data/lib/spree/testing_support/factories/external_reference_factory.rb +8 -0
  972. data/lib/spree/testing_support/factories/fee_factory.rb +8 -0
  973. data/lib/spree/testing_support/factories/fulfillment_factory.rb +32 -0
  974. data/lib/spree/testing_support/factories/fulfillment_item_factory.rb +17 -0
  975. data/lib/spree/testing_support/factories/gateway_customer_factory.rb +1 -1
  976. data/lib/spree/testing_support/factories/gift_card_factory.rb +2 -2
  977. data/lib/spree/testing_support/factories/import_factory.rb +33 -1
  978. data/lib/spree/testing_support/factories/line_item_factory.rb +10 -5
  979. data/lib/spree/testing_support/factories/market_factory.rb +5 -12
  980. data/lib/spree/testing_support/factories/media_factory.rb +36 -0
  981. data/lib/spree/testing_support/factories/newsletter_subscriber_factory.rb +1 -1
  982. data/lib/spree/testing_support/factories/number_sequence_factory.rb +7 -0
  983. data/lib/spree/testing_support/factories/options_factory.rb +5 -5
  984. data/lib/spree/testing_support/factories/order_factory.rb +39 -23
  985. data/lib/spree/testing_support/factories/order_group_factory.rb +29 -0
  986. data/lib/spree/testing_support/factories/package_type_factory.rb +36 -0
  987. data/lib/spree/testing_support/factories/payment_factory.rb +7 -7
  988. data/lib/spree/testing_support/factories/payment_method_factory.rb +5 -5
  989. data/lib/spree/testing_support/factories/payment_session_factory.rb +10 -6
  990. data/lib/spree/testing_support/factories/payment_setup_session_factory.rb +2 -2
  991. data/lib/spree/testing_support/factories/payment_split_factory.rb +10 -0
  992. data/lib/spree/testing_support/factories/price_adjustment_tier_factory.rb +7 -0
  993. data/lib/spree/testing_support/factories/price_factory.rb +6 -0
  994. data/lib/spree/testing_support/factories/price_rule_factory.rb +0 -10
  995. data/lib/spree/testing_support/factories/product_collection_factory.rb +8 -0
  996. data/lib/spree/testing_support/factories/product_factory.rb +35 -7
  997. data/lib/spree/testing_support/factories/product_type_custom_field_definition_factory.rb +10 -0
  998. data/lib/spree/testing_support/factories/product_type_factory.rb +12 -0
  999. data/lib/spree/testing_support/factories/promotion_factory.rb +4 -0
  1000. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +1 -1
  1001. data/lib/spree/testing_support/factories/purchase_order_factory.rb +49 -0
  1002. data/lib/spree/testing_support/factories/refresh_token_factory.rb +2 -0
  1003. data/lib/spree/testing_support/factories/refund_factory.rb +1 -2
  1004. data/lib/spree/testing_support/factories/return_factory.rb +52 -0
  1005. data/lib/spree/testing_support/factories/return_reason_factory.rb +19 -0
  1006. data/lib/spree/testing_support/factories/role_factory.rb +1 -0
  1007. data/lib/spree/testing_support/factories/saved_report_factory.rb +7 -0
  1008. data/lib/spree/testing_support/factories/seller_factory.rb +34 -0
  1009. data/lib/spree/testing_support/factories/seller_payout_factory.rb +14 -0
  1010. data/lib/spree/testing_support/factories/seller_requirement_factory.rb +61 -0
  1011. data/lib/spree/testing_support/factories/seller_requirement_submission_factory.rb +32 -0
  1012. data/lib/spree/testing_support/factories/seller_transfer_factory.rb +21 -0
  1013. data/lib/spree/testing_support/factories/shipping_label_factory.rb +44 -0
  1014. data/lib/spree/testing_support/factories/state_factory.rb +18 -5
  1015. data/lib/spree/testing_support/factories/stock_level_factory.rb +24 -0
  1016. data/lib/spree/testing_support/factories/stock_location_factory.rb +12 -6
  1017. data/lib/spree/testing_support/factories/stock_movement_factory.rb +20 -3
  1018. data/lib/spree/testing_support/factories/stock_receipt_factory.rb +37 -0
  1019. data/lib/spree/testing_support/factories/stock_reservation_factory.rb +11 -8
  1020. data/lib/spree/testing_support/factories/stock_transfer_factory.rb +53 -6
  1021. data/lib/spree/testing_support/factories/store_credit_factory.rb +1 -3
  1022. data/lib/spree/testing_support/factories/supplier_factory.rb +17 -0
  1023. data/lib/spree/testing_support/factories/tax_exemption_certificate_factory.rb +18 -0
  1024. data/lib/spree/testing_support/factories/tax_identifier_factory.rb +33 -0
  1025. data/lib/spree/testing_support/factories/tax_line_factory.rb +19 -0
  1026. data/lib/spree/testing_support/factories/tax_rate_factory.rb +5 -2
  1027. data/lib/spree/testing_support/factories/taxon_factory.rb +6 -23
  1028. data/lib/spree/testing_support/factories/taxonomy_factory.rb +8 -0
  1029. data/lib/spree/testing_support/factories/user_factory.rb +8 -12
  1030. data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
  1031. data/lib/spree/testing_support/factories/wishlist_factory.rb +1 -1
  1032. data/lib/spree/testing_support/factories/wishlist_item_factory.rb +10 -0
  1033. data/lib/spree/testing_support/factories/zone_factory.rb +2 -25
  1034. data/lib/spree/testing_support/factories/zone_member_factory.rb +2 -1
  1035. data/lib/spree/testing_support/factories.rb +1 -6
  1036. data/lib/spree/testing_support/imports.rb +16 -0
  1037. data/lib/spree/testing_support/label_provider.rb +49 -0
  1038. data/lib/spree/testing_support/lifecycle_events.rb +6 -1
  1039. data/lib/spree/testing_support/metadata.rb +38 -36
  1040. data/lib/spree/testing_support/order_walkthrough.rb +46 -36
  1041. data/lib/spree/testing_support/preferences.rb +39 -0
  1042. data/lib/spree/testing_support/purchase_order.rb +111 -0
  1043. data/lib/spree/testing_support/store.rb +6 -2
  1044. data/lib/spree/testing_support/tax_identifier_validators.rb +68 -0
  1045. data/lib/spree/translations.rb +139 -5
  1046. data/lib/spree/upgrades/5_4_to_5_5/manifest.yml +1 -1
  1047. data/lib/spree/upgrades/5_5_to_5_6/manifest.yml +17 -9
  1048. data/lib/spree/upgrades/5_6_to_6_0/manifest.yml +683 -0
  1049. data/lib/spree/validators.rb +74 -0
  1050. data/lib/spree/workflow.rb +335 -0
  1051. data/lib/tasks/backfill_custom_field_definition_stores.rake +82 -0
  1052. data/lib/tasks/backfill_import_export_tenancy.rake +93 -0
  1053. data/lib/tasks/backfill_library_media_placements.rake +29 -0
  1054. data/lib/tasks/backfill_media_store_ids.rake +70 -0
  1055. data/lib/tasks/backfill_reason_store_ids.rake +28 -0
  1056. data/lib/tasks/capture_methods_migration.rake +30 -0
  1057. data/lib/tasks/carts_migration.rake +113 -0
  1058. data/lib/tasks/categories_and_collections.rake +188 -0
  1059. data/lib/tasks/cli.rake +22 -3
  1060. data/lib/tasks/consolidate_metadata.rake +73 -0
  1061. data/lib/tasks/core.rake +1 -11
  1062. data/lib/tasks/deliveries_migration.rake +52 -0
  1063. data/lib/tasks/delivery_method_rules_migration.rake +51 -0
  1064. data/lib/tasks/delivery_migration.rake +213 -0
  1065. data/lib/tasks/delivery_profiles_migration.rake +109 -0
  1066. data/lib/tasks/fold_store_credit_categories.rake +40 -0
  1067. data/lib/tasks/fulfillment_statuses_migration.rake +59 -0
  1068. data/lib/tasks/inventory_operations_migration.rake +223 -0
  1069. data/lib/tasks/markets.rake +7 -2
  1070. data/lib/tasks/media.rake +2 -2
  1071. data/lib/tasks/media_class_rename.rake +56 -0
  1072. data/lib/tasks/migrate_country_state_codes.rake +228 -0
  1073. data/lib/tasks/migrate_promotion_option_value_rules.rake +124 -0
  1074. data/lib/tasks/migrate_returns.rake +322 -0
  1075. data/lib/tasks/migrate_rich_text_to_columns.rake +128 -0
  1076. data/lib/tasks/migrate_users_to_customers.rake +161 -0
  1077. data/lib/tasks/order_coupon_code_backfill.rake +32 -0
  1078. data/lib/tasks/order_market_backfill.rake +27 -0
  1079. data/lib/tasks/package_types.rake +62 -0
  1080. data/lib/tasks/price_history.rake +49 -6
  1081. data/lib/tasks/products.rake +21 -2
  1082. data/lib/tasks/remove_master_variant.rake +58 -0
  1083. data/lib/tasks/rich_text.rake +44 -0
  1084. data/lib/tasks/seller_sample_data.rake +142 -0
  1085. data/lib/tasks/setup.rake +18 -0
  1086. data/lib/tasks/single_store_associations.rake +11 -0
  1087. data/lib/tasks/stock.rake +15 -0
  1088. data/lib/tasks/store_binding_migration.rake +33 -0
  1089. data/lib/tasks/store_settings.rake +104 -0
  1090. data/lib/tasks/tax_zones_migration.rake +147 -0
  1091. data/lib/tasks/taxons.rake +9 -10
  1092. data/lib/tasks/typed_adjustments_migration.rake +189 -0
  1093. data/lib/tasks/typed_stock_movements_migration.rake +250 -0
  1094. data/lib/tasks/upgrade.rake +13 -8
  1095. data/spec/fixtures/files/eu_vat_numbers.txt +56 -0
  1096. data/spec/fixtures/files/price_list_prices_import.csv +4 -0
  1097. data/spec/fixtures/files/products_import.csv +1 -1
  1098. data/spec/fixtures/tiny-video.mp4 +0 -0
  1099. metadata +788 -541
  1100. data/app/assets/config/spree_core_manifest.js +0 -4
  1101. data/app/assets/images/google_on_white_hdpi.png +0 -0
  1102. data/app/assets/images/logo.png +0 -0
  1103. data/app/assets/images/payment_icons/ach.svg +0 -1
  1104. data/app/assets/images/payment_icons/achdirectdebit.svg +0 -1
  1105. data/app/assets/images/payment_icons/ada.svg +0 -1
  1106. data/app/assets/images/payment_icons/adyen.svg +0 -1
  1107. data/app/assets/images/payment_icons/affinbank.svg +0 -1
  1108. data/app/assets/images/payment_icons/affirm.svg +0 -1
  1109. data/app/assets/images/payment_icons/afterpay.svg +0 -1
  1110. data/app/assets/images/payment_icons/airtel_money.svg +0 -1
  1111. data/app/assets/images/payment_icons/airteltigo_mobile_money.svg +0 -1
  1112. data/app/assets/images/payment_icons/alandsbanken.svg +0 -1
  1113. data/app/assets/images/payment_icons/alipay.svg +0 -1
  1114. data/app/assets/images/payment_icons/alipay_hk.svg +0 -1
  1115. data/app/assets/images/payment_icons/alliancebank.svg +0 -1
  1116. data/app/assets/images/payment_icons/alma.svg +0 -1
  1117. data/app/assets/images/payment_icons/amazon.svg +0 -1
  1118. data/app/assets/images/payment_icons/ambank.svg +0 -1
  1119. data/app/assets/images/payment_icons/american_express.svg +0 -1
  1120. data/app/assets/images/payment_icons/apecoin.svg +0 -1
  1121. data/app/assets/images/payment_icons/apple_pay.svg +0 -1
  1122. data/app/assets/images/payment_icons/arbitrum.svg +0 -1
  1123. data/app/assets/images/payment_icons/atome.svg +0 -1
  1124. data/app/assets/images/payment_icons/authorizenet.svg +0 -1
  1125. data/app/assets/images/payment_icons/avalanche.svg +0 -1
  1126. data/app/assets/images/payment_icons/bacs.svg +0 -1
  1127. data/app/assets/images/payment_icons/bancontact.svg +0 -1
  1128. data/app/assets/images/payment_icons/bangkokbank.svg +0 -1
  1129. data/app/assets/images/payment_icons/bankislam.svg +0 -1
  1130. data/app/assets/images/payment_icons/bankmuamalat.svg +0 -1
  1131. data/app/assets/images/payment_icons/bankofamerica.svg +0 -1
  1132. data/app/assets/images/payment_icons/bankrakyat.svg +0 -1
  1133. data/app/assets/images/payment_icons/banktransfer.svg +0 -1
  1134. data/app/assets/images/payment_icons/base.svg +0 -1
  1135. data/app/assets/images/payment_icons/becs.svg +0 -1
  1136. data/app/assets/images/payment_icons/benefit.svg +0 -1
  1137. data/app/assets/images/payment_icons/billie.svg +0 -1
  1138. data/app/assets/images/payment_icons/bitcoin.svg +0 -1
  1139. data/app/assets/images/payment_icons/bitcoin_cash.svg +0 -1
  1140. data/app/assets/images/payment_icons/bizum.svg +0 -1
  1141. data/app/assets/images/payment_icons/blik.svg +0 -1
  1142. data/app/assets/images/payment_icons/bnbchain.svg +0 -1
  1143. data/app/assets/images/payment_icons/bogus.svg +0 -1
  1144. data/app/assets/images/payment_icons/bogus_app_coin.svg +0 -1
  1145. data/app/assets/images/payment_icons/boleto.svg +0 -1
  1146. data/app/assets/images/payment_icons/boost.svg +0 -1
  1147. data/app/assets/images/payment_icons/braintree.svg +0 -1
  1148. data/app/assets/images/payment_icons/buckaroopaybybank.svg +0 -1
  1149. data/app/assets/images/payment_icons/busd.svg +0 -1
  1150. data/app/assets/images/payment_icons/cartes_bancaires.svg +0 -1
  1151. data/app/assets/images/payment_icons/cash.svg +0 -1
  1152. data/app/assets/images/payment_icons/cashappafterpay.svg +0 -1
  1153. data/app/assets/images/payment_icons/cashapppay.svg +0 -1
  1154. data/app/assets/images/payment_icons/checkout_finance.svg +0 -1
  1155. data/app/assets/images/payment_icons/chinabank.svg +0 -1
  1156. data/app/assets/images/payment_icons/clearpay.svg +0 -1
  1157. data/app/assets/images/payment_icons/collector_bank.svg +0 -1
  1158. data/app/assets/images/payment_icons/dai.svg +0 -1
  1159. data/app/assets/images/payment_icons/dana.svg +0 -1
  1160. data/app/assets/images/payment_icons/dankort.svg +0 -1
  1161. data/app/assets/images/payment_icons/danske_bank.svg +0 -1
  1162. data/app/assets/images/payment_icons/deutschebank.svg +0 -1
  1163. data/app/assets/images/payment_icons/diners_club.svg +0 -1
  1164. data/app/assets/images/payment_icons/directbanktransferlatinamerica.svg +0 -1
  1165. data/app/assets/images/payment_icons/discover.svg +0 -1
  1166. data/app/assets/images/payment_icons/dogecoin.svg +0 -1
  1167. data/app/assets/images/payment_icons/duitnow.svg +0 -1
  1168. data/app/assets/images/payment_icons/eft_secure.svg +0 -1
  1169. data/app/assets/images/payment_icons/eftpos_au.svg +0 -1
  1170. data/app/assets/images/payment_icons/eftposau.svg +0 -1
  1171. data/app/assets/images/payment_icons/elo.svg +0 -1
  1172. data/app/assets/images/payment_icons/eos.svg +0 -1
  1173. data/app/assets/images/payment_icons/eps.svg +0 -1
  1174. data/app/assets/images/payment_icons/ethereum.svg +0 -1
  1175. data/app/assets/images/payment_icons/eurobonuscheckout.svg +0 -1
  1176. data/app/assets/images/payment_icons/ezcash.svg +0 -1
  1177. data/app/assets/images/payment_icons/fantom.svg +0 -1
  1178. data/app/assets/images/payment_icons/fpx.svg +0 -1
  1179. data/app/assets/images/payment_icons/gcash.svg +0 -1
  1180. data/app/assets/images/payment_icons/generic.svg +0 -1
  1181. data/app/assets/images/payment_icons/genericbank.svg +0 -1
  1182. data/app/assets/images/payment_icons/gift-card.svg +0 -1
  1183. data/app/assets/images/payment_icons/giropay.svg +0 -1
  1184. data/app/assets/images/payment_icons/glbepaypal.svg +0 -1
  1185. data/app/assets/images/payment_icons/gmobanktransfer.svg +0 -1
  1186. data/app/assets/images/payment_icons/gnosis.svg +0 -1
  1187. data/app/assets/images/payment_icons/google_pay.svg +0 -1
  1188. data/app/assets/images/payment_icons/google_wallet.svg +0 -1
  1189. data/app/assets/images/payment_icons/gopay.svg +0 -1
  1190. data/app/assets/images/payment_icons/grabpay.svg +0 -1
  1191. data/app/assets/images/payment_icons/gusd.svg +0 -1
  1192. data/app/assets/images/payment_icons/handelsbanken.svg +0 -1
  1193. data/app/assets/images/payment_icons/hongleongbank.svg +0 -1
  1194. data/app/assets/images/payment_icons/hypercard.svg +0 -1
  1195. data/app/assets/images/payment_icons/hypercash.svg +0 -1
  1196. data/app/assets/images/payment_icons/ideal.svg +0 -1
  1197. data/app/assets/images/payment_icons/in3viaideal.svg +0 -1
  1198. data/app/assets/images/payment_icons/inbank.svg +0 -1
  1199. data/app/assets/images/payment_icons/jcb.svg +0 -1
  1200. data/app/assets/images/payment_icons/kakao_pay.svg +0 -1
  1201. data/app/assets/images/payment_icons/kasikornbank.svg +0 -1
  1202. data/app/assets/images/payment_icons/klarna-pay-later.svg +0 -1
  1203. data/app/assets/images/payment_icons/klarna-pay-now.svg +0 -1
  1204. data/app/assets/images/payment_icons/klarna-slice-it.svg +0 -1
  1205. data/app/assets/images/payment_icons/klarna.svg +0 -1
  1206. data/app/assets/images/payment_icons/knet.svg +0 -1
  1207. data/app/assets/images/payment_icons/krungthaibank.svg +0 -1
  1208. data/app/assets/images/payment_icons/landbank.svg +0 -1
  1209. data/app/assets/images/payment_icons/laybuybyklarna.svg +0 -1
  1210. data/app/assets/images/payment_icons/litecoin.svg +0 -1
  1211. data/app/assets/images/payment_icons/lunchcheck.svg +0 -1
  1212. data/app/assets/images/payment_icons/mach.svg +0 -1
  1213. data/app/assets/images/payment_icons/mada.svg +0 -1
  1214. data/app/assets/images/payment_icons/maestro.svg +0 -1
  1215. data/app/assets/images/payment_icons/master.svg +0 -1
  1216. data/app/assets/images/payment_icons/mayabank.svg +0 -1
  1217. data/app/assets/images/payment_icons/maybank.svg +0 -1
  1218. data/app/assets/images/payment_icons/maybankm2u.svg +0 -1
  1219. data/app/assets/images/payment_icons/maybankqrpay.svg +0 -1
  1220. data/app/assets/images/payment_icons/mbway.svg +0 -1
  1221. data/app/assets/images/payment_icons/mcash.svg +0 -1
  1222. data/app/assets/images/payment_icons/medicinosbankas.svg +0 -1
  1223. data/app/assets/images/payment_icons/mercadopago.svg +0 -1
  1224. data/app/assets/images/payment_icons/metrobank.svg +0 -1
  1225. data/app/assets/images/payment_icons/mobilepay.svg +0 -1
  1226. data/app/assets/images/payment_icons/momopay.svg +0 -1
  1227. data/app/assets/images/payment_icons/monero.svg +0 -1
  1228. data/app/assets/images/payment_icons/mtn_mobile_money.svg +0 -1
  1229. data/app/assets/images/payment_icons/mybank.svg +0 -1
  1230. data/app/assets/images/payment_icons/naver_pay.svg +0 -1
  1231. data/app/assets/images/payment_icons/nelo.svg +0 -1
  1232. data/app/assets/images/payment_icons/netbanking.svg +0 -1
  1233. data/app/assets/images/payment_icons/novalnetdirectdebitach.svg +0 -1
  1234. data/app/assets/images/payment_icons/nubank.svg +0 -1
  1235. data/app/assets/images/payment_icons/ocbcbank.svg +0 -1
  1236. data/app/assets/images/payment_icons/offlinebanktransferlatinamerica.svg +0 -1
  1237. data/app/assets/images/payment_icons/ola_money.svg +0 -1
  1238. data/app/assets/images/payment_icons/oney.svg +0 -1
  1239. data/app/assets/images/payment_icons/onlinebanking.svg +0 -1
  1240. data/app/assets/images/payment_icons/onlinebanktransfer.svg +0 -1
  1241. data/app/assets/images/payment_icons/orangemobilemoney.svg +0 -1
  1242. data/app/assets/images/payment_icons/otpbank.svg +0 -1
  1243. data/app/assets/images/payment_icons/oxxo.svg +0 -1
  1244. data/app/assets/images/payment_icons/paybybank.svg +0 -1
  1245. data/app/assets/images/payment_icons/paybybankmollie.svg +0 -1
  1246. data/app/assets/images/payment_icons/paybybankus.svg +0 -1
  1247. data/app/assets/images/payment_icons/paycash.svg +0 -1
  1248. data/app/assets/images/payment_icons/payco.svg +0 -1
  1249. data/app/assets/images/payment_icons/payeverpaybybank.svg +0 -1
  1250. data/app/assets/images/payment_icons/payme.svg +0 -1
  1251. data/app/assets/images/payment_icons/paynow.svg +0 -1
  1252. data/app/assets/images/payment_icons/paynowmbank.svg +0 -1
  1253. data/app/assets/images/payment_icons/paypal.svg +0 -1
  1254. data/app/assets/images/payment_icons/paypo.svg +0 -1
  1255. data/app/assets/images/payment_icons/payrexxbanktransfer.svg +0 -1
  1256. data/app/assets/images/payment_icons/payrexxpaybybank.svg +0 -1
  1257. data/app/assets/images/payment_icons/paysafecash.svg +0 -1
  1258. data/app/assets/images/payment_icons/pix.svg +0 -1
  1259. data/app/assets/images/payment_icons/polygon.svg +0 -1
  1260. data/app/assets/images/payment_icons/przelewy24.svg +0 -1
  1261. data/app/assets/images/payment_icons/publicbank.svg +0 -1
  1262. data/app/assets/images/payment_icons/publicbank_pbe.svg +0 -1
  1263. data/app/assets/images/payment_icons/qr_promptpay.svg +0 -1
  1264. data/app/assets/images/payment_icons/rabobank.svg +0 -1
  1265. data/app/assets/images/payment_icons/revolut.svg +0 -1
  1266. data/app/assets/images/payment_icons/rhbbank.svg +0 -1
  1267. data/app/assets/images/payment_icons/riverty.svg +0 -1
  1268. data/app/assets/images/payment_icons/safetypaybanktransfer.svg +0 -1
  1269. data/app/assets/images/payment_icons/samsung_pay.svg +0 -1
  1270. data/app/assets/images/payment_icons/satispay.svg +0 -1
  1271. data/app/assets/images/payment_icons/scalapay.svg +0 -1
  1272. data/app/assets/images/payment_icons/scotiabank.svg +0 -1
  1273. data/app/assets/images/payment_icons/seabankid.svg +0 -1
  1274. data/app/assets/images/payment_icons/seabankph.svg +0 -1
  1275. data/app/assets/images/payment_icons/sepa_bank_transfer.svg +0 -1
  1276. data/app/assets/images/payment_icons/sepadebit.svg +0 -22
  1277. data/app/assets/images/payment_icons/sepadirectdebit.svg +0 -1
  1278. data/app/assets/images/payment_icons/seveneleven.svg +0 -1
  1279. data/app/assets/images/payment_icons/shib.svg +0 -1
  1280. data/app/assets/images/payment_icons/shopcash.svg +0 -1
  1281. data/app/assets/images/payment_icons/siauliubankas.svg +0 -1
  1282. data/app/assets/images/payment_icons/skeps.svg +0 -1
  1283. data/app/assets/images/payment_icons/snap_checkout.svg +0 -1
  1284. data/app/assets/images/payment_icons/sofort.svg +0 -1
  1285. data/app/assets/images/payment_icons/softbank.svg +0 -1
  1286. data/app/assets/images/payment_icons/spei.svg +0 -1
  1287. data/app/assets/images/payment_icons/storecredit.svg +0 -1
  1288. data/app/assets/images/payment_icons/stripe.svg +0 -1
  1289. data/app/assets/images/payment_icons/sveacheckout.svg +0 -1
  1290. data/app/assets/images/payment_icons/swedbank.svg +0 -1
  1291. data/app/assets/images/payment_icons/swish.svg +0 -1
  1292. data/app/assets/images/payment_icons/tbibank.svg +0 -1
  1293. data/app/assets/images/payment_icons/thanachartbank.svg +0 -1
  1294. data/app/assets/images/payment_icons/tnmmoney.svg +0 -1
  1295. data/app/assets/images/payment_icons/touchngo.svg +0 -1
  1296. data/app/assets/images/payment_icons/trustly.svg +0 -1
  1297. data/app/assets/images/payment_icons/twint.svg +0 -1
  1298. data/app/assets/images/payment_icons/uaevisa.svg +0 -1
  1299. data/app/assets/images/payment_icons/unionpay.svg +0 -1
  1300. data/app/assets/images/payment_icons/unzerbanktransfer.svg +0 -1
  1301. data/app/assets/images/payment_icons/upi.svg +0 -1
  1302. data/app/assets/images/payment_icons/usbank.svg +0 -1
  1303. data/app/assets/images/payment_icons/usdc.svg +0 -1
  1304. data/app/assets/images/payment_icons/usdt.svg +0 -1
  1305. data/app/assets/images/payment_icons/venmo.svg +0 -1
  1306. data/app/assets/images/payment_icons/vipps.svg +0 -1
  1307. data/app/assets/images/payment_icons/visa.svg +0 -1
  1308. data/app/assets/images/payment_icons/volksbank.svg +0 -1
  1309. data/app/assets/images/payment_icons/waavepaybybank.svg +0 -1
  1310. data/app/assets/images/payment_icons/walley.svg +0 -1
  1311. data/app/assets/images/payment_icons/wbtc.svg +0 -1
  1312. data/app/assets/images/payment_icons/wechatpay.svg +0 -1
  1313. data/app/assets/images/payment_icons/whishcheckout.svg +0 -1
  1314. data/app/assets/images/payment_icons/wingbank.svg +0 -1
  1315. data/app/assets/images/payment_icons/xrp.svg +0 -1
  1316. data/app/assets/images/payment_icons/zip.svg +0 -1
  1317. data/app/controllers/spree/base_controller.rb +0 -11
  1318. data/app/finders/concerns/spree/product_filterable.rb +0 -9
  1319. data/app/finders/spree/addresses/find.rb +0 -27
  1320. data/app/finders/spree/base_finder.rb +0 -14
  1321. data/app/finders/spree/countries/find.rb +0 -31
  1322. data/app/finders/spree/credit_cards/find.rb +0 -12
  1323. data/app/finders/spree/option_values/find_available.rb +0 -28
  1324. data/app/finders/spree/orders/find_complete.rb +0 -114
  1325. data/app/finders/spree/orders/find_current.rb +0 -24
  1326. data/app/finders/spree/orders/finder_helper.rb +0 -17
  1327. data/app/finders/spree/products/find.rb +0 -328
  1328. data/app/finders/spree/taxons/find.rb +0 -99
  1329. data/app/finders/spree/variants/find.rb +0 -30
  1330. data/app/finders/spree/variants/option_types_finder.rb +0 -21
  1331. data/app/helpers/spree/addresses_helper.rb +0 -97
  1332. data/app/helpers/spree/base_helper.rb +0 -132
  1333. data/app/helpers/spree/currency_helper.rb +0 -46
  1334. data/app/helpers/spree/integrations_helper.rb +0 -15
  1335. data/app/helpers/spree/locale_helper.rb +0 -44
  1336. data/app/helpers/spree/localized_names_helper.rb +0 -25
  1337. data/app/helpers/spree/products_helper.rb +0 -147
  1338. data/app/helpers/spree/shipment_helper.rb +0 -12
  1339. data/app/javascript/spree/core/controllers/address_autocomplete_controller.js +0 -230
  1340. data/app/javascript/spree/core/controllers/address_form_controller.js +0 -98
  1341. data/app/javascript/spree/core/controllers/disable_submit_button_controller.js +0 -19
  1342. data/app/javascript/spree/core/controllers/enable_button_controller.js +0 -29
  1343. data/app/javascript/spree/core/helpers/address_autocomplete/google_places_suggestions_provider.js +0 -161
  1344. data/app/javascript/spree/core/helpers/debounce.js +0 -9
  1345. data/app/javascript/spree/core/helpers/scroll_lock.js +0 -25
  1346. data/app/jobs/spree/media/migrate_product_assets_job.rb +0 -83
  1347. data/app/jobs/spree/reports/generate_job.rb +0 -23
  1348. data/app/mailers/spree/report_mailer.rb +0 -20
  1349. data/app/models/concerns/spree/adjustment_source.rb +0 -58
  1350. data/app/models/concerns/spree/default_price.rb +0 -138
  1351. data/app/models/concerns/spree/display_on.rb +0 -50
  1352. data/app/models/concerns/spree/image_methods.rb +0 -40
  1353. data/app/models/concerns/spree/legacy_multi_store_support.rb +0 -48
  1354. data/app/models/concerns/spree/metafield_filterable.rb +0 -162
  1355. data/app/models/concerns/spree/metafields.rb +0 -256
  1356. data/app/models/concerns/spree/number_as_param.rb +0 -13
  1357. data/app/models/concerns/spree/store_scoped_resource.rb +0 -37
  1358. data/app/models/concerns/spree/unique_name.rb +0 -12
  1359. data/app/models/spree/adjustable/adjuster/base.rb +0 -25
  1360. data/app/models/spree/adjustable/adjuster/promotion.rb +0 -41
  1361. data/app/models/spree/adjustable/adjuster/tax.rb +0 -26
  1362. data/app/models/spree/adjustable/adjustments_updater.rb +0 -74
  1363. data/app/models/spree/adjustable/promotion_accumulator.rb +0 -78
  1364. data/app/models/spree/adjustment.rb +0 -130
  1365. data/app/models/spree/asset/support/active_storage.rb +0 -26
  1366. data/app/models/spree/calculator/default_tax.rb +0 -87
  1367. data/app/models/spree/calculator/returns/default_refund_amount.rb +0 -40
  1368. data/app/models/spree/customer_return.rb +0 -94
  1369. data/app/models/spree/image/configuration/active_storage.rb +0 -11
  1370. data/app/models/spree/image.rb +0 -6
  1371. data/app/models/spree/legacy_admin_user.rb +0 -31
  1372. data/app/models/spree/legacy_user.rb +0 -33
  1373. data/app/models/spree/log_entry.rb +0 -30
  1374. data/app/models/spree/metafield_definition/search_capabilities.rb +0 -104
  1375. data/app/models/spree/metafields/boolean.rb +0 -15
  1376. data/app/models/spree/metafields/json.rb +0 -37
  1377. data/app/models/spree/metafields/long_text.rb +0 -11
  1378. data/app/models/spree/metafields/number.rb +0 -23
  1379. data/app/models/spree/metafields/rich_text.rb +0 -18
  1380. data/app/models/spree/metafields/short_text.rb +0 -15
  1381. data/app/models/spree/option_type_prototype.rb +0 -9
  1382. data/app/models/spree/order/address_book.rb +0 -100
  1383. data/app/models/spree/order/checkout.rb +0 -350
  1384. data/app/models/spree/order/currency_updater.rb +0 -37
  1385. data/app/models/spree/order/digital.rb +0 -60
  1386. data/app/models/spree/order/gift_card.rb +0 -71
  1387. data/app/models/spree/order/payments.rb +0 -64
  1388. data/app/models/spree/order/store_credit.rb +0 -110
  1389. data/app/models/spree/order/webhooks.rb +0 -19
  1390. data/app/models/spree/order_approval.rb +0 -19
  1391. data/app/models/spree/order_cancellation.rb +0 -19
  1392. data/app/models/spree/order_contents.rb +0 -31
  1393. data/app/models/spree/order_routing/strategy/legacy.rb +0 -33
  1394. data/app/models/spree/payment/webhooks.rb +0 -15
  1395. data/app/models/spree/permission_sets/base.rb +0 -81
  1396. data/app/models/spree/permission_sets/configuration_management.rb +0 -64
  1397. data/app/models/spree/permission_sets/dashboard_display.rb +0 -17
  1398. data/app/models/spree/permission_sets/default_customer.rb +0 -83
  1399. data/app/models/spree/permission_sets/order_display.rb +0 -27
  1400. data/app/models/spree/permission_sets/order_management.rb +0 -33
  1401. data/app/models/spree/permission_sets/product_display.rb +0 -27
  1402. data/app/models/spree/permission_sets/product_management.rb +0 -28
  1403. data/app/models/spree/permission_sets/promotion_management.rb +0 -22
  1404. data/app/models/spree/permission_sets/role_management.rb +0 -21
  1405. data/app/models/spree/permission_sets/stock_display.rb +0 -19
  1406. data/app/models/spree/permission_sets/stock_management.rb +0 -19
  1407. data/app/models/spree/permission_sets/super_user.rb +0 -28
  1408. data/app/models/spree/permission_sets/user_display.rb +0 -19
  1409. data/app/models/spree/permission_sets/user_management.rb +0 -20
  1410. data/app/models/spree/product/webhooks.rb +0 -17
  1411. data/app/models/spree/prototype_taxon.rb +0 -9
  1412. data/app/models/spree/reimbursement/credit.rb +0 -27
  1413. data/app/models/spree/reimbursement/reimbursement_type_engine.rb +0 -44
  1414. data/app/models/spree/reimbursement/reimbursement_type_validator.rb +0 -15
  1415. data/app/models/spree/reimbursement.rb +0 -167
  1416. data/app/models/spree/reimbursement_performer.rb +0 -34
  1417. data/app/models/spree/reimbursement_tax_calculator.rb +0 -37
  1418. data/app/models/spree/reimbursement_type/credit.rb +0 -13
  1419. data/app/models/spree/reimbursement_type/exchange.rb +0 -9
  1420. data/app/models/spree/reimbursement_type/original_payment.rb +0 -13
  1421. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +0 -64
  1422. data/app/models/spree/reimbursement_type/store_credit.rb +0 -20
  1423. data/app/models/spree/reimbursement_type.rb +0 -22
  1424. data/app/models/spree/report.rb +0 -140
  1425. data/app/models/spree/report_line_item.rb +0 -27
  1426. data/app/models/spree/report_line_items/products_performance.rb +0 -76
  1427. data/app/models/spree/report_line_items/sales_total.rb +0 -49
  1428. data/app/models/spree/reports/products_performance.rb +0 -44
  1429. data/app/models/spree/reports/sales_total.rb +0 -18
  1430. data/app/models/spree/return_authorization.rb +0 -109
  1431. data/app/models/spree/return_item/eligibility_validator/base_validator.rb +0 -24
  1432. data/app/models/spree/return_item/eligibility_validator/default.rb +0 -30
  1433. data/app/models/spree/return_item/eligibility_validator/inventory_shipped.rb +0 -16
  1434. data/app/models/spree/return_item/eligibility_validator/no_reimbursements.rb +0 -16
  1435. data/app/models/spree/return_item/eligibility_validator/order_completed.rb +0 -16
  1436. data/app/models/spree/return_item/eligibility_validator/rma_required.rb +0 -16
  1437. data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +0 -16
  1438. data/app/models/spree/return_item/exchange_variant_eligibility/same_option_value.rb +0 -34
  1439. data/app/models/spree/return_item/exchange_variant_eligibility/same_product.rb +0 -9
  1440. data/app/models/spree/return_item.rb +0 -287
  1441. data/app/models/spree/returns_calculator.rb +0 -7
  1442. data/app/models/spree/search_provider/meilisearch.rb +0 -551
  1443. data/app/models/spree/shipment/custom_events.rb +0 -47
  1444. data/app/models/spree/shipment/webhooks.rb +0 -11
  1445. data/app/models/spree/shipment_handler.rb +0 -38
  1446. data/app/models/spree/shipping_category.rb +0 -25
  1447. data/app/models/spree/shipping_method_category.rb +0 -8
  1448. data/app/models/spree/shipping_method_zone.rb +0 -8
  1449. data/app/models/spree/state_change.rb +0 -12
  1450. data/app/models/spree/stock/splitter/digital.rb +0 -35
  1451. data/app/models/spree/stock/splitter/shipping_category.rb +0 -31
  1452. data/app/models/spree/stock_item/webhooks.rb +0 -6
  1453. data/app/models/spree/stock_movement/webhooks.rb +0 -6
  1454. data/app/models/spree/variant/webhooks.rb +0 -6
  1455. data/app/presenters/spree/csv/metafields_helper.rb +0 -17
  1456. data/app/presenters/spree/search_provider/product_presenter.rb +0 -158
  1457. data/app/presenters/spree/variant_presenter.rb +0 -81
  1458. data/app/presenters/spree/variants/option_types_presenter.rb +0 -87
  1459. data/app/services/spree/account/addresses/create.rb +0 -8
  1460. data/app/services/spree/account/addresses/update.rb +0 -8
  1461. data/app/services/spree/account/create.rb +0 -17
  1462. data/app/services/spree/account/update.rb +0 -15
  1463. data/app/services/spree/cart/add_item.rb +0 -63
  1464. data/app/services/spree/cart/associate.rb +0 -29
  1465. data/app/services/spree/cart/change_currency.rb +0 -27
  1466. data/app/services/spree/cart/create.rb +0 -26
  1467. data/app/services/spree/cart/destroy.rb +0 -50
  1468. data/app/services/spree/cart/empty.rb +0 -38
  1469. data/app/services/spree/cart/estimate_shipping_rates.rb +0 -39
  1470. data/app/services/spree/cart/recalculate.rb +0 -35
  1471. data/app/services/spree/cart/remove_item.rb +0 -39
  1472. data/app/services/spree/cart/remove_line_item.rb +0 -28
  1473. data/app/services/spree/cart/remove_out_of_stock_items.rb +0 -65
  1474. data/app/services/spree/cart/set_quantity.rb +0 -32
  1475. data/app/services/spree/cart/update.rb +0 -37
  1476. data/app/services/spree/carts/complete.rb +0 -50
  1477. data/app/services/spree/carts/upsert_items.rb +0 -76
  1478. data/app/services/spree/checkout/complete.rb +0 -23
  1479. data/app/services/spree/checkout/get_shipping_rates.rb +0 -52
  1480. data/app/services/spree/checkout/next.rb +0 -13
  1481. data/app/services/spree/checkout/select_shipping_method.rb +0 -63
  1482. data/app/services/spree/checkout/update.rb +0 -72
  1483. data/app/services/spree/credit_cards/destroy.rb +0 -25
  1484. data/app/services/spree/fulfillments/create.rb +0 -259
  1485. data/app/services/spree/gift_cards/apply.rb +0 -78
  1486. data/app/services/spree/gift_cards/redeem.rb +0 -17
  1487. data/app/services/spree/gift_cards/remove.rb +0 -39
  1488. data/app/services/spree/line_items/create.rb +0 -20
  1489. data/app/services/spree/line_items/destroy.rb +0 -18
  1490. data/app/services/spree/line_items/helper.rb +0 -11
  1491. data/app/services/spree/line_items/update.rb +0 -17
  1492. data/app/services/spree/orders/build_shipments.rb +0 -29
  1493. data/app/services/spree/orders/cancel.rb +0 -54
  1494. data/app/services/spree/orders/complete.rb +0 -53
  1495. data/app/services/spree/orders/update_contact_information.rb +0 -19
  1496. data/app/services/spree/orders/upsert_items.rb +0 -70
  1497. data/app/services/spree/payments/handle_webhook.rb +0 -57
  1498. data/app/services/spree/search_provider/metafield_schema.rb +0 -144
  1499. data/app/services/spree/seeds/countries.rb +0 -35
  1500. data/app/services/spree/seeds/default_reimbursement_types.rb +0 -12
  1501. data/app/services/spree/seeds/shipping_categories.rb +0 -12
  1502. data/app/services/spree/seeds/states.rb +0 -82
  1503. data/app/services/spree/seeds/stock_locations.rb +0 -18
  1504. data/app/services/spree/seeds/store_credit_categories.rb +0 -14
  1505. data/app/services/spree/seeds/zones.rb +0 -52
  1506. data/app/services/spree/shipments/add_item.rb +0 -32
  1507. data/app/services/spree/shipments/change_state.rb +0 -14
  1508. data/app/services/spree/shipments/create.rb +0 -48
  1509. data/app/services/spree/shipments/helper.rb +0 -23
  1510. data/app/services/spree/shipments/remove_item.rb +0 -55
  1511. data/app/services/spree/stores/settings_defaults_by_country.rb +0 -38
  1512. data/app/services/spree/themes/duplicator.rb +0 -40
  1513. data/app/sorters/spree/base_sorter.rb +0 -47
  1514. data/app/sorters/spree/classifications/sort.rb +0 -68
  1515. data/app/sorters/spree/products/sort.rb +0 -73
  1516. data/app/subscribers/spree/report_subscriber.rb +0 -26
  1517. data/app/views/spree/addresses/_form.html.erb +0 -59
  1518. data/app/views/spree/addresses/_suggestions_box.erb +0 -14
  1519. data/app/views/spree/admin_user_mailer/confirmation_email.html.erb +0 -7
  1520. data/app/views/spree/report_mailer/report_done.html.erb +0 -7
  1521. data/app/views/spree/shared/_google_places_api_loader.html.erb +0 -7
  1522. data/app/views/spree/shared/_mailer_line_item.html.erb +0 -12
  1523. data/app/views/spree/shared/_payment.html.erb +0 -52
  1524. data/config/importmap.rb +0 -15
  1525. data/config/initializers/carmen.rb +0 -23
  1526. data/config/initializers/rails61_fixes.rb +0 -1
  1527. data/db/migrate/20250120152208_add_default_locale_to_action_text_rich_texts.rb +0 -7
  1528. data/db/migrate/20250122113708_add_first_and_last_name_to_spree_admin_class.rb +0 -9
  1529. data/db/migrate/20250204162453_create_spree_reports.rb +0 -13
  1530. data/db/migrate/20250217171018_create_action_text_video_embeds.rb +0 -11
  1531. data/db/migrate/20250508060800_add_selected_locale_to_spree_admin_users.rb +0 -8
  1532. data/db/migrate/20260429000001_create_spree_order_cancellations.rb +0 -25
  1533. data/db/migrate/20260429000002_create_spree_order_approvals.rb +0 -22
  1534. data/db/sample_data/markets.rb +0 -64
  1535. data/db/sample_data/metafield_definitions.rb +0 -7
  1536. data/db/sample_data/shipping_methods.rb +0 -61
  1537. data/lib/generators/spree/authentication/custom/custom_generator.rb +0 -49
  1538. data/lib/generators/spree/authentication/custom/templates/authentication_helpers.rb.tt +0 -50
  1539. data/lib/generators/spree/authentication/devise/devise_generator.rb +0 -84
  1540. data/lib/generators/spree/authentication/devise/templates/authentication_helpers.rb.tt +0 -50
  1541. data/lib/generators/spree/dummy/templates/app/assets/config/manifest.js +0 -0
  1542. data/lib/spree/core/components.rb +0 -31
  1543. data/lib/spree/core/controller_helpers/auth.rb +0 -52
  1544. data/lib/spree/core/controller_helpers/currency.rb +0 -59
  1545. data/lib/spree/core/controller_helpers/locale.rb +0 -99
  1546. data/lib/spree/core/controller_helpers/order.rb +0 -172
  1547. data/lib/spree/core/controller_helpers/strong_parameters.rb +0 -48
  1548. data/lib/spree/core/controller_helpers/turbo.rb +0 -19
  1549. data/lib/spree/core/partials.rb +0 -42
  1550. data/lib/spree/core/previews/report_preview.rb +0 -40
  1551. data/lib/spree/permitted_attributes.rb +0 -337
  1552. data/lib/spree/testing_support/authorization_helpers.rb +0 -72
  1553. data/lib/spree/testing_support/caching.rb +0 -47
  1554. data/lib/spree/testing_support/capybara_config.rb +0 -45
  1555. data/lib/spree/testing_support/capybara_ext.rb +0 -83
  1556. data/lib/spree/testing_support/controller_requests.rb +0 -11
  1557. data/lib/spree/testing_support/factories/adjustment_factory.rb +0 -28
  1558. data/lib/spree/testing_support/factories/asset_factory.rb +0 -12
  1559. data/lib/spree/testing_support/factories/customer_return_factory.rb +0 -36
  1560. data/lib/spree/testing_support/factories/digital_factory.rb +0 -10
  1561. data/lib/spree/testing_support/factories/image_factory.rb +0 -11
  1562. data/lib/spree/testing_support/factories/inventory_unit_factory.rb +0 -18
  1563. data/lib/spree/testing_support/factories/log_entry_factory.rb +0 -6
  1564. data/lib/spree/testing_support/factories/metafield_definition_factory.rb +0 -82
  1565. data/lib/spree/testing_support/factories/metafield_factory.rb +0 -68
  1566. data/lib/spree/testing_support/factories/prototype_factory.rb +0 -9
  1567. data/lib/spree/testing_support/factories/reimbursement_credit_factory.rb +0 -7
  1568. data/lib/spree/testing_support/factories/reimbursement_factory.rb +0 -16
  1569. data/lib/spree/testing_support/factories/reimbursement_type_factory.rb +0 -7
  1570. data/lib/spree/testing_support/factories/report_factory.rb +0 -33
  1571. data/lib/spree/testing_support/factories/return_authorization_factory.rb +0 -21
  1572. data/lib/spree/testing_support/factories/return_item_factory.rb +0 -14
  1573. data/lib/spree/testing_support/factories/shipment_factory.rb +0 -21
  1574. data/lib/spree/testing_support/factories/shipping_category_factory.rb +0 -9
  1575. data/lib/spree/testing_support/factories/shipping_method_factory.rb +0 -31
  1576. data/lib/spree/testing_support/factories/shipping_rate_factory.rb +0 -7
  1577. data/lib/spree/testing_support/factories/state_change_factory.rb +0 -8
  1578. data/lib/spree/testing_support/factories/stock_item_factory.rb +0 -22
  1579. data/lib/spree/testing_support/factories/store_credit_category_factory.rb +0 -9
  1580. data/lib/spree/testing_support/factories/store_credit_type_factory.rb +0 -16
  1581. data/lib/spree/testing_support/factories/wished_variant_factory.rb +0 -6
  1582. data/lib/spree/webhooks.rb +0 -22
  1583. data/lib/tasks/role_users.rake +0 -21
  1584. data/vendor/javascript/@rails--request.js.js +0 -4
  1585. data/vendor/javascript/@stimulus-components--auto-submit.js +0 -4
  1586. data/vendor/javascript/stimulus-reveal-controller.js +0 -4
  1587. data/vendor/javascript/stimulus-textarea-autogrow.js +0 -4
  1588. data/vendor/javascript/tailwindcss-stimulus-components.js +0 -4
@@ -0,0 +1,66 @@
1
+ module Spree
2
+ # A number derived from the parent purchase rather than generated and
3
+ # stored (docs/plans/6.0-document-numbers.md): `R1001-F1`, `R1001-P2`.
4
+ #
5
+ # Fulfillments and payments are children of one order, and a number that
6
+ # names its parent reads better everywhere it appears — a merchant reading
7
+ # `R1001-F2` in a support conversation knows immediately which order and
8
+ # which parcel, where `F0000123456` told them nothing. It also costs
9
+ # nothing to maintain: no counter, no collision handling, and the child
10
+ # automatically follows whatever format the merchant chose for orders.
11
+ #
12
+ # Rows created before 6.0 keep their stored number, so gateway references
13
+ # and packing slips already in the wild still resolve. New rows never write
14
+ # the column — it is frozen legacy data awaiting the 6.1 drop.
15
+ module DerivedNumber
16
+ extend ActiveSupport::Concern
17
+
18
+ class_methods do
19
+ # @param infix [String] separates the parent number from the position,
20
+ # e.g. 'F' for fulfillments
21
+ def derives_number(infix:)
22
+ class_attribute :number_infix, default: infix, instance_writer: false
23
+ end
24
+ end
25
+
26
+ # @return [String, nil] the stored number on legacy rows, otherwise one
27
+ # derived from the parent purchase and this record's position among its
28
+ # siblings
29
+ def number
30
+ stored = self[:number]
31
+ return stored if stored.present?
32
+
33
+ parent = owner
34
+ return if parent.nil?
35
+
36
+ "#{parent.number}-#{self.class.number_infix}#{position_among_siblings}"
37
+ end
38
+
39
+ private
40
+
41
+ # Position is 1-based over siblings ordered by id, counting canceled and
42
+ # failed rows so a label never shifts when a sibling changes status. An
43
+ # unsaved record sorts last, which is what a merchant watching a new row
44
+ # appear expects.
45
+ def position_among_siblings
46
+ scope = sibling_scope
47
+ return 1 if scope.nil?
48
+
49
+ earlier = id.nil? ? scope.count : scope.where(scope.arel_table[:id].lt(id)).count
50
+
51
+ earlier + 1
52
+ end
53
+
54
+ # The siblings sharing this record's parent. Nil when there is no parent
55
+ # to group by.
56
+ def sibling_scope
57
+ parent = owner
58
+ return if parent.nil?
59
+
60
+ association = self.class.name.demodulize.underscore.pluralize
61
+ return unless parent.respond_to?(association)
62
+
63
+ parent.public_send(association).unscope(:order)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,89 @@
1
+ module Spree
2
+ # Anything that keeps an address book: a customer, a company node, and
3
+ # whatever comes next.
4
+ #
5
+ # Owners already differ in what they call their default slots — a customer
6
+ # has +bill_address_id+ / +ship_address_id+, a company node
7
+ # +default_bill_address_id+ / +default_ship_address_id+ — so the columns are
8
+ # declared once here and every caller asks the owner instead of knowing
9
+ # which of them it is holding.
10
+ #
11
+ # class Spree::Company < Spree.base_class
12
+ # has_address_book bill: :default_bill_address_id, ship: :default_ship_address_id
13
+ # end
14
+ module HasAddressBook
15
+ extend ActiveSupport::Concern
16
+
17
+ class_methods do
18
+ # @param bill [Symbol] column holding the default billing address id
19
+ # @param ship [Symbol] column holding the default shipping address id
20
+ def has_address_book(bill:, ship:)
21
+ class_attribute :default_address_columns, instance_writer: false, default: { bill: bill, ship: ship }
22
+ end
23
+ end
24
+
25
+ # Points this owner's default slots at an address.
26
+ #
27
+ # Writes the columns directly: callers have already established that the
28
+ # address is this owner's, so the ownership validation this skips cannot
29
+ # fail, and skipping it avoids re-running a whole validation set to move
30
+ # one foreign key.
31
+ #
32
+ # Each flag has three meanings, and they are all different: true promotes
33
+ # this address, false gives up the slot — but only when this address is
34
+ # what currently holds it, since another entry's default is not this
35
+ # caller's business — and nil leaves the slot alone.
36
+ #
37
+ # @param address_id [Integer]
38
+ # @param billing [Boolean, nil] promote to, or release, the billing slot
39
+ # @param shipping [Boolean, nil] promote to, or release, the shipping slot
40
+ def assign_default_address(address_id:, billing: true, shipping: true)
41
+ promoted = {}
42
+ released = []
43
+
44
+ { bill: billing, ship: shipping }.each do |kind, flag|
45
+ column = default_address_columns[kind]
46
+
47
+ if flag
48
+ promoted[column] = address_id
49
+ elsif flag == false
50
+ released << column
51
+ end
52
+ end
53
+
54
+ promote_default_columns(promoted)
55
+ release_default_columns(released, address_id)
56
+
57
+ # Promotion writes the in-memory attributes on its way through; a
58
+ # release goes around them, so only that leaves this instance stale.
59
+ reload if persisted? && released.any?
60
+ end
61
+
62
+ # @param kind [Symbol] :bill or :ship
63
+ # @return [Integer, nil] the address this owner prefills that slot with
64
+ def default_address_id(kind)
65
+ public_send(default_address_columns.fetch(kind))
66
+ end
67
+
68
+ private
69
+
70
+ def promote_default_columns(columns)
71
+ return if columns.empty?
72
+
73
+ update_columns(**columns, updated_at: Time.current)
74
+ end
75
+
76
+ # Released in one conditional statement rather than read-then-write: a
77
+ # request giving up a slot must not undo a promotion that landed between
78
+ # the two. The WHERE clause is the check, so a slot already moved on is
79
+ # simply not matched.
80
+ def release_default_columns(columns, address_id)
81
+ return if columns.empty?
82
+
83
+ columns.each do |column|
84
+ self.class.where(id: id, column => address_id).
85
+ update_all(column => nil, updated_at: Time.current)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,360 @@
1
+ module Spree
2
+ module HasCustomFields
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ # @param key_with_namespace [String] the dotted `"namespace.key"` form
7
+ # @param store [Spree::Store, nil] the store the definition belongs to;
8
+ # defaults to the current request's store, since definitions are
9
+ # store-owned and there is no global schema to fall back on.
10
+ def ensure_custom_field_definition_exists!(key_with_namespace, store: Spree::Current.store)
11
+ namespace, key = extract_namespace_and_key(key_with_namespace)
12
+ raise ArgumentError, 'a store is required to create a custom field definition' if store.nil?
13
+
14
+ store.custom_field_definitions.find_or_create_by!(
15
+ namespace: namespace, key: key, resource_type: self.name
16
+ )
17
+ end
18
+
19
+ def extract_namespace_and_key(key_with_namespace)
20
+ namespace = key_with_namespace.to_s.split('.').first
21
+ key = key_with_namespace.to_s.split('.').last
22
+ [namespace, key]
23
+ end
24
+
25
+ # Deprecated 6.0 names, removed in 6.1.
26
+ def ensure_metafield_definition_exists!(key_with_namespace, store: Spree::Current.store)
27
+ Spree::Deprecation.warn('ensure_metafield_definition_exists! is deprecated and will be removed in Spree 6.1. Use ensure_custom_field_definition_exists! instead.')
28
+ ensure_custom_field_definition_exists!(key_with_namespace, store: store)
29
+ end
30
+
31
+ def with_metafield_key(key_with_namespace)
32
+ Spree::Deprecation.warn('.with_metafield_key is deprecated and will be removed in Spree 6.1. Use .with_custom_field_key instead.')
33
+ with_custom_field_key(key_with_namespace)
34
+ end
35
+
36
+ def with_metafield_key_value(key_with_namespace, value)
37
+ Spree::Deprecation.warn('.with_metafield_key_value is deprecated and will be removed in Spree 6.1. Use .with_custom_field_key_value instead.')
38
+ with_custom_field_key_value(key_with_namespace, value)
39
+ end
40
+ end
41
+
42
+ included do
43
+ has_many :custom_fields, -> { includes(:custom_field_definition) }, as: :resource, class_name: 'Spree::CustomField', dependent: :destroy
44
+ has_many :storefront_custom_fields, -> { includes(:custom_field_definition).storefront_visible }, as: :resource, class_name: 'Spree::CustomField'
45
+
46
+ # Deprecated 6.0 association names, removed in 6.1. `private_metafields`
47
+ # has no replacement — read `custom_fields` and filter, or query
48
+ # Spree::CustomField.admin_only directly.
49
+ has_many :metafields, -> { includes(:custom_field_definition) }, as: :resource, class_name: 'Spree::CustomField', deprecated: true
50
+ has_many :public_metafields, -> { includes(:custom_field_definition).storefront_visible }, as: :resource, class_name: 'Spree::CustomField', deprecated: true
51
+ has_many :private_metafields, -> { includes(:custom_field_definition).admin_only }, as: :resource, class_name: 'Spree::CustomField', deprecated: true
52
+
53
+ accepts_nested_attributes_for :custom_fields, allow_destroy: true, reject_if: lambda { |attrs|
54
+ attrs[:custom_field_definition_id].blank? || (attrs[:id].blank? && attrs[:value].blank?)
55
+ }
56
+
57
+ # Override custom_fields_attributes= to automatically mark existing custom fields
58
+ # with empty values for destruction
59
+ def custom_fields_attributes=(attributes)
60
+ attributes = attributes.values if attributes.is_a?(Hash)
61
+
62
+ attributes.each do |attrs|
63
+ # If this is an existing custom field (has an id) and value is blank,
64
+ # mark it for destruction
65
+ if attrs[:id].present? && value_blank?(attrs[:value])
66
+ attrs[:_destroy] = true
67
+ end
68
+ end
69
+
70
+ super(attributes)
71
+ end
72
+
73
+ # Bulk writer reached via flat params on the admin API v3
74
+ # (`custom_fields: [...]`); also works through
75
+ # `Model.new(permitted_params)` since Rails routes the key to this writer.
76
+ #
77
+ # Upsert semantics by `custom_field_definition_id`: existing entries
78
+ # for the same definition are updated, missing entries are created.
79
+ # Partial: definitions NOT in the array are left untouched, so the
80
+ # client can patch one field at a time without resending the rest.
81
+ # Blank values on an existing custom field destroy it (mirrors the dedicated
82
+ # endpoint's behavior via `custom_fields_attributes=`).
83
+ def custom_fields=(attributes)
84
+ return if attributes.blank?
85
+ return super(attributes) if attributes.first.is_a?(Spree::CustomField)
86
+
87
+ assign_custom_field_attrs(attributes)
88
+ end
89
+
90
+ after_save :apply_pending_custom_fields, if: -> { @pending_custom_field_attrs.present? }
91
+
92
+ scope :with_custom_field_key, ->(key_with_namespace) {
93
+ namespace, key = extract_namespace_and_key(key_with_namespace)
94
+ joins(custom_fields: :custom_field_definition).
95
+ where(Spree::CustomFieldDefinition.table_name => { namespace: namespace, key: key })
96
+ }
97
+ scope :with_custom_field_key_value, ->(key_with_namespace, value) {
98
+ namespace, key = extract_namespace_and_key(key_with_namespace)
99
+
100
+ joins(custom_fields: :custom_field_definition)
101
+ .where(Spree::CustomFieldDefinition.table_name => { namespace: namespace, key: key })
102
+ .where(Spree::CustomField.table_name => { value: value })
103
+ }
104
+
105
+ def extract_namespace_and_key(key_with_namespace)
106
+ self.class.extract_namespace_and_key(key_with_namespace)
107
+ end
108
+
109
+ # Upsert a single custom field value on this resource. The first
110
+ # argument locates the definition by any of:
111
+ #
112
+ # - `"namespace.key"` string — auto-creates the definition if missing
113
+ # (backend-internal callers that don't know the id upfront).
114
+ # - {Spree::CustomFieldDefinition} instance.
115
+ # - Integer / numeric String — raw definition id.
116
+ # - Prefixed-id String (`"cfdef_..."`) — decoded to the definition id.
117
+ #
118
+ # Blank values (nil or empty/whitespace string) destroy any existing
119
+ # custom field for the definition. Empty containers (`[]`, `{}`) and
120
+ # numeric / boolean falsy values are real values, not blanks.
121
+ #
122
+ # @param definition_or_key [String, Integer, Spree::CustomFieldDefinition]
123
+ # @param value [Object] the value to persist; type is enforced by the
124
+ # typed custom-field subclass (Boolean, Number, Json, ShortText, …).
125
+ # @return [Spree::CustomField, nil] the persisted custom field, or nil when
126
+ # the value was blank and any existing row was destroyed.
127
+ # @raise [ArgumentError] if `definition_or_key` doesn't resolve to a
128
+ # known definition.
129
+ def set_custom_field(definition_or_key, value)
130
+ definition_id = resolve_custom_field_definition_id(definition_or_key)
131
+ custom_field = custom_fields.find_or_initialize_by(custom_field_definition_id: definition_id)
132
+ if value_blank?(value)
133
+ custom_field.destroy if custom_field.persisted?
134
+ return nil
135
+ end
136
+
137
+ # JSON custom fields store canonical JSON in the underlying text column.
138
+ # Coerce Hash/Array values BEFORE assignment, since the STI subclass
139
+ # (`Spree::CustomFields::Json`) isn't switched on until before_validation,
140
+ # so its custom `value=` writer doesn't run yet on a fresh
141
+ # `find_or_initialize_by` record.
142
+ if (value.is_a?(Hash) || value.is_a?(Array)) &&
143
+ custom_field.custom_field_definition&.field_type == 'json'
144
+ value = value.to_json
145
+ end
146
+
147
+ custom_field.value = value
148
+ custom_field.save!
149
+ custom_field
150
+ end
151
+
152
+ def get_custom_field(key_with_namespace)
153
+ namespace, key = extract_namespace_and_key(key_with_namespace)
154
+ custom_fields.with_key(namespace, key).first
155
+ end
156
+
157
+ def has_custom_field?(key_with_namespace)
158
+ if key_with_namespace.is_a?(Spree::CustomFieldDefinition)
159
+ namespace = key_with_namespace.namespace
160
+ key = key_with_namespace.key
161
+ elsif key_with_namespace.is_a?(String)
162
+ namespace, key = extract_namespace_and_key(key_with_namespace)
163
+ else
164
+ raise ArgumentError, "Invalid key_with_namespace: #{key_with_namespace.inspect}"
165
+ end
166
+
167
+ custom_fields.with_key(namespace, key).exists?
168
+ end
169
+
170
+ # Deprecated 6.0 names, removed in 6.1.
171
+ def set_metafield(definition_or_key, value)
172
+ Spree::Deprecation.warn('#set_metafield is deprecated and will be removed in Spree 6.1. Use #set_custom_field instead.')
173
+ set_custom_field(definition_or_key, value)
174
+ end
175
+
176
+ def get_metafield(key_with_namespace)
177
+ Spree::Deprecation.warn('#get_metafield is deprecated and will be removed in Spree 6.1. Use #get_custom_field instead.')
178
+ get_custom_field(key_with_namespace)
179
+ end
180
+
181
+ def has_metafield?(key_with_namespace)
182
+ Spree::Deprecation.warn('#has_metafield? is deprecated and will be removed in Spree 6.1. Use #has_custom_field? instead.')
183
+ has_custom_field?(key_with_namespace)
184
+ end
185
+
186
+ # Legacy payloads key the definition as `metafield_definition_id`, which
187
+ # the new writer rejects — translate rather than silently dropping them.
188
+ def metafields_attributes=(attributes)
189
+ Spree::Deprecation.warn('#metafields_attributes= is deprecated and will be removed in Spree 6.1. Use #custom_fields_attributes= instead.')
190
+
191
+ attributes = attributes.values if attributes.is_a?(Hash)
192
+ translated = attributes.map do |attrs|
193
+ attrs = attrs.respond_to?(:to_h) ? attrs.to_h : attrs
194
+ attrs = attrs.with_indifferent_access
195
+ attrs[:custom_field_definition_id] ||= attrs.delete(:metafield_definition_id)
196
+ attrs
197
+ end
198
+
199
+ self.custom_fields_attributes = translated
200
+ end
201
+
202
+ private
203
+
204
+ # Decide whether a custom-field value should trigger the destroy-existing
205
+ # branch. Ruby's `blank?` reports `false`, `0`, `[]`, `{}` as blank, but
206
+ # for typed custom fields those are real values:
207
+ #
208
+ # - Boolean `false` / Numeric `0` — real values, never destroy.
209
+ # - Empty Array / Hash — a JSON custom field storing `[]` or `{}` is a
210
+ # meaningful value (an empty list / object), not a clear signal.
211
+ #
212
+ # Only `nil` and empty/whitespace strings count as "missing".
213
+ #
214
+ # @param value [Object]
215
+ # @return [Boolean]
216
+ def value_blank?(value)
217
+ return true if value.nil?
218
+ return value.strip.empty? if value.is_a?(String)
219
+
220
+ false
221
+ end
222
+
223
+ def assign_custom_field_attrs(attributes)
224
+ if new_record?
225
+ # Persisting custom_fields requires a persisted parent (resource_id NOT
226
+ # NULL). Stash the attrs and replay them after the parent is saved.
227
+ @pending_custom_field_attrs = attributes
228
+ return
229
+ end
230
+
231
+ apply_custom_field_attrs(attributes)
232
+ end
233
+
234
+ def apply_pending_custom_fields
235
+ attrs = @pending_custom_field_attrs
236
+ @pending_custom_field_attrs = nil
237
+ apply_custom_field_attrs(attrs)
238
+ end
239
+
240
+ def apply_custom_field_attrs(attributes)
241
+ attributes = attributes.values if attributes.is_a?(Hash)
242
+ attributes.each_with_index do |raw, index|
243
+ attrs = raw.respond_to?(:to_h) ? raw.to_h : raw
244
+ attrs = attrs.with_indifferent_access
245
+ definition_id = attrs[:custom_field_definition_id] || attrs[:metafield_definition_id]
246
+ next if definition_id.blank?
247
+
248
+ begin
249
+ set_custom_field(definition_id, attrs[:value])
250
+ rescue ArgumentError => e
251
+ # Convert an unknown / malformed definition id into a field-level
252
+ # validation error so the controller returns 422 with structured
253
+ # `details`, instead of leaking ArgumentError as a 400/500.
254
+ errors.add("custom_fields[#{index}].custom_field_definition_id", e.message)
255
+ raise ActiveRecord::RecordInvalid, self
256
+ end
257
+ end
258
+ end
259
+
260
+ # Resolve any of the supported reference shapes to a raw definition id.
261
+ # See {#set_custom_field} for the accepted shapes.
262
+ #
263
+ # Every shape is checked against this record's store: definitions are
264
+ # store-owned, so one store's record must not end up carrying another
265
+ # store's definition whichever way the caller names it.
266
+ #
267
+ # @param definition_or_key [String, Integer, Spree::CustomFieldDefinition]
268
+ # @return [Integer, String] the definition's primary key value (Integer
269
+ # for legacy integer-id setups, String for UUID setups).
270
+ # @raise [ArgumentError] for unknown / malformed input, or a definition
271
+ # belonging to another store.
272
+ def resolve_custom_field_definition_id(definition_or_key)
273
+ case definition_or_key
274
+ when Spree::CustomFieldDefinition
275
+ # A loaded record already carries its store, so compare in memory
276
+ # rather than paying a lookup to learn what is in hand.
277
+ unless definition_or_key.store_id == custom_field_definition_store.id
278
+ raise ArgumentError, "Unknown custom field definition id: #{definition_or_key.full_key.inspect}"
279
+ end
280
+
281
+ definition_or_key.id
282
+ when Integer
283
+ find_definition_id_in_store!(definition_or_key, definition_or_key)
284
+ when String
285
+ resolve_custom_field_definition_id_from_string(definition_or_key)
286
+ else
287
+ raise ArgumentError, "Invalid definition_or_key: #{definition_or_key.inspect}"
288
+ end
289
+ end
290
+
291
+ # @param value [String] one of: `"namespace.key"`, a prefixed id
292
+ # (`"cfdef_..."`), or a bare numeric id (`"42"`).
293
+ # @return [Integer, String] the resolved definition's primary key value.
294
+ # @raise [ArgumentError] if the string doesn't match any known shape.
295
+ def resolve_custom_field_definition_id_from_string(value)
296
+ # `"namespace.key"` — backend-internal callers that don't know the id;
297
+ # auto-create the definition if missing.
298
+ if value.include?('.')
299
+ namespace, key = extract_namespace_and_key(value)
300
+ return custom_field_definition_store.custom_field_definitions.find_or_create_by!(
301
+ namespace: namespace, key: key, resource_type: self.class.name
302
+ ).id
303
+ end
304
+
305
+ # Prefixed id (`"cfdef_..."`/`"mfd_..."`). Use the canonical predicate
306
+ # so single-segment names with underscores (e.g. `"product_specs"`)
307
+ # don't get mistaken for prefixed ids.
308
+ #
309
+ # Both id shapes are resolved through the store rather than the class.
310
+ # That is what stops one store's record carrying another store's
311
+ # definition, and it also covers the phantom-id case: Sqids will
312
+ # happily decode any all-lowercase alphanumeric string to an integer
313
+ # that matches no row, and without the existence check
314
+ # `find_or_initialize_by(custom_field_definition_id: phantom_id)` would
315
+ # later raise a confusing "CustomField definition must exist" 422
316
+ # instead of an "unknown id" one.
317
+ if Spree::PrefixedId.prefixed_id?(value)
318
+ decoded = Spree::CustomFieldDefinition.decode_prefixed_id(value)
319
+ return find_definition_id_in_store!(decoded, value)
320
+ end
321
+
322
+ # Bare numeric id ("42"). Reject anything else outright.
323
+ raise ArgumentError, "Invalid custom field definition reference: #{value.inspect}" unless /\A\d+\z/.match?(value)
324
+
325
+ find_definition_id_in_store!(value, value)
326
+ end
327
+
328
+ # @param id [Integer, String, nil] the decoded primary key
329
+ # @param reference [String] what the caller passed, for the error message
330
+ # @return [Integer, String] the definition's own primary key value
331
+ # @raise [ArgumentError] when this store has no such definition.
332
+ def find_definition_id_in_store!(id, reference)
333
+ definition = id && custom_field_definition_store.custom_field_definitions.find_by(id: id)
334
+ raise ArgumentError, "Unknown custom field definition id: #{reference.inspect}" if definition.nil?
335
+
336
+ definition.id
337
+ end
338
+
339
+ # The store whose custom-field schema this record's fields are defined
340
+ # in. A record that owns a store answers with it; one that reaches a
341
+ # store through its owner overrides this (see Spree::Payment,
342
+ # Spree::Variant); the genuinely global records — a customer, an
343
+ # address — fall through to the current request's store, since their
344
+ # fields still belong to one.
345
+ #
346
+ # Override rather than extending a chain here: which owner holds the
347
+ # store is the host's own fact, and a chain of `try`s silently answers
348
+ # for the wrong one when a host matches none of its steps.
349
+ #
350
+ # @return [Spree::Store]
351
+ # @raise [ArgumentError] when none is available.
352
+ def custom_field_definition_store
353
+ store = try(:store) || Spree::Current.store
354
+ raise ArgumentError, 'a store is required to resolve a custom field definition' if store.nil?
355
+
356
+ store
357
+ end
358
+ end
359
+ end
360
+ end
@@ -0,0 +1,95 @@
1
+ module Spree
2
+ # Gives a model identities in external systems (ERP, PIM, DAM, CRM) through
3
+ # {Spree::ExternalReference}. Opt-in per resource rather than on
4
+ # {Spree::Base}: only records a connector actually syncs need the association.
5
+ module HasExternalReferences
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ has_many :external_references, class_name: 'Spree::ExternalReference', as: :resource, dependent: :destroy
10
+
11
+ # Scope-friendly so controllers can chain it onto an already store-scoped
12
+ # relation: `current_store.products.with_external_id('erp', 'MAT-100')`.
13
+ # Scoping the lookup to the store is the caller's job, exactly as with any
14
+ # other id coming off a request.
15
+ scope :with_external_id, lambda { |system, external_id|
16
+ joins(:external_references).where(
17
+ spree_external_references: {
18
+ system: Spree::ExternalReference.normalize_system(system),
19
+ external_id: external_id.to_s.strip
20
+ }
21
+ )
22
+ }
23
+ end
24
+
25
+ # @param system [String, Symbol] the external system's key
26
+ # @return [String, nil] the identifier that system knows this record by
27
+ def external_id_for(system)
28
+ key = Spree::ExternalReference.normalize_system(system)
29
+
30
+ if external_references.loaded?
31
+ external_references.detect { |reference| reference.system == key }&.external_id
32
+ else
33
+ external_references.for_system(key).pick(:external_id)
34
+ end
35
+ end
36
+
37
+ # Creates or updates this record's identity in one external system.
38
+ #
39
+ # @param system [String, Symbol] the external system's key
40
+ # @param external_id [String, nil] blank removes the reference
41
+ # @param metadata [Hash, nil] connector bookkeeping (version, etag, synced at)
42
+ # @return [Spree::ExternalReference, nil] nil when the reference was removed
43
+ def set_external_id(system, external_id, metadata: nil)
44
+ key = Spree::ExternalReference.normalize_system(system)
45
+ reference = external_references.for_system(key).first
46
+
47
+ if external_id.to_s.strip.blank?
48
+ reference&.destroy
49
+ external_references.reset
50
+ return nil
51
+ end
52
+
53
+ reference ||= external_references.build(system: key)
54
+ reference.external_id = external_id
55
+ reference.metadata = metadata if metadata.present?
56
+ reference.store ||= external_reference_store
57
+ # A connector re-sending what it read is the steady state; an unchanged
58
+ # reference must not pay the two uniqueness SELECTs a save costs.
59
+ reference.save! if reference.new_record? || reference.changed?
60
+ # Reset rather than reload: the next reader refetches, and a batch of
61
+ # writes pays for one SELECT at the end instead of one per system.
62
+ external_references.reset
63
+ reference
64
+ end
65
+
66
+ # Writes several references at once, leaving systems the payload does not
67
+ # mention untouched — a connector states its own key without disturbing
68
+ # another system's. Accepts the `{ system => external_id }` map the admin
69
+ # serializers render, or a list of `{ system:, external_id: }` entries.
70
+ #
71
+ # @param references [Hash{String,Symbol=>String}, Array<Hash>]
72
+ # @return [void]
73
+ def assign_external_references(references)
74
+ Spree::ExternalReference.normalize_references(references).each do |reference|
75
+ set_external_id(reference[:system], reference[:external_id], metadata: reference[:metadata])
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ # A reference belongs to the same store as the record it identifies.
82
+ #
83
+ # Store-owning models answer directly;
84
+ # variants and stock levels carry no store of their own and reach it
85
+ # through the product. Anything else is left nil here — the reference
86
+ # includes {Spree::SingleStoreResource}, whose ensure_store callback
87
+ # falls back to the request's store, and stating that fallback twice
88
+ # would let the two quietly diverge.
89
+ def external_reference_store
90
+ return store if respond_to?(:store) && store.present?
91
+
92
+ product.store if respond_to?(:product) && product&.store.present?
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,71 @@
1
+ module Spree
2
+ # Geography as reference data (docs/plans/6.0-drop-country-state-models.md):
3
+ # a model stores ISO codes — `country_code`, and `state_code` where
4
+ # subdivisions matter — and reads them back as {Spree::Country} /
5
+ # {Spree::State} value objects.
6
+ #
7
+ # class Spree::StockLocation < Spree.base_class
8
+ # has_iso_geography
9
+ # end
10
+ #
11
+ # Included into {Spree::Base}, so the macro is available on every model and
12
+ # nothing happens until one calls it. Callers assign codes — the macro
13
+ # defines no country=/state= object writers; a model that needs them
14
+ # ({Spree::Address}) layers its own on top.
15
+ module HasIsoGeography
16
+ extend ActiveSupport::Concern
17
+
18
+ # Matching compares stored codes verbatim, so 'us' has to become 'US'
19
+ # before it is written. Applied through +normalizes+, it also normalizes
20
+ # values passed to `where` queries against these columns.
21
+ UPCASE = ->(value) { value.presence&.to_s&.upcase }
22
+
23
+ class_methods do
24
+ # @param state [Boolean] whether the model also carries a `state_code` column
25
+ def has_iso_geography(state: true)
26
+ normalizes :country_code, with: UPCASE
27
+
28
+ # @return [Spree::Country, nil]
29
+ define_method(:country) do
30
+ Spree::Country.by_iso(country_code) if country_code.present?
31
+ end
32
+
33
+ # A code nothing recognises is rejected rather than stored: every
34
+ # consumer matches codes verbatim, so a bad one silently matches
35
+ # nothing. Gated on change so historical rows stay updatable even if
36
+ # the registry's curation shifts under them.
37
+ validate :country_code_must_resolve, if: -> { new_record? || will_save_change_to_country_code? }
38
+ define_method(:country_code_must_resolve) do
39
+ return if country_code.blank?
40
+
41
+ errors.add(:country_code, :invalid) if Spree::Country.by_iso(country_code).nil?
42
+ end
43
+ private :country_code_must_resolve
44
+
45
+ return unless state
46
+
47
+ normalizes :state_code, with: UPCASE
48
+
49
+ # @return [Spree::State, nil]
50
+ define_method(:state) do
51
+ Spree::State.resolve(country_code, state_code) if country_code.present? && state_code.present?
52
+ end
53
+
54
+ # A subdivision code is only meaningful within its country, so it is
55
+ # checked against the country's own list (retired codes resolve
56
+ # through their successors). Without a country there is nothing to
57
+ # check against — the code is left alone.
58
+ validate :state_code_must_resolve,
59
+ if: -> { new_record? || will_save_change_to_state_code? || will_save_change_to_country_code? }
60
+ define_method(:state_code_must_resolve) do
61
+ return if state_code.blank? || country_code.blank?
62
+ # An unresolvable country already got its own error.
63
+ return if Spree::Country.by_iso(country_code).nil?
64
+
65
+ errors.add(:state_code, :invalid) if Spree::IsoData.subdivision_code(country_code, state_code).nil?
66
+ end
67
+ private :state_code_must_resolve
68
+ end
69
+ end
70
+ end
71
+ end