@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.
Files changed (120) hide show
  1. package/content/learn/architecture.mdx +166 -263
  2. package/content/learn/introduction.mdx +9 -1
  3. package/content/learn/use-cases.mdx +70 -0
  4. package/content/platform/attribute/concepts/attribute-types.mdx +73 -46
  5. package/content/platform/attribute/concepts/global-vs-inline.mdx +54 -32
  6. package/content/platform/attribute/concepts/variant-axes.mdx +54 -32
  7. package/content/platform/attribute/guides/attach-attributes-to-a-product.mdx +96 -53
  8. package/content/platform/attribute/guides/create-a-variant-axis.mdx +106 -57
  9. package/content/platform/attribute/guides/create-an-attribute.mdx +105 -56
  10. package/content/platform/attribute/overview.mdx +37 -33
  11. package/content/platform/attribute/reference/data-models.mdx +53 -38
  12. package/content/platform/attribute/reference/events.mdx +47 -24
  13. package/content/platform/attribute/reference/links.mdx +98 -27
  14. package/content/platform/attribute/reference/service.mdx +71 -32
  15. package/content/platform/attribute/reference/workflows.mdx +158 -28
  16. package/content/platform/catalog/concepts/master-products.mdx +39 -37
  17. package/content/platform/catalog/concepts/product-seller-allowlist.mdx +56 -35
  18. package/content/platform/catalog/concepts/status-lifecycle.mdx +55 -49
  19. package/content/platform/catalog/concepts/variants-categories-collections.mdx +55 -35
  20. package/content/platform/catalog/guides/allowlist-stores.mdx +100 -37
  21. package/content/platform/catalog/guides/create-a-master-product.mdx +124 -48
  22. package/content/platform/catalog/guides/publish-or-reject-a-product.mdx +120 -55
  23. package/content/platform/catalog/overview.mdx +39 -35
  24. package/content/platform/catalog/reference/data-models.mdx +154 -43
  25. package/content/platform/catalog/reference/events.mdx +41 -25
  26. package/content/platform/catalog/reference/links.mdx +196 -28
  27. package/content/platform/catalog/reference/service.mdx +57 -35
  28. package/content/platform/catalog/reference/workflows.mdx +124 -30
  29. package/content/platform/commission/concepts/order-commission-lines.mdx +54 -52
  30. package/content/platform/commission/concepts/rule-matching.mdx +53 -63
  31. package/content/platform/commission/concepts/rules-and-rates.mdx +61 -59
  32. package/content/platform/commission/guides/batch-update-rules.mdx +69 -41
  33. package/content/platform/commission/guides/create-a-rate.mdx +101 -53
  34. package/content/platform/commission/guides/refresh-order-commission-lines.mdx +104 -35
  35. package/content/platform/commission/overview.mdx +43 -35
  36. package/content/platform/commission/reference/data-models.mdx +59 -45
  37. package/content/platform/commission/reference/events.mdx +28 -34
  38. package/content/platform/commission/reference/links.mdx +42 -33
  39. package/content/platform/commission/reference/service.mdx +103 -28
  40. package/content/platform/commission/reference/workflows.mdx +101 -27
  41. package/content/platform/offer/concepts/pricing-and-inventory.mdx +63 -49
  42. package/content/platform/offer/concepts/shipping.mdx +28 -29
  43. package/content/platform/offer/concepts/what-is-an-offer.mdx +48 -45
  44. package/content/platform/offer/guides/bulk-create-offers.mdx +97 -61
  45. package/content/platform/offer/guides/create-an-offer.mdx +112 -60
  46. package/content/platform/offer/guides/manage-offer-inventory.mdx +78 -38
  47. package/content/platform/offer/overview.mdx +39 -32
  48. package/content/platform/offer/reference/data-models.mdx +77 -47
  49. package/content/platform/offer/reference/events.mdx +44 -18
  50. package/content/platform/offer/reference/links.mdx +92 -40
  51. package/content/platform/offer/reference/service.mdx +66 -31
  52. package/content/platform/offer/reference/workflows.mdx +146 -37
  53. package/content/platform/order-group/concepts/computed-totals.mdx +40 -37
  54. package/content/platform/order-group/concepts/order-splitting.mdx +41 -39
  55. package/content/platform/order-group/concepts/the-order-group.mdx +39 -32
  56. package/content/platform/order-group/guides/list-order-groups.mdx +96 -56
  57. package/content/platform/order-group/guides/retrieve-an-order-group.mdx +93 -42
  58. package/content/platform/order-group/guides/split-a-cart.mdx +115 -40
  59. package/content/platform/order-group/overview.mdx +42 -32
  60. package/content/platform/order-group/reference/data-models.mdx +48 -31
  61. package/content/platform/order-group/reference/events.mdx +29 -17
  62. package/content/platform/order-group/reference/links.mdx +90 -29
  63. package/content/platform/order-group/reference/service.mdx +55 -31
  64. package/content/platform/order-group/reference/workflows.mdx +83 -24
  65. package/content/platform/payout/concepts/account-lifecycle.mdx +64 -67
  66. package/content/platform/payout/concepts/accounts-and-onboarding.mdx +50 -40
  67. package/content/platform/payout/concepts/payout-pipeline.mdx +70 -73
  68. package/content/platform/payout/guides/create-a-payout-account.mdx +65 -41
  69. package/content/platform/payout/guides/process-a-provider-webhook.mdx +84 -38
  70. package/content/platform/payout/guides/start-provider-onboarding.mdx +90 -46
  71. package/content/platform/payout/overview.mdx +43 -34
  72. package/content/platform/payout/reference/data-models.mdx +63 -36
  73. package/content/platform/payout/reference/events.mdx +56 -30
  74. package/content/platform/payout/reference/links.mdx +52 -22
  75. package/content/platform/payout/reference/service.mdx +72 -33
  76. package/content/platform/payout/reference/workflows.mdx +80 -19
  77. package/content/platform/product-edit/concepts/change-actions.mdx +52 -45
  78. package/content/platform/product-edit/concepts/change-pipeline.mdx +60 -52
  79. package/content/platform/product-edit/concepts/status-and-auto-confirm.mdx +43 -46
  80. package/content/platform/product-edit/guides/confirm-or-decline-a-change.mdx +104 -56
  81. package/content/platform/product-edit/guides/edit-a-product.mdx +126 -46
  82. package/content/platform/product-edit/guides/request-a-revision.mdx +99 -39
  83. package/content/platform/product-edit/overview.mdx +41 -34
  84. package/content/platform/product-edit/reference/data-models.mdx +73 -47
  85. package/content/platform/product-edit/reference/events.mdx +39 -29
  86. package/content/platform/product-edit/reference/links.mdx +32 -24
  87. package/content/platform/product-edit/reference/service.mdx +45 -26
  88. package/content/platform/product-edit/reference/workflows.mdx +173 -31
  89. package/content/platform/review/concepts/product-vs-seller-reviews.mdx +42 -41
  90. package/content/platform/review/concepts/ratings-and-moderation.mdx +45 -44
  91. package/content/platform/review/concepts/the-review-model.mdx +52 -45
  92. package/content/platform/review/guides/compute-aggregate-ratings.mdx +62 -37
  93. package/content/platform/review/guides/create-a-review.mdx +109 -39
  94. package/content/platform/review/guides/moderate-a-review.mdx +83 -37
  95. package/content/platform/review/guides/respond-to-a-review.mdx +85 -40
  96. package/content/platform/review/overview.mdx +43 -33
  97. package/content/platform/review/reference/data-models.mdx +41 -27
  98. package/content/platform/review/reference/events.mdx +55 -37
  99. package/content/platform/review/reference/links.mdx +80 -22
  100. package/content/platform/review/reference/service.mdx +61 -33
  101. package/content/platform/review/reference/workflows.mdx +80 -24
  102. package/content/platform/store/concepts/lifecycle.mdx +68 -44
  103. package/content/platform/store/concepts/store-entity.mdx +45 -27
  104. package/content/platform/store/concepts/team.mdx +56 -35
  105. package/content/platform/store/guides/create-a-store.mdx +102 -35
  106. package/content/platform/store/guides/manage-the-team.mdx +122 -32
  107. package/content/platform/store/guides/moderate-a-store.mdx +107 -38
  108. package/content/platform/store/overview.mdx +41 -34
  109. package/content/platform/store/reference/data-models.mdx +132 -57
  110. package/content/platform/store/reference/events.mdx +42 -17
  111. package/content/platform/store/reference/links.mdx +67 -49
  112. package/content/platform/store/reference/service.mdx +105 -33
  113. package/content/platform/store/reference/workflows.mdx +304 -24
  114. package/content/references/api/conventions.mdx +20 -0
  115. package/content/resources/integrations/magento2.mdx +162 -0
  116. package/content/resources/integrations/overview.mdx +10 -0
  117. package/content/resources/integrations/stripe-connect.mdx +1 -1
  118. package/content/resources/tutorials/custom-api-route.mdx +3 -2
  119. package/llms.txt +113 -111
  120. package/package.json +1 -1
