@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,58 +1,86 @@
1
1
  ---
2
2
  title: "Batch-update commission rules"
3
3
  sidebarTitle: "Batch-update rules"
4
- description: "Create, update, and delete a rate's rules in a single call."
4
+ description: "Add, change, and remove a commission rate's rules in one workflow run with batchCommissionRulesWorkflow."
5
5
  ---
6
6
 
7
- In this guide, you'll learn how to manage the rules that scope a commission rate
8
- from your own server code, adding, changing, and removing them in one atomic
9
- operation.
7
+ Change the rules that scope a commission rate in one run, for example to move a seller onto a negotiated rate or to retarget a rate at a new category.
10
8
 
11
- ## Run the workflow
9
+ ## Before you begin
12
10
 
13
- `batchCommissionRulesWorkflow` applies creates, updates, and deletes to a single
14
- rate's rules in parallel. Pass the target `commission_rate_id` and any of the
15
- `create`, `update`, and `delete` arrays.
11
+ You need the following:
16
12
 
17
- ```ts title="src/api/custom/rules/route.ts"
18
- import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
19
- import { batchCommissionRulesWorkflow } from "@mercurjs/core/workflows"
13
+ - The id of the rate to change, such as `comrate_01JD8Q1234567`
14
+ - The ids of the rules to update or delete, from the rate’s `rules` relation
20
15
 
21
- export async function POST(req: MedusaRequest, res: MedusaResponse) {
22
- const { result } = await batchCommissionRulesWorkflow(req.scope).run({
23
- input: {
24
- commission_rate_id: "comrate_123",
25
- create: [
26
- { reference: "seller", reference_id: "sel_123" },
27
- { reference: "product_category", reference_id: "pcat_shoes" },
28
- ],
29
- update: [{ id: "comrule_456", reference_id: "pcat_boots" }],
30
- delete: ["comrule_789"],
31
- },
32
- })
16
+ <Steps>
17
+ <Step title="Look up the rate's rules">
18
+ List the rate’s current rules through the module service.
33
19
 
34
- res.json(result)
35
- }
36
- ```
20
+ ```ts
21
+ import { MercurModules } from "@mercurjs/types"
37
22
 
38
- The result groups the affected rules as `{ created, updated, deleted }`.
23
+ const commission = container.resolve(MercurModules.COMMISSION)
24
+
25
+ const rules = await commission.listCommissionRules({
26
+ commission_rate_id: "comrate_01JD8Q1234567",
27
+ })
28
+ ```
29
+
30
+ Each rule has an `id`, a `reference`, and a `reference_id`. You need the `id` to update or delete a rule.
31
+
32
+ </Step>
33
+ <Step title="Run the batch">
34
+ Call `batchCommissionRulesWorkflow` from an API route. This route adds a seller rule, retargets a category rule, and removes a product rule.
35
+
36
+ ```ts title="src/api/admin/commission-scopes/route.ts"
37
+ import type {
38
+ MedusaRequest,
39
+ MedusaResponse,
40
+ } from "@medusajs/framework/http"
41
+ import { batchCommissionRulesWorkflow } from "@mercurjs/core/workflows"
42
+
43
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
44
+ const { result } = await batchCommissionRulesWorkflow(req.scope).run({
45
+ input: {
46
+ commission_rate_id: "comrate_01JD8Q1234567",
47
+ create: [{ reference: "seller", reference_id: "sel_01JD8Q1234567" }],
48
+ update: [
49
+ { id: "comrule_01JD8Q1234567", reference_id: "pcat_01JD8Q1234568" },
50
+ ],
51
+ delete: ["comrule_01JD8Q1234569"],
52
+ },
53
+ })
54
+
55
+ res.json(result)
56
+ }
57
+ ```
58
+
59
+ The result is `{ created, updated, deleted }`: the created and updated rules, and the deleted ids.
60
+
61
+ </Step>
62
+ </Steps>
63
+
64
+ ## How the three operations run
65
+
66
+ The workflow runs `createCommissionRulesStep`, `updateCommissionRulesStep`, and `deleteCommissionRulesStep` in parallel. Each array is optional, and an empty or missing one is a no-op. If any step fails, the others roll back: created rules are deleted, updated rules get their old values, and deleted rules are created again.
39
67
 
40
68
  <Note>
