@mercurjs/docs 2.3.8-canary.3 → 2.3.9-canary.1
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/content/learn/architecture.mdx +166 -263
- package/content/learn/introduction.mdx +9 -1
- package/content/learn/use-cases.mdx +70 -0
- package/content/platform/attribute/concepts/attribute-types.mdx +73 -46
- package/content/platform/attribute/concepts/global-vs-inline.mdx +54 -32
- package/content/platform/attribute/concepts/variant-axes.mdx +54 -32
- package/content/platform/attribute/guides/attach-attributes-to-a-product.mdx +96 -53
- package/content/platform/attribute/guides/create-a-variant-axis.mdx +106 -57
- package/content/platform/attribute/guides/create-an-attribute.mdx +105 -56
- package/content/platform/attribute/overview.mdx +37 -33
- package/content/platform/attribute/reference/data-models.mdx +53 -38
- package/content/platform/attribute/reference/events.mdx +47 -24
- package/content/platform/attribute/reference/links.mdx +98 -27
- package/content/platform/attribute/reference/service.mdx +71 -32
- package/content/platform/attribute/reference/workflows.mdx +158 -28
- package/content/platform/catalog/concepts/master-products.mdx +39 -37
- package/content/platform/catalog/concepts/product-seller-allowlist.mdx +56 -35
- package/content/platform/catalog/concepts/status-lifecycle.mdx +55 -49
- package/content/platform/catalog/concepts/variants-categories-collections.mdx +55 -35
- package/content/platform/catalog/guides/allowlist-stores.mdx +100 -37
- package/content/platform/catalog/guides/create-a-master-product.mdx +124 -48
- package/content/platform/catalog/guides/publish-or-reject-a-product.mdx +120 -55
- package/content/platform/catalog/overview.mdx +39 -35
- package/content/platform/catalog/reference/data-models.mdx +154 -43
- package/content/platform/catalog/reference/events.mdx +41 -25
- package/content/platform/catalog/reference/links.mdx +196 -28
- package/content/platform/catalog/reference/service.mdx +57 -35
- package/content/platform/catalog/reference/workflows.mdx +124 -30
- package/content/platform/commission/concepts/order-commission-lines.mdx +54 -52
- package/content/platform/commission/concepts/rule-matching.mdx +53 -63
- package/content/platform/commission/concepts/rules-and-rates.mdx +61 -59
- package/content/platform/commission/guides/batch-update-rules.mdx +69 -41
- package/content/platform/commission/guides/create-a-rate.mdx +101 -53
- package/content/platform/commission/guides/refresh-order-commission-lines.mdx +104 -35
- package/content/platform/commission/overview.mdx +43 -35
- package/content/platform/commission/reference/data-models.mdx +59 -45
- package/content/platform/commission/reference/events.mdx +28 -34
- package/content/platform/commission/reference/links.mdx +42 -33
- package/content/platform/commission/reference/service.mdx +103 -28
- package/content/platform/commission/reference/workflows.mdx +101 -27
- package/content/platform/offer/concepts/pricing-and-inventory.mdx +63 -49
- package/content/platform/offer/concepts/shipping.mdx +28 -29
- package/content/platform/offer/concepts/what-is-an-offer.mdx +48 -45
- package/content/platform/offer/guides/bulk-create-offers.mdx +97 -61
- package/content/platform/offer/guides/create-an-offer.mdx +112 -60
- package/content/platform/offer/guides/manage-offer-inventory.mdx +78 -38
- package/content/platform/offer/overview.mdx +39 -32
- package/content/platform/offer/reference/data-models.mdx +77 -47
- package/content/platform/offer/reference/events.mdx +44 -18
- package/content/platform/offer/reference/links.mdx +92 -40
- package/content/platform/offer/reference/service.mdx +66 -31
- package/content/platform/offer/reference/workflows.mdx +146 -37
- package/content/platform/order-group/concepts/computed-totals.mdx +40 -37
- package/content/platform/order-group/concepts/order-splitting.mdx +41 -39
- package/content/platform/order-group/concepts/the-order-group.mdx +39 -32
- package/content/platform/order-group/guides/list-order-groups.mdx +96 -56
- package/content/platform/order-group/guides/retrieve-an-order-group.mdx +93 -42
- package/content/platform/order-group/guides/split-a-cart.mdx +115 -40
- package/content/platform/order-group/overview.mdx +42 -32
- package/content/platform/order-group/reference/data-models.mdx +48 -31
- package/content/platform/order-group/reference/events.mdx +29 -17
- package/content/platform/order-group/reference/links.mdx +90 -29
- package/content/platform/order-group/reference/service.mdx +55 -31
- package/content/platform/order-group/reference/workflows.mdx +83 -24
- package/content/platform/payout/concepts/account-lifecycle.mdx +64 -67
- package/content/platform/payout/concepts/accounts-and-onboarding.mdx +50 -40
- package/content/platform/payout/concepts/payout-pipeline.mdx +70 -73
- package/content/platform/payout/guides/create-a-payout-account.mdx +65 -41
- package/content/platform/payout/guides/process-a-provider-webhook.mdx +84 -38
- package/content/platform/payout/guides/start-provider-onboarding.mdx +90 -46
- package/content/platform/payout/overview.mdx +43 -34
- package/content/platform/payout/reference/data-models.mdx +63 -36
- package/content/platform/payout/reference/events.mdx +56 -30
- package/content/platform/payout/reference/links.mdx +52 -22
- package/content/platform/payout/reference/service.mdx +72 -33
- package/content/platform/payout/reference/workflows.mdx +80 -19
- package/content/platform/product-edit/concepts/change-actions.mdx +52 -45
- package/content/platform/product-edit/concepts/change-pipeline.mdx +60 -52
- package/content/platform/product-edit/concepts/status-and-auto-confirm.mdx +43 -46
- package/content/platform/product-edit/guides/confirm-or-decline-a-change.mdx +104 -56
- package/content/platform/product-edit/guides/edit-a-product.mdx +126 -46
- package/content/platform/product-edit/guides/request-a-revision.mdx +99 -39
- package/content/platform/product-edit/overview.mdx +41 -34
- package/content/platform/product-edit/reference/data-models.mdx +73 -47
- package/content/platform/product-edit/reference/events.mdx +39 -29
- package/content/platform/product-edit/reference/links.mdx +32 -24
- package/content/platform/product-edit/reference/service.mdx +45 -26
- package/content/platform/product-edit/reference/workflows.mdx +173 -31
- package/content/platform/review/concepts/product-vs-seller-reviews.mdx +42 -41
- package/content/platform/review/concepts/ratings-and-moderation.mdx +45 -44
- package/content/platform/review/concepts/the-review-model.mdx +52 -45
- package/content/platform/review/guides/compute-aggregate-ratings.mdx +62 -37
- package/content/platform/review/guides/create-a-review.mdx +109 -39
- package/content/platform/review/guides/moderate-a-review.mdx +83 -37
- package/content/platform/review/guides/respond-to-a-review.mdx +85 -40
- package/content/platform/review/overview.mdx +43 -33
- package/content/platform/review/reference/data-models.mdx +41 -27
- package/content/platform/review/reference/events.mdx +55 -37
- package/content/platform/review/reference/links.mdx +80 -22
- package/content/platform/review/reference/service.mdx +61 -33
- package/content/platform/review/reference/workflows.mdx +80 -24
- package/content/platform/store/concepts/lifecycle.mdx +68 -44
- package/content/platform/store/concepts/store-entity.mdx +45 -27
- package/content/platform/store/concepts/team.mdx +56 -35
- package/content/platform/store/guides/create-a-store.mdx +102 -35
- package/content/platform/store/guides/manage-the-team.mdx +122 -32
- package/content/platform/store/guides/moderate-a-store.mdx +107 -38
- package/content/platform/store/overview.mdx +41 -34
- package/content/platform/store/reference/data-models.mdx +132 -57
- package/content/platform/store/reference/events.mdx +42 -17
- package/content/platform/store/reference/links.mdx +67 -49
- package/content/platform/store/reference/service.mdx +105 -33
- package/content/platform/store/reference/workflows.mdx +304 -24
- package/content/references/api/conventions.mdx +20 -0
- package/content/resources/integrations/magento2.mdx +162 -0
- package/content/resources/integrations/overview.mdx +10 -0
- package/content/resources/integrations/stripe-connect.mdx +1 -1
- package/content/resources/tutorials/custom-api-route.mdx +3 -2
- package/llms.txt +113 -111
- package/package.json +1 -1
|
@@ -1,58 +1,133 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Split a cart into
|
|
2
|
+
title: "Split a cart into an order group"
|
|
3
3
|
sidebarTitle: "Split a cart"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Run completeCartWithSplitOrdersWorkflow from your own code and change the split with its validate and setOrderStatus hooks."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
your own server code, such as a custom complete-cart route.
|
|
7
|
+
Run the checkout split yourself when you build a custom completion flow, or hook into it when you need to block a checkout or set the initial status of each seller’s order.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
`completeCartWithSplitOrdersWorkflow`. It takes a cart that may hold offers from
|
|
12
|
-
several sellers, creates one order per seller, and wraps them in an `OrderGroup`.
|
|
9
|
+
## Before you begin
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
You need the following:
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import { completeCartWithSplitOrdersWorkflow } from "@mercurjs/core/workflows"
|
|
13
|
+
- **A cart ready to complete**: items bought through offers, a shipping method for each seller that ships, and a payment session
|
|
14
|
+
- **Mercur’s cart completion in place**: Mercur’s cart completion route already runs this workflow, so you only need your own route for a custom flow
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
## Complete a cart from a custom route
|
|
17
|
+
|
|
18
|
+
<Steps>
|
|
19
|
+
<Step title="Run the workflow">
|
|
20
|
+
Call `completeCartWithSplitOrdersWorkflow` with the cart id. Set `throwOnError: false` so you can handle payment errors yourself.
|
|
21
|
+
|
|
22
|
+
```ts title="src/api/store/carts/[id]/place/route.ts"
|
|
23
|
+
import type {
|
|
24
|
+
MedusaRequest,
|
|
25
|
+
MedusaResponse,
|
|
26
|
+
} from "@medusajs/framework/http"
|
|
27
|
+
import {
|
|
28
|
+
completeCartWithSplitOrdersWorkflow,
|
|
29
|
+
} from "@mercurjs/core/workflows"
|
|
30
|
+
|
|
31
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
32
|
+
const { result, errors } = await completeCartWithSplitOrdersWorkflow(
|
|
33
|
+
req.scope
|
|
34
|
+
).run({
|
|
35
|
+
input: { cart_id: req.params.id },
|
|
36
|
+
throwOnError: false,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
if (errors?.[0]) {
|
|
40
|
+
throw errors[0].error
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
res.json({ order_group_id: result.order_group_id })
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The workflow returns `{ order_group_id }`. It runs once per cart: a second call for the same cart returns the existing group’s id.
|
|
48
|
+
</Step>
|
|
49
|
+
<Step title="Return the group to the shopper">
|
|
50
|
+
Load the group with `query.graph` and send it back instead of the bare id:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
|
|
54
|
+
|
|
55
|
+
const { data: [order_group] } = await query.graph({
|
|
56
|
+
entity: "order_group",
|
|
57
|
+
fields: ["id", "display_id", "total", "orders.id", "orders.total"],
|
|
58
|
+
filters: { id: result.order_group_id },
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`ContainerRegistrationKeys` comes from `@medusajs/framework/utils`.
|
|
63
|
+
</Step>
|
|
64
|
+
</Steps>
|
|
65
|
+
|
|
66
|
+
## Handle a failed payment authorization
|
|
67
|
+
|
|
68
|
+
The workflow authorizes the payment session after it creates the orders. If authorization fails, the workflow rolls back: it deletes the group, and Medusa’s steps undo the orders, links, and reservations. Mercur’s own route answers `PAYMENT_AUTHORIZATION_ERROR` and `PAYMENT_REQUIRES_MORE_ERROR` with a `200` that carries the cart and the error, so the storefront can retry payment. Do the same in a custom route:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { MedusaError } from "@medusajs/framework/utils"
|
|
24
72
|
|
|
25
|
-
|
|
73
|
+
const retryable: string[] = [
|
|
74
|
+
MedusaError.Types.PAYMENT_AUTHORIZATION_ERROR,
|
|
75
|
+
MedusaError.Types.PAYMENT_REQUIRES_MORE_ERROR,
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
if (errors?.[0] && retryable.includes(errors[0].error?.type)) {
|
|
79
|
+
res.json({ type: "cart", error: errors[0].error.message })
|
|
80
|
+
return
|
|
26
81
|
}
|
|
27
82
|
```
|
|
28
83
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
84
|
+
Throw every other error so Medusa’s error handler responds with the matching status.
|
|
85
|
+
|
|
86
|
+
## Block a checkout with the validate hook
|
|
87
|
+
|
|
88
|
+
The `validate` hook runs before the split and receives the workflow `input` and the `cart`. Throw to stop the checkout:
|
|
89
|
+
|
|
90
|
+
```ts title="src/workflows/hooks/validate-split-cart.ts"
|
|
91
|
+
import { MedusaError } from "@medusajs/framework/utils"
|
|
92
|
+
import { completeCartWithSplitOrdersWorkflow } from "@mercurjs/core/workflows"
|
|
93
|
+
|
|
94
|
+
completeCartWithSplitOrdersWorkflow.hooks.validate(async ({ cart }) => {
|
|
95
|
+
if (!cart.email) {
|
|
96
|
+
throw new MedusaError(
|
|
97
|
+
MedusaError.Types.INVALID_DATA,
|
|
98
|
+
"Add an email address before you complete the cart"
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The hook runs on every cart completion, including completions started by a payment webhook through `processPaymentWorkflow`.
|
|
105
|
+
|
|
106
|
+
## Set the initial order status with setOrderStatus
|
|
33
107
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
108
|
+
Child orders start as `pending`. Return a status from the `setOrderStatus` hook to change that, for example when sellers must accept an order before they fulfill it:
|
|
109
|
+
|
|
110
|
+
```ts title="src/workflows/hooks/set-split-order-status.ts"
|
|
111
|
+
import { OrderStatus } from "@medusajs/framework/utils"
|
|
112
|
+
import { StepResponse } from "@medusajs/framework/workflows-sdk"
|
|
113
|
+
import { completeCartWithSplitOrdersWorkflow } from "@mercurjs/core/workflows"
|
|
114
|
+
|
|
115
|
+
completeCartWithSplitOrdersWorkflow.hooks.setOrderStatus(async () => {
|
|
116
|
+
return new StepResponse({
|
|
117
|
+
status: OrderStatus.REQUIRES_ACTION,
|
|
118
|
+
status_by_seller_id: { sel_01JD8Q1234567: OrderStatus.PENDING },
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
```
|
|
39
122
|
|
|
40
|
-
|
|
123
|
+
`status` applies to every child order. `status_by_seller_id` overrides it for the sellers you list. Return nothing to keep `pending`.
|
|
41
124
|
|
|
42
|
-
|
|
43
|
-
single transaction:
|
|
125
|
+
## React to the new group
|
|
44
126
|
|
|
45
|
-
|
|
46
|
-
- creates one child `Order` per seller from that seller's items and shipping
|
|
47
|
-
- links each order to the group, its seller, and the originating cart
|
|
48
|
-
- mirrors line-item → offer links, reserves offer inventory, and splits payment captures proportionally
|
|
49
|
-
- refreshes commission lines per order and marks the cart `completed_at`
|
|
127
|
+
The split emits `order_group.created` with the group id, and `order.placed` once for each child order. Subscribe to the first for purchase-level work, such as a single confirmation email, and to the second for per-seller work. The [event reference](/platform/order-group/reference/events) has a subscriber example.
|
|
50
128
|
|
|
51
|
-
|
|
52
|
-
for the group.
|
|
129
|
+
## Next steps
|
|
53
130
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
split without forking it.
|
|
58
|
-
</Tip>
|
|
131
|
+
- [How the split assigns items, shipping, and promotions](/platform/order-group/concepts/order-splitting)
|
|
132
|
+
- [`completeCartWithSplitOrdersWorkflow` reference](/platform/order-group/reference/workflows#completecartwithsplitordersworkflow)
|
|
133
|
+
- [Retrieve the new group](/platform/order-group/guides/retrieve-an-order-group)
|
|
@@ -1,83 +1,93 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Order
|
|
2
|
+
title: "Order groups"
|
|
3
3
|
sidebarTitle: "Overview"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Turn a cart with items from several sellers into per-seller orders under one group the shopper can track."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Use
|
|
8
|
-
one coherent order for the shopper.
|
|
7
|
+
Use order groups to give the shopper one purchase while each seller gets an order of their own.
|
|
9
8
|
|
|
10
|
-
A marketplace cart can
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
group gives you a single handle over the whole purchase.
|
|
9
|
+
A marketplace cart can hold offers from several sellers. At checkout, Mercur creates one child order per seller and wraps them in an order group. The group is the record the shopper sees as “my order”, while each seller fulfills, returns, and refunds their own child order. The group stores almost nothing itself: its seller count and total are summed from the child orders every time you read it.
|
|
10
|
+
|
|
11
|
+
<img className="block dark:hidden" src="/images/figures/order-group-overview-light.svg" alt="The order_group record og_01JD8Q1234567 in front, with display_id 98, its customer and read-only cart link, and computed seller_count 2 and total 87.00. Behind it, the order_group_order link lists the two child orders it sums: 47.00 for ACME and 40.00 for GLOBEX." />
|
|
12
|
+
<img className="hidden dark:block" src="/images/figures/order-group-overview-dark.svg" alt="The order_group record og_01JD8Q1234567 in front, with display_id 98, its customer and read-only cart link, and computed seller_count 2 and total 87.00. Behind it, the order_group_order link lists the two child orders it sums: 47.00 for ACME and 40.00 for GLOBEX." />
|
|
15
13
|
|
|
16
14
|
<Note>
|
|
17
|
-
An order group is the `OrderGroup`
|
|
18
|
-
(id prefix `og`), not a module of its own. There is no `ORDER_GROUP` module
|
|
19
|
-
key. Resolve its service through `MercurModules.SELLER`.
|
|
15
|
+
An order group is the `OrderGroup` data model (id prefix `og`). It belongs to the Seller module, not a module of its own, so there is no `ORDER_GROUP` key. Resolve its service with `MercurModules.SELLER`.
|
|
20
16
|
</Note>
|
|
21
17
|
|
|
22
18
|
## Key features
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
20
|
+
Order groups cover a multi-seller purchase from checkout to the order history:
|
|
21
|
+
|
|
22
|
+
- **Split checkout**: `completeCartWithSplitOrdersWorkflow` turns one cart into one order per seller under a single group
|
|
23
|
+
- **One group per cart**: completing the same cart twice returns the existing group instead of splitting again
|
|
24
|
+
- **Readable reference**: an auto-incrementing `display_id` that shoppers and operators can quote
|
|
25
|
+
- **Frozen cart link**: a read-only `cart_id` that points at the completed cart
|
|
26
|
+
- **Live totals**: `seller_count` and `total` are computed from the child orders at query time, never stored
|
|
27
|
+
- **Derived child statuses**: the read workflows add `payment_status` and `fulfillment_status` to every child order
|
|
28
|
+
- **Seller scoping**: the list workflow can trim each group down to one seller’s orders
|
|
29
|
+
|
|
30
|
+
## How it works
|
|
31
|
+
|
|
32
|
+
A group comes to life when a cart completes:
|
|
33
|
+
|
|
34
|
+
1. The shopper completes a cart that holds offers from ACME and GLOBEX.
|
|
35
|
+
2. `completeCartWithSplitOrdersWorkflow` groups the line items by `item.offer.seller_id`.
|
|
36
|
+
3. It creates one `OrderGroup` and one child `Order` per seller, then links them.
|
|
37
|
+
4. It authorizes the cart’s payment and refreshes commission lines for each order.
|
|
38
|
+
5. It emits `order.placed` for each child order and `order_group.created` for the group.
|
|
39
|
+
6. When you read the group, the Seller module sums its child orders into `seller_count` and `total`.
|
|
30
40
|
|
|
31
41
|
## Get started
|
|
32
42
|
|
|
33
|
-
Learn how the
|
|
43
|
+
Learn how the group, the split, and the computed totals fit together.
|
|
34
44
|
|
|
35
45
|
<CardGroup cols={2}>
|
|
36
46
|
<Card title="The order group" icon="layer-group" href="/platform/order-group/concepts/the-order-group">
|
|
37
|
-
The
|
|
47
|
+
The record over a multi-seller purchase, its `display_id`, and the cart link.
|
|
38
48
|
</Card>
|
|
39
49
|
<Card title="Order splitting" icon="scissors" href="/platform/order-group/concepts/order-splitting">
|
|
40
|
-
How
|
|
50
|
+
How checkout turns one cart into one order per seller.
|
|
41
51
|
</Card>
|
|
42
52
|
<Card title="Computed totals" icon="calculator" href="/platform/order-group/concepts/computed-totals">
|
|
43
|
-
|
|
53
|
+
Where `seller_count`, `total`, and child order statuses come from.
|
|
44
54
|
</Card>
|
|
45
55
|
</CardGroup>
|
|
46
56
|
|
|
47
57
|
## Examples
|
|
48
58
|
|
|
49
|
-
Build against
|
|
59
|
+
Build against order groups in your own server code.
|
|
50
60
|
|
|
51
61
|
<CardGroup cols={2}>
|
|
52
62
|
<Card title="Retrieve an order group" icon="magnifying-glass" href="/platform/order-group/guides/retrieve-an-order-group">
|
|
53
|
-
Load
|
|
63
|
+
Load one group with its child orders and their statuses.
|
|
54
64
|
</Card>
|
|
55
65
|
<Card title="List order groups" icon="list" href="/platform/order-group/guides/list-order-groups">
|
|
56
|
-
|
|
66
|
+
Filter, page, and scope groups to a seller.
|
|
57
67
|
</Card>
|
|
58
68
|
<Card title="Split a cart" icon="scissors" href="/platform/order-group/guides/split-a-cart">
|
|
59
|
-
Complete a
|
|
69
|
+
Complete a cart into a group and hook into the split.
|
|
60
70
|
</Card>
|
|
61
71
|
</CardGroup>
|
|
62
72
|
|
|
63
73
|
## Resources
|
|
64
74
|
|
|
65
|
-
|
|
75
|
+
The data model, links, workflows, service methods, and events behind order groups.
|
|
66
76
|
|
|
67
77
|
<CardGroup cols={2}>
|
|
68
78
|
<Card title="Data models" icon="table" href="/platform/order-group/reference/data-models">
|
|
69
|
-
The `OrderGroup`
|
|
79
|
+
The `OrderGroup` model, its fields, and indexes.
|
|
70
80
|
</Card>
|
|
71
81
|
<Card title="Links" icon="link" href="/platform/order-group/reference/links">
|
|
72
|
-
How
|
|
82
|
+
How a group connects to its cart, orders, sellers, and offers.
|
|
73
83
|
</Card>
|
|
74
84
|
<Card title="Workflows" icon="diagram-project" href="/platform/order-group/reference/workflows">
|
|
75
|
-
|
|
85
|
+
The checkout split, the read workflows, and their hooks.
|
|
76
86
|
</Card>
|
|
77
87
|
<Card title="Service" icon="gear" href="/platform/order-group/reference/service">
|
|
78
|
-
Seller module methods for
|
|
88
|
+
Seller module methods for order group records.
|
|
79
89
|
</Card>
|
|
80
90
|
<Card title="Events" icon="bell" href="/platform/order-group/reference/events">
|
|
81
|
-
|
|
91
|
+
The events emitted when a cart splits into a group.
|
|
82
92
|
</Card>
|
|
83
93
|
</CardGroup>
|
|
@@ -1,40 +1,57 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Order group data models"
|
|
3
3
|
sidebarTitle: "Data models"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Fields, indexes, and relations of the OrderGroup data model in the Seller module."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
order-group module. This reference lists its data model and fields. For the full
|
|
9
|
-
module overview, see the [Order Group overview](/platform/order-group/overview).
|
|
7
|
+
Order groups have one data model, `OrderGroup`, registered on the Seller module. There is no separate order group module: resolve it with `MercurModules.SELLER`. The model is defined in `packages/core/src/modules/seller/models/order-group.ts`, and its record type is `OrderGroupDTO` from `@mercurjs/types`.
|
|
10
8
|
|
|
11
9
|
## OrderGroup
|
|
12
10
|
|
|
13
|
-
Table `order_group`, id prefix `og`.
|
|
14
|
-
created from a single cart.
|
|
11
|
+
The parent record over the child orders created from one completed cart. Table `order_group`, id prefix `og`.
|
|
15
12
|
|
|
16
|
-
| Field | Type |
|
|
13
|
+
| Field | Type | Description |
|
|
17
14
|
| --- | --- | --- |
|
|
18
|
-
| `id` | text | Primary key
|
|
19
|
-
| `display_id` |
|
|
20
|
-
| `customer_id` | text |
|
|
21
|
-
| `cart_id` | text |
|
|
22
|
-
| `seller_count` | number |
|
|
23
|
-
| `total` | bigNumber |
|
|
24
|
-
| `created_at`
|
|
25
|
-
| `
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
`
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
15
|
+
| `id` | `text` | Primary key with the prefix `og` |
|
|
16
|
+
| `display_id` | `autoincrement` | Integer assigned by the database in creation order, for people to quote |
|
|
17
|
+
| `customer_id` | `text`, nullable | Id of the customer on the completed cart, or `null` when the cart had none |
|
|
18
|
+
| `cart_id` | `text` | Id of the completed cart; backs the read-only link to the Cart module |
|
|
19
|
+
| `seller_count` | `number`, computed | Number of distinct sellers across the group’s child orders; not stored |
|
|
20
|
+
| `total` | `bigNumber`, computed | Sum of the child orders’ `current_order_total`; not stored, returned as a `number` |
|
|
21
|
+
| `created_at` | `dateTime` | Set when the record is created |
|
|
22
|
+
| `updated_at` | `dateTime` | Set when the record changes |
|
|
23
|
+
| `deleted_at` | `dateTime`, nullable | Soft-delete marker |
|
|
24
|
+
|
|
25
|
+
The computed fields are filled by the Seller module’s `OrderGroupRepository` on every read. See [Computed totals](/platform/order-group/concepts/computed-totals).
|
|
26
|
+
|
|
27
|
+
### Indexes
|
|
28
|
+
|
|
29
|
+
The model declares three partial indexes, each limited to rows where `deleted_at IS NULL`:
|
|
30
|
+
|
|
31
|
+
| Index | Columns | Serves |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `IDX_order_group_cart_id` | `cart_id` | The one-group-per-cart lookup at checkout |
|
|
34
|
+
| `IDX_order_group_customer_id_created_at` | `customer_id`, `created_at` | A customer’s order history, newest first |
|
|
35
|
+
| `IDX_order_group_created_at` | `created_at` | The default newest-first list |
|
|
36
|
+
|
|
37
|
+
### Relations
|
|
38
|
+
|
|
39
|
+
`OrderGroup` has no relations inside the Seller module. It reaches other modules through module links:
|
|
40
|
+
|
|
41
|
+
| Alias | Target | Cardinality | Link |
|
|
42
|
+
| --- | --- | --- | --- |
|
|
43
|
+
| `orders` | `Order` (Order module) | One group to many orders | `order_group_order` |
|
|
44
|
+
| `cart` | `Cart` (Cart module) | One group to one cart, read-only | `cart_id` field |
|
|
45
|
+
|
|
46
|
+
See [Links](/platform/order-group/reference/links) for the definitions and `query.graph` examples.
|
|
47
|
+
|
|
48
|
+
## Mutation types
|
|
49
|
+
|
|
50
|
+
`@mercurjs/types` exports the input shapes for the generated create and update methods:
|
|
51
|
+
|
|
52
|
+
| Type | Fields |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `CreateOrderGroupDTO` | `cart_id: string`, `customer_id?: string \| null` |
|
|
55
|
+
| `UpdateOrderGroupDTO` | `id: string`, `customer_id?: string`, `cart_id?: string` |
|
|
56
|
+
|
|
57
|
+
Checkout creates every group through `createOrderGroupStep`. Mercur never updates a group after that.
|
|
@@ -1,22 +1,40 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Order group events"
|
|
3
3
|
sidebarTitle: "Events"
|
|
4
|
-
description: "
|
|
4
|
+
description: "The events emitted when checkout splits a cart into an order group, with their payloads and a subscriber example."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Order groups emit one event of their own, `order_group.created`, when checkout splits a cart. The same run emits Medusa’s `order.placed` for every child order. Subscribe to these events to send confirmations, sync external systems, or start follow-up workflows.
|
|
8
|
+
|
|
9
|
+
## Events
|
|
10
|
+
|
|
11
|
+
Both events come from `completeCartWithSplitOrdersWorkflow`. Neither is emitted when the workflow returns an existing group for a cart that was already split.
|
|
12
|
+
|
|
13
|
+
| Event | Emitted when | Payload |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `order_group.created` | Checkout creates a group for a completed cart | `{ id }`, the group id |
|
|
16
|
+
| `order.placed` | Checkout creates a child order, once per seller | `{ id }`, the order id |
|
|
17
|
+
|
|
18
|
+
The event name is available as `OrderGroupWorkflowEvents.CREATED` from `@mercurjs/core/workflows`. `order.placed` is Medusa’s `OrderWorkflowEvents.PLACED` from `@medusajs/framework/utils`.
|
|
19
|
+
|
|
20
|
+
## Subscribe to a new group
|
|
21
|
+
|
|
22
|
+
Use `order_group.created` for work that concerns the whole purchase, such as one confirmation email for a checkout that spans three sellers:
|
|
10
23
|
|
|
11
24
|
```ts title="src/subscribers/order-group-created.ts"
|
|
12
25
|
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
26
|
+
import { getOrderGroupDetailWorkflow } from "@mercurjs/core/workflows"
|
|
13
27
|
|
|
14
28
|
export default async function orderGroupCreatedHandler({
|
|
15
29
|
event,
|
|
16
30
|
container,
|
|
17
31
|
}: SubscriberArgs<{ id: string }>) {
|
|
18
|
-
const
|
|
19
|
-
|
|
32
|
+
const { result: group } = await getOrderGroupDetailWorkflow(container).run({
|
|
33
|
+
input: {
|
|
34
|
+
order_group_id: event.data.id,
|
|
35
|
+
fields: ["id", "display_id", "total", "orders.seller.name"],
|
|
36
|
+
},
|
|
37
|
+
})
|
|
20
38
|
}
|
|
21
39
|
|
|
22
40
|
export const config: SubscriberConfig = {
|
|
@@ -24,14 +42,8 @@ export const config: SubscriberConfig = {
|
|
|
24
42
|
}
|
|
25
43
|
```
|
|
26
44
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| Event | Emitted when | Payload |
|
|
30
|
-
| --- | --- | --- |
|
|
31
|
-
| `order_group.created` | A cart is split and its parent group is created | `{ id }` |
|
|
45
|
+
The subscriber loads the new group with its child orders and sellers, ready to pass to your notification provider.
|
|
32
46
|
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
`order_group.created` when you need the purchase as a whole.
|
|
37
|
-
</Note>
|
|
47
|
+
<Tip>
|
|
48
|
+
Subscribe to `order.placed` instead when the work belongs to one seller, such as notifying that seller of a new order. Each child order fires its own event.
|
|
49
|
+
</Tip>
|
|
@@ -1,45 +1,106 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Order group links"
|
|
3
3
|
sidebarTitle: "Links"
|
|
4
|
-
description: "
|
|
4
|
+
description: "The module links that connect an order group to its cart and child orders, and its orders to sellers and offers."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
Mercur modules never reference each other directly, so an order group reaches carts and orders through module links. Two links start at the group. Two more, on the child orders, connect each order to its seller and each order line item to its offer. All four are defined in `packages/core/src/links/`, and checkout creates their rows when it splits a cart.
|
|
8
|
+
|
|
9
|
+
## Order group to order
|
|
10
|
+
|
|
11
|
+
Connects a group to its child orders, one per seller.
|
|
12
|
+
|
|
13
|
+
| | |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| **Sides** | `OrderGroup` (Seller module) and `Order` (Order module) |
|
|
16
|
+
| **Cardinality** | One group to many orders |
|
|
17
|
+
| **Table** | `order_group_order` |
|
|
18
|
+
| **Defined in** | `order-group-order-link.ts` |
|
|
12
19
|
|
|
13
20
|
```ts
|
|
14
|
-
const { data:
|
|
21
|
+
const { data: [group] } = await query.graph({
|
|
15
22
|
entity: "order_group",
|
|
16
|
-
fields: ["id", "display_id", "
|
|
23
|
+
fields: ["id", "display_id", "orders.id", "orders.total"],
|
|
24
|
+
filters: { id: "og_01JD8Q1234567" },
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
To go from an order to its group, query the link entity directly:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const { data: [row] } = await query.graph({
|
|
32
|
+
entity: "order_group_order",
|
|
33
|
+
fields: ["order_group_id"],
|
|
34
|
+
filters: { order_id: "order_01JD8Q1234568" },
|
|
17
35
|
})
|
|
18
36
|
```
|
|
19
37
|
|
|
20
|
-
##
|
|
38
|
+
## Order group to cart
|
|
21
39
|
|
|
22
|
-
|
|
40
|
+
Exposes the completed cart a group was created from. The link is read-only: it reads the group’s `cart_id` column and has no table of its own.
|
|
41
|
+
|
|
42
|
+
| | |
|
|
23
43
|
| --- | --- |
|
|
24
|
-
| **
|
|
25
|
-
| **
|
|
44
|
+
| **Sides** | `OrderGroup.cart_id` (Seller module) and `Cart` (Cart module) |
|
|
45
|
+
| **Cardinality** | One group to one cart |
|
|
46
|
+
| **Table** | None, `readOnly: true` |
|
|
47
|
+
| **Defined in** | `order-group-cart-link.ts` |
|
|
26
48
|
|
|
27
|
-
|
|
49
|
+
```ts
|
|
50
|
+
const { data: [group] } = await query.graph({
|
|
51
|
+
entity: "order_group",
|
|
52
|
+
fields: ["id", "cart.id", "cart.email", "cart.completed_at"],
|
|
53
|
+
filters: { id: "og_01JD8Q1234567" },
|
|
54
|
+
})
|
|
55
|
+
```
|
|
28
56
|
|
|
29
|
-
|
|
57
|
+
You can’t create or dismiss this link with `link.create` or `link.dismiss`. It changes only if `cart_id` changes, and Mercur never updates it.
|
|
30
58
|
|
|
31
|
-
|
|
59
|
+
## Order to seller
|
|
60
|
+
|
|
61
|
+
Connects each child order to the seller who fulfills it.
|
|
62
|
+
|
|
63
|
+
| | |
|
|
32
64
|
| --- | --- |
|
|
33
|
-
| **
|
|
34
|
-
| **
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
65
|
+
| **Sides** | `Order` (Order module) and `Seller` (Seller module) |
|
|
66
|
+
| **Cardinality** | Many orders to one seller |
|
|
67
|
+
| **Link entity** | `order_seller` |
|
|
68
|
+
| **Defined in** | `order-seller-link.ts` |
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const { data: [group] } = await query.graph({
|
|
72
|
+
entity: "order_group",
|
|
73
|
+
fields: ["id", "orders.id", "orders.seller.id", "orders.seller.name"],
|
|
74
|
+
filters: { id: "og_01JD8Q1234567" },
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`getOrderGroupsListWorkflow` reads `orders.seller.id` to trim each group to one seller when you pass `sellerId`.
|
|
79
|
+
|
|
80
|
+
## Order line item to offer
|
|
81
|
+
|
|
82
|
+
Records which offer each order line item was bought from. Checkout copies it from the matching cart line item’s offer link.
|
|
83
|
+
|
|
84
|
+
| | |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| **Sides** | `OrderLineItem` (Order module) and `Offer` (Offer module) |
|
|
87
|
+
| **Cardinality** | Many order line items to one offer |
|
|
88
|
+
| **Defined in** | `order-line-item-offer-link.ts` |
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const { data: [group] } = await query.graph({
|
|
92
|
+
entity: "order_group",
|
|
93
|
+
fields: ["id", "orders.items.id", "orders.items.offer.id"],
|
|
94
|
+
filters: { id: "og_01JD8Q1234567" },
|
|
95
|
+
})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The line item side is a list, so one offer can back line items in any number of orders and groups.
|
|
99
|
+
|
|
100
|
+
## Links checkout creates for each order
|
|
101
|
+
|
|
102
|
+
Besides the links above, `completeCartWithSplitOrdersWorkflow` creates these rows for every child order:
|
|
103
|
+
|
|
104
|
+
- **Order to cart**: Medusa’s own link from each child order to the completed cart
|
|
105
|
+
- **Order to promotion**: for each promotion owned by the order’s seller
|
|
106
|
+
- **Seller to customer**: when the customer hasn’t bought from that seller before
|