@spree/docs 0.1.177 → 0.1.178

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 (117) hide show
  1. package/dist/developer/cli/quickstart.md +1 -1
  2. package/dist/developer/contributing/creating-an-extension.md +2 -2
  3. package/dist/developer/core-concepts/addresses.md +3 -3
  4. package/dist/developer/core-concepts/architecture.md +4 -4
  5. package/dist/developer/core-concepts/calculators.md +2 -2
  6. package/dist/developer/core-concepts/carts.md +207 -0
  7. package/dist/developer/core-concepts/channels.md +3 -3
  8. package/dist/developer/core-concepts/customers.md +1 -1
  9. package/dist/developer/core-concepts/events.md +1 -1
  10. package/dist/developer/core-concepts/fulfillments.md +278 -0
  11. package/dist/developer/core-concepts/imports-exports.md +6 -18
  12. package/dist/developer/core-concepts/inventory.md +3 -3
  13. package/dist/developer/core-concepts/media.md +1 -1
  14. package/dist/developer/core-concepts/metafields.md +1 -1
  15. package/dist/developer/core-concepts/orders.md +92 -339
  16. package/dist/developer/core-concepts/payments.md +1 -1
  17. package/dist/developer/core-concepts/promotions.md +68 -195
  18. package/dist/developer/core-concepts/returns-exchanges-claims.md +173 -0
  19. package/dist/developer/core-concepts/store-credits-gift-cards.md +16 -18
  20. package/dist/developer/core-concepts/stores.md +1 -1
  21. package/dist/developer/core-concepts/taxes-discounts-fees.md +199 -0
  22. package/dist/developer/core-concepts/taxes.md +3 -3
  23. package/dist/developer/create-spree-app/quickstart.md +1 -1
  24. package/dist/developer/customization/api.md +36 -11
  25. package/dist/developer/customization/configuration.md +207 -37
  26. package/dist/developer/customization/decorators.md +8 -8
  27. package/dist/developer/customization/permissions.md +34 -229
  28. package/dist/developer/customization/quickstart.md +159 -108
  29. package/dist/developer/customization/validations.md +1 -1
  30. package/dist/developer/dashboard/overview.md +1 -1
  31. package/dist/developer/how-to/build-a-b2b-store.md +21 -0
  32. package/dist/developer/how-to/build-a-marketplace.md +25 -0
  33. package/dist/developer/how-to/custom-api-authentication.md +1 -1
  34. package/dist/developer/how-to/custom-delivery-rate-provider.md +242 -0
  35. package/dist/developer/how-to/custom-document-numbers.md +154 -0
  36. package/dist/developer/how-to/custom-order-routing.md +1 -1
  37. package/dist/developer/how-to/custom-payment-method.md +1 -1
  38. package/dist/developer/how-to/custom-promotion.md +76 -115
  39. package/dist/developer/how-to/custom-report.md +2 -2
  40. package/dist/developer/how-to/custom-stock-splitter.md +5 -5
  41. package/dist/developer/how-to/sell-digital-products.md +20 -0
  42. package/dist/developer/multi-tenant/quickstart.md +1 -1
  43. package/dist/developer/providers/dam.md +14 -0
  44. package/dist/developer/providers/erp.md +31 -0
  45. package/dist/developer/providers/fulfillment.md +25 -0
  46. package/dist/developer/{deployment/telemetry.md → providers/observability.md} +1 -1
  47. package/dist/developer/providers/overview.md +44 -0
  48. package/dist/developer/providers/pim.md +25 -0
  49. package/dist/developer/providers/sso.md +20 -0
  50. package/dist/developer/sdk/admin/extending.md +1 -1
  51. package/dist/developer/sdk/admin/quickstart.md +1 -1
  52. package/dist/developer/sdk/admin/resources.md +1 -1
  53. package/dist/developer/sdk/extending.md +1 -1
  54. package/dist/developer/tutorial/admin-api.md +13 -0
  55. package/dist/developer/tutorial/dashboard-plugin.md +14 -0
  56. package/dist/developer/tutorial/events.md +7 -161
  57. package/dist/developer/tutorial/introduction.md +15 -35
  58. package/dist/developer/tutorial/model.md +7 -98
  59. package/dist/developer/tutorial/store-api.md +13 -0
  60. package/dist/developer/tutorial/storefront.md +12 -0
  61. package/dist/developer/tutorial/testing.md +7 -711
  62. package/dist/developer/upgrades/5.6-to-6.0.md +2 -2
  63. package/package.json +1 -1
  64. package/dist/developer/admin/admin.md +0 -214
  65. package/dist/developer/admin/authentication.md +0 -59
  66. package/dist/developer/admin/components.md +0 -711
  67. package/dist/developer/admin/custom-css.md +0 -256
  68. package/dist/developer/admin/custom-javascript.md +0 -116
  69. package/dist/developer/admin/extending-ui.md +0 -1839
  70. package/dist/developer/admin/form-builder.md +0 -444
  71. package/dist/developer/admin/helper-methods.md +0 -531
  72. package/dist/developer/admin/navigation.md +0 -805
  73. package/dist/developer/admin/tables.md +0 -490
  74. package/dist/developer/advanced/adding_spree_to_rails_app.md +0 -92
  75. package/dist/developer/core-concepts/adjustments.md +0 -113
  76. package/dist/developer/core-concepts/reports.md +0 -208
  77. package/dist/developer/core-concepts/shipments.md +0 -307
  78. package/dist/developer/core-concepts/users.md +0 -303
  79. package/dist/developer/customization/authentication.md +0 -100
  80. package/dist/developer/customization/checkout.md +0 -202
  81. package/dist/developer/customization/emails.md +0 -18
  82. package/dist/developer/customization/routes.md +0 -24
  83. package/dist/developer/multi-vendor/installation.md +0 -61
  84. package/dist/developer/multi-vendor/quickstart.md +0 -17
  85. package/dist/developer/tutorial/admin.md +0 -206
  86. package/dist/developer/tutorial/api.md +0 -606
  87. package/dist/developer/tutorial/extending-models.md +0 -393
  88. package/dist/developer/tutorial/sdk.md +0 -170
  89. package/dist/developer/upgrades/2.0-to-2.1.md +0 -46
  90. package/dist/developer/upgrades/2.1-to-2.2.md +0 -59
  91. package/dist/developer/upgrades/2.2-to-2.3.md +0 -44
  92. package/dist/developer/upgrades/2.3-to-2.4.md +0 -42
  93. package/dist/developer/upgrades/3.0-to-3.1.md +0 -47
  94. package/dist/developer/upgrades/3.1-to-3.2.md +0 -34
  95. package/dist/developer/upgrades/3.2-to-3.3.md +0 -70
  96. package/dist/developer/upgrades/3.3-to-3.4.md +0 -36
  97. package/dist/developer/upgrades/3.4-to-3.5.md +0 -44
  98. package/dist/developer/upgrades/3.5-to-3.6.md +0 -40
  99. package/dist/developer/upgrades/3.6-to-3.7.md +0 -62
  100. package/dist/developer/upgrades/3.7-to-4.0.md +0 -152
  101. package/dist/developer/upgrades/4.0-to-4.1.md +0 -92
  102. package/dist/developer/upgrades/4.1-to-4.2.md +0 -109
  103. package/dist/developer/upgrades/4.10-to-5.0.md +0 -131
  104. package/dist/developer/upgrades/4.2-to-4.3.md +0 -100
  105. package/dist/developer/upgrades/4.3-to-4.4.md +0 -125
  106. package/dist/developer/upgrades/4.4-to-4.5.md +0 -94
  107. package/dist/developer/upgrades/4.5-to-4.6.md +0 -119
  108. package/dist/developer/upgrades/4.6-to-4.7.md +0 -39
  109. package/dist/developer/upgrades/4.8-to-4.9.md +0 -24
  110. package/dist/developer/upgrades/4.9-to-4.10.md +0 -24
  111. package/dist/developer/upgrades/4.x-to-4.8.md +0 -52
  112. package/dist/developer/upgrades/5.0-to-5.1.md +0 -28
  113. package/dist/developer/upgrades/5.1-to-5.2.md +0 -131
  114. package/dist/developer/upgrades/5.2-to-5.3.md +0 -338
  115. package/dist/developer/upgrades/5.3-to-5.4.md +0 -277
  116. package/dist/developer/upgrades/5.4-to-5.5.md +0 -301
  117. package/dist/developer/upgrades/5.5-to-5.6.md +0 -207