41
- Every rule's `reference` must be one of the five dimensions: `product`,
42
- `product_type`, `product_collection`, `product_category`, or `seller`. The
43
- `reference_id` is the id of the specific record in that dimension.
69
+ A rolled-back delete creates new rule records with the same `reference` and `reference_id`. The rules keep their meaning, but their ids change.
44
70
  </Note>
45
71
 
46
- ## How scoping changes matching
72
+ ## How the new rules change matching
73
+
74
+ Adding rules narrows a rate. Rules on the same dimension are alternatives, and rules on different dimensions must all match. Adding the `seller` rule above to a rate that already had a `product_category` rule raises its specificity from 1 to 2, so it now beats single-dimension rates on that seller’s lines in that category.
75
+
76
+ Use only the five supported references: `product`, `product_type`, `product_collection`, `product_category`, and `seller`. The module stores any string, and a rule with an unknown reference makes the rate match nothing.
77
+
78
+ ## Recompute existing orders
79
+
80
+ Rule changes affect orders placed or refreshed after the change. To apply new rules to existing orders, run `refreshOrderCommissionLinesWorkflow` for them.
47
81
 
48
- Adding rules **narrows** a rate. Rules on the same dimension OR together. Rules
49
- across dimensions AND together. The two `create` rules above make the rate match
50
- only lines that are both from seller `sel_123` **and** in category `pcat_shoes`,
51
- raising the rate's specificity to `2`.
82
+ ## Next steps
52
83
 
53
- <Tip>
54
- Increasing a rate's specificity makes it win over less-specific rates on the
55
- lines it matches. See
56
- [Rule matching](/platform/commission/concepts/rule-matching) for how
57
- most-specific-wins and tie-breaks resolve.
58
- </Tip>
84
+ - [Refresh order commission lines after a rule change](/platform/commission/guides/refresh-order-commission-lines)
85
+ - [See how specificity and tie-breaks pick a rate](/platform/commission/concepts/rule-matching)
86
+ - [Input and output of batchCommissionRulesWorkflow](/platform/commission/reference/workflows)
@@ -1,72 +1,120 @@
1
1
  ---
2
2
  title: "Create a commission rate"
3
3
  sidebarTitle: "Create a rate"
4
- description: "Create a commission rate programmatically with createCommissionRatesWorkflow."
4
+ description: "Create percentage and fixed commission rates from a seed script or API route with createCommissionRatesWorkflow."
5
5
  ---
6
6
 
7
- In this guide, you'll learn how to create a commission rate from your own server
8
- code. This is useful in a seed script, a custom API route, or an onboarding flow.
7
+ Create commission rates from your own server code, for example to seed a new marketplace or to set a seller’s rate during onboarding.
9
8
 
10
- Mercur exposes a `createCommissionRatesWorkflow` that creates one or more
11
- `CommissionRate` records. Run it from any place that has access to the Medusa
12
- container.
9
+ ## Before you begin
13
10
 
14
- ## Run the workflow
11
+ You need the following:
15
12
 
