@mercurjs/docs 2.3.8-canary.3 → 2.3.8-canary.4
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/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/llms.txt +111 -111
- package/package.json +1 -1
|
@@ -1,55 +1,145 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Manage
|
|
2
|
+
title: "Manage a store's team from server code"
|
|
3
3
|
sidebarTitle: "Manage the team"
|
|
4
|
-
description: "Invite
|
|
4
|
+
description: "Invite members, accept invites, add existing members, change roles, and remove members with the Seller module workflows."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
code. You can invite members, add them directly, and update their roles.
|
|
7
|
+
Manage a store’s team from your own server code when you migrate staff from another system, sync people from an identity provider, or build your own team screens. Every change runs through a workflow that validates the owner rules and emits an event.
|
|
9
8
|
|
|
10
|
-
##
|
|
9
|
+
## Before you begin
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
The invitee sets up access and is linked to the store when they accept.
|
|
11
|
+
You need the following in place:
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import { inviteSellerWorkflow } from "@mercurjs/core/workflows"
|
|
13
|
+
- A store id, such as `sel_01JD8Q1234567`
|
|
14
|
+
- A notification provider for email, if you send invite links from a subscriber
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
await inviteSellerWorkflow(req.scope).run({
|
|
21
|
-
input: {
|
|
22
|
-
email: "ops@acme.com",
|
|
23
|
-
seller_id: req.params.id,
|
|
24
|
-
},
|
|
25
|
-
})
|
|
16
|
+
## Invite and onboard a member
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
<Steps>
|
|
19
|
+
<Step title="Create the invite">
|
|
20
|
+
`createMemberInvitesWorkflow` takes an array of invites, each with `seller_id`, `email`, and `role_id`. It signs a token for each one and fails if an email already belongs to the store.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { SellerRole } from "@mercurjs/types"
|
|
24
|
+
import { createMemberInvitesWorkflow } from "@mercurjs/core/workflows"
|
|
25
|
+
|
|
26
|
+
const { result: invites } = await createMemberInvitesWorkflow(
|
|
27
|
+
container
|
|
28
|
+
).run({
|
|
29
|
+
input: [
|
|
30
|
+
{
|
|
31
|
+
seller_id: "sel_01JD8Q1234567",
|
|
32
|
+
email: "ops@acme.com",
|
|
33
|
+
role_id: SellerRole.ORDER_MANAGEMENT,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
</Step>
|
|
39
|
+
<Step title="Send the invite link">
|
|
40
|
+
The workflow emits `member_invite.created` once per invite, with `id`, `token`, and `expires_at`. Mercur doesn’t email team invites itself, so send the link from a subscriber.
|
|
41
|
+
|
|
42
|
+
```ts title="src/subscribers/member-invite-created.ts"
|
|
43
|
+
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
44
|
+
import { Modules } from "@medusajs/framework/utils"
|
|
45
|
+
import { MercurModules } from "@mercurjs/types"
|
|
46
|
+
|
|
47
|
+
export default async function inviteCreated({
|
|
48
|
+
event,
|
|
49
|
+
container,
|
|
50
|
+
}: SubscriberArgs<{ id: string; token: string }>) {
|
|
51
|
+
const sellers = container.resolve(MercurModules.SELLER)
|
|
52
|
+
const invite = await sellers.retrieveMemberInvite(event.data.id)
|
|
53
|
+
await container.resolve(Modules.NOTIFICATION).createNotifications({
|
|
54
|
+
to: invite.email,
|
|
55
|
+
channel: "email",
|
|
56
|
+
template: "member-invite",
|
|
57
|
+
data: { token: event.data.token },
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const config: SubscriberConfig = { event: "member_invite.created" }
|
|
62
|
+
```
|
|
63
|
+
</Step>
|
|
64
|
+
<Step title="Accept the invite">
|
|
65
|
+
When the invitee signs up or signs in, run `acceptMemberInviteWorkflow` with the token and their auth identity. It returns the member.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { acceptMemberInviteWorkflow } from "@mercurjs/core/workflows"
|
|
30
69
|
|
|
31
|
-
|
|
70
|
+
const { result: member } = await acceptMemberInviteWorkflow(
|
|
71
|
+
req.scope
|
|
72
|
+
).run({
|
|
73
|
+
input: {
|
|
74
|
+
invite_token: "your_invite_token",
|
|
75
|
+
auth_identity_id: req.auth_context.auth_identity_id,
|
|
76
|
+
first_name: "Ola",
|
|
77
|
+
last_name: "Nordmann",
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
```
|
|
32
81
|
|
|
33
|
-
|
|
34
|
-
|
|
82
|
+
The workflow upserts the member by email, creates the membership with the invite’s role, and deletes the invite. Pass `member_id` when the person is already a member of another store, so the workflow leaves their auth identity as it is.
|
|
83
|
+
</Step>
|
|
84
|
+
</Steps>
|
|
85
|
+
|
|
86
|
+
## Resend or revoke an invite
|
|
87
|
+
|
|
88
|
+
`resendMemberInviteWorkflow` takes `invite_id` and `seller_id`. It deletes the invite and creates a fresh one with a new token and expiry, then emits `member_invite.created` again. `deleteMemberInviteWorkflow` takes `invite_id` and deletes the invite without a replacement.
|
|
89
|
+
|
|
90
|
+
## Add an existing member directly
|
|
91
|
+
|
|
92
|
+
Skip the invite when the person already has a `Member` record, for example after a migration. `addSellerMemberWorkflow` creates the membership and returns it.
|
|
35
93
|
|
|
36
94
|
```ts
|
|
95
|
+
import { SellerRole } from "@mercurjs/types"
|
|
37
96
|
import { addSellerMemberWorkflow } from "@mercurjs/core/workflows"
|
|
38
97
|
|
|
39
98
|
await addSellerMemberWorkflow(container).run({
|
|
40
99
|
input: {
|
|
41
|
-
seller_id: "
|
|
42
|
-
|
|
100
|
+
seller_id: "sel_01JD8Q1234567",
|
|
101
|
+
member_id: "mem_01JD8Q1234567",
|
|
102
|
+
role_id: SellerRole.SUPPORT,
|
|
43
103
|
},
|
|
44
104
|
})
|
|
45
105
|
```
|
|
46
106
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
107
|
+
The membership is unique on `(seller_id, member_id)`, so adding the same member twice fails.
|
|
108
|
+
|
|
109
|
+
## Change a role or remove a member
|
|
110
|
+
|
|
111
|
+
Both workflows take the membership id, `seller_member_id`, not the member id. Both reject the owner membership with a `NOT_ALLOWED` error.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { SellerRole } from "@mercurjs/types"
|
|
115
|
+
import {
|
|
116
|
+
removeSellerMemberWorkflow,
|
|
117
|
+
updateMemberRoleWorkflow,
|
|
118
|
+
} from "@mercurjs/core/workflows"
|
|
119
|
+
|
|
120
|
+
await updateMemberRoleWorkflow(container).run({
|
|
121
|
+
input: {
|
|
122
|
+
seller_member_id: "selmem_01JD8Q1234567",
|
|
123
|
+
role_id: SellerRole.ACCOUNTING,
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
await removeSellerMemberWorkflow(container).run({
|
|
128
|
+
input: {
|
|
129
|
+
seller_member_id: "selmem_01JD8Q1234567",
|
|
130
|
+
seller_id: "sel_01JD8Q1234567",
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Removing a membership keeps the `Member` record, so the person keeps access to their other stores.
|
|
136
|
+
|
|
137
|
+
## Update a member’s profile
|
|
138
|
+
|
|
139
|
+
`updateMemberWorkflow` changes `first_name`, `last_name`, and `locale` on members that match a `selector`. It exposes a `membersUpdated` hook and doesn’t emit an event.
|
|
51
140
|
|
|
52
|
-
##
|
|
141
|
+
## Next steps
|
|
53
142
|
|
|
54
|
-
|
|
55
|
-
|
|
143
|
+
- [How store teams work](/platform/store/concepts/team)
|
|
144
|
+
- [Event reference](/platform/store/reference/events)
|
|
145
|
+
- [Workflows reference](/platform/store/reference/workflows)
|
|
@@ -1,59 +1,128 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Approve, suspend, and terminate stores"
|
|
3
3
|
sidebarTitle: "Moderate stores"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Move stores through their lifecycle from server code, extend each transition with a hook, and react to the events."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
own server code. Each transition has a dedicated workflow, so the side effects
|
|
9
|
-
(events, notifications, and compensation) run consistently.
|
|
7
|
+
Drive a store through its lifecycle from your own server code, for example to auto-approve vetted sellers or to suspend a store when a risk check fails. Each transition is a workflow that validates the current status, writes the change, emits an event, and exposes a hook.
|
|
10
8
|
|
|
11
|
-
##
|
|
9
|
+
## Moderate a store
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
<Steps>
|
|
12
|
+
<Step title="Approve a pending store">
|
|
13
|
+
`approveSellerWorkflow` moves a `pending_approval` store to `open` and stamps `approved_at`.
|
|
14
14
|
|
|
15
|
-
```ts title="src/api/
|
|
16
|
-
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
17
|
-
import { approveSellerWorkflow } from "@mercurjs/core/workflows"
|
|
15
|
+
```ts title="src/api/admin/stores/[id]/vet/route.ts"
|
|
16
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
17
|
+
import { approveSellerWorkflow } from "@mercurjs/core/workflows"
|
|
18
18
|
|
|
19
|
-
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
20
|
+
await approveSellerWorkflow(req.scope).run({
|
|
21
|
+
input: { seller_id: req.params.id },
|
|
22
|
+
})
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
```
|
|
24
|
+
res.sendStatus(200)
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
</Step>
|
|
28
|
+
<Step title="Suspend and reinstate a store">
|
|
29
|
+
`suspendSellerWorkflow` takes an optional `reason`, which it saves in `status_reason`. `unsuspendSellerWorkflow` reopens the store and clears the reason.
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
```ts
|
|
32
|
+
import {
|
|
33
|
+
suspendSellerWorkflow,
|
|
34
|
+
unsuspendSellerWorkflow,
|
|
35
|
+
} from "@mercurjs/core/workflows"
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
await suspendSellerWorkflow(container).run({
|
|
38
|
+
input: { seller_id: "sel_01JD8Q1234567", reason: "Chargeback review" },
|
|
39
|
+
})
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
await unsuspendSellerWorkflow(container).run({
|
|
42
|
+
input: { seller_id: "sel_01JD8Q1234567" },
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
</Step>
|
|
46
|
+
<Step title="Terminate a store">
|
|
47
|
+
`terminateSellerWorkflow` accepts a `pending_approval` or `suspended` store. Suspend an `open` store first.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { terminateSellerWorkflow } from "@mercurjs/core/workflows"
|
|
51
|
+
|
|
52
|
+
await terminateSellerWorkflow(container).run({
|
|
53
|
+
input: { seller_id: "sel_01JD8Q1234567", reason: "Policy breach" },
|
|
54
|
+
})
|
|
55
|
+
```
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
To undo it, run `unterminateSellerWorkflow`. It returns the store to `suspended`, and you reopen it with `unsuspendSellerWorkflow`.
|
|
58
|
+
</Step>
|
|
59
|
+
</Steps>
|
|
60
|
+
|
|
61
|
+
## Reject a pending application
|
|
62
|
+
|
|
63
|
+
Mercur has no separate reject workflow. Run `suspendSellerWorkflow` on the `pending_approval` store with a `reason`: it stamps `rejected_at` and keeps the store out of the Store API. Terminate it afterwards if the decision is final.
|
|
64
|
+
|
|
65
|
+
## Handle a failed transition
|
|
66
|
+
|
|
67
|
+
Each workflow checks the starting status and fails with a `NOT_ALLOWED` error when the transition isn’t allowed. Nothing is written in that case. Pass `throwOnError: false` to read the error instead of catching it.
|
|
44
68
|
|
|
45
69
|
```ts
|
|
70
|
+
import { MedusaError } from "@medusajs/framework/utils"
|
|
46
71
|
import { terminateSellerWorkflow } from "@mercurjs/core/workflows"
|
|
47
72
|
|
|
48
|
-
await terminateSellerWorkflow(container).run({
|
|
73
|
+
const { errors } = await terminateSellerWorkflow(container).run({
|
|
74
|
+
input: { seller_id: "sel_01JD8Q1234567" },
|
|
75
|
+
throwOnError: false,
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const notAllowed = errors.some(
|
|
79
|
+
({ error }) => error.type === MedusaError.Types.NOT_ALLOWED
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
An `open` store makes `notAllowed` true here, with the message “Cannot terminate an open seller. Suspend or close first.”
|
|
84
|
+
|
|
85
|
+
The workflow also fails when the seller id doesn’t exist, because its lookup step runs with `throwIfKeyNotFound`.
|
|
86
|
+
|
|
87
|
+
## Extend a transition with a hook
|
|
88
|
+
|
|
89
|
+
Each lifecycle workflow exposes a hook that receives `seller_id` and `additional_data`. Register a handler to run your own step inside the transition.
|
|
90
|
+
|
|
91
|
+
```ts title="src/workflows/hooks/seller-approved.ts"
|
|
92
|
+
import { approveSellerWorkflow } from "@mercurjs/core/workflows"
|
|
93
|
+
|
|
94
|
+
approveSellerWorkflow.hooks.sellerApproved(
|
|
95
|
+
async ({ seller_id }, { container }) => {
|
|
96
|
+
const logger = container.resolve("logger")
|
|
97
|
+
logger.info(`Store ${seller_id} approved`)
|
|
98
|
+
}
|
|
99
|
+
)
|
|
49
100
|
```
|
|
50
101
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
102
|
+
The other hooks follow the same shape: `sellerSuspended`, `sellerUnsuspended`, `sellerTerminated`, and `sellerUnterminated`.
|
|
103
|
+
|
|
104
|
+
## Run side effects from a subscriber
|
|
105
|
+
|
|
106
|
+
Subscribe to the lifecycle events for work that shouldn’t block the transition, such as emails. Each event carries `{ id }`, the seller id.
|
|
107
|
+
|
|
108
|
+
```ts title="src/subscribers/store-suspended.ts"
|
|
109
|
+
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
110
|
+
|
|
111
|
+
export default async function storeSuspended({
|
|
112
|
+
event,
|
|
113
|
+
container,
|
|
114
|
+
}: SubscriberArgs<{ id: string }>) {
|
|
115
|
+
const logger = container.resolve("logger")
|
|
116
|
+
logger.info(`Store ${event.data.id} suspended`)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const config: SubscriberConfig = {
|
|
120
|
+
event: "seller.suspended",
|
|
121
|
+
}
|
|
122
|
+
```
|
|
54
123
|
|
|
55
|
-
##
|
|
124
|
+
## Next steps
|
|
56
125
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
[
|
|
126
|
+
- [Store statuses and transitions](/platform/store/concepts/lifecycle)
|
|
127
|
+
- [Event reference](/platform/store/reference/events)
|
|
128
|
+
- [Workflows reference](/platform/store/reference/workflows)
|
|
@@ -1,46 +1,53 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Stores"
|
|
3
3
|
sidebarTitle: "Overview"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Control who sells on your marketplace, who works on each store, and when a store can trade."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Use Mercur to
|
|
8
|
-
person on a store's team can do.
|
|
7
|
+
Use Mercur to decide who can sell on your marketplace and what each person on a store’s team can do.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
store
|
|
14
|
-
details used to settle payouts. Every offer, order, payout, and storefront page
|
|
15
|
-
belongs to a store, and all of it is exposed directly through the Admin and
|
|
16
|
-
Vendor APIs.
|
|
9
|
+
A store is the account a seller trades under. Offers, orders, payouts, and storefront pages all link back to it, and its team works only inside it. The Seller module holds the store record, its business details, its members and invites, and its status. Other marketplace modules attach to a store through module links, never through direct references.
|
|
10
|
+
|
|
11
|
+
<img className="block dark:hidden" src="/images/figures/store-overview-light.svg" alt="A Stores list from the Seller module showing four stores, each with its status, currency, member count, and premium flag, in front of the Team panel for acme-supplies with three members and their seller roles." />
|
|
12
|
+
<img className="hidden dark:block" src="/images/figures/store-overview-dark.svg" alt="A Stores list from the Seller module showing four stores, each with its status, currency, member count, and premium flag, in front of the Team panel for acme-supplies with three members and their seller roles." />
|
|
17
13
|
|
|
18
14
|
<Note>
|
|
19
|
-
|
|
20
|
-
The API and core modules call the same record a `Seller` (id prefix `sel`). You
|
|
21
|
-
never need to know Medusa to work with stores.
|
|
15
|
+
The Admin and Vendor panels call it a store. The code calls the same record a `Seller` (id prefix `sel`), and you resolve its module with `MercurModules.SELLER` from `@mercurjs/types`.
|
|
22
16
|
</Note>
|
|
23
17
|
|
|
24
18
|
## Key features
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
32
|
-
- **
|
|
20
|
+
The Seller module covers the full life of a store account:
|
|
21
|
+
|
|
22
|
+
- **Many-to-many teams**: a member can belong to several stores and picks the active one per request
|
|
23
|
+
- **Owner protection**: the store’s owner membership can’t be removed or have its role changed
|
|
24
|
+
- **Seller roles**: each membership stores one of five `SellerRole` values, from administration to support
|
|
25
|
+
- **Token-based invites**: signed invite tokens that expire after 7 days by default
|
|
26
|
+
- **Governed lifecycle**: four statuses, each transition run by its own workflow with a hook and an event
|
|
27
|
+
- **Scheduled closures**: a `closed_from` and `closed_to` window that hides a store from the Store API without changing its status
|
|
28
|
+
- **Premium flag**: an `is_premium` boolean the operator sets for featured placement
|
|
29
|
+
- **Region assignment**: every store links to one or more regions, starting with the default region
|
|
30
|
+
|
|
31
|
+
## How it works
|
|
32
|
+
|
|
33
|
+
A store moves from creation to trading in a fixed order:
|
|
34
|
+
|
|
35
|
+
1. A seller registers, or your code runs `createSellersWorkflow`, and the store starts in `pending_approval`
|
|
36
|
+
2. The workflow links the store to the default region and to any `region_ids` you pass
|
|
37
|
+
3. The first member joins as owner, either at registration or by accepting the invite the workflow sends
|
|
38
|
+
4. The operator runs `approveSellerWorkflow`, and the store becomes `open`
|
|
39
|
+
5. The Store API lists the store and its offers while it’s `open` and outside a closure window
|
|
33
40
|
|
|
34
41
|
## Get started
|
|
35
42
|
|
|
36
|
-
Learn how
|
|
43
|
+
Learn how stores, teams, and statuses fit together.
|
|
37
44
|
|
|
38
45
|
<CardGroup cols={2}>
|
|
39
46
|
<Card title="The store" icon="store" href="/platform/store/concepts/store-entity">
|
|
40
|
-
The seller
|
|
47
|
+
The seller record, its currency, regions, and business details.
|
|
41
48
|
</Card>
|
|
42
49
|
<Card title="Team & members" icon="users" href="/platform/store/concepts/team">
|
|
43
|
-
|
|
50
|
+
Members, owners, roles, invites, and the active store.
|
|
44
51
|
</Card>
|
|
45
52
|
<Card title="Lifecycle" icon="arrows-rotate" href="/platform/store/concepts/lifecycle">
|
|
46
53
|
Statuses, transitions, scheduled closures, and premium.
|
|
@@ -49,38 +56,38 @@ Learn how the domain fits together.
|
|
|
49
56
|
|
|
50
57
|
## Examples
|
|
51
58
|
|
|
52
|
-
Build against
|
|
59
|
+
Build against stores in your own server code.
|
|
53
60
|
|
|
54
61
|
<CardGroup cols={2}>
|
|
55
62
|
<Card title="Create a store" icon="plus" href="/platform/store/guides/create-a-store">
|
|
56
|
-
Run `createSellersWorkflow` from a route or seed script.
|
|
63
|
+
Run `createSellersWorkflow` from a route or a seed script.
|
|
57
64
|
</Card>
|
|
58
65
|
<Card title="Moderate stores" icon="gavel" href="/platform/store/guides/moderate-a-store">
|
|
59
|
-
Approve, suspend, and
|
|
66
|
+
Approve, suspend, terminate, and reinstate stores in code.
|
|
60
67
|
</Card>
|
|
61
68
|
<Card title="Manage the team" icon="user-plus" href="/platform/store/guides/manage-the-team">
|
|
62
|
-
Invite and
|
|
69
|
+
Invite, add, re-role, and remove members.
|
|
63
70
|
</Card>
|
|
64
71
|
</CardGroup>
|
|
65
72
|
|
|
66
73
|
## Resources
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
The data models, links, workflows, service methods, and events behind stores.
|
|
69
76
|
|
|
70
77
|
<CardGroup cols={2}>
|
|
71
78
|
<Card title="Data models" icon="table" href="/platform/store/reference/data-models">
|
|
72
|
-
|
|
79
|
+
`Seller`, `Member`, `SellerMember`, `MemberInvite`, and the satellite records.
|
|
73
80
|
</Card>
|
|
74
81
|
<Card title="Links" icon="link" href="/platform/store/reference/links">
|
|
75
|
-
How
|
|
82
|
+
How a store connects to orders, offers, payouts, regions, and more.
|
|
76
83
|
</Card>
|
|
77
84
|
<Card title="Workflows" icon="diagram-project" href="/platform/store/reference/workflows">
|
|
78
|
-
|
|
85
|
+
Store, lifecycle, and team workflows with their hooks.
|
|
79
86
|
</Card>
|
|
80
87
|
<Card title="Service" icon="gear" href="/platform/store/reference/service">
|
|
81
|
-
|
|
88
|
+
Seller module service methods for direct reads and writes.
|
|
82
89
|
</Card>
|
|
83
90
|
<Card title="Events" icon="bell" href="/platform/store/reference/events">
|
|
84
|
-
Events emitted as stores and
|
|
91
|
+
Events emitted as stores, members, and invites change.
|
|
85
92
|
</Card>
|
|
86
93
|
</CardGroup>
|