@@ -1,89 +1,164 @@
1
1
  ---
2
- title: "Data models"
2
+ title: "Seller module data models"
3
3
  sidebarTitle: "Data models"
4
- description: "The data models owned by the Store (Seller) domain."
4
+ description: "Every data model in the Seller module, with fields, types, defaults, indexes, and relations."
5
5
  ---
6
6
 
7
- The Store domain is owned by the **Seller module**. This reference lists its data
8
- models and their fields. For the full module overview, see the
9
- [Store overview](/platform/store/overview).
7
+ The Seller module (`MercurModules.SELLER`) owns the store, its business details, and its team. Every model also has the standard `created_at`, `updated_at`, and `deleted_at` columns, which the tables below leave out.
10
8
 
11
9
  ## Seller
12
10
 
13
- Table `seller`, id prefix `sel`. The store account and profile.
11
+ The store account and its public profile. Table `seller`, id prefix `sel`.
14
12
 
15
- | Field | Type | Notes |
13
+ | Field | Type | Description |
16
14
  | --- | --- | --- |
17
- | `id` | text | Primary key |
18
- | `name` | text | Unique, searchable |
19
- | `handle` | text | Unique; auto-generated from `name` when omitted |
20
- | `email` | text | Unique, searchable |
21
- | `phone` | text | Nullable |
22
- | `description` | text | Nullable |
23
- | `logo` / `banner` | text | Nullable |
24
- | `website_url` | text | Nullable |
25
- | `external_id` | text | Nullable; unique when set |
26
- | `currency_code` | text | The store's single operating currency |
27
- | `status` | enum | `SellerStatus`, default `pending_approval` |
28
- | `status_reason` | text | Nullable |
29
- | `approved_at` / `rejected_at` | dateTime | Nullable |
30
- | `is_premium` | boolean | Default `false`; operator-set only |
31
- | `closed_from` / `closed_to` | dateTime | Nullable; scheduled closure window |
32
- | `closure_note` | text | Nullable |
33
- | `metadata` | json | Nullable |
34
-
35
- Relations: `professional_details`, `address`, `payment_details` (one-to-one,
36
- deleted with the seller), `members` (many-to-many through `SellerMember`),
37
- `member_invites` (one-to-many, deleted with the seller).
15
+ | `id` | `text` | Primary key |
16
+ | `name` | `text` | Searchable, unique |
17
+ | `handle` | `text` | Searchable, unique, generated from `name` when omitted |
18
+ | `email` | `text` | Searchable, unique |
19
+ | `phone` | `text` | Nullable |
20
+ | `description` | `text` | Nullable |
21
+ | `logo` | `text` | Nullable, image URL |
22
+ | `banner` | `text` | Nullable, image URL |
23
+ | `website_url` | `text` | Searchable, nullable |
24
+ | `external_id` | `text` | Searchable, nullable, unique when set |
25
+ | `currency_code` | `text` | The store’s settlement currency |
26
+ | `status` | `enum` | `SellerStatus`, default `pending_approval` |
27
+ | `status_reason` | `text` | Nullable, set by suspend and terminate |
28
+ | `approved_at` | `dateTime` | Nullable, set on first approval |
29
+ | `rejected_at` | `dateTime` | Nullable, set on first suspension |
30
+ | `is_premium` | `boolean` | Default `false` |
31
+ | `default_leadtime_to_ship` | `number` | Default `2`, in days |
32
+ | `closed_from` | `dateTime` | Nullable, start of a scheduled closure |
33
+ | `closed_to` | `dateTime` | Nullable, end of a scheduled closure |
34
+ | `closure_note` | `text` | Nullable |
35
+ | `metadata` | `json` | Nullable |
36
+
37
+ Unique indexes on `name`, `handle`, `email`, and `external_id` apply only to rows that aren’t deleted. An extra index on `(status, closed_from, closed_to)` serves the Store API visibility filter.
38
+
39
+ Relations:
40
+
41
+ - **`professional_details`**: has one `ProfessionalDetails`, deleted with the seller
42
+ - **`address`**: has one `SellerAddress`, deleted with the seller
43
+ - **`payment_details`**: has one `PaymentDetails`, deleted with the seller
44
+ - **`members`**: many-to-many with `Member` through `SellerMember`, detached when the seller is deleted
45
+ - **`member_invites`**: has many `MemberInvite`, deleted with the seller
46
+
47
+ ## SellerStatus
48
+
49
+ The enum in `@mercurjs/types` that types `Seller.status`.
50
+
51
+ | Key | Value |
52
+ | --- | --- |
53
+ | `OPEN` | `open` |
54
+ | `PENDING_APPROVAL` | `pending_approval` |
55
+ | `SUSPENDED` | `suspended` |
56
+ | `TERMINATED` | `terminated` |
38
57
 