16
- ```ts title="src/api/custom/route.ts"
17
- import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
18
- import { createCommissionRatesWorkflow } from "@mercurjs/core/workflows"
19
- import { CommissionRateType } from "@mercurjs/types"
13
+ - A Mercur project with `@mercurjs/core` registered through `withMercur()`
14
+ - The id of any seller, product, or category you want to scope a rate to
20
15
 
21
- export async function POST(req: MedusaRequest, res: MedusaResponse) {
22
- const { result } = await createCommissionRatesWorkflow(req.scope).run({
23
- input: [
24
- {
25
- name: "Standard",
26
- type: CommissionRateType.PERCENTAGE,
27
- value: 10,
16
+ <Steps>
17
+ <Step title="Create a percentage rate">
18
+ Run `createCommissionRatesWorkflow` with an array of rates. This seed script creates a 12% rate for apparel.
19
+
20
+ ```ts title="src/scripts/seed-commission.ts"
21
+ import type { ExecArgs } from "@medusajs/framework/types"
22
+ import { CommissionRateType } from "@mercurjs/types"
23
+ import { createCommissionRatesWorkflow } from "@mercurjs/core/workflows"
24
+
25
+ export default async function seedCommission({ container }: ExecArgs) {
26
+ const { result } = await createCommissionRatesWorkflow(container).run({
27
+ input: [
28
+ {
29
+ name: "Apparel",
30
+ code: "apparel",
31
+ type: CommissionRateType.PERCENTAGE,
32
+ value: 12,
33
+ },
34
+ ],
35
+ })
36
+
37
+ console.log(result.map((rate) => rate.id))
38
+ }
39
+ ```
40
+
41
+ The workflow returns the created rates in input order. If you leave out `code`, the module generates one from `name` with a random suffix, so set it when other code needs to find the rate by code.
42
+
43
+ </Step>
44
+ <Step title="Run the script">
45
+ Run the script with the Medusa CLI from your API app.
46
+
47
+ ```bash
48
+ npx medusa exec ./src/scripts/seed-commission.ts
49
+ ```
50
+
51
+ A rate without rules matches every line, so it competes with the global rate until you scope it.
52
+
53
+ </Step>
54
+ <Step title="Scope the rate">
55
+ Attach rules with `batchCommissionRulesWorkflow`, passing the id of the rate you created.
56
+
57
+ ```ts title="src/scripts/seed-commission.ts"
58
+ import { batchCommissionRulesWorkflow } from "@mercurjs/core/workflows"
59
+
60
+ await batchCommissionRulesWorkflow(container).run({
61
+ input: {
62
+ commission_rate_id: result[0].id,
63
+ create: [
64
+ { reference: "product_type", reference_id: "ptyp_01JD8Q1234567" },
65
+ ],
28
66
  },
29
- ],
30
- })
67
+ })
68
+ ```
69
+
70
+ The rate now matches only lines whose product has that type. See [Batch-update commission rules](/platform/commission/guides/batch-update-rules) for updates and deletes.
71
+
72
+ </Step>
73
+ </Steps>
31
74
 
32
- res.status(201).json({ commission_rate: result[0] })
75
+ ## Create a fixed rate with per-currency amounts
76
+
77
+ A fixed rate takes an amount per currency in `values`, and `value` is the fallback. `CreateCommissionRateDTO` doesn’t declare `values` or `rules`, but the module creates both as nested records.
78
+
79
+ ```ts title="src/scripts/seed-commission.ts"
80
+ const flatFee = {
81
+ name: "Flat fee",
82
+ type: CommissionRateType.FIXED,
83
+ value: 3,
84
+ values: [
85
+ { currency_code: "usd", amount: 2.5 },
86
+ { currency_code: "eur", amount: 2 },
87
+ ],
88
+ rules: [{ reference: "seller", reference_id: "sel_01JD8Q1234567" }],
33
89
  }