@@ -1,277 +0,0 @@
1
- ---
2
- title: Upgrading to Spree 5.4
3
- description: Upgrade a Spree 5.3 application to Spree 5.4 — remove spree_sample, update gems, run migrations, switch to AdminUserMethods, and backfill image thumbnail IDs.
4
- ---
5
-
6
- > **INFO:** Before proceeding to upgrade, please ensure you're at [Spree 5.3](5.2-to-5.3.md)
7
-
8
- ## Upgrade steps
9
-
10
- ### Remove `spree_sample` gem from your Gemfile
11
-
12
- Samples are now included in the `spree` gem. If you've added previously `spree_sample` to your Gemfile, remove it by running:
13
-
14
- ```bash
15
- bundle remove spree_sample
16
- ```
17
-
18
- ### Update gems
19
-
20
- ```bash
21
- bundle update
22
- ```
23
-
24
- ### Fetch and run missing migrations
25
-
26
- ```bash
27
- bin/rake spree:install:migrations && bin/rails db:migrate
28
- ```
29
-
30
- ### Fix your Admin user class
31
-
32
- Your admin user model needs to include the `Spree::AdminUserMethods` concern instead of `Spree::UserMethods`.
33
- Previously `UserMethods` bundled `AdminUserMethods` but that caused all kinds of issues.
34
-
35
- So if you have a model like this:
36
-
37
- ```ruby
38
- class Spree::AdminUser < Spree::Base
39
- include Spree::UserMethods
40
-
41
- # ... other model code ...
42
- end
43
- ```
44
-
45
- You need to change it to this:
46
-
47
- ```ruby
48
- class Spree::AdminUser < Spree::Base
49
- include Spree::AdminUserMethods
50
-
51
- # ... other model code ...
52
- end
53
- ```
54
-
55
- By default that file is located at `app/models/spree/admin_user.rb`.
56
-
57
- ### Backfill Image Thumbnail IDs
58
-
59
- Spree 5.4 adds a `primary_media` association to both `Product` and `Variant` models. This greatly speeds up rendering Product lists everywhere (API, Admin Dashboard and `spree_storefront`), as previously we've had to load all media/images for each product and determine which one is the one to render a thumbnail.
60
-
61
- To generate the new association you will need to run a rake task (both in development and production environments):
62
-
63
- ```bash
64
- bin/rails spree:media:backfill_primary_media
65
- ```
66
-
67
- As above, this process can take a while depending on the size of your product catalog.
68
-
69
- For new products this will be set automatically and you won't need to run this rake task more than once.
70
-
71
- ### Prefixed IDs
72
-
73
- Spree 5.4 by default uses prefixed IDs for resources (eg. `prod_6VsgxZbenF`) instead of just IDs from the database. These IDs are now used in Admin Dashboard, API v3, Events system and Webhooks.
74
-
75
- #### Event Subscribers
76
-
77
- If you previously added Subscribers for Events, eg. `order.completed` with code such as:
78
-
79
- ```ruby
80
- module MyApp
81
- class OrderAuditSubscriber < Spree::Subscriber
82
- subscribes_to 'order.completed'
83
-
84
- on 'order.completed', :log_order_completed
85
-
86
- private
87
-
88
- def find_order(event)
89
- Spree::Order.find(event.payload[:id])
90
- end
91
- end
92
- end
93
- ```
94
-
95
- You will need to update your code to use the new prefixed IDs, from:
96
-
97
- ```ruby
98
- Spree::Order.find(event.payload[:id])
99
- ```
100
-
101
- to:
102
-
103
- ```ruby
104
- Spree::Order.find_by_prefix_id!(event.payload[:id])
105
- ```
106
-
107
- You can also use `find_by_prefix_id` without the bang (`!`) to gracefully handle cases where the record might not exist.
108
-
109
- #### Adding Prefixed IDs support to your custom models
110
-
111
- All models inheriting from `Spree::Base` (or `Spree.base_class`) can support Prefixed IDs by adding the following code to your model:
112
-
113
- ```ruby
114
- class MyModel < Spree::Base
115
- has_prefix_id :mm
116
-
117
- # ...
118
- end
119
- ```
120
-
121
- Prefix length isn't limited by default, but we recommend to keep it short.
122
-
123
- ### Migrate Checkout Zones to Markets
124
-
125
- Spree 5.4 introduces [Markets](../core-concepts/markets.md) as the primary way to manage which countries are available for checkout, along with their currencies and locales. The legacy `checkout_zone` field on the Store model is now deprecated and will be removed in Spree 6.0.
126
-
127
- New stores automatically get a default market created from their `default_country` — no manual setup needed. For existing stores that used `checkout_zone`, run the migration rake task:
128
-
129
- ```bash
130
- bin/rake spree:markets:migrate_checkout_zones
131
- ```
132
-
133
- This will:
134
- 1. Read the `checkout_zone` countries from each store
135
- 2. Create a default Market with those countries, currency, and locale
136
- 3. Clear the `checkout_zone_id` column
137
-
138
- > **WARNING:** You will need to run this rake task locally and on your production environment. After running, verify your markets are set up correctly in the Admin Dashboard under **Settings → Markets**.
139
-
140
- #### Deprecated Store methods
141
-
142
- The following Store methods now emit deprecation warnings and will be removed in Spree 5.5:
143
-
144
- | Deprecated method | Replacement |
145
- |---|---|
146
- | `store.checkout_zone` | Use [Markets](../core-concepts/markets.md) to manage countries |
147
- | `store.checkout_zone=` | Use [Markets](../core-concepts/markets.md) to manage countries |
148
-
149
- The `store.default_country` reader now returns the first country (by name) from the store's default market. The `store.default_country_iso=` setter still works and is used to set the country when creating a store — a default market is automatically created from it.
150
-
151
- #### Code that references `checkout_zone` for tax
152
-
153
- If your application used `store.checkout_zone` as a tax zone fallback, update it to use `Spree::Zone.default_tax` instead:
154
-
155
- ```ruby
156
- # Before
157
- zone = current_store.checkout_zone
158
-
159
- # After
160
- zone = Spree::Zone.default_tax
161
- ```
162
-
163
- ### ActiveMerchant removed from Spree Core
164
-
165
- Spree 5.4 no longer depends on the `activemerchant` gem. All internal usages have been replaced with lightweight Spree-native classes:
166
-
167
- | ActiveMerchant class | Spree replacement |
168
- |---|---|
169
- | `ActiveMerchant::Billing::Response` | `Spree::PaymentResponse` |
170
- | `ActiveMerchant::ConnectionError` | `Spree::PaymentConnectionError` |
171
-
172
- `Spree::PaymentResponse` is a drop-in replacement with the same constructor signature:
173
-
174
- ```ruby
175
- Spree::PaymentResponse.new(success, message, params = {}, options = {})
176
- ```
177
-
178
- It supports the same methods: `success?`, `message`, `params`, `authorization`, `avs_result`, `cvv_result`, `test?`, and YAML serialization (for log entries).
179
-
180
- #### Updating custom payment methods
181
-
182
- If you have a custom payment method (gateway) that returns `ActiveMerchant::Billing::Response`, update it to return `Spree::PaymentResponse` instead:
183
-
184
- ```ruby
185
- # Before
186
- def authorize(money, source, options = {})
187
- # ...
188
- ActiveMerchant::Billing::Response.new(true, 'Success', {},
189
- authorization: transaction_id, test: test?)
190
- end
191
-
192
- # After
193
- def authorize(money, source, options = {})
194
- # ...
195
- Spree::PaymentResponse.new(true, 'Success', {},
196
- authorization: transaction_id, test: test?)
197
- end
198
- ```
199
-
200
- If your gateway rescues `ActiveMerchant::ConnectionError`, update it to rescue `Spree::PaymentConnectionError`:
201
-
202
- ```ruby
203
- # Before
204
- rescue ActiveMerchant::ConnectionError => e
205
-
206
- # After
207
- rescue Spree::PaymentConnectionError => e
208
- ```
209
-
210
- #### Using `spree_gateway` or other ActiveMerchant-based extensions
211
-
212
- If you use the [`spree_gateway`](https://github.com/spree/spree_gateway) gem or another extension that depends on ActiveMerchant, add `activemerchant` directly to your application's `Gemfile`:
213
-
214
- ```ruby
215
- gem 'activemerchant'
216
- ```
217
-
218
- These extensions will continue to work — Spree's `LogEntry#parsed_details` still deserializes `ActiveMerchant::Billing::Response` objects when the gem is present.
219
-
220
- #### Address hash method renamed
221
-
222
- `Spree::Address#active_merchant_hash` has been renamed to `#gateway_hash`. A backwards-compatible alias is provided, so existing code continues to work without changes.
223
-
224
- ### (Optional) Install Legacy API v2 extension
225
-
226
- Spree 5.4 ships with API v3, which marks deprecation of API v2. API v2 is still available but you need to install it separately. If you currently use API v2, you can do this by running the following command:
227
-
228
- ```bash
229
- bundle add spree_legacy_api_v2
230
- ```
231
-
232
- If you have tests for API v2 endpoints in your application, you will need to include some files in your `rails_helper.rb`:
233
-
234
- ```ruby
235
- require 'jsonapi/rspec'
236
- require 'spree_legacy_api_v2/testing_support/v2/base'
237
- require 'spree_legacy_api_v2/testing_support/factories'
238
- require 'spree_legacy_api_v2/testing_support/v2/current_order'
239
- require 'spree_legacy_api_v2/testing_support/v2/platform_contexts'
240
- require 'spree_legacy_api_v2/testing_support/v2/serializers_params'
241
-
242
- RSpec.configure do |config|
243
- config.include JSONAPI::RSpec, type: :request # required for API v2 request specs
244
- end
245
- ```
246
-
247
- Also, add `jsonapi-rspec` gem to your `Gemfile`:
248
-
249
- ```ruby
250
- gem 'jsonapi-rspec', group: :test
251
- ```
252
-
253
- And run `bundle install`
254
-
255
- ### (Optional) Install Legacy Product Properties extension
256
-
257
- Product Properties have been extracted from Spree core to a separate gem `spree_legacy_product_properties`. Product Properties were already deprecated in favor of [Metafields](../core-concepts/metafields.md) and disabled by default since Spree 5.1.
258
-
259
- If you have `product_properties_enabled: true` in your Spree configuration or rely on Product Properties in any way, install the extension:
260
-
261
- ```bash
262
- bundle add spree_legacy_product_properties
263
- ```
264
-
265
- No data migration is needed — the gem uses the same database tables. All existing product properties, property definitions, and associations will continue to work as before.
266
-
267
- > **WARNING:** If you skip this step and had Product Properties enabled, any code referencing `product.product_properties`, `product.property()`, `product.set_property()`, or the admin Properties page will stop working.
268
-
269
- ### (Optional) Install Spree Posts extension
270
-
271
- Posts and Post Categories management were extracted from Spree core into a separate gem `spree_posts`.
272
-
273
- If you use these features before run this command to restore them:
274
-
275
- ```bash
276
- bundle add spree_posts
277
- ```
@@ -1,301 +0,0 @@
1
- ---
2
- title: Upgrading to Spree 5.5
3
- description: Step-by-step guide to upgrading a Spree 5.4 application to Spree 5.5, including gem updates, migrations, and breaking changes to review.
4
- ---
5
-
6
- > **INFO:** Before proceeding to upgrade, please ensure you're at [Spree 5.4](5.3-to-5.4.md).
7
-
8
- The upgrade is usually completed in five steps:
9
-
10
- 1. **Update the Ruby gems** which power Spree API
11
- 2. **Run database migrations** — to migrate your existing schema to the new version
12
- 3. **Run data backfills** — to move your existing data into the new schema and power new features
13
- 4. Apply optional configuration and review behavior changes — to take advantage of new features and avoid surprises
14
-
15
- ## How to upgrade
16
-
17
- For applications created via `create-spree-app` command we greatly recommend using the Spree CLI to perform the upgrade. It provides a guided experience with prompts and handles the first three steps for you. If you prefer to run the commands manually or not using docker for local development, you can follow the "Without Spree CLI" path.
18
-
19
-
20
- ```bash Spree CLI (Docker)
21
- spree upgrade
22
- ```
23
-
24
- ```bash Without Spree CLI
25
- # cd backend if you're in the monorepo root
26
- bundle update
27
- bundle exec rake spree:install:migrations && bin/rails db:migrate
28
- bundle exec rake spree:upgrade
29
- ```
30
-
31
-
32
- The **Spree CLI** path runs all three commands for you with prompts. Recommended for local development. If you don't have the CLI yet, either install it globally or run it through `npx`:
33
-
34
- ```bash
35
- # install once and use `spree …` everywhere
36
- npm install -g @spree/cli
37
-
38
- # or invoke without installing (each command runs through npx)
39
- npx @spree/cli upgrade
40
- ```
41
-
42
- The **Without Spree CLI** path is the bare equivalent. Use this on production: `bundle update` and `db:migrate` are part of your existing deploy pipeline (Heroku release phase, K8s init container, Capistrano hook, Render auto-migrate). Once the 5.5 release is up, run `bundle exec rake spree:upgrade` from a one-off dyno / job container / `kubectl exec` to perform the data backfills.
43
-
44
- Skipping versions and re-running are both safe — `bundle exec rake spree:upgrade` figures out what still needs to happen and does nothing on data that's already migrated.
45
-
46
- ## What the upgrade does
47
-
48
- This is reference material — what `bundle exec rake spree:upgrade` (and equivalently `spree upgrade`) actually executes on your data. Skip if you trust the tool; read on if something failed or you're curious.
49
-
50
- ### Migrate legacy variant-pinned media
51
-
52
- In 5.5 the [product is the default owner of media](../core-concepts/media.md#product-level-gallery). Existing variant-pinned images keep rendering, but new admin uploads attach to the product. To consolidate both into a single gallery, the upgrade runs:
53
-
54
-
55
- ```bash Spree CLI (Docker)
56
- spree rake spree:media:migrate_master_images_to_product_media
57
- ```
58
-
59
- ```bash Without Spree CLI
60
- bundle exec rake spree:media:migrate_master_images_to_product_media
61
- ```
62
-
63
-
64
- The task enqueues one `Spree::Media::MigrateProductAssetsJob` per product onto the `images` queue — make sure your job runner is processing that queue. Each job is idempotent, so re-running the task is safe; it skips products that no longer have variant-pinned assets.
65
-
66
- For larger catalogs, tune the batching with `BATCH_SIZE`:
67
-
68
-
69
- ```bash Spree CLI (Docker)
70
- spree rake spree:media:migrate_master_images_to_product_media BATCH_SIZE=1000
71
- ```
72
-
73
- ```bash Without Spree CLI
74
- bundle exec rake spree:media:migrate_master_images_to_product_media BATCH_SIZE=1000
75
- ```
76
-
77
-
78
- > **WARNING:** Run the task locally and on production. It does not block storefront rendering — new uploads attach to the product immediately — but until the enqueued jobs finish, old assets remain pinned to variants.
79
-
80
- ### Run the Channels upgrade
81
-
82
- Spree 5.5 introduces [Sales Channels](../core-concepts/channels.md) — a per-store distribution surface (online storefront, POS, marketplace integration, wholesale portal). Products are published to a channel via the new `spree_product_publications` join table, and orders are attributed to a channel via `spree_orders.channel_id`.
83
-
84
- The migrations add a `default` boolean on `spree_channels`, a `store_id` column on `spree_products`, and create the new `spree_product_publications` table — **but they do not seed default channels, attach existing products to a store, or backfill order channels**. That work is done by an idempotent rake task:
85
-
86
-
87
- ```bash Spree CLI (Docker)
88
- spree rake spree:channels:upgrade
89
- ```
90
-
91
- ```bash Without Spree CLI
92
- bundle exec rake spree:channels:upgrade
93
- ```
94
-
95
-
96
- The task runs four sub-tasks in order:
97
-
98
- 1. `spree:channels:create_defaults` — creates the default "Online Store" channel for every existing store (via `Store#ensure_default_channel`).
99
- 2. `spree:upgrade:populate_publications` — for every product that doesn't yet have a `store_id`, picks a "home" store from the legacy `spree_products_stores` join (preferring the store flagged `default: true`, otherwise the earliest row), sets `spree_products.store_id`, and creates a `spree_product_publications` row on each attached store's default channel. Runs in a transaction per product so a partial failure leaves nothing half-applied.
100
- 3. `spree:channels:backfill_order_channel_ids` — sets `spree_orders.channel_id` from the legacy `spree_orders.channel` string column. Unknown codes auto-create a new channel under that store. NULL/blank values map to the default channel.
101
- 4. `spree:channels:backfill_product_publication_dates` — copies the deprecated `Product.available_on` and `Product.discontinue_on` columns into each publication's `published_at` / `unpublished_at` (only where the publication's date is currently NULL).
102
-
103
- The task is fully idempotent — safe to re-run if it fails partway, and a no-op on stores/products/orders that have already been upgraded.
104
-
105
- > **WARNING:** Until `spree:channels:upgrade` runs, every product has `store_id IS NULL` and is invisible to `Product.for_store(store)`. The admin product list, storefront catalog, and search indexer all return empty. Run the task immediately after `db:migrate`.
106
-
107
- ### Reindex products
108
-
109
- The last step rebuilds the search index against the configured [search provider](../core-concepts/search-filtering.md):
110
-
111
-
112
- ```bash Spree CLI (Docker)
113
- spree rake spree:search:reindex
114
- ```
115
-
116
- ```bash Without Spree CLI
117
- bundle exec rake spree:search:reindex
118
- ```
119
-
120
-
121
- This is a no-op on the default Database provider (there is no external index to maintain). For Meilisearch — or any other external search provider — it is required, and it must run **after** the Channels upgrade: products only become visible to `Product.for_store` once they have a `store_id`, so reindexing before the channels step would index zero products. The manifest orders the steps accordingly.
122
-
123
- #### Multi-store catalogs
124
-
125
- If you have products attached to multiple stores via the legacy `spree_products_stores` join, the `populate_publications` task picks **one** "home" store per product and creates publications on every store's default channel. The `spree_products_stores` table is **kept** as legacy compat surface.
126
-
127
- For single-store deployments this is invisible; you can move on without touching `spree_products_stores` again.
128
-
129
- #### Behavioral changes from the Channels upgrade
130
-
131
- - Newly-created products in **the dashboard SPA** are auto-published on the store's default channel; the merchant can untick channels post-create via the Publishing card.
132
- - Newly-created products via the **Admin API** are NOT auto-published — the caller must supply `product_publications: [{ channel_id }]` on create or use `POST /api/v3/admin/channels/:id/add_products` afterwards.
133
- - `Product.available_on=` and `Product.discontinue_on=` setters emit deprecation warnings and now write to every per-channel publication's `published_at` / `unpublished_at`. Reading these attributes on a product prefers the current-channel publication's value over the legacy column.
134
- - `Spree::Channel#add_products(product_ids)` is idempotent and **preserves existing publication windows** when called without `published_at`/`unpublished_at` kwargs.
135
-
136
- Orders modified after the upgrade auto-set `channel_id` via the model's `before_validation :ensure_channel_presence` callback, so `backfill_order_channel_ids` is only strictly required for orders that aren't touched again post-upgrade — but running it at upgrade time avoids surprises later. The legacy `channel` string column is **kept** on `spree_orders` and ignored by ActiveRecord (`Spree::Order` declares it in `ignored_columns`). It will be dropped in a later Spree release once everyone has had a chance to run the backfill.
137
-
138
- ## Update the Spree SDK
139
-
140
- Spree 5.5 ships alongside `@spree/sdk` 1.1. The backend upgrade never touches your frontend source — bump the SDK in every JavaScript consumer of the Store API and take it through your normal PR/CI cycle:
141
-
142
- ```bash
143
- # create-spree-app projects: the Next.js storefront
144
- cd apps/storefront
145
- npm install @spree/sdk@^1.1
146
- ```
147
-
148
- If you maintain a separate storefront repo or other integrations, repeat there. The `spree upgrade` command detects the conventional `apps/storefront` and reminds you with the currently-declared version in its "Next steps" panel.
149
-
150
- | Spree backend | `@spree/sdk` |
151
- |---|---|
152
- | 5.4 | 1.0.x |
153
- | 5.5 | 1.1+ |
154
-
155
- The SDK bump pairs with one storefront code change in this release: the [payment method `type` shorthand](#payment-method-type-on-the-wire-is-now-a-shorthand-not-a-rails-class-name) — update your gateway map when you bump.
156
-
157
- ## Required post-upgrade configuration
158
-
159
- `bundle exec rake spree:upgrade` doesn't touch your job-runner config — every app uses a different scheduler, so this one is on you.
160
-
161
- ### Schedule the Stock Reservations expiry job
162
-
163
- Spree 5.5 introduces time-limited stock reservations during checkout to prevent two customers from buying the same last unit at the same time. Abandoned checkouts leave behind expired reservation rows, and Spree does **not** auto-schedule the cleanup — your application's job runner must run `Spree::StockReservations::ExpireJob` periodically (every minute is the recommended cadence).
164
-
165
- If you skip this step, expired reservations accumulate in the table indefinitely. The Quantifier still ignores them at availability-check time (so customers see correct stock), but the table grows unbounded.
166
-
167
- #### sidekiq-cron
168
-
169
- ```yaml
170
- # config/sidekiq_cron.yml
171
- expire_stock_reservations:
172
- cron: "* * * * *"
173
- class: "Spree::StockReservations::ExpireJob"
174
- queue: default
175
- ```
176
-
177
- #### solid_queue
178
-
179
- ```yaml
180
- # config/recurring.yml
181
- expire_stock_reservations:
182
- schedule: every minute
183
- class: Spree::StockReservations::ExpireJob
184
- ```
185
-
186
- #### good_job
187
-
188
- ```ruby
189
- # config/initializers/good_job.rb
190
- Rails.application.configure do
191
- config.good_job.cron = {
192
- expire_stock_reservations: {
193
- cron: '* * * * *',
194
- class: 'Spree::StockReservations::ExpireJob'
195
- }
196
- }
197
- end
198
- ```
199
-
200
- ## Optional tuning
201
-
202
- Defaults are sensible for most stores. Reach for these only if you have a specific reason.
203
-
204
- ### Tune the reservation TTL
205
-
206
- The default reservation TTL is **10 minutes**. To override globally:
207
-
208
- ```ruby
209
- # config/initializers/spree.rb
210
- Spree::Config[:default_stock_reservation_ttl_minutes] = 15
211
- ```
212
-
213
- To override per Store, set the preference on the Store record:
214
-
215
- ```ruby
216
- store.update!(preferred_stock_reservation_ttl_minutes: 20)
217
- ```
218
-
219
- The per-Store value, when set, takes precedence over the global default.
220
-
221
- ### Disable Stock Reservations
222
-
223
- Stock reservations are enabled by default. To opt out and revert to pre-5.5 behavior (no holds during checkout, Quantifier returns raw `count_on_hand`):
224
-
225
- ```ruby
226
- # config/initializers/spree.rb
227
- Spree::Config[:stock_reservations_enabled] = false
228
- ```
229
-
230
- The Quantifier short-circuits before any reservation query when this is `false`, so there's no runtime cost and no table growth.
231
-
232
- ### Opt out of rules-based Order Routing
233
-
234
- Spree 5.5 introduces [Order Routing](../core-concepts/shipments.md#order-routing) — a configurable, per-channel pipeline that decides which stock locations fulfill an order. Every store and every channel ships with three default rules (Preferred Location → Minimize Splits → Default Location) that produce sensible behavior out of the box, with no migration work required.
235
-
236
- If you've heavily customized fulfillment in Spree 5.4 and aren't ready to adopt the new rules engine, you can keep the legacy pre-5.5 routing by switching the store's strategy to `Spree::OrderRouting::Strategy::Legacy`:
237
-
238
- ```ruby
239
- store.update!(preferred_order_routing_strategy: 'Spree::OrderRouting::Strategy::Legacy')
240
- ```
241
-
242
- The Legacy strategy delegates to `Spree::Stock::Coordinator`, which is the exact pre-5.5 packing pipeline — every active stock location is packed, the Prioritizer distributes inventory units across the resulting packages, and no merchant routing rules are consulted. Your existing customizations on `Coordinator`, `Packer`, `Prioritizer`, and the splitters keep working unchanged.
243
-
244
- > **WARNING:** `Spree::OrderRouting::Strategy::Legacy` **was removed in Spree 6.0**. It exists only on the 5.5/5.6 line, as a temporary escape hatch while you evaluate the Rules strategy. Stores still carrying this value fall back to the default Rules strategy on 6.0 (with a logged warning), so clear the preference before upgrading.
245
-
246
- ## Behavior changes to review
247
-
248
- These don't require any rake task — but storefronts, integrations, and merchant-facing dashboards may need code changes to handle them correctly.
249
-
250
- ### Cart changes during checkout can now fail with insufficient stock
251
-
252
- When a customer is in checkout and tries to add an item, increase a quantity, or remove a line item, Spree now re-checks whether the cart still fits in available stock (subtracting what other customers are holding in their own active checkouts). If it doesn't, the change is rejected up front instead of silently completing and failing later at order submission.
253
-
254
- Storefronts and custom integrations that act on the cart should expect this new failure path and surface the error to the customer.
255
-
256
- ### Storefront availability drops faster under contention
257
-
258
- Other customers now see availability reduced by all active reservations, not just by completed orders. This is the intended fix to overselling — but if you have a real-time inventory dashboard that reads `count_on_hand` directly (rather than going through Spree's availability checks), you'll want to expose a "Reserved" axis to merchants so they can see in-checkout demand.
259
-
260
- ### Payment method `type` on the wire is now a shorthand, not a Rails class name
261
-
262
- The `type` attribute on `Spree::PaymentMethod` (returned by both the Store API and the Admin API) used to be the full Rails STI class name — `"SpreeStripe::Gateway"`, `"SpreeAdyen::Gateway"`, `"Spree::PaymentMethod::Check"`. In 5.5 it switches to a stable shorthand derived from `Spree::Base.api_type`:
263
-
264
- | Class | Pre-5.5 `type` | 5.5+ `type` |
265
- | ---------------------------------- | ------------------------------- | ------------------ |
266
- | `Spree::PaymentMethod::Check` | `Spree::PaymentMethod::Check` | `check` |
267
- | `Spree::PaymentMethod::StoreCredit`| `Spree::PaymentMethod::StoreCredit` | `store_credit` |
268
- | `SpreeStripe::Gateway` | `SpreeStripe::Gateway` | `stripe` |
269
- | `SpreeAdyen::Gateway` | `SpreeAdyen::Gateway` | `adyen` |
270
- | `SpreePaypalCheckout::Gateway` | `SpreePaypalCheckout::Gateway` | `paypal_checkout` |
271
- | `SpreeRazorpayCheckout::Gateway` | `SpreeRazorpayCheckout::Gateway`| `razorpay_checkout`|
272
-
273
- The shorthand is also what `POST /api/v3/admin/payment_methods` now expects as `type` when creating a new method, and what `GET /api/v3/admin/payment_methods/types` returns in its `type` field.
274
-
275
- This is a breaking change for any storefront or integration that **string-matches the payment method type** to pick which payment-gateway SDK to load. The official Spree Next.js storefront resolves the gateway in `src/lib/utils/payment-gateway.ts`; update its map to key on the new shorthand:
276
-
277
- ```ts
278
- const GATEWAY_TYPE_MAP: Record<string, GatewayId> = {
279
- // 5.5+ shorthands
280
- stripe: "stripe",
281
- adyen: "adyen",
282
- paypal_checkout: "paypal",
283
- razorpay_checkout: "razorpay",
284
- // Pre-5.5 Rails class names — keep while you have older backends in
285
- // the field; drop once everyone is on 5.5+.
286
- "SpreeStripe::Gateway": "stripe",
287
- "SpreeAdyen::Gateway": "adyen",
288
- "SpreePaypalCheckout::Gateway": "paypal",
289
- "SpreeRazorpayCheckout::Gateway": "razorpay",
290
- };
291
- ```
292
-
293
- If you maintain a custom storefront, search it for the legacy class strings (`"SpreeStripe::Gateway"`, `"SpreePaypalCheckout::Gateway"`, etc.) and add the corresponding 5.5+ shorthand alongside each one. The symptom of missing this is checkout rendering a generic "this payment method is not yet supported" placeholder instead of the gateway's SDK form.
294
-
295
- ### Order Routing chooses location order via merchant rules instead of database order
296
-
297
- The default routing strategy (`Spree::OrderRouting::Strategy::Rules`) packs the same set of stock locations as before, but the **order** in which locations are tried is now determined by the routing rules — Preferred Location → Minimize Splits → Default Location — rather than by raw database row order. The unit distribution (Prioritizer + Adjuster) is unchanged: top-ranked location's packages get first pick of on-hand inventory, the rest spills over.
298
-
299
- For most stores this is invisible: when one location can fulfill the entire cart, that location now wins consistently (instead of depending on database iteration order). When the cart needs to split across locations, the same multi-location split happens — just with the location order driven by rules.
300
-
301
- If you rely on the legacy "every location packed in iteration order, no rule consulted" behavior, see [Opt out of rules-based Order Routing](#opt-out-of-rules-based-order-routing) above.