39
58
  ## ProfessionalDetails
40
59
 
41
- Table `professional_details`, id prefix `selprodet`. Presence marks the store as
42
- a registered business.
60
+ A store’s registered business identity. Table `professional_details`, id prefix `selprodet`.
43
61
 
44
- | Field | Type |
45
- | --- | --- |
46
- | `corporate_name` | text, nullable |
47
- | `registration_number` | text, nullable |
48
- | `tax_id` | text, nullable |
62
+ | Field | Type | Description |
63
+ | --- | --- | --- |
64
+ | `corporate_name` | `text` | Nullable |
65
+ | `registration_number` | `text` | Nullable |
66
+ | `tax_id` | `text` | Nullable |
67
+ | `seller_id` | `text` | Belongs to `Seller` |
49
68
 
50
69
  ## SellerAddress
51
70
 
52
- Table `seller_address`, id prefix `seladdr`. Fields: `name`, `company`,
53
- `first_name`, `last_name`, `address_1`, `address_2`, `city`, `country_code`,
54
- `province`, `postal_code`, `phone`, and `metadata`. All are nullable.
71
+ A store’s postal address. Table `seller_address`, id prefix `seladdr`.
72
+
73
+ | Field | Type | Description |
74
+ | --- | --- | --- |
75
+ | `name` | `text` | Searchable, nullable |
76
+ | `company` | `text` | Searchable, nullable |
77
+ | `first_name` | `text` | Searchable, nullable |
78
+ | `last_name` | `text` | Searchable, nullable |
79
+ | `address_1` | `text` | Searchable, nullable |
80
+ | `address_2` | `text` | Searchable, nullable |
81
+ | `city` | `text` | Searchable, nullable |
82
+ | `country_code` | `text` | Nullable |
83
+ | `province` | `text` | Searchable, nullable |
84
+ | `postal_code` | `text` | Searchable, nullable |
85
+ | `phone` | `text` | Nullable |
86
+ | `metadata` | `json` | Nullable |
87
+ | `seller_id` | `text` | Belongs to `Seller` |
55
88
 
