@spree/docs 0.1.177 → 0.1.179
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/developer/cli/quickstart.md +1 -1
- package/dist/developer/contributing/creating-an-extension.md +2 -2
- package/dist/developer/core-concepts/addresses.md +3 -3
- package/dist/developer/core-concepts/architecture.md +4 -4
- package/dist/developer/core-concepts/calculators.md +2 -2
- package/dist/developer/core-concepts/carts.md +207 -0
- package/dist/developer/core-concepts/channels.md +3 -3
- package/dist/developer/core-concepts/customers.md +1 -1
- package/dist/developer/core-concepts/events.md +1 -1
- package/dist/developer/core-concepts/fulfillments.md +278 -0
- package/dist/developer/core-concepts/imports-exports.md +6 -18
- package/dist/developer/core-concepts/inventory.md +3 -3
- package/dist/developer/core-concepts/media.md +1 -1
- package/dist/developer/core-concepts/metafields.md +1 -1
- package/dist/developer/core-concepts/orders.md +92 -339
- package/dist/developer/core-concepts/payments.md +1 -1
- package/dist/developer/core-concepts/promotions.md +68 -195
- package/dist/developer/core-concepts/returns-exchanges-claims.md +173 -0
- package/dist/developer/core-concepts/store-credits-gift-cards.md +16 -18
- package/dist/developer/core-concepts/stores.md +1 -1
- package/dist/developer/core-concepts/taxes-discounts-fees.md +199 -0
- package/dist/developer/core-concepts/taxes.md +3 -3
- package/dist/developer/create-spree-app/quickstart.md +1 -1
- package/dist/developer/customization/api.md +36 -11
- package/dist/developer/customization/configuration.md +208 -37
- package/dist/developer/customization/decorators.md +8 -8
- package/dist/developer/customization/permissions.md +34 -229
- package/dist/developer/customization/quickstart.md +159 -108
- package/dist/developer/customization/validations.md +1 -1
- package/dist/developer/dashboard/overview.md +1 -1
- package/dist/developer/how-to/build-a-b2b-store.md +21 -0
- package/dist/developer/how-to/build-a-marketplace.md +25 -0
- package/dist/developer/how-to/custom-api-authentication.md +1 -1
- package/dist/developer/how-to/custom-delivery-rate-provider.md +242 -0
- package/dist/developer/how-to/custom-document-numbers.md +154 -0
- package/dist/developer/how-to/custom-order-routing.md +1 -1
- package/dist/developer/how-to/custom-payment-method.md +1 -1
- package/dist/developer/how-to/custom-promotion.md +76 -115
- package/dist/developer/how-to/custom-report.md +2 -2
- package/dist/developer/how-to/custom-stock-splitter.md +5 -5
- package/dist/developer/how-to/sell-digital-products.md +20 -0
- package/dist/developer/multi-tenant/quickstart.md +1 -1
- package/dist/developer/providers/dam.md +14 -0
- package/dist/developer/providers/erp.md +31 -0
- package/dist/developer/providers/fulfillment.md +25 -0
- package/dist/developer/{deployment/telemetry.md → providers/observability.md} +1 -1
- package/dist/developer/providers/overview.md +44 -0
- package/dist/developer/providers/pim.md +25 -0
- package/dist/developer/providers/sso.md +20 -0
- package/dist/developer/sdk/admin/extending.md +1 -1
- package/dist/developer/sdk/admin/quickstart.md +1 -1
- package/dist/developer/sdk/admin/resources.md +1 -1
- package/dist/developer/sdk/extending.md +1 -1
- package/dist/developer/tutorial/admin-api.md +13 -0
- package/dist/developer/tutorial/dashboard-plugin.md +14 -0
- package/dist/developer/tutorial/events.md +7 -161
- package/dist/developer/tutorial/introduction.md +15 -35
- package/dist/developer/tutorial/model.md +7 -98
- package/dist/developer/tutorial/store-api.md +13 -0
- package/dist/developer/tutorial/storefront.md +12 -0
- package/dist/developer/tutorial/testing.md +7 -711
- package/dist/developer/upgrades/5.6-to-6.0.md +2 -2
- package/package.json +1 -1
- package/dist/developer/admin/admin.md +0 -214
- package/dist/developer/admin/authentication.md +0 -59
- package/dist/developer/admin/components.md +0 -711
- package/dist/developer/admin/custom-css.md +0 -256
- package/dist/developer/admin/custom-javascript.md +0 -116
- package/dist/developer/admin/extending-ui.md +0 -1839
- package/dist/developer/admin/form-builder.md +0 -444
- package/dist/developer/admin/helper-methods.md +0 -531
- package/dist/developer/admin/navigation.md +0 -805
- package/dist/developer/admin/tables.md +0 -490
- package/dist/developer/advanced/adding_spree_to_rails_app.md +0 -92
- package/dist/developer/core-concepts/adjustments.md +0 -113
- package/dist/developer/core-concepts/reports.md +0 -208
- package/dist/developer/core-concepts/shipments.md +0 -307
- package/dist/developer/core-concepts/users.md +0 -303
- package/dist/developer/customization/authentication.md +0 -100
- package/dist/developer/customization/checkout.md +0 -202
- package/dist/developer/customization/emails.md +0 -18
- package/dist/developer/customization/routes.md +0 -24
- package/dist/developer/multi-vendor/installation.md +0 -61
- package/dist/developer/multi-vendor/quickstart.md +0 -17
- package/dist/developer/tutorial/admin.md +0 -206
- package/dist/developer/tutorial/api.md +0 -606
- package/dist/developer/tutorial/extending-models.md +0 -393
- package/dist/developer/tutorial/sdk.md +0 -170
- package/dist/developer/upgrades/2.0-to-2.1.md +0 -46
- package/dist/developer/upgrades/2.1-to-2.2.md +0 -59
- package/dist/developer/upgrades/2.2-to-2.3.md +0 -44
- package/dist/developer/upgrades/2.3-to-2.4.md +0 -42
- package/dist/developer/upgrades/3.0-to-3.1.md +0 -47
- package/dist/developer/upgrades/3.1-to-3.2.md +0 -34
- package/dist/developer/upgrades/3.2-to-3.3.md +0 -70
- package/dist/developer/upgrades/3.3-to-3.4.md +0 -36
- package/dist/developer/upgrades/3.4-to-3.5.md +0 -44
- package/dist/developer/upgrades/3.5-to-3.6.md +0 -40
- package/dist/developer/upgrades/3.6-to-3.7.md +0 -62
- package/dist/developer/upgrades/3.7-to-4.0.md +0 -152
- package/dist/developer/upgrades/4.0-to-4.1.md +0 -92
- package/dist/developer/upgrades/4.1-to-4.2.md +0 -109
- package/dist/developer/upgrades/4.10-to-5.0.md +0 -131
- package/dist/developer/upgrades/4.2-to-4.3.md +0 -100
- package/dist/developer/upgrades/4.3-to-4.4.md +0 -125
- package/dist/developer/upgrades/4.4-to-4.5.md +0 -94
- package/dist/developer/upgrades/4.5-to-4.6.md +0 -119
- package/dist/developer/upgrades/4.6-to-4.7.md +0 -39
- package/dist/developer/upgrades/4.8-to-4.9.md +0 -24
- package/dist/developer/upgrades/4.9-to-4.10.md +0 -24
- package/dist/developer/upgrades/4.x-to-4.8.md +0 -52
- package/dist/developer/upgrades/5.0-to-5.1.md +0 -28
- package/dist/developer/upgrades/5.1-to-5.2.md +0 -131
- package/dist/developer/upgrades/5.2-to-5.3.md +0 -338
- package/dist/developer/upgrades/5.3-to-5.4.md +0 -277
- package/dist/developer/upgrades/5.4-to-5.5.md +0 -301
- package/dist/developer/upgrades/5.5-to-5.6.md +0 -207
|
@@ -82,7 +82,7 @@ erDiagram
|
|
|
82
82
|
- **Stock Item** → Tracks quantity (`count_on_hand`) for a specific Variant at a specific Stock Location
|
|
83
83
|
- **Stock Movement** → Records changes to Stock Item quantities (purchases, returns, transfers)
|
|
84
84
|
- **Stock Transfer** → Moves inventory between Stock Locations, creating Stock Movements at source and destination
|
|
85
|
-
- **Inventory Unit** → Represents individual units in [Orders](orders.md) and [Shipments](
|
|
85
|
+
- **Inventory Unit** → Represents individual units in [Orders](orders.md) and [Shipments](fulfillments.md)
|
|
86
86
|
- **Stock Reservation** → Time-limited soft hold on a Stock Item during checkout, scoped to a specific Order and Line Item
|
|
87
87
|
|
|
88
88
|
## Inventory Management
|
|
@@ -276,7 +276,7 @@ When a cart change in checkout would push the order beyond available stock, the
|
|
|
276
276
|
|
|
277
277
|
### Background expiry
|
|
278
278
|
|
|
279
|
-
Abandoned checkouts leave behind expired reservation rows. Spree provides a job to clean them up but does **not** auto-schedule it — your application's job runner needs to invoke it periodically (every minute is typical). See the [5.4 to 5.5 upgrade guide](
|
|
279
|
+
Abandoned checkouts leave behind expired reservation rows. Spree provides a job to clean them up but does **not** auto-schedule it — your application's job runner needs to invoke it periodically (every minute is typical). See the [5.4 to 5.5 upgrade guide](/v5/developer/upgrades/5.4-to-5.5#schedule-the-stock-reservations-expiry-job) for sidekiq-cron, solid_queue, and good_job snippets.
|
|
280
280
|
|
|
281
281
|
### Backorderable items
|
|
282
282
|
|
|
@@ -319,7 +319,7 @@ If you don't need to track inventory, you can disable it:
|
|
|
319
319
|
## Related Documentation
|
|
320
320
|
|
|
321
321
|
- [Products](products.md) - Product and variant management
|
|
322
|
-
- [Shipments](
|
|
322
|
+
- [Shipments](fulfillments.md) - How inventory relates to shipments
|
|
323
323
|
- [Orders](orders.md) - How inventory is allocated to orders
|
|
324
324
|
- [Admin SDK resources](../sdk/admin/resources.md) - `stockLocations`, `stockItems`, and `stockTransfers` methods used in the examples above
|
|
325
325
|
- [Admin API authentication](../../api-reference/admin-api/authentication.md) - How to obtain and scope the secret key (`sk_xxx`) used by these calls
|
|
@@ -104,7 +104,7 @@ Variants belonging to a different product are silently dropped — the API rejec
|
|
|
104
104
|
|
|
105
105
|
The Store API's `media` field on a product returns its gallery — product-level media when present, falling back to legacy variant-pinned images during the transition. On a variant, `media` returns the assets linked to that variant via `variant_ids`, falling back to direct variant uploads.
|
|
106
106
|
|
|
107
|
-
This dual rendering means existing storefronts keep working during the upgrade; new uploads attach to the product, and you opt into a [one-shot migration](
|
|
107
|
+
This dual rendering means existing storefronts keep working during the upgrade; new uploads attach to the product, and you opt into a [one-shot migration](/v5/developer/upgrades/5.4-to-5.5) to re-home legacy variant-pinned data when convenient.
|
|
108
108
|
|
|
109
109
|
### Video
|
|
110
110
|
|
|
@@ -280,7 +280,7 @@ Spree has two permanent, complementary systems for custom data — **metadata fo
|
|
|
280
280
|
|
|
281
281
|
**Use [Metadata](../customization/metadata.md)** for external system IDs, tracking attribution, syncing with integrations, or simple write-and-forget data that only backend systems need to read.
|
|
282
282
|
|
|
283
|
-
> **WARNING:** Product Properties are deprecated and will be removed in Spree 6.0. For new projects, always use Metafields. For existing projects, plan to migrate using the [migration guide](
|
|
283
|
+
> **WARNING:** Product Properties are deprecated and will be removed in Spree 6.0. For new projects, always use Metafields. For existing projects, plan to migrate using the [migration guide](/v5/developer/upgrades/5.1-to-5.2#migrate-to-metafields-or-keep-using-product-properties).
|
|
284
284
|
|
|
285
285
|
## Related Documentation
|
|
286
286
|
|
|
@@ -1,409 +1,162 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Orders
|
|
3
|
-
description: How Spree models orders —
|
|
3
|
+
description: How Spree models orders — a permanent record created by completing a cart, with separate payment and delivery statuses.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
An order is
|
|
8
|
+
An order is a placed purchase. It's created by completing a [Cart](carts.md) and holds its own copy of everything the customer agreed to — items, prices, taxes, discounts and delivery.
|
|
9
9
|
|
|
10
10
|
```mermaid
|
|
11
11
|
erDiagram
|
|
12
12
|
Order ||--o{ LineItem : "has many"
|
|
13
|
-
Order ||--o{
|
|
13
|
+
Order ||--o{ Fulfillment : "has many"
|
|
14
14
|
Order ||--o{ Payment : "has many"
|
|
15
|
-
Order ||--o{
|
|
16
|
-
Order }o--||
|
|
17
|
-
Order }o--||
|
|
18
|
-
Order }o--|| User : "belongs to"
|
|
19
|
-
Order }o--|| Store : "belongs to"
|
|
20
|
-
LineItem }o--|| Variant : "belongs to"
|
|
21
|
-
Shipment }o--|| StockLocation : "ships from"
|
|
22
|
-
Payment }o--|| PaymentMethod : "belongs to"
|
|
15
|
+
Order ||--o{ Return : "has many"
|
|
16
|
+
Order }o--|| Cart : "created from"
|
|
17
|
+
Order }o--|| Customer : "belongs to"
|
|
23
18
|
|
|
24
19
|
Order {
|
|
25
20
|
string number
|
|
26
|
-
string
|
|
27
|
-
string
|
|
28
|
-
string
|
|
29
|
-
|
|
30
|
-
string payment_state
|
|
31
|
-
string shipment_state
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
LineItem {
|
|
35
|
-
integer quantity
|
|
36
|
-
decimal price
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
Shipment {
|
|
40
|
-
string number
|
|
41
|
-
string state
|
|
42
|
-
string tracking
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
Payment {
|
|
46
|
-
decimal amount
|
|
47
|
-
string state
|
|
21
|
+
string payment_status
|
|
22
|
+
string fulfillment_status
|
|
23
|
+
string total
|
|
24
|
+
datetime completed_at
|
|
48
25
|
}
|
|
49
26
|
```
|
|
50
27
|
|
|
51
|
-
|
|
52
|
-
- **Line Items** link orders to [Variants](products.md#variants) (what was purchased)
|
|
53
|
-
- **[Shipments](shipments.md)** handle fulfillment from stock locations
|
|
54
|
-
- **[Payments](payments.md)** track payment attempts and their states
|
|
55
|
-
- **[Adjustments](adjustments.md)** apply taxes, promotions, and shipping costs
|
|
56
|
-
- **[Addresses](addresses.md)** store billing and shipping information
|
|
57
|
-
|
|
58
|
-
## Order Attributes
|
|
59
|
-
|
|
60
|
-
The API returns these key fields on every order:
|
|
28
|
+
## Order attributes
|
|
61
29
|
|
|
62
30
|
| Attribute | Description |
|
|
63
|
-
|
|
64
|
-
| `
|
|
31
|
+
|---|---|
|
|
32
|
+
| `id` | Order ID, e.g. `or_86Rf07xd4z` |
|
|
33
|
+
| `number` | Order number shown to customers, e.g. `R1001` — sequential by default, [customizable](../how-to/custom-document-numbers.md) |
|
|
34
|
+
| `cart_id` | The cart this order came from |
|
|
65
35
|
| `email` | Customer's email address |
|
|
66
|
-
| `currency` | Order currency
|
|
36
|
+
| `currency` | Order currency, e.g. `USD` |
|
|
67
37
|
| `total_quantity` | Total number of items |
|
|
38
|
+
| `payment_status` | See [statuses](#statuses) below |
|
|
39
|
+
| `fulfillment_status` | See [statuses](#statuses) below |
|
|
68
40
|
| `item_total` / `display_item_total` | Sum of line item prices |
|
|
69
41
|
| `delivery_total` / `display_delivery_total` | Delivery cost |
|
|
70
42
|
| `tax_total` / `display_tax_total` | Total tax |
|
|
71
|
-
| `discount_total` / `display_discount_total` | Total discount
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `fulfillment_status` | Fulfillment status (`pending`, `ready`, `partial`, `shipped`, `backorder`) |
|
|
76
|
-
| `completed_at` | Timestamp when the order was placed |
|
|
77
|
-
|
|
78
|
-
The [`display_*` fields return formatted strings with currency symbols](../../api-reference/store-api/monetary-amounts.md) (e.g., `"$15.99"`).
|
|
79
|
-
|
|
80
|
-
## Cart
|
|
81
|
-
|
|
82
|
-
A cart is simply an order in the `cart` state. Guest carts are [identified by a cart token; authenticated users' carts are linked to their account](../../api-reference/store-api/authentication.md).
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```typescript Store SDK
|
|
86
|
-
// Create a cart
|
|
87
|
-
const cart = await client.carts.create()
|
|
88
|
-
// cart.token => "abc123" (save this for guest checkout)
|
|
89
|
-
|
|
90
|
-
// Get existing cart
|
|
91
|
-
const cart = await client.carts.get(cartId, { spreeToken: 'xxx' })
|
|
92
|
-
|
|
93
|
-
// Add an item
|
|
94
|
-
const updatedOrder = await client.carts.items.create(cart.id, {
|
|
95
|
-
variant_id: 'var_xxx',
|
|
96
|
-
quantity: 2,
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
// Update quantity
|
|
100
|
-
await client.carts.items.update(cart.id, 'li_xxx', {
|
|
101
|
-
quantity: 3,
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
// Remove an item
|
|
105
|
-
await client.carts.items.delete(cart.id, 'li_xxx')
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
```bash cURL
|
|
109
|
-
# Create a cart
|
|
110
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/carts' \
|
|
111
|
-
-H 'X-Spree-API-Key: pk_xxx'
|
|
112
|
-
|
|
113
|
-
# Get existing cart
|
|
114
|
-
curl 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
|
|
115
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
116
|
-
-H 'X-Spree-Token: abc123'
|
|
117
|
-
|
|
118
|
-
# Add an item
|
|
119
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_xxx/items' \
|
|
120
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
121
|
-
-H 'X-Spree-Token: abc123' \
|
|
122
|
-
-H 'Content-Type: application/json' \
|
|
123
|
-
-d '{ "variant_id": "var_xxx", "quantity": 2 }'
|
|
124
|
-
|
|
125
|
-
# Update quantity
|
|
126
|
-
curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx/items/li_xxx' \
|
|
127
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
128
|
-
-H 'X-Spree-Token: abc123' \
|
|
129
|
-
-H 'Content-Type: application/json' \
|
|
130
|
-
-d '{ "quantity": 3 }'
|
|
131
|
-
|
|
132
|
-
# Remove an item
|
|
133
|
-
curl -X DELETE 'https://api.mystore.com/api/v3/store/carts/cart_xxx/items/li_xxx' \
|
|
134
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
135
|
-
-H 'X-Spree-Token: abc123'
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
Every item mutation returns the full updated order with recalculated totals.
|
|
140
|
-
|
|
141
|
-
## Checkout Flow
|
|
142
|
-
|
|
143
|
-
The checkout is a state machine that advances the order through a series of steps. Each step collects required information before allowing the order to proceed.
|
|
144
|
-
|
|
145
|
-
**Step 1: cart**
|
|
146
|
-
|
|
147
|
-
Customer has items in their cart. This is the starting state.
|
|
148
|
-
|
|
149
|
-
**Step 2: address**
|
|
43
|
+
| `discount_total` / `display_discount_total` | Total discount |
|
|
44
|
+
| `total` / `display_total` | Order total |
|
|
45
|
+
| `amount_due` / `display_amount_due` | Still outstanding |
|
|
46
|
+
| `completed_at` | When the order was placed |
|
|
150
47
|
|
|
151
|
-
|
|
48
|
+
Every amount comes in two forms: `total` is the raw value (`"135.60"`) and [`display_total` is formatted for the currency](../../api-reference/store-api/monetary-amounts.md) (`"$135.60"`). Render the `display_` one.
|
|
152
49
|
|
|
153
|
-
|
|
50
|
+
## Statuses
|
|
154
51
|
|
|
155
|
-
|
|
52
|
+
An order tracks payment and delivery separately, because they genuinely move at different speeds. An order can be paid but not yet sent, or sent and later partly refunded.
|
|
156
53
|
|
|
157
|
-
|
|
54
|
+
**`payment_status`**
|
|
158
55
|
|
|
159
|
-
|
|
56
|
+
| Value | Meaning |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `none` | Nothing paid or authorized yet |
|
|
59
|
+
| `authorized` | Money is held but not taken |
|
|
60
|
+
| `partially_paid` | Some of the total has been taken |
|
|
61
|
+
| `paid` | Fully paid |
|
|
62
|
+
| `partially_refunded` | Some money returned |
|
|
63
|
+
| `refunded` | Everything returned |
|
|
64
|
+
| `overcharged` | More was taken than the order total |
|
|
65
|
+
| `voided` | The hold was released without taking money |
|
|
160
66
|
|
|
161
|
-
|
|
67
|
+
**`fulfillment_status`**
|
|
162
68
|
|
|
163
|
-
|
|
69
|
+
| Value | Meaning |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `unfulfilled` | Nothing has gone out yet |
|
|
72
|
+
| `backorder` | Waiting on stock |
|
|
73
|
+
| `partial` | Some of it has gone out |
|
|
74
|
+
| `fulfilled` | Everything has gone out |
|
|
75
|
+
| `delivered` | The customer has all of it |
|
|
76
|
+
| `canceled` | Nothing will be sent |
|
|
164
77
|
|
|
165
|
-
|
|
78
|
+
A canceled parcel is ignored while others are still live, so an order whose second parcel was recalled is described by the first.
|
|
166
79
|
|
|
167
|
-
|
|
80
|
+
Both are worked out automatically from the order's payments, refunds and fulfillments. You change an order's status by acting on those — taking a payment, sending a parcel, issuing a refund — never by setting the status yourself.
|
|
168
81
|
|
|
82
|
+
## Reading an order
|
|
169
83
|
|
|
170
|
-
|
|
84
|
+
A customer can fetch their own order; guests use the order token they got at checkout.
|
|
171
85
|
|
|
172
86
|
|
|
173
87
|
```typescript Store SDK
|
|
174
|
-
//
|
|
175
|
-
await client.
|
|
176
|
-
email: 'john@example.com',
|
|
177
|
-
shipping_address: {
|
|
178
|
-
first_name: 'John', last_name: 'Doe',
|
|
179
|
-
address1: '123 Main St', city: 'Los Angeles',
|
|
180
|
-
country_iso: 'US', state_abbr: 'CA', postal_code: '90001',
|
|
181
|
-
phone: '555-0100',
|
|
182
|
-
},
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
// Get fulfillments and select a delivery rate
|
|
186
|
-
// (the Store API/SDK exposes shipments as `fulfillments`)
|
|
187
|
-
const cart = await client.carts.get(cartId)
|
|
188
|
-
await client.carts.fulfillments.update(cartId, cart.fulfillments[0].id, {
|
|
189
|
-
selected_delivery_rate_id: 'rate_xxx',
|
|
190
|
-
})
|
|
88
|
+
// A single order
|
|
89
|
+
const order = await client.orders.get('or_xxx')
|
|
191
90
|
|
|
192
|
-
//
|
|
193
|
-
const
|
|
194
|
-
payment_method_id: 'pm_xxx',
|
|
195
|
-
})
|
|
196
|
-
// session.external_data.client_secret => use with Stripe.js
|
|
197
|
-
|
|
198
|
-
// Complete the payment session after provider confirmation
|
|
199
|
-
await client.carts.paymentSessions.complete(cartId, session.id)
|
|
200
|
-
|
|
201
|
-
// Complete the order
|
|
202
|
-
await client.carts.complete(cartId)
|
|
91
|
+
// The signed-in customer's order history
|
|
92
|
+
const orders = await client.customers.orders.list({ per_page: 20 })
|
|
203
93
|
```
|
|
204
94
|
|
|
205
95
|
```bash cURL
|
|
206
|
-
|
|
207
|
-
curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
|
|
208
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
209
|
-
-H 'X-Spree-Token: abc123' \
|
|
210
|
-
-H 'Content-Type: application/json' \
|
|
211
|
-
-d '{
|
|
212
|
-
"email": "john@example.com",
|
|
213
|
-
"shipping_address": {
|
|
214
|
-
"first_name": "John", "last_name": "Doe",
|
|
215
|
-
"address1": "123 Main St", "city": "Los Angeles",
|
|
216
|
-
"country_iso": "US", "state_abbr": "CA", "postal_code": "90001",
|
|
217
|
-
"phone": "555-0100"
|
|
218
|
-
}
|
|
219
|
-
}'
|
|
220
|
-
|
|
221
|
-
# Select a delivery rate
|
|
222
|
-
curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx/fulfillments/ful_xxx' \
|
|
96
|
+
curl 'https://api.mystore.com/api/v3/store/orders/or_xxx' \
|
|
223
97
|
-H 'X-Spree-API-Key: pk_xxx' \
|
|
224
|
-
-H 'X-Spree-Token:
|
|
225
|
-
-H 'Content-Type: application/json' \
|
|
226
|
-
-d '{ "selected_delivery_rate_id": "rate_xxx" }'
|
|
227
|
-
|
|
228
|
-
# Complete the order
|
|
229
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_xxx/complete' \
|
|
230
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
231
|
-
-H 'X-Spree-Token: abc123'
|
|
98
|
+
-H 'X-Spree-Token: order_token_xxx'
|
|
232
99
|
```
|
|
233
100
|
|
|
234
101
|
|
|
235
|
-
##
|
|
102
|
+
## Managing orders
|
|
236
103
|
|
|
237
|
-
|
|
104
|
+
Back-office work happens through the Admin API.
|
|
238
105
|
|
|
239
106
|
|
|
240
|
-
```typescript Store SDK
|
|
241
|
-
// Apply a discount code
|
|
242
|
-
await client.carts.discountCodes.apply(cartId, 'SAVE20')
|
|
243
|
-
|
|
244
|
-
// Remove a discount code
|
|
245
|
-
await client.carts.discountCodes.remove(cartId, 'SAVE20')
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
```bash cURL
|
|
249
|
-
# Apply a discount code
|
|
250
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_xxx/discount_codes' \
|
|
251
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
252
|
-
-H 'X-Spree-Token: abc123' \
|
|
253
|
-
-H 'Content-Type: application/json' \
|
|
254
|
-
-d '{ "code": "SAVE20" }'
|
|
255
|
-
|
|
256
|
-
# Remove a discount code
|
|
257
|
-
curl -X DELETE 'https://api.mystore.com/api/v3/store/carts/cart_xxx/discount_codes/SAVE20' \
|
|
258
|
-
-H 'X-Spree-API-Key: pk_xxx' \
|
|
259
|
-
-H 'X-Spree-Token: abc123'
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
## Order History
|
|
264
|
-
|
|
265
|
-
Authenticated customers can view their past orders:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
```typescript Store SDK
|
|
269
|
-
// List past orders
|
|
270
|
-
const { data: orders } = await client.customer.orders.list()
|
|
271
|
-
|
|
272
|
-
// Get a specific order with details
|
|
273
|
-
const order = await client.orders.get('or_xxx', {
|
|
274
|
-
expand: ['items', 'fulfillments', 'payments'],
|
|
275
|
-
})
|
|
276
|
-
```
|
|
277
|
-
|
|
278
107
|
```typescript Admin SDK
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
```bash cURL
|
|
283
|
-
# List past orders
|
|
284
|
-
curl 'https://api.mystore.com/api/v3/store/customer/orders' \
|
|
285
|
-
-H 'Authorization: Bearer <jwt_token>'
|
|
286
|
-
|
|
287
|
-
# Get a specific order
|
|
288
|
-
curl 'https://api.mystore.com/api/v3/store/orders/or_xxx?expand=items,fulfillments,payments' \
|
|
289
|
-
-H 'Authorization: Bearer <jwt_token>'
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
## Managing Orders
|
|
294
|
-
|
|
295
|
-
Everything above is the **Store API** — the customer's own cart and orders. Back-office order management (listing every order, creating phone/manual orders, capturing payments, cancelling) uses the [Admin API](../../api-reference/admin-api/introduction.md).
|
|
296
|
-
|
|
297
|
-
### Listing and creating orders
|
|
298
|
-
|
|
299
|
-
List orders with [Ransack filters and pagination](../../api-reference/admin-api/querying.md) (`state_eq`, `limit`, sorting). A draft order is created in one call; pass line items as `items` (each `{ variant_id, quantity }`):
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
```typescript Admin SDK
|
|
303
|
-
import { createAdminClient } from '@spree/admin-sdk'
|
|
304
|
-
|
|
305
|
-
const client = createAdminClient({
|
|
306
|
-
baseUrl: 'https://store.example.com',
|
|
307
|
-
secretKey: 'sk_xxx',
|
|
108
|
+
// Find orders needing attention
|
|
109
|
+
const orders = await adminClient.orders.list({
|
|
110
|
+
filter: { payment_status_eq: 'paid', fulfillment_status_eq: 'unfulfilled' },
|
|
308
111
|
})
|
|
309
112
|
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
email: 'buyer@example.com',
|
|
316
|
-
items: [{ variant_id: 'variant_xxx', quantity: 2 }],
|
|
317
|
-
currency: 'USD',
|
|
113
|
+
// Cancel an order
|
|
114
|
+
await adminClient.orders.cancel('or_xxx', {
|
|
115
|
+
reason: 'customer',
|
|
116
|
+
restock_items: true,
|
|
117
|
+
refund_payments: true,
|
|
318
118
|
})
|
|
319
|
-
```
|
|
320
119
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
spree api post /orders -d '{
|
|
324
|
-
"email": "buyer@example.com",
|
|
325
|
-
"items": [{ "variant_id": "variant_xxx", "quantity": 2 }]
|
|
326
|
-
}'
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
### Order state actions
|
|
331
|
-
|
|
332
|
-
Orders move through their [state machine](#checkout-flow) via dedicated actions rather than raw `state` writes:
|
|
120
|
+
// Take an authorized payment
|
|
121
|
+
await adminClient.orders.payments.capture('or_xxx', 'pay_xxx')
|
|
333
122
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
await client.orders.resume('or_xxx')
|
|
340
|
-
await client.orders.resendConfirmation('or_xxx')
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
```bash CLI
|
|
344
|
-
spree api patch /orders/or_xxx/complete
|
|
345
|
-
spree api patch /orders/or_xxx/cancel -d '{"reason": "customer"}'
|
|
346
|
-
spree api patch /orders/or_xxx/approve
|
|
123
|
+
// Refund against a specific payment
|
|
124
|
+
await adminClient.orders.refunds.create('or_xxx', {
|
|
125
|
+
payment_id: 'pay_xxx',
|
|
126
|
+
amount: '25.00',
|
|
127
|
+
})
|
|
347
128
|
```
|
|
348
129
|
|
|
130
|
+
```bash cURL
|
|
131
|
+
curl 'https://api.mystore.com/api/v3/admin/orders?filter[payment_status_eq]=paid' \
|
|
132
|
+
-H 'X-Spree-API-Key: sk_xxx'
|
|
349
133
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
```typescript Admin SDK
|
|
356
|
-
await client.orders.payments.capture('or_xxx', 'pay_xxx')
|
|
357
|
-
await client.orders.payments.void('or_xxx', 'pay_xxx')
|
|
358
|
-
await client.orders.refunds.create('or_xxx', { payment_id: 'pay_xxx', amount: '19.99' })
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
```bash CLI
|
|
362
|
-
spree api patch /orders/or_xxx/payments/pay_xxx/capture
|
|
363
|
-
spree api post /orders/or_xxx/refunds -d '{"payment_id": "pay_xxx", "amount": "19.99"}'
|
|
134
|
+
curl -X PATCH 'https://api.mystore.com/api/v3/admin/orders/or_xxx/cancel' \
|
|
135
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
136
|
+
-H 'Content-Type: application/json' \
|
|
137
|
+
-d '{ "reason": "customer", "restock_items": true }'
|
|
364
138
|
```
|
|
365
139
|
|
|
366
140
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
Line items represent individual products in an order. Each line item links to a [Variant](products.md#variants) and tracks the quantity and price at the time of purchase.
|
|
370
|
-
|
|
371
|
-
When a variant is added to an order, the price is locked on the line item. If the variant's price changes later, existing orders are unaffected.
|
|
372
|
-
|
|
373
|
-
## Adjustments
|
|
141
|
+
Canceling records who canceled and why, puts stock back, and settles any payments.
|
|
374
142
|
|
|
375
|
-
|
|
143
|
+
## Orders don't change quietly
|
|
376
144
|
|
|
377
|
-
|
|
145
|
+
A placed order is meant to stay put. Its items and prices are written when the cart is completed and then left alone, so an order keeps saying what the customer actually agreed to — even if a product's price changes the next day.
|
|
378
146
|
|
|
379
|
-
|
|
380
|
-
|-------|-------------|
|
|
381
|
-
| `balance_due` | Payment total is less than the order total |
|
|
382
|
-
| `paid` | Payment total equals the order total |
|
|
383
|
-
| `credit_owed` | Payment total exceeds the order total (refund pending) |
|
|
384
|
-
| `failed` | Most recent payment attempt failed |
|
|
385
|
-
| `void` | Order was canceled and payments voided |
|
|
147
|
+
Where admin edits are allowed, totals are re-added from the order's existing rows rather than worked out again from scratch. Editing an order must never quietly re-apply today's promotions and hand the customer a different discount than the one they accepted.
|
|
386
148
|
|
|
387
|
-
##
|
|
149
|
+
## Money on an order
|
|
388
150
|
|
|
389
|
-
|
|
151
|
+
Tax, discounts and fees are kept as separate records, so you can ask what tax was charged without picking through a mixed list. See [Taxes, Discounts & Fees](taxes-discounts-fees.md).
|
|
390
152
|
|
|
391
|
-
|
|
392
|
-
|--------|-------------|
|
|
393
|
-
| `pending` | All fulfillments are pending |
|
|
394
|
-
| `ready` | All fulfillments are ready to ship |
|
|
395
|
-
| `partial` | At least one fulfillment is shipped, others are not |
|
|
396
|
-
| `shipped` | All fulfillments have been shipped |
|
|
397
|
-
| `backorder` | Some inventory is on backorder |
|
|
153
|
+
## Events
|
|
398
154
|
|
|
399
|
-
|
|
155
|
+
Orders publish [events](events.md) — `order.placed`, `order.canceled`, `order.paid` and more — which also reach [webhooks](webhooks.md). This is the right way to push orders to another system, trigger fulfillment, or start an email flow.
|
|
400
156
|
|
|
401
|
-
## Related
|
|
157
|
+
## Related
|
|
402
158
|
|
|
403
|
-
- [
|
|
404
|
-
- [
|
|
405
|
-
- [
|
|
406
|
-
- [
|
|
407
|
-
- [Promotions](promotions.md) — Discounts and coupon codes
|
|
408
|
-
- [Checkout Customization](../customization/checkout.md) — Customizing the checkout flow
|
|
409
|
-
- [Events](events.md) — Subscribe to order events (e.g., `order.completed`)
|
|
159
|
+
- [Carts](carts.md) — shopping and checkout
|
|
160
|
+
- [Fulfillments](fulfillments.md) — getting items to the customer
|
|
161
|
+
- [Returns, Exchanges & Claims](returns-exchanges-claims.md) — after the sale
|
|
162
|
+
- [Payments](payments.md) — payment methods and processing
|
|
@@ -682,7 +682,7 @@ See [Events](events.md) for more details on subscribing to events.
|
|
|
682
682
|
- [Payments (Store SDK)](../sdk/store/payments.md) - SDK how-to for payment sessions, payments, and setup sessions
|
|
683
683
|
- [Build a Custom Payment Method](../how-to/custom-payment-method.md) - Step-by-step guide to creating your own payment gateway integration
|
|
684
684
|
- [Orders](orders.md) - Order management and state machine
|
|
685
|
-
- [Checkout Customization](
|
|
685
|
+
- [Checkout Customization](carts.md) - Customizing the checkout flow
|
|
686
686
|
- [Events](events.md) - Subscribe to payment events
|
|
687
687
|
|
|
688
688
|
## Key Services
|