@spree/docs 0.1.247 → 0.1.249
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.
- package/dist/api-reference/admin-api/authentication.md +34 -14
- package/dist/api-reference/admin-api/endpoints.md +366 -14
- package/dist/api-reference/admin-api/errors.md +2 -2
- package/dist/api-reference/admin-api/introduction.md +3 -3
- package/dist/api-reference/admin-api/querying.md +6 -6
- package/dist/api-reference/store-api/monetary-amounts.md +5 -5
- package/dist/api-reference/webhooks-events.md +330 -335
- package/dist/developer/agentic/agent-skills.md +5 -2
- package/dist/developer/agentic/llm-docs.md +2 -1
- package/dist/developer/cli/admin-api.md +1 -1
- package/dist/developer/cli/quickstart.md +2 -2
- package/dist/developer/contributing/creating-an-extension.md +292 -146
- package/dist/developer/contributing/developing-spree.md +13 -17
- package/dist/developer/core-concepts/catalogs.md +2 -2
- package/dist/developer/core-concepts/channels.md +3 -3
- package/dist/developer/core-concepts/companies.md +2 -1
- package/dist/developer/core-concepts/delivery-setup.md +2 -2
- package/dist/developer/core-concepts/discounts.md +3 -3
- package/dist/developer/core-concepts/events.md +6 -5
- package/dist/developer/core-concepts/freight.md +3 -2
- package/dist/developer/core-concepts/fulfillments.md +10 -8
- package/dist/developer/core-concepts/imports-exports.md +11 -8
- package/dist/developer/core-concepts/inventory.md +2 -2
- package/dist/developer/core-concepts/media.md +14 -14
- package/dist/developer/core-concepts/orders.md +2 -2
- package/dist/developer/core-concepts/payments.md +1 -2
- package/dist/developer/core-concepts/products.md +6 -6
- package/dist/developer/core-concepts/reporting.md +4 -3
- package/dist/developer/core-concepts/returns-exchanges-claims.md +7 -7
- package/dist/developer/core-concepts/search-filtering.md +3 -3
- package/dist/developer/core-concepts/sellers.md +22 -3
- package/dist/developer/core-concepts/staff-roles.md +4 -2
- package/dist/developer/core-concepts/store-credits-gift-cards.md +1 -1
- package/dist/developer/core-concepts/stores.md +2 -2
- package/dist/developer/core-concepts/translations.md +12 -8
- package/dist/developer/core-concepts/webhooks.md +19 -18
- package/dist/developer/create-spree-app/quickstart.md +2 -7
- package/dist/developer/customization/api.md +1 -1
- package/dist/developer/customization/checkout.md +2 -2
- package/dist/developer/customization/dependencies.md +53 -37
- package/dist/developer/customization/permissions.md +2 -2
- package/dist/developer/dashboard/concepts.md +1 -1
- package/dist/developer/dashboard/customization/navigation.md +3 -2
- package/dist/developer/dashboard/customization/permissions.md +6 -6
- package/dist/developer/dashboard/plugins/publishing.md +4 -4
- package/dist/developer/dashboard/plugins/scaffolding.md +1 -1
- package/dist/developer/dashboard/public-api.md +1 -1
- package/dist/developer/dashboard/recipes/attribute-end-to-end.md +3 -18
- package/dist/developer/deployment/aws.md +1 -1
- package/dist/developer/deployment/aws_ecs.md +3 -3
- package/dist/developer/deployment/background_jobs.md +9 -3
- package/dist/developer/deployment/docker.md +1 -2
- package/dist/developer/deployment/emails.md +3 -1
- package/dist/developer/deployment/environment_variables.md +2 -2
- package/dist/developer/deployment/render.md +2 -2
- package/dist/developer/how-to/build-a-marketplace.md +2 -2
- package/dist/developer/how-to/custom-api-authentication.md +1 -1
- package/dist/developer/how-to/custom-delivery-rate-provider.md +11 -3
- package/dist/developer/how-to/custom-document-numbers.md +1 -1
- package/dist/developer/how-to/custom-order-routing.md +15 -14
- package/dist/developer/how-to/custom-payment-method.md +17 -19
- package/dist/developer/how-to/custom-promotion.md +4 -4
- package/dist/developer/how-to/custom-search-provider.md +12 -5
- package/dist/developer/how-to/custom-stock-splitter.md +25 -24
- package/dist/developer/how-to/sell-digital-products.md +1 -1
- package/dist/developer/multi-tenant/quickstart.md +2 -2
- package/dist/developer/providers/payouts.md +6 -2
- package/dist/developer/sdk/admin/querying-and-errors.md +1 -1
- package/dist/developer/sdk/admin/quickstart.md +4 -4
- package/dist/developer/sdk/authentication.md +5 -2
- package/dist/developer/sdk/store/cart-checkout.md +4 -4
- package/dist/developer/storefront/nextjs/emails.md +4 -2
- package/dist/developer/storefront/nextjs/testing.md +1 -1
- package/dist/developer/upgrades/5.6-to-6.0.md +51 -20
- package/dist/integrations/search/meilisearch.md +4 -4
- package/package.json +1 -1
|
@@ -33,7 +33,7 @@ await adminClient.products.update('prod_86Rf07xd4z', {
|
|
|
33
33
|
curl -X PATCH 'https://api.mystore.com/api/v3/admin/products/prod_86Rf07xd4z' \
|
|
34
34
|
-H 'X-Spree-API-Key: sk_xxx' \
|
|
35
35
|
-H 'Content-Type: application/json' \
|
|
36
|
-
-d '{ "delivery_profile_id": "
|
|
36
|
+
-d '{ "delivery_profile_id": "fp_digital" }'
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
|
|
@@ -25,7 +25,7 @@ All data is fully isolated besides the staff users, which can manage multiple te
|
|
|
25
25
|
## Prerequisites
|
|
26
26
|
|
|
27
27
|
* You need to be on Spree 5.1+, we recommend using [CLI](../getting-started.md) to setup your Spree application.
|
|
28
|
-
* You need to set 2 environment variables in your `
|
|
28
|
+
* You need to set 2 environment variables in your `server` directory:
|
|
29
29
|
* `KEYGEN_ACCOUNT_ID`
|
|
30
30
|
* `KEYGEN_LICENSE_KEY`
|
|
31
31
|
* Both PostgreSQL and MySQL are supported
|
|
@@ -84,7 +84,7 @@ spree eject
|
|
|
84
84
|
```yaml docker-compose.yml
|
|
85
85
|
x-app: &app
|
|
86
86
|
build:
|
|
87
|
-
context: ./
|
|
87
|
+
context: ./server
|
|
88
88
|
dockerfile: Dockerfile
|
|
89
89
|
target: dev
|
|
90
90
|
secrets: # [!code ++]
|
|
@@ -130,10 +130,14 @@ end
|
|
|
130
130
|
### Register it
|
|
131
131
|
|
|
132
132
|
```ruby server/config/initializers/spree.rb
|
|
133
|
-
|
|
134
|
-
Spree.
|
|
133
|
+
Rails.application.config.after_initialize do
|
|
134
|
+
Spree.integrations << 'MyApp::AcmeIntegration'
|
|
135
|
+
Spree.payout_providers << MyApp::PayoutProvider
|
|
136
|
+
end
|
|
135
137
|
```
|
|
136
138
|
|
|
139
|
+
Register inside `after_initialize`: Spree sets up its own integrations list after your initializers run, so an entry added at the top level of the file would be dropped.
|
|
140
|
+
|
|
137
141
|
The operator then picks it under **Settings → Marketplace**, which is the store's `payout_provider` preference. The picker is built from the registry, so your provider appears alongside the built-in one and reports whether the store can use it today:
|
|
138
142
|
|
|
139
143
|
|
|
@@ -10,7 +10,7 @@ Collection endpoints support [Ransack](https://activerecord-hackery.github.io/ra
|
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
const { data: orders } = await client.orders.list({
|
|
13
|
-
status_eq: '
|
|
13
|
+
status_eq: 'placed', // exact match
|
|
14
14
|
total_gteq: 100, // greater than or equal
|
|
15
15
|
email_cont: '@example.com', // substring match
|
|
16
16
|
customer_id_eq: 'cus_xxx', // prefixed IDs work directly
|
|
@@ -6,12 +6,12 @@ description: "Install and configure @spree/admin-sdk, the official TypeScript cl
|
|
|
6
6
|
|
|
7
7
|
[`@spree/admin-sdk`](https://www.npmjs.com/package/@spree/admin-sdk) is the official TypeScript SDK for the [Admin API v3](../../../api-reference/admin-api/introduction.md) — the back-office counterpart to [`@spree/sdk`](../quickstart.md). Use it to build integrations, automations, internal tools, and custom admin UIs: manage products, orders, customers, stock, promotions, webhooks, and more.
|
|
8
8
|
|
|
9
|
-
> **
|
|
9
|
+
> **NOTE:** `@spree/admin-sdk` 1.x works with the Spree 6.0 Admin API. Check the [changelog](https://github.com/spree/spree/blob/main/packages/admin-sdk/CHANGELOG.md) when updating.
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install @spree/admin-sdk
|
|
14
|
+
npm install @spree/admin-sdk
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Quick start
|
|
@@ -26,9 +26,9 @@ const client = createAdminClient({
|
|
|
26
26
|
secretKey: process.env.SPREE_SECRET_KEY, // sk_xxx — server-side only
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
// List
|
|
29
|
+
// List recently placed orders
|
|
30
30
|
const { data: orders, meta } = await client.orders.list({
|
|
31
|
-
status_eq: '
|
|
31
|
+
status_eq: 'placed',
|
|
32
32
|
sort: '-completed_at',
|
|
33
33
|
limit: 25,
|
|
34
34
|
})
|
|
@@ -41,8 +41,11 @@ const orders = await client.customer.orders.list({}, { token })
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
|
-
//
|
|
45
|
-
|
|
44
|
+
// Exchange the refresh_token returned by login for a new access token.
|
|
45
|
+
// The refresh token rotates, so store the new one as well.
|
|
46
|
+
const { token: newToken, refresh_token: newRefreshToken } = await client.auth.refresh({
|
|
47
|
+
refresh_token: refreshToken,
|
|
48
|
+
})
|
|
46
49
|
```
|
|
47
50
|
|
|
48
51
|
## Register New Customer
|
|
@@ -28,7 +28,7 @@ const carts = await client.carts.list();
|
|
|
28
28
|
await client.carts.delete(cartId, { spreeToken: cart.token });
|
|
29
29
|
|
|
30
30
|
// Associate guest cart with authenticated user
|
|
31
|
-
// (after user logs in,
|
|
31
|
+
// (after user logs in, assign the guest cart to their account — carts are not merged)
|
|
32
32
|
await client.carts.associate(cartId, {
|
|
33
33
|
token: jwtToken, // User's JWT token
|
|
34
34
|
spreeToken: cart.token, // Guest cart token
|
|
@@ -112,8 +112,8 @@ await client.carts.update(cartId, {
|
|
|
112
112
|
city: 'New York',
|
|
113
113
|
postal_code: '10001',
|
|
114
114
|
phone: '+1 555 123 4567',
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
country_code: 'US',
|
|
116
|
+
state_code: 'NY',
|
|
117
117
|
},
|
|
118
118
|
billing_address_id: 'addr_xxx', // Or use existing address by ID
|
|
119
119
|
}, { spreeToken: cart.token });
|
|
@@ -177,7 +177,7 @@ The cart and order responses break the amount the customer pays into these total
|
|
|
177
177
|
### Get a Completed Order
|
|
178
178
|
|
|
179
179
|
```typescript
|
|
180
|
-
const order = await client.orders.get('
|
|
180
|
+
const order = await client.orders.get('or_xxx', { // prefixed order ID (or the cart ID)
|
|
181
181
|
expand: ['items', 'fulfillments'],
|
|
182
182
|
}, { spreeToken: cart.token });
|
|
183
183
|
```
|
|
@@ -23,6 +23,8 @@ Email templates are React components in `src/lib/emails/`:
|
|
|
23
23
|
|
|
24
24
|
Customize a template by editing its file directly — they use `@react-email/components` for email-safe layout primitives.
|
|
25
25
|
|
|
26
|
+
> **NOTE:** The storefront listens for `order.completed` and `order.shipped`, the names these events had before Spree 6.0. Spree 6.0 still sends them alongside the new names, `order.placed` and `order.fulfilled`, but stops in Spree 6.1. Before upgrading to 6.1, switch the storefront handlers and your webhook endpoint subscriptions to the new names.
|
|
27
|
+
|
|
26
28
|
## Previewing
|
|
27
29
|
|
|
28
30
|
Run the storefront in development and open [http://localhost:3001/dev/emails](http://localhost:3001/dev/emails):
|
|
@@ -68,11 +70,11 @@ To add a new email type:
|
|
|
68
70
|
1. Create a template in `src/lib/emails/`.
|
|
69
71
|
2. Add a handler function in `src/lib/webhooks/handlers.ts`.
|
|
70
72
|
3. Register the event in `route.ts`.
|
|
71
|
-
4. Subscribe to the event in **Spree Admin → Settings →
|
|
73
|
+
4. Subscribe to the event in **Spree Admin → Settings → Developer → Webhooks**.
|
|
72
74
|
|
|
73
75
|
## Setup
|
|
74
76
|
|
|
75
|
-
1. **Create a webhook endpoint** in Spree Admin → Settings →
|
|
77
|
+
1. **Create a webhook endpoint** in Spree Admin → Settings → Developer → Webhooks. Subscribe to `order.completed`, `order.canceled`, `order.shipped`, and `customer.password_reset_requested`, and copy the secret key into `SPREE_WEBHOOK_SECRET`.
|
|
76
78
|
|
|
77
79
|
2. **Receive webhooks locally.** Expose the storefront with a public URL so Spree can reach it — the simplest option is a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/):
|
|
78
80
|
|
|
@@ -65,7 +65,7 @@ A project scaffolded with [`create-spree-app`](../../create-spree-app/quickstart
|
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
# From the project root — build the customized backend image
|
|
68
|
-
docker build -t project-spree:e2e ./
|
|
68
|
+
docker build -t project-spree:e2e ./server
|
|
69
69
|
|
|
70
70
|
# From apps/storefront — run E2E against it
|
|
71
71
|
cd apps/storefront
|
|
@@ -36,7 +36,14 @@ bundle exec rake spree:upgrade
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Before running `bundle update`, update your `Gemfile`: the Rails admin (`spree_admin`) and Rails storefront (`spree_storefront`) are not part of Spree 6.0. Remove both and add `spree_dashboard`, which serves the new React admin dashboard at `/dashboard`.
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
# Gemfile
|
|
43
|
+
gem 'spree_dashboard'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Re-running is safe — `bundle exec rake spree:upgrade` figures out what still needs to happen and does nothing on data that's already migrated. It also runs every data backfill from earlier upgrades (5.4 → 5.5 and 5.5 → 5.6), so any you missed along the way are caught up. That does not remove the requirement above: upgrade your application to 5.6 first.
|
|
40
47
|
|
|
41
48
|
## What the upgrade does
|
|
42
49
|
|
|
@@ -56,7 +63,7 @@ Every order that never completed and was never canceled becomes a `Spree::Cart`
|
|
|
56
63
|
bundle exec rake spree:migrate_adjustments_to_typed_rows
|
|
57
64
|
```
|
|
58
65
|
|
|
59
|
-
Rebuilds `spree_adjustments` into `Spree::TaxLine`, `Spree::Discount` and `Spree::Fee` rows. Orders whose typed sums do not reconcile with the stored totals are left untouched and flagged (`
|
|
66
|
+
Rebuilds `spree_adjustments` into `Spree::TaxLine`, `Spree::Discount` and `Spree::Fee` rows. Orders whose typed sums do not reconcile with the stored totals are left untouched and flagged (`metadata['typed_adjustments_frozen']`) for manual review instead of silently changing money.
|
|
60
67
|
|
|
61
68
|
### Backfill fulfillment and delivery naming
|
|
62
69
|
|
|
@@ -94,14 +101,14 @@ Category and collection descriptions, policy bodies, and order and customer inte
|
|
|
94
101
|
|
|
95
102
|
Run this **after** two earlier steps, both load-bearing: the categories step re-points the rows from `Spree::Taxon` to `Spree::Category` so this one can still find them, and the customers step populates `spree_customers` — a note is copied onto the customer row it belongs to, so running before those rows exist would treat every legacy customer note as orphaned and skip it for good. Following the manifest order handles this for you.
|
|
96
103
|
|
|
97
|
-
Content is sanitized on the way in, and **the 6.0 allowlist is much narrower than 5.6's**: it permits only what the dashboard's editor emits — paragraphs, headings, `strong`/`em`/`s`/`u`/`code`, `pre`, `blockquote`, lists, `hr`, `br
|
|
104
|
+
Content is sanitized on the way in, and **the 6.0 allowlist is much narrower than 5.6's**: it permits only what the dashboard's editor emits — paragraphs, headings, `strong`/`em`/`s`/`u`/`code`, `pre`, `blockquote`, lists, `hr`, `br`, links and images. Tables, `div`/`span`, inline `style` and arbitrary `class` attributes are no longer permitted. Text inside a stripped tag survives; its formatting does not. The exceptions are `script` and `style`, which are removed along with their contents — a script body would otherwise reappear as visible text.
|
|
98
105
|
|
|
99
106
|
If your descriptions rely on richer markup, permit it in an initializer **before** running the task and before saving anything under 6.0:
|
|
100
107
|
|
|
101
108
|
```ruby
|
|
102
109
|
# config/initializers/spree.rb
|
|
103
|
-
Spree::RichTextSanitizer.allowed_tags += %w[table thead tbody tr th td
|
|
104
|
-
Spree::RichTextSanitizer.allowed_attributes += %w[
|
|
110
|
+
Spree::RichTextSanitizer.allowed_tags += %w[table thead tbody tr th td]
|
|
111
|
+
Spree::RichTextSanitizer.allowed_attributes += %w[colspan rowspan]
|
|
105
112
|
```
|
|
106
113
|
|
|
107
114
|
The Action Text rows are left in place as a rollback path and are dropped with the tables in 6.1.
|
|
@@ -153,6 +160,24 @@ Rows written before the upgrade carry an id and an empty type; this task fills
|
|
|
153
160
|
the type in. Until it runs they still read as the staff member they always
|
|
154
161
|
were, with a deprecation warning. Safe to re-run at any time.
|
|
155
162
|
|
|
163
|
+
### Move users onto the Customer and AdminUser models
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
bundle exec rake spree:upgrade:migrate_users_to_customers
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Copies your legacy Devise customer table (default `spree_users`) into `spree_customers`, keeping the same ids, and carries existing passwords over so customers and staff can keep signing in. The source table is left in place as a safety net.
|
|
170
|
+
|
|
171
|
+
> **WARNING:** Passwords carry over only if your application **never configured a Devise pepper**. The task stops if it finds one. Because Devise is no longer loaded in 6.0, the task usually cannot check for itself — it stops until you confirm no pepper was used by re-running it with `CONFIRM_NO_PEPPER=true`. If you did use a pepper, single sign-on, or a non-bcrypt password format, skip this step and keep your own customer model by setting `Spree.customer_class`.
|
|
172
|
+
|
|
173
|
+
### Name countries and states by ISO code
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
bundle exec rake spree:upgrade:migrate_country_state_codes
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Countries and states are no longer database records in 6.0. Addresses, delivery zone members, market countries, stock locations and stores now name them by ISO code (`country_code`, `state_code`), and this task fills those columns from the old `country_id` / `state_id` references. The old `country_iso` / `state_abbr` names still work on addresses for one release.
|
|
180
|
+
|
|
156
181
|
## The Cart/Order split
|
|
157
182
|
|
|
158
183
|
The single biggest change. What used to be one `Spree::Order` living through checkout and beyond is now two models:
|
|
@@ -180,17 +205,17 @@ The replacement model:
|
|
|
180
205
|
|
|
181
206
|
```ruby
|
|
182
207
|
# config/initializers/spree.rb
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
)
|
|
191
|
-
end
|
|
208
|
+
Spree::Checkout::Registry.add_requirement(
|
|
209
|
+
step: :payment,
|
|
210
|
+
field: :po_number,
|
|
211
|
+
message: 'PO number is required',
|
|
212
|
+
satisfied: ->(cart) { cart.metadata['po_number'].present? },
|
|
213
|
+
applicable: ->(cart) { cart.customer.present? }
|
|
214
|
+
)
|
|
192
215
|
```
|
|
193
216
|
|
|
217
|
+
Register at the top level of the initializer, not inside `to_prepare`: the registry is never reset, so a `to_prepare` block would add the requirement again on every code reload in development.
|
|
218
|
+
|
|
194
219
|
The requirement appears in the Cart API's `requirements` array (so a storefront rendering the feed generically needs zero changes) *and* blocks completion. `register_step` adds whole steps (spliced into `checkout_steps` at `before:`/`after:` anchors); built-in steps are customized through `Registry.base_steps` — an ordered `{ name => applicability }` hash you can mutate directly (`base_steps.delete('confirm')`).
|
|
195
220
|
- **The API `requirements` array now carries a stable `code`** on every entry (`email_required`, `out_of_stock`, `guest_checkout_not_allowed`, ...). Additive change — existing consumers keep working.
|
|
196
221
|
- **The delivery requirement is keyed `delivery_method`, not `shipping_method`.** Its entry is now `{ step: 'delivery', field: 'delivery_method', code: 'delivery_method_required' }`. A storefront that renders the feed generically needs no change; one that keys off the field or code to highlight a specific input must switch both tokens. The `Spree.t('checkout_requirements.shipping_method_required')` translation key was renamed to `checkout_requirements.delivery_method_required` — override it under the new key.
|
|
@@ -211,7 +236,7 @@ Behavior to review:
|
|
|
211
236
|
|
|
212
237
|
Transition-triggered recalculation is gone with the machine. Instead:
|
|
213
238
|
|
|
214
|
-
- **`Spree::Carts::RecalculateTotals`** is the single totals seam: money inputs, typed-row regeneration (promotions via the winner-only adjuster, tax via `Spree.
|
|
239
|
+
- **`Spree::Carts::RecalculateTotals`** is the single totals seam: money inputs, typed-row regeneration (promotions via the winner-only adjuster, tax via the market's tax provider, falling back to `Spree.default_tax_provider`), folding and one persist. It runs on the writes that matter — item changes, address/market changes (which also re-price items and rebuild delivery proposals) — not on step transitions.
|
|
215
240
|
- Promotion eligibility is evaluated against **current** totals in the same recalculation — a cart crossing a coupon threshold gets the discount on that recalculation, not the next one.
|
|
216
241
|
- **Completed orders are money-frozen.** Typed rows are never regenerated post-placement; recalculation only re-sums them. Post-placement money edits go through the explicit admin services (`Orders::Discounts::*`, `Orders::Fees::*`), which write rows and re-sum.
|
|
217
242
|
- `Spree::OrderUpdater` and `Spree::CartUpdater` remain as deprecated shells — every method warns and runs the full recalculation. Removed in 6.1.
|
|
@@ -287,10 +312,15 @@ Core ships exactly one policy rule — a return window read from `market.preferr
|
|
|
287
312
|
Replace it by swapping the handler:
|
|
288
313
|
|
|
289
314
|
```ruby
|
|
290
|
-
|
|
291
|
-
|
|
315
|
+
# config/initializers/spree.rb
|
|
316
|
+
Rails.application.config.after_initialize do
|
|
317
|
+
Spree.hooks.unregister('returns.create.validate', 'Spree::Returns::EligibilityValidator')
|
|
318
|
+
Spree.hooks.register('returns.create.validate', 'MyStore::ReturnPolicy')
|
|
319
|
+
end
|
|
292
320
|
```
|
|
293
321
|
|
|
322
|
+
Wrap the swap in `after_initialize`: core registers the default validator after your initializers load, so an `unregister` at the top level of an initializer would run too early and do nothing.
|
|
323
|
+
|
|
294
324
|
A handler receives the workflow (so it can read `order`, `items`, `created_by`, `order.market`) and calls `workflow.reject!(message)` to veto. Every one of the fifteen transitions has a leading `validate` hook, so the same seam gates approving, receiving and refunding.
|
|
295
325
|
|
|
296
326
|
> **WARNING:** `requires_manual_intervention?` has no equivalent. The old validators could mark an item eligible-but-flagged for manual review; a handler now either accepts or vetoes. If you relied on that middle state, model it explicitly — an added status, or a metafield your handler sets.
|
|
@@ -319,7 +349,7 @@ A handler receives the workflow (so it can read `order`, `items`, `created_by`,
|
|
|
319
349
|
| `carts_complete_service` | `carts_complete_workflow` | `Spree::Carts::Complete` |
|
|
320
350
|
| `order_cancel_service` | `order_cancel_workflow` | `Spree::Orders::Cancel` |
|
|
321
351
|
| `order_complete_service` | `order_complete_workflow` | `Spree::Orders::Complete` |
|
|
322
|
-
| `shipment_update_service` | `
|
|
352
|
+
| `shipment_update_service`, `fulfillment_update_service` | `fulfillment_update_workflow` | `Spree::Fulfillments::Update` |
|
|
323
353
|
|
|
324
354
|
New seams with no legacy counterpart:
|
|
325
355
|
|
|
@@ -581,7 +611,7 @@ to `Spree::Base`.
|
|
|
581
611
|
|
|
582
612
|
`Spree::StateChange` and `Spree::LogEntry` are removed — the models, the `state_changes` associations on `Order`, `Payment` and `Fulfillment`, the `log_entries` associations on `Payment` and `Refund`, and everything that wrote to them. Both were write-only: nothing in Spree read the rows back, and the admin screens that displayed them are gone.
|
|
583
613
|
|
|
584
|
-
**Events are the audit trail now.** Instead of querying state-change rows, subscribe to the lifecycle events that already fire on every meaningful transition: `order.placed`, `order.canceled`, `payment.completed`, `payment.voided`, `fulfillment.
|
|
614
|
+
**Events are the audit trail now.** Instead of querying state-change rows, subscribe to the lifecycle events that already fire on every meaningful transition: `order.placed`, `order.canceled`, `payment.completed`, `payment.voided`, `fulfillment.fulfilled`, `fulfillment.delivered`, `fulfillment.canceled`, and the rest. If you need a persistent history, write it from a subscriber.
|
|
585
615
|
|
|
586
616
|
**Gateway responses are no longer stored in your database.** `LogEntry` kept every gateway response as serialized YAML. For transaction forensics, use your payment provider's dashboard — `Payment#gateway_dashboard_payment_url` links straight to the transaction — or `Spree::PaymentSession`, which holds the gateway-side state for session-based providers.
|
|
587
617
|
|
|
@@ -620,7 +650,8 @@ Every rename keeps the legacy name working for one release with a deprecation wa
|
|
|
620
650
|
| `Spree::PresentationTranslatable` | `Spree::LabelTranslatable` |
|
|
621
651
|
| `Spree::WishedItem`, `Wishlist#wished_items`, `#wished_items_count` | `Spree::WishlistItem`, `#wishlist_items`, `#wishlist_items_count` (class and table renamed; the `wi_` prefixed IDs are unchanged, so client-held IDs keep resolving) |
|
|
622
652
|
| `use_billing` / `clone_billing_address` | `use_shipping` (shipping address is canonical) |
|
|
623
|
-
| `Fulfillment#ship`, `#ship
|
|
653
|
+
| `Fulfillment#ship`, `#ship!` | `Spree.fulfillment_fulfill_workflow.call(fulfillment:)` (`Spree::Fulfillments::Fulfill`) |
|
|
654
|
+
| `Fulfillment#shipped?`, `#can_ship?`, `#shipping_method`, `#add_shipping_method` | `#fulfilled?`, `#can_fulfill?`, `#delivery_method`, `#add_delivery_method` |
|
|
624
655
|
| `LineItem#target_shipment` | `#target_fulfillment` |
|
|
625
656
|
| `Order#create_proposed_shipments` / `#create_proposed_fulfillments` | `#rebuild_fulfillments!` (Cart ships with the new name only) |
|
|
626
657
|
| `Order#remove_out_of_stock_items!` | cart-side only (`Spree::Carts::RemoveOutOfStockItems`) |
|
|
@@ -5,7 +5,7 @@ description: "Set up Meilisearch in Spree for fast, typo-tolerant product search
|
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
[Meilisearch](https://www.meilisearch.com/) is a fast, open-source search engine that provides typo tolerance, relevance ranking, faceted filtering, and sub-50ms search responses.
|
|
8
|
+
[Meilisearch](https://www.meilisearch.com/) is a fast, open-source search engine that provides typo tolerance, relevance ranking, faceted filtering, and sub-50ms search responses. The official `spree_meilisearch` gem provides a Meilisearch search provider that replaces the default SQL-based search.
|
|
9
9
|
|
|
10
10
|
**When to use Meilisearch:**
|
|
11
11
|
- Catalogs with 1,000+ products
|
|
@@ -48,7 +48,7 @@ docker run -d --name meilisearch \
|
|
|
48
48
|
### 2. Add the gem to your Gemfile
|
|
49
49
|
|
|
50
50
|
```ruby
|
|
51
|
-
gem '
|
|
51
|
+
gem 'spree_meilisearch'
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
|
|
@@ -77,7 +77,7 @@ MEILISEARCH_URL=http://localhost:7700
|
|
|
77
77
|
|
|
78
78
|
```ruby
|
|
79
79
|
# config/initializers/spree.rb
|
|
80
|
-
Spree.search_provider = '
|
|
80
|
+
Spree.search_provider = 'SpreeMeilisearch::SearchProvider'
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
### 5. Index your products
|
|
@@ -216,7 +216,7 @@ The Meilisearch provider automatically configures these filterable attributes:
|
|
|
216
216
|
- `name` — product name (in document locale)
|
|
217
217
|
- `description` — product description (in document locale)
|
|
218
218
|
- `sku` — variant SKU
|
|
219
|
-
- `option_values` — option value
|
|
219
|
+
- `option_values` — option value labels (e.g., "Red", "Small")
|
|
220
220
|
- `category_names` — category names
|
|
221
221
|
- `tags` — product tags
|
|
222
222
|
|