56
89
  ## PaymentDetails
57
90
 
58
- Table `payment_details`, id prefix `selpaydet`. Fields: `country_code`,
59
- `holder_name`, `bank_name`, `iban`, `bic`, `routing_number`, and
60
- `account_number`. All are nullable.
91
+ A store’s bank account details. Table `payment_details`, id prefix `selpaydet`.
92
+
93
+ | Field | Type | Description |
94
+ | --- | --- | --- |
95
+ | `country_code` | `text` | Nullable |
96
+ | `holder_name` | `text` | Nullable |
97
+ | `bank_name` | `text` | Nullable |
98
+ | `iban` | `text` | Nullable |
99
+ | `bic` | `text` | Nullable |
100
+ | `routing_number` | `text` | Nullable |
101
+ | `account_number` | `text` | Nullable |
102
+ | `seller_id` | `text` | Belongs to `Seller` |
61
103
 
62
104
  ## Member
63
105
 
64
- Table `member`, id prefix `mem`. A dashboard user that can belong to one or more
65
- stores.
106
+ A person who can work for one or more stores. Table `member`, id prefix `mem`.
66
107
 
67
- | Field | Type | Notes |
108
+ | Field | Type | Description |
68
109
  | --- | --- | --- |
69
- | `email` | text | Unique, searchable |
70
- | `first_name` / `last_name` | text | Nullable |
71
- | `locale` | text | Nullable |
72
- | `is_active` | boolean | Default `true` |
73
- | `metadata` | json | Nullable |
110
+ | `id` | `text` | Primary key |
111
+ | `email` | `text` | Searchable, unique across the marketplace |
112
+ | `first_name` | `text` | Searchable, nullable |
113
+ | `last_name` | `text` | Searchable, nullable |
114
+ | `locale` | `text` | Nullable |
115
+ | `is_active` | `boolean` | Default `true` |
116
+ | `metadata` | `json` | Nullable |
117
+
118
+ Relations: `sellers`, many-to-many with `Seller` through `SellerMember`.
74
119
 
75
120
  ## SellerMember
76
121
 
77
- Table `seller_member`, id prefix `selmem`. Pivot between `Seller` and `Member`,
78
- unique on `(seller_id, member_id)`.
122
+ One member’s membership in one store. Table `seller_member`, id prefix `selmem`, unique on `(seller_id, member_id)`.
79
123
 
80
- | Field | Type | Notes |
124
+ | Field | Type | Description |
81
125
  | --- | --- | --- |
82
- | `role_id` | text | Nullable; resolved against the RBAC roles module |
83
- | `is_owner` | boolean | Default `false` |
84
- | `metadata` | json | Nullable |
126
+ | `id` | `text` | Primary key |
127
+ | `seller_id` | `text` | Belongs to `Seller` |
128
+ | `member_id` | `text` | Belongs to `Member` |
129
+ | `role_id` | `text` | Nullable, a `SellerRole` value |
130
+ | `is_owner` | `boolean` | Default `false` |
131
+ | `metadata` | `json` | Nullable |
132
+
133
+ ## SellerRole
134
+
135
+ The enum in `@mercurjs/types` whose values go in `role_id`.
136
+
137
+ | Key | Value |
138
+ | --- | --- |
139
+ | `SELLER_ADMINISTRATION` | `role_seller_administration` |
140
+ | `INVENTORY_MANAGEMENT` | `role_seller_inventory_management` |
141
+ | `ORDER_MANAGEMENT` | `role_seller_order_management` |
142
+ | `ACCOUNTING` | `role_seller_accounting` |
143
+ | `SUPPORT` | `role_seller_support` |
85
144
 
86
145
  ## MemberInvite
87
146
 
88
- Table `member_invite`, id prefix `meminv`. A pending team invitation, carrying
89
- the invited `email`, target `seller_id`, `role_id`, and an expiry.
147
+ A pending invitation to join a store. Table `member_invite`, id prefix `meminv`.
148
+
149
+ | Field | Type | Description |
150
+ | --- | --- | --- |
151
+ | `id` | `text` | Primary key |
152
+ | `email` | `text` | Searchable, the invited address |
153
+ | `token` | `text` | Signed JWT, indexed |
154
+ | `accepted` | `boolean` | Default `false` |
155
+ | `expires_at` | `dateTime` | Set by the service, 7 days out by default |
156
+ | `role_id` | `text` | The `SellerRole` the member gets on accept |
157
+ | `seller_id` | `text` | Belongs to `Seller` |
158
+ | `metadata` | `json` | Nullable |
159
+
160
+ A unique index on `(email, seller_id)` covers invites that aren’t accepted or deleted, so a store has one open invite per email.
161
+
162
+ ## OrderGroup
163
+
164
+ The Seller module also holds the `OrderGroup` model, which groups the per-store orders split from one cart. See the [order group data models](/platform/order-group/reference/data-models) for its fields.
@@ -1,22 +1,23 @@
1
1
  ---
2
- title: "Event reference"
2
+ title: "Seller module events"
3
3
  sidebarTitle: "Events"