90
+
91
+ await createCommissionRatesWorkflow(container).run({ input: [flatFee] })
34
92
  ```
35
93
 
36
- <Note>
37
- The workflow takes an **array** of rates and returns the created records. When
38
- you omit `code`, the module generates a unique one from `name`.
39
- </Note>
40
-
41
- ## Create a fixed, per-currency rate
42
-
43
- For a flat fee, use `CommissionRateType.FIXED` and pass per-currency `values`.
44
- The scalar `value` is the fallback when no currency matches.
45
-
46
- ```ts
47
- await createCommissionRatesWorkflow(req.scope).run({
48
- input: [
49
- {
50
- name: "Flat fee",
51
- type: CommissionRateType.FIXED,
52
- value: 5,
53
- values: [
54
- { currency_code: "usd", amount: 5 },
55
- { currency_code: "eur", amount: 4 },
56
- ],
57
- },
58
- ],
94
+ Declaring the rate as a variable keeps TypeScript from rejecting the extra `values` and `rules` keys. The result is a flat fee per line item for one seller: 2.5 in USD, 2 in EUR, and 3 in any other currency.
95
+
96
+ ## Change the global commission
97
+
98
+ The global rate is the one with `is_default: true`. Look it up, then update it with `updateCommissionRatesWorkflow`.
99
+
100
+ ```ts title="src/scripts/seed-commission.ts"
101
+ import { MercurModules } from "@mercurjs/types"
102
+ import { updateCommissionRatesWorkflow } from "@mercurjs/core/workflows"
103
+
104
+ const commission = container.resolve(MercurModules.COMMISSION)
105
+ const [globalRate] = await commission.listCommissionRates({
106
+ is_default: true,
107
+ })
108
+
109
+ await updateCommissionRatesWorkflow(container).run({
110
+ input: [{ id: globalRate.id, value: 10, include_shipping: true }],
59
111
  })
60
112
  ```
61
113
 
62
- ## Scope the rate
114
+ This raises the baseline to 10% and turns on shipping commission. Only the global rate’s `include_shipping` produces shipping lines.
63
115
 
64
- A rate created without rules is a catch-all. To scope it to part of the catalog,
65
- attach rules with
66
- [`batchCommissionRulesWorkflow`](/platform/commission/guides/batch-update-rules).
116
+ ## Next steps
67
117
 
68
- <Tip>
69
- Only the global rate (`is_default`) may commission shipping. To let the global
70
- rate take a cut of shipping, update it with `include_shipping: true` via
71
- `updateCommissionRatesWorkflow`.
72
- </Tip>
118
+ - [Scope rates with batchCommissionRulesWorkflow](/platform/commission/guides/batch-update-rules)
119
+ - [Recompute existing orders after changing rates](/platform/commission/guides/refresh-order-commission-lines)
120
+ - [See how the winning rate is picked](/platform/commission/concepts/rule-matching)
@@ -1,55 +1,124 @@
1
1
  ---
2
2
  title: "Refresh order commission lines"
3
3
  sidebarTitle: "Refresh order lines"
4
- description: "Recompute an order's commission lines after it changes."
4
+ description: "Recompute commission lines for existing orders, and pass extra data to the commission provider with workflow hooks."
5
5
  ---
6
6
 
7
- In this guide, you'll learn how to recompute the commission lines for an order
8
- from your own server code. Mercur already refreshes lines automatically at
9
- checkout and on order changes. Reach for this workflow when you change an order
10
- outside those paths, or when backfilling.
7
+ Recompute the commission lines of existing orders, for example after you change rates or when you change an order outside Mercur’s own workflows. Mercur already refreshes lines at checkout and on order edits, returns, claims, and exchanges.
11
8
 
12
- ## Run the workflow
9
+ <Steps>
10
+ <Step title="Run the workflow">
11
+ Pass the ids of the orders to `refreshOrderCommissionLinesWorkflow`. This route refreshes one order.
13
12
 
14
- `refreshOrderCommissionLinesWorkflow` reads each order, resolves the matching
15
- rate for every item and shipping method, and writes the resulting
16
- `CommissionLine` records.
13
+ ```ts title="src/api/admin/orders/[id]/recompute-commission/route.ts"
14
+ import type {
15
+ MedusaRequest,
16
+ MedusaResponse,
17
+ } from "@medusajs/framework/http"
18
+ import { refreshOrderCommissionLinesWorkflow } from "@mercurjs/core/workflows"
17
19
 
18
- ```ts title="src/api/custom/refresh/route.ts"
19
- import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
20
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
21
+ const { result } = await refreshOrderCommissionLinesWorkflow(
22
+ req.scope
23
+ ).run({
24
+ input: { order_ids: [req.params.id] },
25
+ })
26
+
27
+ res.json({ commission_lines: result })
28
+ }
29
+ ```
30
+
31
+ The workflow returns the lines it wrote for all the orders. It throws if any id doesn’t belong to an order.
32
+
33
+ </Step>
34
+ <Step title="Check the result">
35
+ Read the lines back through `query.graph`, filtering by the order’s item ids.
36
+
37
+ ```ts
38
+ const { data: lines } = await query.graph({
39
+ entity: "commission_line",
40
+ fields: ["item_id", "shipping_method_id", "code", "rate", "amount"],
41
+ filters: { item_id: ["ordli_01JD8Q1234567"] },
42
+ })
43
+ ```
44
+
45
+ Item lines carry `item_id`. Shipping lines carry `shipping_method_id` and the description `Shipping Commission`.
46
+
47
+ </Step>
48
+ </Steps>
49
+
50
+ ## Backfill existing orders
51
+
52
+ The workflow takes any number of order ids and resolves them in one batch, so the rates load once per run. For a backfill, page through orders and refresh each page.
53
+
54
+ ```ts title="src/scripts/backfill-commission.ts"
55
+ import type { ExecArgs } from "@medusajs/framework/types"
56
+ import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
20
57
  import { refreshOrderCommissionLinesWorkflow } from "@mercurjs/core/workflows"
21
58
 
22
- export async function POST(req: MedusaRequest, res: MedusaResponse) {
23
- const { result } = await refreshOrderCommissionLinesWorkflow(req.scope).run({
24
- input: { order_ids: [req.params.id] },
25
- })
59
+ export default async function backfill({ container }: ExecArgs) {
60
+ const query = container.resolve(ContainerRegistrationKeys.QUERY)
61
+ const take = 100
62
+
63
+ for (let skip = 0; ; skip += take) {
64
+ const { data } = await query.graph({
65
+ entity: "order",
66
+ fields: ["id"],
67
+ pagination: { skip, take },
68
+ })
69
+ if (!data.length) break
26
70
 
27
- res.json({ commission_lines: result })
71
+ await refreshOrderCommissionLinesWorkflow(container).run({
72
+ input: { order_ids: data.map((order) => order.id) },
73
+ })
74
+ }
28
75
  }
29
76
  ```
30
77
 
31
- <Note>
32
- The workflow takes an array of `order_ids`, so you can refresh many orders in
33
- one run. This is useful for backfilling after you change your commission
34
- configuration.
35
- </Note>
78
+ Each page is one workflow run. A refresh replaces lines by item and shipping method, so you can re-run the script safely.
36
79
 
37
- ## Idempotency
80
+ ## Pass extra data with setCommissionContext
38
81
 
39
- The refresh is a **delete-then-insert** for each affected item and shipping
40
- method, so re-running it never duplicates lines. You can call it as often as you
41
- need without cleaning up first.
82
+ The `setCommissionContext` hook receives the calculation contexts before they reach the provider. Return a `StepResponse` with new contexts to fill `additional_context` for a custom provider, or return nothing to keep them.
42
83
 
43
- ## When it runs automatically
84
+ ```ts title="src/workflows/hooks/commission-context.ts"
85
+ import { StepResponse } from "@medusajs/framework/workflows-sdk"
86
+ import { refreshOrderCommissionLinesWorkflow } from "@mercurjs/core/workflows"
87
+
88
+ refreshOrderCommissionLinesWorkflow.hooks.setCommissionContext(
89
+ ({ contexts }) =>
90
+ new StepResponse(
91
+ contexts.map((context) => ({
92
+ ...context,
93
+ additional_context: { tier: "gold" },
94
+ }))
95
+ )
96
+ )
97
+ ```
98
+
99
+ Each context already has `order_id`, `seller_id`, `currency_code`, `items`, and `shipping_methods`. Items carry the product’s `tags` and `attribute_value_ids`, which the `system` provider ignores but your own provider can use.
100
+
101
+ ## React with commissionLinesUpserted
102
+
103
+ The `commissionLinesUpserted` hook runs after the lines are written, as part of the same workflow run. If your handler throws, the run fails, and at checkout that fails the cart completion too.
104
+
105
+ ```ts title="src/workflows/hooks/commission-written.ts"
106
+ import { refreshOrderCommissionLinesWorkflow } from "@mercurjs/core/workflows"
107
+
108
+ refreshOrderCommissionLinesWorkflow.hooks.commissionLinesUpserted(
109
+ async ({ order_ids, commission_lines }, { container }) => {
110
+ const logger = container.resolve("logger")
111
+ logger.info(
112
+ `${commission_lines.length} lines for ${order_ids.join(", ")}`
113
+ )
114
+ }
115
+ )
116
+ ```
44
117
 
45
- You rarely need to call this by hand. Mercur runs it for you:
118
+ Use this hook to sync commission to an external ledger. Use the [order events](/platform/commission/reference/events) instead when your side effect shouldn’t be able to block the refresh.
46
119
 
47
- - **At checkout:** as each per-seller order is created from the split cart.
48
- - **On order changes:** a subscriber re-runs it when an order edit is
49
- confirmed, or a return, claim, or exchange is created.
120
+ ## Next steps
50
121
 
51
- <Tip>
52
- To hook your own logic into these moments, subscribe to the same order events
53
- rather than re-running this workflow. See the
54
- [Events reference](/platform/commission/reference/events).
55
- </Tip>
122
+ - [What a commission line records](/platform/commission/concepts/order-commission-lines)
123
+ - [Write a custom commission provider](/platform/commission/reference/service)
124
+ - [Hooks of every commission workflow](/platform/commission/reference/workflows)
@@ -1,86 +1,94 @@
1
1
  ---
2
- title: "Commission"
2
+ title: "Commissions"
3
3
  sidebarTitle: "Overview"
4
- description: "Configure how the marketplace takes its cut of every seller order."
4
+ description: "Set the share of each sale the marketplace keeps, scope it to sellers and parts of the catalog, and record it per order line."
5
5
  ---
6
6
 
7
- Use Mercur to keep financial control over what share of each sale the
8
- marketplace keeps and each seller earns.
7
+ Use Mercur to decide what share of each sale the marketplace keeps and what each seller earns.
9
8
 
10
- Financial control over the marketplace runs through commission. You set
11
- policy-based **rates** (fixed or percentage) and scope them to parts of your
12
- catalog with **rules**. Mercur resolves the right rate for every order line by
13
- most-specific-wins and writes an auditable **commission line**. That line is the
14
- exact amount deducted before the seller is paid out, computed in arbitrary
15
- precision so the numbers reconcile.
9
+ Commission is the marketplace’s cut of a seller order. You define rates as a percentage or a fixed amount and scope them with rules to sellers, products, types, collections, or categories. When an order is placed, Mercur picks the most specific matching rate for every line item and writes a commission line with the amount. The payout for that order is the order total minus the sum of its commission lines.
10
+
11
+ <img className="block dark:hidden" src="/images/figures/commission-overview-light.svg" alt="Commission rates behind the commission lines of order #100: the Linen shirt line matches the 12% acme-apparel rate for € 5.64, while the Desk lamp line and the shipping method fall back to the 10% default rate." />
12
+ <img className="hidden dark:block" src="/images/figures/commission-overview-dark.svg" alt="Commission rates behind the commission lines of order #100: the Linen shirt line matches the 12% acme-apparel rate for € 5.64, while the Desk lamp line and the shipping method fall back to the 10% default rate." />
16
13
 
17
14
  <Note>
18
- **Commission = the `CommissionRate` + `CommissionRule` entities.** A rate is
19
- the number, either a percentage or a fixed amount. Rules scope that rate to a
20
- slice of the catalog. Every marketplace has one **Global Commission**. This is
21
- the `is_default` rate that applies when nothing more specific matches.
15
+ The Commission module owns four data models: `CommissionRate` (`comrate`), `CommissionRule` (`comrule`), `CommissionRateValue` (`comval`), and `CommissionLine` (`comline`). Resolve its service with `MercurModules.COMMISSION` from `@mercurjs/types`.
22
16
  </Note>
23
17
 
24
18
  ## Key features
25
19
 
26
- - **Fixed or percentage:** a percentage of the line, or a flat per-currency amount.
27
- - **Per-currency amounts:** fixed rates carry an amount per currency, falling back to a default `value`.
28
- - **Five scoping dimensions:** match on `product`, `product_type`, `product_collection`, `product_category`, and `seller`.
29
- - **Most-specific-wins:** the rate scoped on the most dimensions wins, and ties break to the oldest rate.
30
- - **Shipping commission:** only the global rate may commission shipping (`include_shipping`).
31
- - **Automatic order lines:** a commission line is generated per item and recomputed when an order changes.
32
- - **BigNumber arithmetic:** all commission math uses arbitrary precision for financial accuracy.
20
+ The Commission module covers configuration, resolution, and the per-order record:
21
+
22
+ - **Percentage or fixed rates**: a percent of the line subtotal, or a flat amount per line
23
+ - **Per-currency amounts**: a fixed rate holds one amount per currency and falls back to its `value`
24
+ - **Five scoping dimensions**: rules match on `product`, `product_type`, `product_collection`, `product_category`, and `seller`
25
+ - **Most specific wins**: the matching rate scoped on the most dimensions wins, and ties go to the oldest rate
26
+ - **Global commission**: a seeded `is_default` rate that can’t be deleted and is the only rate that commissions shipping
27
+ - **Lines that follow the order**: lines are written at checkout and recomputed on order edits, returns, claims, and exchanges
28
+ - **Exact arithmetic**: amounts are computed with Medusa’s `MathBN` and stored as big numbers
29
+ - **Pluggable calculation**: swap the built-in `system` provider for your own `ICommissionProvider`
30
+
31
+ ## How it works
32
+
33
+ Commission runs as part of checkout and again whenever the order changes:
34
+
35
+ 1. `completeCartWithSplitOrdersWorkflow` splits the cart into one order per seller.
36
+ 2. It runs `refreshOrderCommissionLinesWorkflow` for the new orders as a nested step.
37
+ 3. The workflow builds one calculation context per order and passes them to the active provider in one batch.
38
+ 4. The `system` provider loads the enabled rates once and picks the winning rate for each item.
39
+ 5. The module replaces the order’s commission lines with the new set.
40
+ 6. When a payout is created, Mercur subtracts the sum of the order’s commission lines from the order total.
33
41
 
34
42
  ## Get started
35
43
 
36
- Learn how the domain fits together.
44
+ Learn how rates, rules, and commission lines fit together.
37
45
 
38
46
  <CardGroup cols={2}>
39
47
  <Card title="Rules & rates" icon="percent" href="/platform/commission/concepts/rules-and-rates">
40
- Fixed vs. percentage rates, per-currency amounts, and the global rate.
48
+ Percentage and fixed rates, per-currency amounts, and the global commission.
41
49
  </Card>
42
50
  <Card title="Rule matching" icon="sliders" href="/platform/commission/concepts/rule-matching">
43
- The five dimensions, most-specific-wins, tie-breaks, and shipping.
51
+ How Mercur picks one rate for each line, and how shipping is handled.
44
52
  </Card>
45
53
  <Card title="Order commission lines" icon="receipt" href="/platform/commission/concepts/order-commission-lines">
46
- How per-order lines are computed and kept in sync.
54
+ What a commission line records and when it’s recomputed.
47
55
  </Card>
48
56
  </CardGroup>
49
57
 
50
58
  ## Examples
51
59
 
52
- Build against the Commission domain in your own code.
60
+ Build against commission in your own server code.
53
61
 
54
62
  <CardGroup cols={2}>
55
63
  <Card title="Create a rate" icon="plus" href="/platform/commission/guides/create-a-rate">
56
- Run `createCommissionRatesWorkflow` from a route or seed script.
64
+ Create percentage and fixed rates with `createCommissionRatesWorkflow`.
57
65
  </Card>
58
66
  <Card title="Batch-update rules" icon="list-check" href="/platform/commission/guides/batch-update-rules">
59
- Create, update, and delete a rate's rules in one call.
67
+ Add, change, and remove a rate’s rules in one workflow run.
60
68
  </Card>
61
69
  <Card title="Refresh order lines" icon="arrows-rotate" href="/platform/commission/guides/refresh-order-commission-lines">
62
- Recompute commission for an order after it changes.
70
+ Recompute commission for orders and extend the calculation context.
63
71
  </Card>
64
72
  </CardGroup>
65
73
 
66
74
  ## Resources
67
75
 
68
- Data models, workflows, service methods, and events for the Commission domain.
76
+ The data models, links, workflows, service methods, and events behind commission.
69
77
 
70
78
  <CardGroup cols={2}>
71
79
  <Card title="Data models" icon="table" href="/platform/commission/reference/data-models">
72
- `CommissionRate`, `CommissionRule`, and related entities.
80
+ Every field of the four commission models.
73
81
  </Card>
74
82
  <Card title="Links" icon="link" href="/platform/commission/reference/links">
75
- How Commission connects to catalog, sellers, and orders.
83
+ How commission records point at the catalog, sellers, and orders.
76
84
  </Card>
77
85
  <Card title="Workflows" icon="diagram-project" href="/platform/commission/reference/workflows">
78
- Rate, rule, and order-line workflows.
86
+ Rate, rule, and order-line workflows with their inputs and hooks.
79
87
  </Card>
80
88
  <Card title="Service" icon="gear" href="/platform/commission/reference/service">
81
- Module service methods for working with records directly.
89
+ Generated and custom service methods, and commission providers.
82
90
  </Card>
83
91
  <Card title="Events" icon="bell" href="/platform/commission/reference/events">
84
- How commission stays in sync with order changes.
92
+ The order events that trigger a recompute.
85
93
  </Card>
86
94
  </CardGroup>