@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,85 +1,92 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Product
|
|
2
|
+
title: "Product edits"
|
|
3
3
|
sidebarTitle: "Overview"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Review every seller edit to a shared product before it lands, and keep a record of who changed what."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Use Mercur to keep a
|
|
8
|
-
master data before it changes.
|
|
7
|
+
Use Mercur to put seller edits to the shared catalog through review, and to keep a durable history of every change to a product.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Each record carries typed actions and a status lifecycle, and the trail records
|
|
15
|
-
who changed what and who approved it.
|
|
9
|
+
Products in Mercur form one shared catalog that every seller sells against, so a seller can’t write to a product directly. Each edit becomes a `ProductChange` record that holds typed actions, one per changed field, variant, or attribute. The change waits as `pending` until an operator confirms or declines it, or its author cancels it. Confirmed changes, together with publish approvals, rejections, and revision requests, form the product’s audit trail.
|
|
10
|
+
|
|
11
|
+
<img className="block dark:hidden" src="/images/figures/product-edit-overview-light.svg" alt="A product's Changes list read through product.changes: a pending UPDATE from the seller sits on top of confirmed PRODUCT_ADD, CHANGE_REQUESTED, UPDATE, and STATUS_CHANGE records that form the audit trail." />
|
|
12
|
+
<img className="hidden dark:block" src="/images/figures/product-edit-overview-dark.svg" alt="A product's Changes list read through product.changes: a pending UPDATE from the seller sits on top of confirmed PRODUCT_ADD, CHANGE_REQUESTED, UPDATE, and STATUS_CHANGE records that form the audit trail." />
|
|
16
13
|
|
|
17
14
|
<Note>
|
|
18
|
-
|
|
19
|
-
and sellers sell against them through offers. Product Edit governs *changes* to
|
|
20
|
-
a product. It never makes a store the owner of one.
|
|
15
|
+
The Product Edit module (`MercurModules.PRODUCT_EDIT`) governs changes to a product. It never makes a store the owner of one. Products live in Medusa’s Product module, and sellers sell them through [offers](/platform/offer/overview).
|
|
21
16
|
</Note>
|
|
22
17
|
|
|
18
|
+
## How it works
|
|
19
|
+
|
|
20
|
+
A seller edit moves through the pipeline in five steps:
|
|
21
|
+
|
|
22
|
+
1. A vendor route runs an edit workflow such as `productEditUpdateProductWorkflow`, which diffs the input against the product and stages a `pending` change with one action per difference.
|
|
23
|
+
2. `autoConfirmProductChangeWorkflow` runs right after staging. With the `product_request` feature flag on, the default, the change stays `pending`.
|
|
24
|
+
3. An operator confirms or declines the change, or the seller cancels it.
|
|
25
|
+
4. On confirm, `applyProductChangeActionsWorkflow` writes the actions to the product through Medusa’s product workflows and marks each action `applied`.
|
|
26
|
+
5. Product creation, publish approvals, rejections, and revision requests are recorded as changes that start out `confirmed`, so the trail is complete without a review.
|
|
27
|
+
|
|
23
28
|
## Key features
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
30
|
+
The module covers the full path of an edit, from diff to audit record:
|
|
31
|
+
|
|
32
|
+
- **Field-level diffs**: the edit workflows stage only the fields, variants, and attributes that differ from the current product
|
|
33
|
+
- **Typed actions**: each change holds `ProductChangeAction` rows such as `UPDATE`, `VARIANT_ADD`, `ATTRIBUTE_UPDATE`, or `PRODUCT_DELETE`
|
|
34
|
+
- **Review queue**: a change moves from `pending` to `confirmed`, `declined`, or `canceled`, each through its own workflow and event
|
|
35
|
+
- **Deferred writes**: actions touch the product only when the change is confirmed
|
|
36
|
+
- **Auto-confirm**: turn off the `product_request` flag, or pass `auto_confirm`, to apply a change in the same run
|
|
37
|
+
- **Revision requests**: an operator sends a proposed product back to its seller with a recorded `CHANGE_REQUESTED` action
|
|
38
|
+
- **One open change per author**: the edit workflows reject a new change while the same author has one pending on the product
|
|
32
39
|
|
|
33
40
|
## Get started
|
|
34
41
|
|
|
35
|
-
Learn how
|
|
42
|
+
Learn how changes, actions, and statuses fit together.
|
|
36
43
|
|
|
37
44
|
<CardGroup cols={2}>
|
|
38
45
|
<Card title="The change pipeline" icon="clock-rotate-left" href="/platform/product-edit/concepts/change-pipeline">
|
|
39
|
-
|
|
46
|
+
How an edit becomes a `ProductChange` and how the audit trail builds up.
|
|
40
47
|
</Card>
|
|
41
48
|
<Card title="Change actions" icon="list-check" href="/platform/product-edit/concepts/change-actions">
|
|
42
|
-
The
|
|
49
|
+
The action types, the `details` each one carries, and how they apply.
|
|
43
50
|
</Card>
|
|
44
51
|
<Card title="Status & auto-confirm" icon="arrows-rotate" href="/platform/product-edit/concepts/status-and-auto-confirm">
|
|
45
|
-
The status lifecycle, revision requests, and
|
|
52
|
+
The status lifecycle, revision requests, and when a change skips review.
|
|
46
53
|
</Card>
|
|
47
54
|
</CardGroup>
|
|
48
55
|
|
|
49
56
|
## Examples
|
|
50
57
|
|
|
51
|
-
Build against the
|
|
58
|
+
Build against the change pipeline in your own server code.
|
|
52
59
|
|
|
53
60
|
<CardGroup cols={2}>
|
|
54
61
|
<Card title="Edit a product" icon="pen" href="/platform/product-edit/guides/edit-a-product">
|
|
55
|
-
Stage
|
|
62
|
+
Stage field, variant, and attribute changes from a custom route.
|
|
56
63
|
</Card>
|
|
57
64
|
<Card title="Confirm or decline" icon="gavel" href="/platform/product-edit/guides/confirm-or-decline-a-change">
|
|
58
|
-
Resolve a pending change
|
|
65
|
+
Resolve a pending change and react to the result.
|
|
59
66
|
</Card>
|
|
60
67
|
<Card title="Request a revision" icon="rotate-left" href="/platform/product-edit/guides/request-a-revision">
|
|
61
|
-
Send a
|
|
68
|
+
Send a proposed product back to its seller with a message.
|
|
62
69
|
</Card>
|
|
63
70
|
</CardGroup>
|
|
64
71
|
|
|
65
72
|
## Resources
|
|
66
73
|
|
|
67
|
-
|
|
74
|
+
The data models, links, workflows, service methods, and events behind product edits.
|
|
68
75
|
|
|
69
76
|
<CardGroup cols={2}>
|
|
70
77
|
<Card title="Data models" icon="table" href="/platform/product-edit/reference/data-models">
|
|
71
|
-
The `ProductChange` and `ProductChangeAction`
|
|
78
|
+
The `ProductChange` and `ProductChangeAction` models and their enums.
|
|
72
79
|
</Card>
|
|
73
80
|
<Card title="Links" icon="link" href="/platform/product-edit/reference/links">
|
|
74
|
-
|
|
81
|
+
The read-only `product.changes` link to Medusa’s Product module.
|
|
75
82
|
</Card>
|
|
76
83
|
<Card title="Workflows" icon="diagram-project" href="/platform/product-edit/reference/workflows">
|
|
77
|
-
|
|
84
|
+
Staging, resolution, apply, edit, and audit workflows with their hooks.
|
|
78
85
|
</Card>
|
|
79
86
|
<Card title="Service" icon="gear" href="/platform/product-edit/reference/service">
|
|
80
|
-
|
|
87
|
+
Generated methods on the Product Edit module service.
|
|
81
88
|
</Card>
|
|
82
89
|
<Card title="Events" icon="bell" href="/platform/product-edit/reference/events">
|
|
83
|
-
|
|
90
|
+
The `product-change.*` events and the revision request event.
|
|
84
91
|
</Card>
|
|
85
92
|
</CardGroup>
|
|
@@ -1,65 +1,91 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Product Edit data models"
|
|
3
3
|
sidebarTitle: "Data models"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Fields, enums, indexes, and relations of the ProductChange and ProductChangeAction models."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Product Edit
|
|
8
|
-
(`MercurModules.PRODUCT_EDIT`). This reference lists its data models and their
|
|
9
|
-
fields.
|
|
7
|
+
The Product Edit module, resolved with `MercurModules.PRODUCT_EDIT` (`"product_edit"`), owns two data models: `ProductChange` and `ProductChangeAction`. Both are defined in `packages/core/src/modules/product-edit/models`. Every model also gets `created_at`, `updated_at`, and `deleted_at` from Medusa.
|
|
10
8
|
|
|
11
9
|
## ProductChange
|
|
12
10
|
|
|
13
|
-
Table `product_change`, id prefix `prodch`.
|
|
14
|
-
product.
|
|
11
|
+
A single reviewable edit to one product. Table `product_change`, id prefix `prodch`.
|
|
15
12
|
|
|
16
|
-
| Field | Type |
|
|
13
|
+
| Field | Type | Description |
|
|
17
14
|
| --- | --- | --- |
|
|
18
|
-
| `id` | text | Primary key |
|
|
19
|
-
| `product_id` | text | The product
|
|
20
|
-
| `status` | enum | `ProductChangeStatus
|
|
21
|
-
| `internal_note` | text |
|
|
22
|
-
| `external_note` | text |
|
|
23
|
-
| `created_by` | text |
|
|
24
|
-
| `confirmed_by`
|
|
25
|
-
| `
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
15
|
+
| `id` | `text` | Primary key, prefixed `prodch` |
|
|
16
|
+
| `product_id` | `text` | The product the change targets |
|
|
17
|
+
| `status` | `enum` | A `ProductChangeStatus` value. Default `pending` |
|
|
18
|
+
| `internal_note` | `text`, nullable | Note for operators |
|
|
19
|
+
| `external_note` | `text`, nullable | Note shown to the seller. Holds the message of a revision request |
|
|
20
|
+
| `created_by` | `text`, nullable | Actor who staged the change: a seller id from vendor routes, a user id from admin routes |
|
|
21
|
+
| `confirmed_by` | `text`, nullable | Actor who confirmed the change |
|
|
22
|
+
| `confirmed_at` | `dateTime`, nullable | When the change was confirmed |
|
|
23
|
+
| `declined_by` | `text`, nullable | Actor who declined the change |
|
|
24
|
+
| `declined_at` | `dateTime`, nullable | When the change was declined |
|
|
25
|
+
| `declined_reason` | `text`, nullable | Reason given on decline |
|
|
26
|
+
| `canceled_by` | `text`, nullable | Actor who canceled the change |
|
|
27
|
+
| `canceled_at` | `dateTime`, nullable | When the change was canceled |
|
|
28
|
+
| `requires_action_by` | `text`, nullable | Reserved. No workflow writes it |
|
|
29
|
+
| `requires_action_at` | `dateTime`, nullable | Reserved. No workflow writes it |
|
|
30
|
+
| `requires_action_reason` | `text`, nullable | Reserved. No workflow writes it |
|
|
31
|
+
| `metadata` | `json`, nullable | Custom key-value data |
|
|
32
|
+
|
|
33
|
+
Relations:
|
|
34
|
+
|
|
35
|
+
- **`actions`**: has many `ProductChangeAction`. The model cascades deletes to its actions
|
|
36
|
+
|
|
37
|
+
Indexes on `status`, on `product_id`, and on `(product_id, status)`, all excluding soft-deleted rows.
|
|
40
38
|
|
|
41
39
|
## ProductChangeAction
|
|
42
40
|
|
|
43
|
-
Table `product_change_action`, id prefix `prodchact`.
|
|
44
|
-
inside a change.
|
|
41
|
+
A single typed operation inside a change. Table `product_change_action`, id prefix `prodchact`.
|
|
45
42
|
|
|
46
|
-
| Field | Type |
|
|
43
|
+
| Field | Type | Description |
|
|
47
44
|
| --- | --- | --- |
|
|
48
|
-
| `id` | text | Primary key |
|
|
49
|
-
| `product_id` | text | The product the action targets
|
|
50
|
-
| `product_change_id` | text |
|
|
51
|
-
| `ordering` | autoincrement |
|
|
52
|
-
| `action` | text | A `ProductChangeActionType` value |
|
|
53
|
-
| `details` | json | Default `{}
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
45
|
+
| `id` | `text` | Primary key, prefixed `prodchact` |
|
|
46
|
+
| `product_id` | `text` | The product the action targets |
|
|
47
|
+
| `product_change_id` | `text`, nullable | The parent change. The foreign key is `ON DELETE SET NULL` |
|
|
48
|
+
| `ordering` | `autoincrement` | Insertion order across all actions |
|
|
49
|
+
| `action` | `text` | A `ProductChangeActionType` value |
|
|
50
|
+
| `details` | `json` | The operation payload. Default `{}` |
|
|
51
|
+
| `reference` | `text`, nullable | Free-form type of a related record. Not set by Mercur |
|
|
52
|
+
| `reference_id` | `text`, nullable | Free-form id of a related record. Not set by Mercur |
|
|
53
|
+
| `internal_note` | `text`, nullable | Note for operators |
|
|
54
|
+
| `applied` | `boolean` | `true` once the action is written to the product. Default `false` |
|
|
55
|
+
|
|
56
|
+
Relations:
|
|
57
|
+
|
|
58
|
+
- **`product_change`**: belongs to `ProductChange`, nullable
|
|
59
|
+
|
|
60
|
+
Indexes on `product_change_id`, `product_id`, `(reference, reference_id)`, and `ordering`, all excluding soft-deleted rows.
|
|
61
|
+
|
|
62
|
+
## ProductChangeStatus
|
|
63
|
+
|
|
64
|
+
The values of `ProductChange.status`, exported from `@mercurjs/types`:
|
|
65
|
+
|
|
66
|
+
| Value | Meaning |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `pending` | Waiting for review |
|
|
69
|
+
| `confirmed` | Approved and applied, or recorded as an audit change |
|
|
70
|
+
| `declined` | Rejected by an operator |
|
|
71
|
+
| `canceled` | Withdrawn before review |
|
|
56
72
|
|
|
57
|
-
##
|
|
73
|
+
## ProductChangeActionType
|
|
58
74
|
|
|
59
|
-
|
|
75
|
+
The values of `ProductChangeAction.action`, exported from `@mercurjs/types`:
|
|
60
76
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
| Value | Applied on confirm |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `UPDATE` | Yes |
|
|
80
|
+
| `STATUS_CHANGE` | Yes |
|
|
81
|
+
| `VARIANT_ADD` | Yes |
|
|
82
|
+
| `VARIANT_UPDATE` | Yes |
|
|
83
|
+
| `VARIANT_REMOVE` | Yes |
|
|
84
|
+
| `ATTRIBUTE_ADD` | Yes |
|
|
85
|
+
| `ATTRIBUTE_UPDATE` | Yes |
|
|
86
|
+
| `ATTRIBUTE_REMOVE` | Yes |
|
|
87
|
+
| `PRODUCT_DELETE` | Yes |
|
|
88
|
+
| `PRODUCT_ADD` | No, audit only |
|
|
89
|
+
| `CHANGE_REQUESTED` | No, audit only |
|
|
64
90
|
|
|
65
|
-
|
|
91
|
+
The `details` shape for each type is listed in [Change actions](/platform/product-edit/concepts/change-actions#action-types). The matching DTOs are `ProductChangeDTO` and `ProductChangeActionDTO`, and the create inputs are `CreateProductChangeDTO` and `CreateProductChangeActionDTO`, all from `@mercurjs/types`.
|
|
@@ -1,22 +1,52 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Product Edit events"
|
|
3
3
|
sidebarTitle: "Events"
|
|
4
|
-
description: "Events emitted
|
|
4
|
+
description: "Events emitted as product changes are staged and resolved, and when an operator requests a revision."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Product change workflows emit events after they commit, so you can run side effects, such as notifying a seller or reindexing search, without polling. The change events are in `ProductChangeWorkflowEvents`, and the revision request event is in `ProductWorkflowEvents`, both exported from `@mercurjs/core/workflows`.
|
|
8
|
+
|
|
9
|
+
## Change events
|
|
10
|
+
|
|
11
|
+
Each change event carries the id of one change. A workflow that handles several changes emits one event per change.
|
|
12
|
+
|
|
13
|
+
| Event | Emitted when | Payload |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `product-change.created` | `stageProductChangeWorkflow` or `createProductChangeWorkflow` creates a change | `{ id }` |
|
|
16
|
+
| `product-change.confirmed` | `confirmProductChangeWorkflow` confirms a change, including auto-confirm | `{ id }` |
|
|
17
|
+
| `product-change.declined` | `rejectProductChangeWorkflow` declines a change | `{ id }` |
|
|
18
|
+
| `product-change.canceled` | `cancelProductChangeWorkflow` cancels a change | `{ id }` |
|
|
19
|
+
|
|
20
|
+
Audit changes from `recordProductAuditChangeWorkflow` emit no change event. An auto-confirmed change emits `product-change.created` and then `product-change.confirmed`.
|
|
21
|
+
|
|
22
|
+
## Revision request event
|
|
23
|
+
|
|
24
|
+
The revision request event comes from `requestProductChangeWorkflow`. Its `id` is the product id, because the request is recorded on the product rather than resolving a change.
|
|
25
|
+
|
|
26
|
+
| Event | Emitted when | Payload |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `product.change-requested` | An operator requests a revision on a `proposed` product | `{ id, message, actor_id }` |
|
|
29
|
+
|
|
30
|
+
## Subscribe to an event
|
|
31
|
+
|
|
32
|
+
This subscriber loads a confirmed change with its actions:
|
|
10
33
|
|
|
11
34
|
```ts title="src/subscribers/product-change-confirmed.ts"
|
|
12
35
|
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
13
36
|
|
|
14
|
-
export default async function
|
|
37
|
+
export default async function handler({
|
|
15
38
|
event,
|
|
16
39
|
container,
|
|
17
40
|
}: SubscriberArgs<{ id: string }>) {
|
|
18
|
-
const
|
|
19
|
-
|
|
41
|
+
const query = container.resolve("query")
|
|
42
|
+
|
|
43
|
+
const { data: [change] } = await query.graph({
|
|
44
|
+
entity: "product_change",
|
|
45
|
+
fields: ["product_id", "created_by", "actions.action"],
|
|
46
|
+
filters: { id: event.data.id },
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// notify change.created_by that change.product_id was updated
|
|
20
50
|
}
|
|
21
51
|
|
|
22
52
|
export const config: SubscriberConfig = {
|
|
@@ -24,24 +54,4 @@ export const config: SubscriberConfig = {
|
|
|
24
54
|
}
|
|
25
55
|
```
|
|
26
56
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| Event | Emitted when | Payload |
|
|
30
|
-
| --- | --- | --- |
|
|
31
|
-
| `product-change.created` | A change is staged | `{ id }` |
|
|
32
|
-
| `product-change.confirmed` | A change is confirmed | `{ id }` |
|
|
33
|
-
| `product-change.declined` | A change is declined | `{ id }` |
|
|
34
|
-
| `product-change.canceled` | A change is canceled | `{ id }` |
|
|
35
|
-
|
|
36
|
-
## Revision events
|
|
37
|
-
|
|
38
|
-
| Event | Emitted when | Payload |
|
|
39
|
-
| --- | --- | --- |
|
|
40
|
-
| `product.change-requested` | An operator requests a revision | `{ id, message, actor_id }` |
|
|
41
|
-
|
|
42
|
-
<Note>
|
|
43
|
-
`product.change-requested` carries the **product** id (not a change id) along
|
|
44
|
-
with the operator's `message` and `actor_id`, because a revision request is
|
|
45
|
-
recorded against the product's audit trail rather than resolving a pending
|
|
46
|
-
change.
|
|
47
|
-
</Note>
|
|
57
|
+
`created_by` tells you who to notify: a seller id for edits from the Vendor panel. To react to declines with the reason, read `declined_reason` the same way from a `product-change.declined` subscriber.
|
|
@@ -1,39 +1,47 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Product Edit links"
|
|
3
3
|
sidebarTitle: "Links"
|
|
4
|
-
description: "
|
|
4
|
+
description: "The read-only link that exposes a product's change history as product.changes."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
**module links**. Once a link is defined, you retrieve related records with
|
|
9
|
-
`query.graph` using the link alias.
|
|
7
|
+
Mercur modules never import each other. They connect through module links, which you read with `query.graph`. The Product Edit module has one link, to Medusa’s Product module.
|
|
10
8
|
|
|
11
|
-
## Product
|
|
9
|
+
## Product to product changes
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
history hangs off the product itself.
|
|
11
|
+
A read-only link that lists a product’s changes under the `changes` alias. It’s defined in `packages/core/src/links/product-change-link.ts`.
|
|
15
12
|
|
|
16
|
-
|
|
|
17
|
-
| --- | --- |
|
|
18
|
-
|
|
|
13
|
+
| Side | Module | Linkable | Key |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| Source | Product (`Modules.PRODUCT`) | `product` | `id` |
|
|
16
|
+
| Target | Product Edit (`MercurModules.PRODUCT_EDIT`) | `product_change` | `product_id` |
|
|
17
|
+
|
|
18
|
+
- **Cardinality**: one product to many changes
|
|
19
|
+
- **Alias**: `changes`, read as `product.changes`
|
|
20
|
+
- **Storage**: no pivot table. The link reads the `product_id` column on `product_change`
|
|
21
|
+
- **Writes**: none. The link is `readOnly`, so you create changes with the [workflows](/platform/product-edit/reference/workflows), never through the link
|
|
22
|
+
|
|
23
|
+
Read a product’s history with its actions:
|
|
19
24
|
|
|
20
25
|
```ts
|
|
21
|
-
const
|
|
26
|
+
const query = container.resolve("query")
|
|
27
|
+
|
|
28
|
+
const { data: [product] } = await query.graph({
|
|
22
29
|
entity: "product",
|
|
23
|
-
fields: [
|
|
30
|
+
fields: [
|
|
31
|
+
"id",
|
|
32
|
+
"title",
|
|
33
|
+
"changes.id",
|
|
34
|
+
"changes.status",
|
|
35
|
+
"changes.created_by",
|
|
36
|
+
"changes.actions.action",
|
|
37
|
+
"changes.actions.details",
|
|
38
|
+
],
|
|
39
|
+
filters: { id: "prod_01JD8Q1234567" },
|
|
24
40
|
})
|
|
25
41
|
```
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
The link is **read-only** and has no pivot table. The FK lives directly on the
|
|
29
|
-
`product_change` row. It exists so you read the audit trail through
|
|
30
|
-
`product.changes`. You can't write a change through the link itself. Stage
|
|
31
|
-
changes with the [workflows](/platform/product-edit/reference/workflows).
|
|
32
|
-
</Note>
|
|
43
|
+
`product.changes` returns every change on the product, including audit changes and resolved ones. To filter by status, query the `product_change` entity with a `product_id` filter instead, because `query.graph` can’t filter on linked records.
|
|
33
44
|
|
|
34
|
-
## Actor
|
|
45
|
+
## Actor fields
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
actor ids (the dashboard user who staged or resolved the change). They are plain
|
|
38
|
-
text references for the audit trail, not module links, so they aren't resolved
|
|
39
|
-
through `query.graph`.
|
|
47
|
+
`created_by`, `confirmed_by`, `declined_by`, and `canceled_by` hold actor ids as plain text: a seller id when the change came from a vendor route, a user id when it came from an admin route. They aren’t module links, so `query.graph` can’t expand them. Resolve the seller or user yourself when you need their details.
|
|
@@ -1,43 +1,62 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Product Edit module service"
|
|
3
3
|
sidebarTitle: "Service"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Resolve the Product Edit module service and call its generated methods for changes and actions."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Product Edit module
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
The Product Edit module service, `ProductChangeModuleService`, reads and writes `ProductChange` and `ProductChangeAction` records directly. It’s a plain `MedusaService` with generated methods only, and no custom methods. Use it in subscribers, scheduled jobs, and workflow steps.
|
|
8
|
+
|
|
9
|
+
## Resolve the service
|
|
10
|
+
|
|
11
|
+
Resolve the service from the Medusa container with `MercurModules.PRODUCT_EDIT`:
|
|
10
12
|
|
|
11
13
|
```ts
|
|
12
14
|
import { MercurModules } from "@mercurjs/types"
|
|
13
15
|
|
|
14
|
-
const
|
|
16
|
+
const productEdit = container.resolve(MercurModules.PRODUCT_EDIT)
|
|
15
17
|
|
|
16
|
-
const [changes, count] = await
|
|
17
|
-
status: "pending",
|
|
18
|
-
}
|
|
18
|
+
const [changes, count] = await productEdit.listAndCountProductChanges(
|
|
19
|
+
{ product_id: "prod_01JD8Q1234567", status: "pending" },
|
|
20
|
+
{ relations: ["actions"], take: 20 }
|
|
21
|
+
)
|
|
19
22
|
```
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
This returns the first 20 pending changes on a product, with their actions, and the total count. For a typed handle, import the class with `import type { ProductChangeModuleService } from "@mercurjs/core/modules/product-edit"` and pass it as the `resolve` generic.
|
|
25
|
+
|
|
26
|
+
## ProductChange methods
|
|
27
|
+
|
|
28
|
+
Medusa generates these methods for the `ProductChange` model:
|
|
29
|
+
|
|
30
|
+
| Method | Signature | Description |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `retrieveProductChange` | `(id, config?)` | Retrieve one change. Throws if it doesn’t exist |
|
|
33
|
+
| `listProductChanges` | `(filters?, config?)` | List changes matching the filters |
|
|
34
|
+
| `listAndCountProductChanges` | `(filters?, config?)` | List changes and return `[changes, count]` |
|
|
35
|
+
| `createProductChanges` | `(data)` | Create one change or an array of them |
|
|
36
|
+
| `updateProductChanges` | `(data)` | Update by `id`, or pass `{ selector, data }` |
|
|
37
|
+
| `deleteProductChanges` | `(ids)` | Delete changes. The model cascades deletes to their actions |
|
|
38
|
+
| `softDeleteProductChanges` | `(ids, config?)` | Soft-delete changes |
|
|
39
|
+
| `restoreProductChanges` | `(ids, config?)` | Restore soft-deleted changes |
|
|
40
|
+
|
|
41
|
+
## ProductChangeAction methods
|
|
42
|
+
|
|
43
|
+
The same set exists for `ProductChangeAction`:
|
|
22
44
|
|
|
23
|
-
|
|
24
|
-
|
|
45
|
+
| Method | Signature | Description |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `retrieveProductChangeAction` | `(id, config?)` | Retrieve one action |
|
|
48
|
+
| `listProductChangeActions` | `(filters?, config?)` | List actions matching the filters |
|
|
49
|
+
| `listAndCountProductChangeActions` | `(filters?, config?)` | List actions and return `[actions, count]` |
|
|
50
|
+
| `createProductChangeActions` | `(data)` | Create one action or an array of them |
|
|
51
|
+
| `updateProductChangeActions` | `(data)` | Update by `id`, or pass `{ selector, data }` |
|
|
52
|
+
| `deleteProductChangeActions` | `(ids)` | Delete actions |
|
|
53
|
+
| `softDeleteProductChangeActions` | `(ids, config?)` | Soft-delete actions |
|
|
54
|
+
| `restoreProductChangeActions` | `(ids, config?)` | Restore soft-deleted actions |
|
|
25
55
|
|
|
26
|
-
|
|
27
|
-
| --- | --- |
|
|
28
|
-
| `createProductChanges(data)` | Create one or more changes |
|
|
29
|
-
| `retrieveProductChange(id, config?)` | Retrieve a change by id |
|
|
30
|
-
| `listProductChanges(filters?, config?)` | List changes matching filters |
|
|
31
|
-
| `listAndCountProductChanges(filters?, config?)` | List changes with a total count |
|
|
32
|
-
| `updateProductChanges(data)` | Update one or more changes |
|
|
33
|
-
| `deleteProductChanges(ids)` | Delete one or more changes |
|
|
56
|
+
## When to use a workflow instead
|
|
34
57
|
|
|
35
|
-
The
|
|
36
|
-
`listProductChangeActions`, `updateProductChangeActions`, and so on.
|
|
58
|
+
The service writes rows and nothing else. Setting `status` to `confirmed` through `updateProductChanges` doesn’t apply the actions, stamp `confirmed_at`, emit `product-change.confirmed`, or run the hooks.
|
|
37
59
|
|
|
38
60
|
<Warning>
|
|
39
|
-
|
|
40
|
-
side effects (confirming, declining, applying actions). The service writes
|
|
41
|
-
records directly and does **not** apply actions to the product, emit events, or
|
|
42
|
-
run compensation.
|
|
61
|
+
Use the [workflows](/platform/product-edit/reference/workflows) for any status change. Keep the service for reads and for fields with no side effects, such as `metadata`.
|
|
43
62
|
</Warning>
|