4
- description: "Events emitted by the Store domain, for subscribers and side effects."
4
+ description: "Every event the store and team workflows emit, when each fires, and its payload."
5
5
  ---
6
6
 
7
- The Store domain emits events as stores and members change. Subscribe to them to
8
- run side effects such as sending notifications, syncing external systems, or
9
- kicking off follow-up workflows, instead of polling.
7
+ The Seller module workflows emit events after they write. Subscribe to them to send notifications, sync an outside system, or start follow-up work without polling. The event names are exported from `@mercurjs/core/workflows` as `SellerWorkflowEvents`, `SellerMemberWorkflowEvents`, and `MemberInviteWorkflowEvents`.
10
8
 
11
9
  ```ts title="src/subscribers/store-approved.ts"
12
10
  import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
11
+ import { MercurModules } from "@mercurjs/types"
13
12
 
14
- export default async function storeApprovedHandler({
13
+ export default async function storeApproved({
15
14
  event,
16
15
  container,
17
16
  }: SubscriberArgs<{ id: string }>) {
18
- const sellerId = event.data.id
19
- // ...send a welcome email, provision resources, etc.
17
+ const sellerService = container.resolve(MercurModules.SELLER)
18
+ const seller = await sellerService.retrieveSeller(event.data.id)
19
+
20
+ container.resolve("logger").info(`${seller.name} is open`)
20
21
  }
21
22
 
22
23
  export const config: SubscriberConfig = {
@@ -24,20 +25,44 @@ export const config: SubscriberConfig = {
24
25
  }
25
26
  ```
26
27
 
28
+ This subscriber loads the store when it’s approved. Store events carry only the id, so retrieve the record when you need more.
29
+
27
30
  ## Store events
28
31
 
32
+ `SellerWorkflowEvents` covers creation, updates, and every status transition.
33
+
29
34
  | Event | Emitted when | Payload |
30
35
  | --- | --- | --- |
31
- | `seller.created` | A store is created | `{ id }` |
32
- | `seller.updated` | A store's profile changes | `{ id }` |
33
- | `seller.approved` | A store is approved (`→ open`) | `{ id }` |
34
- | `seller.suspended` | A store is suspended | `{ id }` |
35
- | `seller.terminated` | A store is terminated | `{ id }` |
36
+ | `seller.created` | `createSellersWorkflow` or `createSellerAccountWorkflow` creates a store, once per store | `{ id }` |
37
+ | `seller.updated` | `updateSellersWorkflow` updates a store, once per store | `{ id }` |
38
+ | `seller.deleted` | `deleteSellersWorkflow` soft deletes a store, once per store | `{ id }` |
39
+ | `seller.approved` | `approveSellerWorkflow` opens a pending store | `{ id }` |
40
+ | `seller.suspended` | `suspendSellerWorkflow` suspends a store | `{ id }` |
41
+ | `seller.unsuspended` | `unsuspendSellerWorkflow` reopens a suspended store | `{ id }` |
42
+ | `seller.terminated` | `terminateSellerWorkflow` terminates a store | `{ id }` |
43
+ | `seller.unterminated` | `unterminateSellerWorkflow` returns a terminated store to `suspended` | `{ id }` |
36
44
 
37
- ## Member events
45
+ The address, professional details, payment details, and region workflows don’t emit events.
46
+
47
+ ## Membership events
48
+
49
+ `SellerMemberWorkflowEvents` covers memberships changed directly. Accepting an invite emits `member_invite.accepted` instead of `seller_member.created`.
38
50
 
39
51
  | Event | Emitted when | Payload |
40
52
  | --- | --- | --- |
41
- | `member_invite.created` | A team invite is sent | `{ id }` |
42
- | `member_invite.accepted` | An invite is accepted | `{ id }` |
43
- | `seller_member.created` | A member is added to a store | `{ id }` |
53
+ | `seller_member.created` | `addSellerMemberWorkflow` adds a member to a store | `{ seller_id, member_id }` |
54
+ | `seller_member.updated` | `updateMemberRoleWorkflow` changes a membership’s role | `{ seller_member_id }` |
55
+ | `seller_member.deleted` | `removeSellerMemberWorkflow` removes a membership | `{ seller_id, seller_member_id }` |
56
+
57
+ ## Invite events
58
+
59
+ `MemberInviteWorkflowEvents` covers team invites. The created payload includes the signed token, so a subscriber can build the invite link.
60
+
61
+ | Event | Emitted when | Payload |
62
+ | --- | --- | --- |
63
+ | `member_invite.created` | `createMemberInvitesWorkflow`, `resendMemberInviteWorkflow`, or `createSellersWorkflow` creates an invite, once per invite | `{ id, token, expires_at }` |
64
+ | `member_invite.accepted` | `acceptMemberInviteWorkflow` turns an invite into a membership | `{ seller_id, member_id }` |
65
+
66
+ <Warning>
67
+ The `member_invite.created` payload carries a working invite token. Don’t log it or forward it to systems that shouldn’t grant store access.
68
+ </Warning>
@@ -1,71 +1,89 @@
1
1
  ---
2
- title: "Links to other modules"
2
+ title: "Seller module links"
3
3
  sidebarTitle: "Links"
