@mercurjs/docs 2.3.8-canary.3 → 2.3.9-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/learn/architecture.mdx +166 -263
- package/content/learn/introduction.mdx +9 -1
- package/content/learn/use-cases.mdx +70 -0
- package/content/platform/attribute/concepts/attribute-types.mdx +73 -46
- package/content/platform/attribute/concepts/global-vs-inline.mdx +54 -32
- package/content/platform/attribute/concepts/variant-axes.mdx +54 -32
- package/content/platform/attribute/guides/attach-attributes-to-a-product.mdx +96 -53
- package/content/platform/attribute/guides/create-a-variant-axis.mdx +106 -57
- package/content/platform/attribute/guides/create-an-attribute.mdx +105 -56
- package/content/platform/attribute/overview.mdx +37 -33
- package/content/platform/attribute/reference/data-models.mdx +53 -38
- package/content/platform/attribute/reference/events.mdx +47 -24
- package/content/platform/attribute/reference/links.mdx +98 -27
- package/content/platform/attribute/reference/service.mdx +71 -32
- package/content/platform/attribute/reference/workflows.mdx +158 -28
- package/content/platform/catalog/concepts/master-products.mdx +39 -37
- package/content/platform/catalog/concepts/product-seller-allowlist.mdx +56 -35
- package/content/platform/catalog/concepts/status-lifecycle.mdx +55 -49
- package/content/platform/catalog/concepts/variants-categories-collections.mdx +55 -35
- package/content/platform/catalog/guides/allowlist-stores.mdx +100 -37
- package/content/platform/catalog/guides/create-a-master-product.mdx +124 -48
- package/content/platform/catalog/guides/publish-or-reject-a-product.mdx +120 -55
- package/content/platform/catalog/overview.mdx +39 -35
- package/content/platform/catalog/reference/data-models.mdx +154 -43
- package/content/platform/catalog/reference/events.mdx +41 -25
- package/content/platform/catalog/reference/links.mdx +196 -28
- package/content/platform/catalog/reference/service.mdx +57 -35
- package/content/platform/catalog/reference/workflows.mdx +124 -30
- package/content/platform/commission/concepts/order-commission-lines.mdx +54 -52
- package/content/platform/commission/concepts/rule-matching.mdx +53 -63
- package/content/platform/commission/concepts/rules-and-rates.mdx +61 -59
- package/content/platform/commission/guides/batch-update-rules.mdx +69 -41
- package/content/platform/commission/guides/create-a-rate.mdx +101 -53
- package/content/platform/commission/guides/refresh-order-commission-lines.mdx +104 -35
- package/content/platform/commission/overview.mdx +43 -35
- package/content/platform/commission/reference/data-models.mdx +59 -45
- package/content/platform/commission/reference/events.mdx +28 -34
- package/content/platform/commission/reference/links.mdx +42 -33
- package/content/platform/commission/reference/service.mdx +103 -28
- package/content/platform/commission/reference/workflows.mdx +101 -27
- package/content/platform/offer/concepts/pricing-and-inventory.mdx +63 -49
- package/content/platform/offer/concepts/shipping.mdx +28 -29
- package/content/platform/offer/concepts/what-is-an-offer.mdx +48 -45
- package/content/platform/offer/guides/bulk-create-offers.mdx +97 -61
- package/content/platform/offer/guides/create-an-offer.mdx +112 -60
- package/content/platform/offer/guides/manage-offer-inventory.mdx +78 -38
- package/content/platform/offer/overview.mdx +39 -32
- package/content/platform/offer/reference/data-models.mdx +77 -47
- package/content/platform/offer/reference/events.mdx +44 -18
- package/content/platform/offer/reference/links.mdx +92 -40
- package/content/platform/offer/reference/service.mdx +66 -31
- package/content/platform/offer/reference/workflows.mdx +146 -37
- package/content/platform/order-group/concepts/computed-totals.mdx +40 -37
- package/content/platform/order-group/concepts/order-splitting.mdx +41 -39
- package/content/platform/order-group/concepts/the-order-group.mdx +39 -32
- package/content/platform/order-group/guides/list-order-groups.mdx +96 -56
- package/content/platform/order-group/guides/retrieve-an-order-group.mdx +93 -42
- package/content/platform/order-group/guides/split-a-cart.mdx +115 -40
- package/content/platform/order-group/overview.mdx +42 -32
- package/content/platform/order-group/reference/data-models.mdx +48 -31
- package/content/platform/order-group/reference/events.mdx +29 -17
- package/content/platform/order-group/reference/links.mdx +90 -29
- package/content/platform/order-group/reference/service.mdx +55 -31
- package/content/platform/order-group/reference/workflows.mdx +83 -24
- package/content/platform/payout/concepts/account-lifecycle.mdx +64 -67
- package/content/platform/payout/concepts/accounts-and-onboarding.mdx +50 -40
- package/content/platform/payout/concepts/payout-pipeline.mdx +70 -73
- package/content/platform/payout/guides/create-a-payout-account.mdx +65 -41
- package/content/platform/payout/guides/process-a-provider-webhook.mdx +84 -38
- package/content/platform/payout/guides/start-provider-onboarding.mdx +90 -46
- package/content/platform/payout/overview.mdx +43 -34
- package/content/platform/payout/reference/data-models.mdx +63 -36
- package/content/platform/payout/reference/events.mdx +56 -30
- package/content/platform/payout/reference/links.mdx +52 -22
- package/content/platform/payout/reference/service.mdx +72 -33
- package/content/platform/payout/reference/workflows.mdx +80 -19
- package/content/platform/product-edit/concepts/change-actions.mdx +52 -45
- package/content/platform/product-edit/concepts/change-pipeline.mdx +60 -52
- package/content/platform/product-edit/concepts/status-and-auto-confirm.mdx +43 -46
- package/content/platform/product-edit/guides/confirm-or-decline-a-change.mdx +104 -56
- package/content/platform/product-edit/guides/edit-a-product.mdx +126 -46
- package/content/platform/product-edit/guides/request-a-revision.mdx +99 -39
- package/content/platform/product-edit/overview.mdx +41 -34
- package/content/platform/product-edit/reference/data-models.mdx +73 -47
- package/content/platform/product-edit/reference/events.mdx +39 -29
- package/content/platform/product-edit/reference/links.mdx +32 -24
- package/content/platform/product-edit/reference/service.mdx +45 -26
- package/content/platform/product-edit/reference/workflows.mdx +173 -31
- package/content/platform/review/concepts/product-vs-seller-reviews.mdx +42 -41
- package/content/platform/review/concepts/ratings-and-moderation.mdx +45 -44
- package/content/platform/review/concepts/the-review-model.mdx +52 -45
- package/content/platform/review/guides/compute-aggregate-ratings.mdx +62 -37
- package/content/platform/review/guides/create-a-review.mdx +109 -39
- package/content/platform/review/guides/moderate-a-review.mdx +83 -37
- package/content/platform/review/guides/respond-to-a-review.mdx +85 -40
- package/content/platform/review/overview.mdx +43 -33
- package/content/platform/review/reference/data-models.mdx +41 -27
- package/content/platform/review/reference/events.mdx +55 -37
- package/content/platform/review/reference/links.mdx +80 -22
- package/content/platform/review/reference/service.mdx +61 -33
- package/content/platform/review/reference/workflows.mdx +80 -24
- package/content/platform/store/concepts/lifecycle.mdx +68 -44
- package/content/platform/store/concepts/store-entity.mdx +45 -27
- package/content/platform/store/concepts/team.mdx +56 -35
- package/content/platform/store/guides/create-a-store.mdx +102 -35
- package/content/platform/store/guides/manage-the-team.mdx +122 -32
- package/content/platform/store/guides/moderate-a-store.mdx +107 -38
- package/content/platform/store/overview.mdx +41 -34
- package/content/platform/store/reference/data-models.mdx +132 -57
- package/content/platform/store/reference/events.mdx +42 -17
- package/content/platform/store/reference/links.mdx +67 -49
- package/content/platform/store/reference/service.mdx +105 -33
- package/content/platform/store/reference/workflows.mdx +304 -24
- package/content/references/api/conventions.mdx +20 -0
- package/content/resources/integrations/magento2.mdx +162 -0
- package/content/resources/integrations/overview.mdx +10 -0
- package/content/resources/integrations/stripe-connect.mdx +1 -1
- package/content/resources/tutorials/custom-api-route.mdx +3 -2
- package/llms.txt +113 -111
- package/package.json +1 -1
|
@@ -1,75 +1,89 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Commission data models"
|
|
3
3
|
sidebarTitle: "Data models"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Every field of CommissionRate, CommissionRule, CommissionRateValue, and CommissionLine."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Commission
|
|
8
|
-
lists its data models and their fields. For the full module overview, see the
|
|
9
|
-
[Commission overview](/platform/commission/overview).
|
|
7
|
+
The Commission module owns four data models, defined in `packages/core/src/modules/commission/models`. Every model also has `created_at`, `updated_at`, and a nullable `deleted_at`, which Medusa adds and the tables below leave out.
|
|
10
8
|
|
|
11
9
|
## CommissionRate
|
|
12
10
|
|
|
13
|
-
Table `commission_rate`, id prefix `comrate`.
|
|
14
|
-
from a sale.
|
|
11
|
+
The rate the marketplace takes from a sale. Table `commission_rate`, id prefix `comrate`.
|
|
15
12
|
|
|
16
|
-
| Field | Type |
|
|
13
|
+
| Field | Type | Description |
|
|
17
14
|
| --- | --- | --- |
|
|
18
15
|
| `id` | text | Primary key |
|
|
19
|
-
| `name` | text |
|
|
20
|
-
| `code` | text | Unique
|
|
21
|
-
| `type` | enum | `CommissionRateType
|
|
22
|
-
| `value` | bigNumber |
|
|
23
|
-
| `currency_code` | text |
|
|
24
|
-
| `include_tax` | boolean | Default `false
|
|
25
|
-
| `include_shipping` | boolean | Default `false
|
|
26
|
-
| `is_enabled` | boolean | Default `true
|
|
27
|
-
| `is_default` | boolean | Default `false
|
|
28
|
-
|
|
29
|
-
Relations:
|
|
30
|
-
|
|
16
|
+
| `name` | text | Display name, searchable |
|
|
17
|
+
| `code` | text | Unique among non-deleted rates and searchable. Generated from `name` when omitted on create |
|
|
18
|
+
| `type` | enum | `CommissionRateType`: `fixed` or `percentage` |
|
|
19
|
+
| `value` | bigNumber | The percent for `percentage`, the fallback amount for `fixed` |
|
|
20
|
+
| `currency_code` | text, nullable | When set, the rate applies only to orders in this currency |
|
|
21
|
+
| `include_tax` | boolean | Default `false`. Adds the line’s `tax_total` to the base amount |
|
|
22
|
+
| `include_shipping` | boolean | Default `false`. Produces shipping lines, on the `is_default` rate only |
|
|
23
|
+
| `is_enabled` | boolean | Default `true`. Disabled rates are skipped |
|
|
24
|
+
| `is_default` | boolean | Default `false`. Marks the global commission, which can’t be deleted |
|
|
25
|
+
|
|
26
|
+
Relations:
|
|
27
|
+
|
|
28
|
+
- **`rules`**: has many `CommissionRule`
|
|
29
|
+
- **`values`**: has many `CommissionRateValue`
|
|
31
30
|
|
|
32
31
|
## CommissionRule
|
|
33
32
|
|
|
34
|
-
Table `commission_rule`, id prefix `comrule`.
|
|
35
|
-
catalog.
|
|
33
|
+
Scopes a rate to one record in one dimension. Table `commission_rule`, id prefix `comrule`.
|
|
36
34
|
|
|
37
|
-
| Field | Type |
|
|
35
|
+
| Field | Type | Description |
|
|
38
36
|
| --- | --- | --- |
|
|
39
37
|
| `id` | text | Primary key |
|
|
40
38
|
| `reference` | text | The dimension: `product`, `product_type`, `product_collection`, `product_category`, or `seller` |
|
|
41
39
|
| `reference_id` | text | The id of the record in that dimension |
|
|
42
|
-
| `
|
|
40
|
+
| `commission_rate_id` | text | Foreign key to the owning rate |
|
|
41
|
+
|
|
42
|
+
Relations:
|
|
43
|
+
|
|
44
|
+
- **`commission_rate`**: belongs to `CommissionRate`
|
|
45
|
+
|
|
46
|
+
The table has an index on `(reference, reference_id)` for non-deleted rows.
|
|
43
47
|
|
|
44
48
|
## CommissionRateValue
|
|
45
49
|
|
|
46
|
-
Table `commission_rate_value`, id prefix `comval`.
|
|
47
|
-
fixed rate.
|
|
50
|
+
A per-currency amount for a fixed rate. Table `commission_rate_value`, id prefix `comval`.
|
|
48
51
|
|
|
49
|
-
| Field | Type |
|
|
52
|
+
| Field | Type | Description |
|
|
50
53
|
| --- | --- | --- |
|
|
51
54
|
| `id` | text | Primary key |
|
|
52
|
-
| `currency_code` | text | The currency this amount applies to |
|
|
53
|
-
| `amount` | bigNumber | The
|
|
54
|
-
| `
|
|
55
|
+
| `currency_code` | text | The currency this amount applies to, such as `usd` |
|
|
56
|
+
| `amount` | bigNumber | The fixed commission per line item in that currency |
|
|
57
|
+
| `commission_rate_id` | text | Foreign key to the owning rate |
|
|
58
|
+
|
|
59
|
+
Relations:
|
|
60
|
+
|
|
61
|
+
- **`commission_rate`**: belongs to `CommissionRate`
|
|
55
62
|
|
|
56
63
|
## CommissionLine
|
|
57
64
|
|
|
58
|
-
Table `commission_line`, id prefix `comline`.
|
|
59
|
-
order line.
|
|
65
|
+
The resolved commission for one order line item or shipping method. Table `commission_line`, id prefix `comline`.
|
|
60
66
|
|
|
61
|
-
| Field | Type |
|
|
67
|
+
| Field | Type | Description |
|
|
62
68
|
| --- | --- | --- |
|
|
63
69
|
| `id` | text | Primary key |
|
|
64
|
-
| `item_id` | text |
|
|
65
|
-
| `shipping_method_id` | text |
|
|
66
|
-
| `commission_rate_id` | text |
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
| `item_id` | text, nullable | The order line item this line commissions |
|
|
71
|
+
| `shipping_method_id` | text, nullable | The order shipping method this line commissions |
|
|
72
|
+
| `commission_rate_id` | text, nullable | The rate that produced the line. Plain text, not a relation |
|
|
73
|
+
| `provider_id` | text | Default `system`. The provider that computed the line |
|
|
74
|
+
| `code` | text | The code of the rate that produced the line |
|
|
75
|
+
| `rate` | float | The percent, or the fixed amount, that was applied |
|
|
76
|
+
| `amount` | bigNumber | The commission amount |
|
|
77
|
+
| `description` | text, nullable | `Shipping Commission` on shipping lines from the `system` provider |
|
|
78
|
+
| `data` | json, nullable | Free data from the provider |
|
|
79
|
+
|
|
80
|
+
The table has indexes on `item_id` and on `shipping_method_id` for non-deleted rows. A line sets one of the two anchors and leaves the other `null`.
|
|
81
|
+
|
|
82
|
+
## Enums
|
|
83
|
+
|
|
84
|
+
`CommissionRateType` is exported from `@mercurjs/types`.
|
|
85
|
+
|
|
86
|
+
| Member | Value |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `CommissionRateType.FIXED` | `fixed` |
|
|
89
|
+
| `CommissionRateType.PERCENTAGE` | `percentage` |
|
|
@@ -1,58 +1,52 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Commission events"
|
|
3
3
|
sidebarTitle: "Events"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Commission emits no domain events of its own. It listens to four order events and recomputes commission lines."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Commission
|
|
8
|
-
are derived data, so instead of broadcasting changes, the module **subscribes**
|
|
9
|
-
to order lifecycle events and recomputes lines whenever an order's composition
|
|
10
|
-
changes.
|
|
7
|
+
The Commission module doesn’t define or emit domain events. Commission lines are derived from the order, so the module listens to order events instead and recomputes the lines when the order’s contents change.
|
|
11
8
|
|
|
12
|
-
## Events
|
|
9
|
+
## Events that trigger a recompute
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
`refreshOrderCommissionLinesWorkflow` for the affected order on each of these
|
|
16
|
-
events:
|
|
11
|
+
The `order-commission-refresh-handler` subscriber, in `packages/core/src/subscribers/order-edit-confirmed.ts`, runs `refreshOrderCommissionLinesWorkflow` for the order on each of these events.
|
|
17
12
|
|
|
18
|
-
| Event | Emitted when |
|
|
19
|
-
| --- | --- |
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
13
|
+
| Event | Emitted when | Payload the subscriber reads |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `order-edit.confirmed` | An order edit is confirmed | `order_id` |
|
|
16
|
+
| `order.return_received` | A return is received | `order_id` |
|
|
17
|
+
| `order.claim_created` | A claim is created | `order_id` |
|
|
18
|
+
| `order.exchange_created` | An exchange is created | `order_id` |
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
events for the same order never duplicates lines.
|
|
20
|
+
The subscriber reads `order_id` and falls back to `id`. It does nothing when the payload has neither. The events come from Medusa as `OrderEditWorkflowEvents.CONFIRMED`, `OrderWorkflowEvents.RETURN_RECEIVED`, `OrderWorkflowEvents.CLAIM_CREATED`, and `OrderWorkflowEvents.EXCHANGE_CREATED`.
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
Checkout doesn’t go through an event. `completeCartWithSplitOrdersWorkflow` runs the refresh as a nested step for every seller order it creates.
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
events the module listens to, then read the refreshed lines from the commission
|
|
32
|
-
module.
|
|
24
|
+
## Run your own logic after a recompute
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
Subscribe to the same order events to run your own logic when an order’s commission may change.
|
|
27
|
+
|
|
28
|
+
```ts title="src/subscribers/commission-audit.ts"
|
|
35
29
|
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
36
30
|
import { OrderWorkflowEvents } from "@medusajs/framework/utils"
|
|
37
31
|
|
|
38
|
-
export default async function
|
|
32
|
+
export default async function commissionAudit({
|
|
39
33
|
event,
|
|
40
34
|
container,
|
|
41
|
-
}: SubscriberArgs<{ order_id
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
// ...read commission lines for the order, notify, sync an external ledger, etc.
|
|
35
|
+
}: SubscriberArgs<{ order_id: string }>) {
|
|
36
|
+
const logger = container.resolve("logger")
|
|
37
|
+
logger.info(`Commission may have changed on ${event.data.order_id}`)
|
|
47
38
|
}
|
|
48
39
|
|
|
49
40
|
export const config: SubscriberConfig = {
|
|
50
|
-
event:
|
|
41
|
+
event: [
|
|
42
|
+
OrderWorkflowEvents.RETURN_RECEIVED,
|
|
43
|
+
OrderWorkflowEvents.CLAIM_CREATED,
|
|
44
|
+
],
|
|
51
45
|
}
|
|
52
46
|
```
|
|
53
47
|
|
|
48
|
+
Subscribers run independently, so this one can run before the refresh finishes. When you need the new lines, use the `commissionLinesUpserted` hook of `refreshOrderCommissionLinesWorkflow`, which runs after they’re written. See [Refresh order commission lines](/platform/commission/guides/refresh-order-commission-lines).
|
|
49
|
+
|
|
54
50
|
<Note>
|
|
55
|
-
Commission
|
|
56
|
-
from the split cart. That refresh happens as a **step inside** the checkout
|
|
57
|
-
workflow rather than via a separate event.
|
|
51
|
+
Like every `MedusaService` module, the Commission service also emits Medusa’s internal data-mutation events when records are created, updated, or deleted. Mercur doesn’t subscribe to them, and this reference doesn’t treat them as a stable contract.
|
|
58
52
|
</Note>
|
|
@@ -1,45 +1,54 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Commission links to other modules"
|
|
3
3
|
sidebarTitle: "Links"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Commission defines no module links. Rules and lines reference the catalog, sellers, and orders by plain id."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
resolved with `query.graph`. The Commission module is deliberately different: it
|
|
9
|
-
defines **no** module links. Instead it connects to the rest of the marketplace
|
|
10
|
-
through **soft references**. These are plain id fields resolved at calculation
|
|
11
|
-
time. This keeps commission configuration independent of the catalog and order
|
|
12
|
-
modules it scopes against.
|
|
7
|
+
The Commission module defines no module links. None of the files in `packages/core/src/links` has a commission side. Rules and lines point at records in other modules through plain id fields, which Mercur resolves at calculation time or which you filter on directly.
|
|
13
8
|
|
|
14
|
-
## Rules
|
|
9
|
+
## Rules point at the catalog and sellers
|
|
15
10
|
|
|
16
|
-
A `CommissionRule`
|
|
17
|
-
`reference` / `reference_id` pair, resolved against the order line's product when
|
|
18
|
-
commission is calculated:
|
|
11
|
+
A `CommissionRule` names its target with `reference` and `reference_id`. The `refreshOrderCommissionLinesWorkflow` reads the target’s fields from the order with `query.graph`, so the commission records never need a link.
|
|
19
12
|
|
|
20
|
-
| `reference` | Points at |
|
|
13
|
+
| `reference` | Points at | Read from the order line |
|
|
21
14
|
| --- | --- | --- |
|
|
22
|
-
| `product` | A master product | `
|
|
23
|
-
| `product_type` | A product type | `
|
|
24
|
-
| `product_collection` | A collection | `
|
|
25
|
-
| `product_category` | A category | `
|
|
26
|
-
| `seller` | A
|
|
15
|
+
| `product` | A master product | `items.product.id` |
|
|
16
|
+
| `product_type` | A product type | `items.product.type_id` |
|
|
17
|
+
| `product_collection` | A product collection | `items.product.collection_id` |
|
|
18
|
+
| `product_category` | A product category | `items.product.categories.id` |
|
|
19
|
+
| `seller` | A seller | `items.offer.seller_id` |
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
The `seller` row goes through the `order-line-item-offer-link` from the Offer module. Products belong to the shared catalog, so the seller of a line is the seller of the offer the customer bought.
|
|
22
|
+
|
|
23
|
+
## Lines point at order items and shipping methods
|
|
24
|
+
|
|
25
|
+
A `CommissionLine` stores `item_id` or `shipping_method_id` as plain text. To get an order’s lines, collect the ids from the order, then filter `commission_line` by them.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
const { data: [order] } = await query.graph({
|
|
29
|
+
entity: "order",
|
|
30
|
+
fields: ["items.id", "shipping_methods.id"],
|
|
31
|
+
filters: { id: "order_01JD8Q1234567" },
|
|
32
|
+
})
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const { data: lines } = await query.graph({
|
|
35
|
+
entity: "commission_line",
|
|
36
|
+
fields: ["item_id", "shipping_method_id", "code", "amount"],
|
|
37
|
+
filters: {
|
|
38
|
+
$or: [
|
|
39
|
+
{ item_id: order.items.map((item) => item.id) },
|
|
40
|
+
{ shipping_method_id: order.shipping_methods.map((m) => m.id) },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
```
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
`item_id` (an order line item) or `shipping_method_id` (a shipping method).
|
|
38
|
-
These are stored as plain ids, so the payout pipeline reads an order's lines by
|
|
39
|
-
querying the commission module directly rather than traversing a link.
|
|
46
|
+
`createPayoutWorkflow` and the order commission-lines routes read lines the same way.
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
## Lines point at their rate
|
|
49
|
+
|
|
50
|
+
`commission_rate_id` on a line is also plain text, not a relation. Query the rate separately if you need more than the `code` the line already stores.
|
|
51
|
+
|
|
52
|
+
<Note>
|
|
53
|
+
Plain ids don’t cascade. Deleting a product, category, or seller leaves its rules in place, where they stop matching. Deleting a rate soft-deletes it and leaves existing lines untouched.
|
|
54
|
+
</Note>
|
|
@@ -1,51 +1,126 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Commission module service"
|
|
3
3
|
sidebarTitle: "Service"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Resolve the Commission module service, its generated and custom methods, and the commission provider interface."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Commission module
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
The Commission module service reads and writes commission records without a workflow. Use it in steps, subscribers, and scheduled jobs, and use the [workflows](/platform/commission/reference/workflows) when you need rollback or the global-rate delete guard.
|
|
8
|
+
|
|
9
|
+
## Resolve the service
|
|
10
|
+
|
|
11
|
+
Resolve the service from the container with `MercurModules.COMMISSION`.
|
|
10
12
|
|
|
11
13
|
```ts
|
|
12
14
|
import { MercurModules } from "@mercurjs/types"
|
|
13
15
|
|
|
14
|
-
const
|
|
16
|
+
const commission = container.resolve(MercurModules.COMMISSION)
|
|
15
17
|
|
|
16
|
-
const [rates, count] = await
|
|
17
|
-
{ is_enabled: true }
|
|
18
|
+
const [rates, count] = await commission.listAndCountCommissionRates(
|
|
19
|
+
{ is_enabled: true },
|
|
20
|
+
{ relations: ["rules", "values"] }
|
|
18
21
|
)
|
|
19
22
|
```
|
|
20
23
|
|
|
24
|
+
The call returns enabled rates with their rules and per-currency values, plus the total count.
|
|
25
|
+
|
|
21
26
|
## Generated methods
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
`CommissionRate`:
|
|
28
|
+
The service extends `MedusaService`, so every model gets the standard methods. For `CommissionRate` they are:
|
|
25
29
|
|
|
26
30
|
| Method | Description |
|
|
27
31
|
| --- | --- |
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `updateCommissionRates(data)` | Update
|
|
33
|
-
| `deleteCommissionRates(ids)` |
|
|
32
|
+
| `retrieveCommissionRate(id, config?)` | Retrieve one rate |
|
|
33
|
+
| `listCommissionRates(filters?, config?)` | List rates |
|
|
34
|
+
| `listAndCountCommissionRates(filters?, config?)` | List rates with a count |
|
|
35
|
+
| `createCommissionRates(data)` | Create one rate or an array of rates |
|
|
36
|
+
| `updateCommissionRates(data)` | Update rates |
|
|
37
|
+
| `deleteCommissionRates(ids)` | Hard-delete rates |
|
|
38
|
+
| `softDeleteCommissionRates(ids)` | Soft-delete rates |
|
|
39
|
+
| `restoreCommissionRates(ids)` | Restore soft-deleted rates |
|
|
40
|
+
|
|
41
|
+
The same set exists for `CommissionRule`, `CommissionRateValue`, and `CommissionLine`, for example `listCommissionRules`, `createCommissionRateValues`, and `retrieveCommissionLine`.
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
`
|
|
37
|
-
|
|
43
|
+
<Warning>
|
|
44
|
+
`deleteCommissionRates` doesn’t check for the global rate. Use `deleteCommissionRatesWorkflow` to keep the `is_default` rate safe.
|
|
45
|
+
</Warning>
|
|
38
46
|
|
|
39
|
-
##
|
|
47
|
+
## Custom methods
|
|
48
|
+
|
|
49
|
+
The service overrides or adds these methods:
|
|
40
50
|
|
|
41
51
|
| Method | Description |
|
|
42
52
|
| --- | --- |
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
53
|
+
| `createCommissionRates(data)` | Fills a missing `code` from `name` plus a random suffix, then creates. Returns one rate for one input, an array for an array |
|
|
54
|
+
| `listCommissionRates(filters?, config?)` | Accepts a virtual `scope_type` filter |
|
|
55
|
+
| `listAndCountCommissionRates(filters?, config?)` | Accepts the same `scope_type` filter |
|
|
56
|
+
| `getCommissionLines(context)` | Computes lines for one context with the default provider. Doesn’t persist |
|
|
57
|
+
| `getCommissionLinesBatch(contexts)` | Computes lines for several contexts, one array per context in order. Doesn’t persist |
|
|
58
|
+
| `upsertCommissionLines(lines)` | Deletes existing lines with the same `item_id` or `shipping_method_id`, then inserts `lines` |
|
|
45
59
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
`getCommissionLines` and `getCommissionLinesBatch` stamp the default provider’s id on any line without a `provider_id`. `getCommissionLinesBatch` falls back to one `getCommissionLines` call per context when the provider has no batch method.
|
|
61
|
+
|
|
62
|
+
## Filter rates by scope type
|
|
63
|
+
|
|
64
|
+
`scope_type` filters rates by the dimensions their rules use, computed in the database. Pass one value, an array, or a comma-separated string. Several values are combined with OR, and an unknown value matches nothing.
|
|
65
|
+
|
|
66
|
+
| `scope_type` | Rates whose rules use |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `store` | `seller` only, without `product_type` or `product_category` |
|
|
69
|
+
| `product_type` | `product_type`, without `seller` or `product_category` |
|
|
70
|
+
| `category` | `product_category`, without `seller` or `product_type` |
|
|
71
|
+
| `store_product_type` | `seller` and `product_type` |
|
|
72
|
+
| `store_category` | `seller` and `product_category`, without `product_type` |
|
|
73
|
+
|
|
74
|
+
## Commission providers
|
|
75
|
+
|
|
76
|
+
A provider computes the lines from a calculation context. The module always registers the built-in `system` provider, which implements the [rule matching](/platform/commission/concepts/rule-matching) algorithm, and uses it unless you configure another one.
|
|
77
|
+
|
|
78
|
+
```ts title="src/modules/tiered-commission/service.ts"
|
|
79
|
+
import { MathBN } from "@medusajs/framework/utils"
|
|
80
|
+
import type {
|
|
81
|
+
CommissionCalculationContext,
|
|
82
|
+
CreateCommissionLineDTO,
|
|
83
|
+
ICommissionProvider,
|
|
84
|
+
} from "@mercurjs/types"
|
|
85
|
+
|
|
86
|
+
export default class TieredCommissionProvider
|
|
87
|
+
implements ICommissionProvider
|
|
88
|
+
{
|
|
89
|
+
static identifier = "tiered"
|
|
90
|
+
|
|
91
|
+
async getCommissionLines(
|
|
92
|
+
context: CommissionCalculationContext
|
|
93
|
+
): Promise<CreateCommissionLineDTO[]> {
|
|
94
|
+
const percent = context.additional_context?.tier === "gold" ? 8 : 12
|
|
95
|
+
return (context.items ?? []).map((item) => ({
|
|
96
|
+
item_id: item.id,
|
|
97
|
+
code: "tiered",
|
|
98
|
+
rate: percent,
|
|
99
|
+
amount: MathBN.div(MathBN.mult(item.subtotal, percent), 100).toNumber(),
|
|
100
|
+
}))
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
A provider class needs a static `identifier` and `getCommissionLines`. It can add `getCommissionLinesBatch(contexts)` to load its data once per batch. The module doesn’t cap `amount`, so keep it within the item’s `total` yourself.
|
|
106
|
+
|
|
107
|
+
Export the class as a module provider so the commission module can register it.
|
|
108
|
+
|
|
109
|
+
```ts title="src/modules/tiered-commission/index.ts"
|
|
110
|
+
import { ModuleProvider } from "@medusajs/framework/utils"
|
|
111
|
+
import { MercurModules } from "@mercurjs/types"
|
|
112
|
+
import TieredCommissionProvider from "./service"
|
|
113
|
+
|
|
114
|
+
export default ModuleProvider(MercurModules.COMMISSION, {
|
|
115
|
+
services: [TieredCommissionProvider],
|
|
116
|
+
})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The module takes these options, typed as `CommissionModuleOptions`:
|
|
120
|
+
|
|
121
|
+
| Option | Description |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| `providers` | Array of `{ resolve, id, options?, is_default? }` registered next to `system` |
|
|
124
|
+
| `default_provider` | Provider id used for every calculation. Overrides `is_default` |
|
|
125
|
+
|
|
126
|
+
A single configured provider becomes the default without `is_default`.
|
|
@@ -1,40 +1,114 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Commission workflows"
|
|
3
3
|
sidebarTitle: "Workflows"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Inputs, outputs, steps, and hooks of the rate, rule, and order-line commission workflows."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
`@mercurjs/core/workflows` and run them against the Medusa container.
|
|
7
|
+
The Commission module ships five workflows, exported from `@mercurjs/core/workflows`. They run against the Medusa container, and each step compensates on failure unless noted. None of them emits an event.
|
|
9
8
|
|
|
10
|
-
##
|
|
9
|
+
## createCommissionRatesWorkflow
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
Creates one or more commission rates. Workflow id `create-commission-rates`.
|
|
12
|
+
|
|
13
|
+
| Input | Type |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| (root) | `CreateCommissionRateDTO[]` |
|
|
16
|
+
|
|
17
|
+
`CreateCommissionRateDTO` takes `name`, `type`, and `value`, and optionally `code`, `currency_code`, `include_tax`, `include_shipping`, `is_enabled`, and `is_default`. The module also accepts nested `rules` and `values` arrays, which the DTO doesn’t declare. A missing `code` is generated from `name`.
|
|
18
|
+
|
|
19
|
+
- **Output**: the created rates, in input order
|
|
20
|
+
- **Steps**: `createCommissionRatesStep`, compensated by deleting the created rates
|
|
21
|
+
- **Hooks**: none
|
|
22
|
+
|
|
23
|
+
## updateCommissionRatesWorkflow
|
|
24
|
+
|
|
25
|
+
Updates fields on one or more rates. Workflow id `update-commission-rates`.
|
|
26
|
+
|
|
27
|
+
| Input | Type |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| (root) | `UpdateCommissionRateDTO[]` |
|
|
30
|
+
|
|
31
|
+
Each item needs an `id` and takes any `CreateCommissionRateDTO` field as optional.
|
|
32
|
+
|
|
33
|
+
- **Output**: the updated rates
|
|
34
|
+
- **Steps**: `updateCommissionRatesStep`
|
|
35
|
+
- **Hooks**: none
|
|
36
|
+
|
|
37
|
+
<Warning>
|
|
38
|
+
The compensation of `updateCommissionRatesStep` re-applies the step’s input, not the previous values. If a later step in a parent workflow fails, the rate keeps the new values.
|
|
39
|
+
</Warning>
|
|
40
|
+
|
|
41
|
+
## deleteCommissionRatesWorkflow
|
|
42
|
+
|
|
43
|
+
Soft-deletes rates after checking that none of them is the global rate. Workflow id `delete-commission-rates`.
|
|
44
|
+
|
|
45
|
+
| Input | Type | Description |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `ids` | `string[]` | Ids of the rates to delete |
|
|
48
|
+
|
|
49
|
+
- **Output**: none
|
|
50
|
+
- **Steps**: `validateCommissionRatesDeletableStep`, which throws `NOT_ALLOWED` for an `is_default` rate, then `deleteCommissionRatesStep`, compensated by restoring the rates
|
|
51
|
+
- **Hooks**: `commissionRatesDeleted`, with `{ ids }`
|
|
52
|
+
|
|
53
|
+
## batchCommissionRulesWorkflow
|
|
54
|
+
|
|
55
|
+
Creates, updates, and deletes the rules of one rate. Workflow id `batch-commission-rules`.
|
|
56
|
+
|
|
57
|
+
| Input | Type | Description |
|
|
13
58
|
| --- | --- | --- |
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
59
|
+
| `commission_rate_id` | `string` | The rate that new rules attach to |
|
|
60
|
+
| `create` | `CreateCommissionRuleDTO[]`, optional | `{ reference, reference_id }` |
|
|
61
|
+
| `update` | `UpdateCommissionRuleDTO[]`, optional | `{ id, reference?, reference_id? }` |
|
|
62
|
+
| `delete` | `string[]`, optional | Ids of rules to delete |
|
|
63
|
+
|
|
64
|
+
- **Output**: `{ created, updated, deleted }`, where `deleted` holds the ids
|
|
65
|
+
- **Steps**: `createCommissionRulesStep`, `updateCommissionRulesStep`, and `deleteCommissionRulesStep`, run in parallel
|
|
66
|
+
- **Hooks**: none
|
|
67
|
+
|
|
68
|
+
Only `create` uses `commission_rate_id`. The ids in `update` and `delete` aren’t checked against it.
|
|
69
|
+
|
|
70
|
+
## refreshOrderCommissionLinesWorkflow
|
|
17
71
|
|
|
18
|
-
|
|
72
|
+
Recomputes and replaces the commission lines of one or more orders. Workflow id `refresh-order-commission-lines`.
|
|
19
73
|
|
|
20
|
-
|
|
|
74
|
+
| Input | Type | Description |
|
|
21
75
|
| --- | --- | --- |
|
|
22
|
-
| `
|
|
76
|
+
| `order_ids` | `string[]` | Orders to refresh. An unknown id throws |
|
|
23
77
|
|
|
24
|
-
|
|
78
|
+
- **Output**: `CommissionLineDTO[]`, the lines written for all the orders
|
|
79
|
+
- **Steps**: `fetch-orders` (`useQueryGraphStep`), `getCommissionLinesStep`, `upsertCommissionLinesStep`
|
|
80
|
+
- **Called by**: `completeCartWithSplitOrdersWorkflow` and the `order-commission-refresh-handler` subscriber
|
|
25
81
|
|
|
26
|
-
|
|
82
|
+
The workflow exposes two hooks:
|
|
83
|
+
|
|
84
|
+
| Hook | Input | Return |
|
|
27
85
|
| --- | --- | --- |
|
|
28
|
-
| `
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
86
|
+
| `setCommissionContext` | `{ contexts: CommissionCalculationContext[] }` | `StepResponse` of new contexts, or nothing |
|
|
87
|
+
| `commissionLinesUpserted` | `{ order_ids, commission_lines }` | Ignored |
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
refreshOrderCommissionLinesWorkflow.hooks.setCommissionContext(
|
|
91
|
+
({ contexts }) =>
|
|
92
|
+
new StepResponse(
|
|
93
|
+
contexts.map((c) => ({ ...c, additional_context: { tier: "gold" } }))
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The handler above adds data to every context before the provider sees it. Neither `getCommissionLinesStep` nor `upsertCommissionLinesStep` defines a compensation.
|
|
99
|
+
|
|
100
|
+
## Exported steps
|
|
101
|
+
|
|
102
|
+
`@mercurjs/core/workflows` also exports each step, with its id, for use in your own workflows:
|
|
103
|
+
|
|
104
|
+
| Step | Id |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `createCommissionRatesStep` | `create-commission-rates-step` |
|
|
107
|
+
| `updateCommissionRatesStep` | `update-commission-rates-step` |
|
|
108
|
+
| `deleteCommissionRatesStep` | `delete-commission-rates-step` |
|
|
109
|
+
| `validateCommissionRatesDeletableStep` | `validate-commission-rates-deletable-step` |
|
|
110
|
+
| `createCommissionRulesStep` | `create-commission-rules-step` |
|
|
111
|
+
| `updateCommissionRulesStep` | `update-commission-rules-step` |
|
|
112
|
+
| `deleteCommissionRulesStep` | `delete-commission-rules-step` |
|
|
113
|
+
| `getCommissionLinesStep` | `get-commission-lines` |
|
|
114
|
+
| `upsertCommissionLinesStep` | `upsert-commission-lines` |
|