4
- description: "How the Store (Seller) domain links to other modules across the marketplace."
4
+ description: "Every module link that connects the Seller module to other modules, with cardinality, source file, and query.graph aliases."
5
5
  ---
6
6
 
7
- Modules in Mercur never reference each other directly. They connect through
8
- **module links**. The Seller module is the most linked domain in the marketplace,
9
- and almost every other module attaches to a store. Once a link is defined, you
10
- retrieve related records with `query.graph` using the link alias.
7
+ Mercur modules never reference each other directly: they connect through module links defined in `packages/core/src/links`. The `seller` entity is the most linked record in the marketplace. Once a link exists, `query.graph` resolves the other side through the link’s alias.
11
8
 
12
9
  ```ts
13
- const { data: stores } = await query.graph({
10
+ import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
11
+
12
+ const query = container.resolve(ContainerRegistrationKeys.QUERY)
13
+
14
+ const { data: [seller] } = await query.graph({
14
15
  entity: "seller",
15
- fields: ["id", "name", "offers.*", "payout_account.*"],
16
+ fields: ["id", "name", "regions.*", "payout_account.*"],
17
+ filters: { id: "sel_01JD8Q1234567" },
16
18
  })
17
19
  ```
18
20
 
19
- ## Commerce
21
+ The tables below list the alias on each side. Read the “From seller” column as a field on `seller`, and the “From the other side” column as a field on the linked entity.
22
+
23
+ ## Catalog and offers
24
+
25
+ These links decide what a store sells and where it’s listed.
26
+
27
+ | Link | Cardinality | From seller | From the other side | File |
28
+ | --- | --- | --- | --- | --- |
29
+ | Product | many-to-many, table `product_seller` | `products` | `product.sellers` | `product-seller-link.ts` |
30
+ | Product category | many-to-many | `product_categories` | `product_category.sellers` | `category-seller-link.ts` |
31
+ | Offer | many offers to one seller, read-only | none | `offer.seller` | `offer-seller-link.ts` |
32
+
33
+ The offer link is read-only and built on the `offer.seller_id` column, so you can’t create or dismiss it through the Link API. Query it from the offer side.
34
+
35
+ ## Orders and payouts
36
+
37
+ These links attach a store’s sales and settlements.
38
+
39
+ | Link | Cardinality | From seller | From the other side | File |
40
+ | --- | --- | --- | --- | --- |
41
+ | Order | many orders to one seller | `orders` | `order.seller` | `order-seller-link.ts` |
42
+ | Payout | many payouts to one seller | `payouts` | `payout.seller` | `payout-seller-link.ts` |
43
+ | Payout account | one-to-one | `payout_account` | `payout_account.seller` | `seller-payout-account-link.ts` |
44
+
45
+ ## Regions and customers
46
+
47
+ These links set where a store trades and who it serves.
48
+
49
+ | Link | Cardinality | From seller | From the other side | File |
50
+ | --- | --- | --- | --- | --- |
51
+ | Region | many-to-many, table `region_seller` | `regions` | `region.sellers` | `region-seller-link.ts` |
52
+ | Customer | many-to-many | `customers` | `customer.sellers` | `seller-customer-link.ts` |
53
+ | Customer group | many groups to one seller | `customer_groups` | `customer_group.seller` | `seller-customer-group-link.ts` |
20
54
 
21
- | Linked module | Relationship |
22
- | --- | --- |
23
- | **Offer** | A store has many offers (`offer.seller_id`, read-only). Offers are how a store sells against a master product. |
24
- | **Product** | Many-to-many allowlist (`product_seller`) that controls which stores may sell a given master product. |
25
- | **Product category** | Many-to-many link to the categories a store is associated with. |
26
- | **Order** | Each order belongs to one store; a store has many orders. |
55
+ `createSellersWorkflow` and `createSellerAccountWorkflow` create the region links. `linkSellerRegionsWorkflow` changes them later.
27
56
 
28
- ## Payouts
57
+ ## Fulfillment and inventory
29
58
 
30
- | Linked module | Relationship |
31
- | --- | --- |
32
- | **Payout** | A store has many payouts. |
33
- | **Payout account** | A store has one payout account (its provider onboarding record). |
59
+ These links scope fulfillment setup and stock to a store.
34
60
 
35
- ## Customers
61
+ | Link | Cardinality | From seller | From the other side | File |
62
+ | --- | --- | --- | --- | --- |
63
+ | Fulfillment set | many sets to one seller | `fulfillment_sets` | `fulfillment_set.seller` | `fulfillment-set-seller-link.ts` |
64
+ | Service zone | many zones to one seller | `service_zones` | `service_zone.seller` | `service-zone-seller-link.ts` |
65
+ | Shipping option | many options to one seller | `shipping_options` | `shipping_option.seller` | `shipping-option-seller-link.ts` |
66
+ | Stock location | many locations to one seller | `stock_locations` | `stock_location.seller` | `stock-location-seller-link.ts` |
67
+ | Inventory item | many items to one seller | `inventory_items` | `inventory_item.seller` | `inventory-item-seller-link.ts` |
36
68
 
37
- | Linked module | Relationship |
38
- | --- | --- |
39
- | **Customer** | Many-to-many link to the customers associated with a store. |
40
- | **Customer group** | A customer group is owned by exactly one store; a store owns many groups. |
69
+ ## Pricing and promotions
41
70
 
42
- ## Fulfillment & inventory
71
+ These links scope a store’s own pricing and marketing.
43
72
 
44
- | Linked module | Relationship |
45
- | --- | --- |
46
- | **Shipping profile** | A store has many shipping profiles. |
47
- | **Shipping option** | A store has many shipping options. |
48
- | **Service zone** | A store has many service zones. |
49
- | **Fulfillment set** | A store has many fulfillment sets. |
50
- | **Stock location** | A store has many stock locations. |
51
- | **Inventory item** | A store has many inventory items. |
73
+ | Link | Cardinality | From seller | From the other side | File |
74
+ | --- | --- | --- | --- | --- |
75
+ | Price list | many lists to one seller | `price_lists` | `price_list.seller` | `price-list-seller-link.ts` |
76
+ | Promotion | many promotions to one seller | `promotions` | `promotion.seller` | `promotion-seller-link.ts` |
77
+ | Campaign | many campaigns to one seller | `campaigns` | `campaign.seller` | `campaign-seller-link.ts` |
52
78
 
53
- ## Pricing & promotions
79
+ ## Reviews
54
80
 
55
- | Linked module | Relationship |
56
- | --- | --- |
57
- | **Price list** | A store has many price lists. |
58
- | **Promotion** | A store has many promotions. |
59
- | **Campaign** | A store has many campaigns. |
81
+ This link attaches customer reviews of a store.
60
82
 
61
- ## Access & reviews
83
+ | Link | Cardinality | From seller | From the other side | File |
84
+ | --- | --- | --- | --- | --- |
85
+ | Review | many reviews to one seller | `reviews` | `review.seller` | `seller-review.ts` |
62
86
 
63
- | Linked module | Relationship |
64
- | --- | --- |
65
- | **RBAC role** | A member's role on a store (`seller_member.role_id`, read-only) resolves against the roles module. |
66
- | **Review** | A store has many reviews. |
87
+ ## Order groups
67
88
 
68
- <Note>
69
- Read-only links (Offer, RBAC role) are resolved from the field on the owning
70
- record and can't be written through the link itself.
71
- </Note>
89
+ The order group links start from `OrderGroup`, which lives in the Seller module, not from `Seller`. See the [order group links](/platform/order-group/reference/links) for `order-group-order-link.ts` and `order-group-cart-link.ts`.
@@ -1,51 +1,123 @@
1
1
  ---
2
- title: "Service reference"
2
+ title: "Seller module service"
3
3
  sidebarTitle: "Service"
4
- description: "The Seller module service and its methods for working with records directly."
4
+ description: "Resolve the Seller module service, and the generated and custom methods it exposes for direct reads and writes."
5
5
  ---
6
6
 
7
- The Seller module exposes a service you can resolve from the Medusa container to
8
- read and write records directly, without going through a workflow. Use it inside
9
- custom services, subscribers, or scheduled jobs.
7
+ The Seller module service reads and writes the module’s records directly, without a workflow. Use it for reads in subscribers, scheduled jobs, and custom steps. Its writes don’t emit events, run hooks, or roll back, so prefer the [workflows](/platform/store/reference/workflows) for changes.
8
+
9
+ ## Resolve the service
10
+
11
+ Resolve the service from the Medusa container with the `MercurModules.SELLER` key from `@mercurjs/types`.
10
12
 
11
13
  ```ts
12
- import { MercurModules } from "@mercurjs/types"
14
+ import { MercurModules, SellerStatus } from "@mercurjs/types"
13
15
 
14
- const sellerModuleService = container.resolve(MercurModules.SELLER)
16
+ const sellerService = container.resolve(MercurModules.SELLER)
15
17
 
16
- const [sellers, count] = await sellerModuleService.listAndCountSellers({
17
- status: "open",
18
- })
18
+ const [sellers, count] = await sellerService.listAndCountSellers(
19
+ { status: SellerStatus.OPEN, is_premium: true },
20
+ { take: 20, order: { created_at: "DESC" } }
21
+ )
19
22
  ```
20
23
 
24
+ This lists the 20 newest open premium stores and the total count of matches.
25
+
21
26
  ## Generated methods
22
27
 
23
- Each data model gets a standard set of auto-generated methods. For `Seller`:
28
+ The service extends Medusa’s `MedusaService`, which generates the same eight methods for every model. For `Seller` they are:
24
29
 
25
30
  | Method | Description |
26
31
  | --- | --- |
27
- | `createSellers(data)` | Create one or more stores |
28
- | `retrieveSeller(id, config?)` | Retrieve a store by id |
29
- | `listSellers(filters?, config?)` | List stores matching filters |
30
- | `listAndCountSellers(filters?, config?)` | List stores with a total count |
31
- | `updateSellers(data)` | Update one or more stores |
32
- | `deleteSellers(ids)` | Delete one or more stores |
32
+ | `retrieveSeller(id, config?)` | Retrieve one store by id |
33
+ | `listSellers(filters?, config?)` | List stores that match filters |
34
+ | `listAndCountSellers(filters?, config?)` | List stores and return the total count |
35
+ | `createSellers(data)` | Create one store or an array of stores |
36
+ | `updateSellers(data)` | Update one store or an array of stores by id |
37
+ | `deleteSellers(ids)` | Hard delete stores |
38
+ | `softDeleteSellers(ids)` | Soft delete stores |
39
+ | `restoreSellers(ids)` | Restore soft deleted stores |
33
40
 
34
- The same set exists for every model in the module, such as `Member`, `SellerMember`,
35
- `MemberInvite`, `ProfessionalDetails`, `SellerAddress`, and `PaymentDetails`
36
- (e.g. `createMembers`, `listMemberInvites`, `updatePaymentDetails`).
41
+ Each model gets the same set under its own name:
37
42
 
38
- ## Team methods
39
-
40
- | Method | Description |
43
+ | Model | Method names |
41
44
  | --- | --- |
42
- | `addSellerMember(data)` | Attach a member to a store |
43
- | `removeSellerMember(sellerId, memberId)` | Detach a member from a store |
44
- | `createMemberInvites(data)` | Create pending team invitations |
45
- | `updateMember(data)` | Update a member record |
46
-
47
- <Warning>
48
- Prefer [workflows](/platform/store/reference/workflows) for anything with side
49
- effects (status changes, invites, payouts). The service writes records
50
- directly and does **not** emit events or run compensation.
51
- </Warning>
45
+ | `Member` | `retrieveMember`, `listMembers`, `createMembers`, `updateMembers`, … |
46
+ | `SellerMember` | `retrieveSellerMember`, `listSellerMembers`, `createSellerMembers`, … |
47
+ | `MemberInvite` | `retrieveMemberInvite`, `listMemberInvites`, `deleteMemberInvites`, … |
48
+ | `SellerAddress` | `listSellerAddresses`, `createSellerAddresses`, `updateSellerAddresses`, … |
49
+ | `ProfessionalDetails` | `listProfessionalDetails`, `createProfessionalDetails`, … |
50
+ | `PaymentDetails` | `listPaymentDetails`, `createPaymentDetails`, `updatePaymentDetails`, … |
51
+ | `OrderGroup` | `retrieveOrderGroup`, `listOrderGroups`, `listAndCountOrderGroups`, … |
52
+
53
+ ## Custom methods
54
+
55
+ The service overrides some generated methods and adds a few of its own.
56
+
57
+ ### createSellers and updateSellers
58
+
59
+ ```ts
60
+ createSellers(
61
+ data: CreateSellerDTO | CreateSellerDTO[]
62
+ ): Promise<SellerDTO | SellerDTO[]>
63
+
64
+ updateSellers(
65
+ data: UpdateSellerDTO | UpdateSellerDTO[]
66
+ ): Promise<SellerDTO | SellerDTO[]>
67
+ ```
68
+
69
+ Both validate `handle` and throw `INVALID_DATA` when it isn’t URL safe. When `handle` is missing and `name` is present, both set the handle from the name.
70
+
71
+ ### upsertMembers
72
+
73
+ ```ts
74
+ upsertMembers(
75
+ data: {
76
+ email: string
77
+ first_name?: string | null
78
+ last_name?: string | null
79
+ }[]
80
+ ): Promise<MemberDTO[]>
81
+ ```
82
+
83
+ Matches members by `email` and creates the missing ones. For existing members, it fills `first_name` and `last_name` only when they’re empty. It returns the members in input order.
84
+
85
+ ### createMemberInvites
86
+
87
+ ```ts
88
+ createMemberInvites(
89
+ data: CreateMemberInviteDTO | CreateMemberInviteDTO[]
90
+ ): Promise<MemberInviteDTO | MemberInviteDTO[]>
91
+ ```
92
+
93
+ Throws `INVALID_DATA` if an email already belongs to the target store. For each invite, it signs a JWT with the module’s `jwt_secret`, stores it in `token`, and sets `expires_at` from `invite_valid_duration`.
94
+
95
+ ### validateMemberInviteToken
96
+
97
+ ```ts
98
+ validateMemberInviteToken(token: string): Promise<MemberInviteDTO>
99
+ ```
100
+
101
+ Verifies the token’s signature and returns its invite. Throws `INVALID_DATA` for a bad signature, and `NOT_ALLOWED` when the invite is accepted or expired.
102
+
103
+ ### getStatistics
104
+
105
+ ```ts
106
+ getStatistics(): Promise<SellerStatisticsOutput>
107
+ ```
108
+
109
+ Counts stores by status and returns `{ total, premium, by_status }`, where `by_status` has a key for every `SellerStatus` value.
110
+
111
+ ### Order group reads
112
+
113
+ `listOrderGroups`, `listAndCountOrderGroups`, and `retrieveOrderGroup` go through a custom repository that computes `seller_count` and `total`. See the [order group service](/platform/order-group/reference/service).
114
+
115
+ ## Module options
116
+
117
+ The service reads these options from its module registration, typed by `SellerModuleOptions`:
118
+
119
+ | Option | Default | Description |
120
+ | --- | --- | --- |
121
+ | `invite_valid_duration` | `604800` | Invite lifetime in seconds, 7 days |
122
+ | `jwt_secret` | `projectConfig.http.jwtSecret` | Secret used to sign and verify invite tokens |
123
+ | `vendor_url` | `MERCUR_VENDOR_URL`, or `""` | Base URL of the Vendor panel |