@mercurjs/docs 2.2.1 → 2.3.0-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/home.mdx +107 -0
- package/content/learn/architecture.mdx +168 -83
- package/content/learn/introduction.mdx +161 -56
- package/content/learn/migration-to-2-0.mdx +187 -0
- package/content/learn/why-mercur.mdx +91 -0
- package/content/platform/attribute/concepts/attribute-types.mdx +59 -0
- package/content/platform/attribute/concepts/global-vs-inline.mdx +50 -0
- package/content/platform/attribute/concepts/variant-axes.mdx +61 -0
- package/content/platform/attribute/guides/attach-attributes-to-a-product.mdx +69 -0
- package/content/platform/attribute/guides/create-a-variant-axis.mdx +83 -0
- package/content/platform/attribute/guides/create-an-attribute.mdx +81 -0
- package/content/platform/attribute/overview.mdx +87 -0
- package/content/platform/attribute/reference/data-models.mdx +56 -0
- package/content/platform/attribute/reference/events.mdx +41 -0
- package/content/platform/attribute/reference/links.mdx +45 -0
- package/content/platform/attribute/reference/service.mdx +49 -0
- package/content/platform/attribute/reference/workflows.mdx +45 -0
- package/content/platform/catalog/concepts/master-products.mdx +54 -0
- package/content/platform/catalog/concepts/product-seller-allowlist.mdx +48 -0
- package/content/platform/catalog/concepts/status-lifecycle.mdx +58 -0
- package/content/platform/catalog/concepts/variants-categories-collections.mdx +49 -0
- package/content/platform/catalog/guides/allowlist-stores.mdx +59 -0
- package/content/platform/catalog/guides/create-a-master-product.mdx +70 -0
- package/content/platform/catalog/guides/publish-or-reject-a-product.mdx +79 -0
- package/content/platform/catalog/overview.mdx +90 -0
- package/content/platform/catalog/reference/data-models.mdx +66 -0
- package/content/platform/catalog/reference/events.mdx +41 -0
- package/content/platform/catalog/reference/links.mdx +44 -0
- package/content/platform/catalog/reference/service.mdx +52 -0
- package/content/platform/catalog/reference/workflows.mdx +40 -0
- package/content/platform/commission/concepts/order-commission-lines.mdx +65 -0
- package/content/platform/commission/concepts/rule-matching.mdx +86 -0
- package/content/platform/commission/concepts/rules-and-rates.mdx +84 -0
- package/content/platform/commission/guides/batch-update-rules.mdx +58 -0
- package/content/platform/commission/guides/create-a-rate.mdx +72 -0
- package/content/platform/commission/guides/refresh-order-commission-lines.mdx +55 -0
- package/content/platform/commission/overview.mdx +86 -0
- package/content/platform/commission/reference/data-models.mdx +75 -0
- package/content/platform/commission/reference/events.mdx +58 -0
- package/content/platform/commission/reference/links.mdx +45 -0
- package/content/platform/commission/reference/service.mdx +51 -0
- package/content/platform/commission/reference/workflows.mdx +40 -0
- package/content/platform/offer/concepts/pricing-and-inventory.mdx +72 -0
- package/content/platform/offer/concepts/shipping.mdx +48 -0
- package/content/platform/offer/concepts/what-is-an-offer.mdx +65 -0
- package/content/platform/offer/guides/bulk-create-offers.mdx +84 -0
- package/content/platform/offer/guides/create-an-offer.mdx +83 -0
- package/content/platform/offer/guides/manage-offer-inventory.mdx +53 -0
- package/content/platform/offer/overview.mdx +84 -0
- package/content/platform/offer/reference/data-models.mdx +56 -0
- package/content/platform/offer/reference/events.mdx +39 -0
- package/content/platform/offer/reference/links.mdx +60 -0
- package/content/platform/offer/reference/service.mdx +53 -0
- package/content/platform/offer/reference/workflows.mdx +38 -0
- package/content/platform/order-group/concepts/computed-totals.mdx +59 -0
- package/content/platform/order-group/concepts/order-splitting.mdx +61 -0
- package/content/platform/order-group/concepts/the-order-group.mdx +64 -0
- package/content/platform/order-group/guides/list-order-groups.mdx +67 -0
- package/content/platform/order-group/guides/retrieve-an-order-group.mdx +63 -0
- package/content/platform/order-group/guides/split-a-cart.mdx +58 -0
- package/content/platform/order-group/overview.mdx +83 -0
- package/content/platform/order-group/reference/data-models.mdx +40 -0
- package/content/platform/order-group/reference/events.mdx +37 -0
- package/content/platform/order-group/reference/links.mdx +45 -0
- package/content/platform/order-group/reference/service.mdx +50 -0
- package/content/platform/order-group/reference/workflows.mdx +39 -0
- package/content/platform/payout/concepts/account-lifecycle.mdx +75 -0
- package/content/platform/payout/concepts/accounts-and-onboarding.mdx +70 -0
- package/content/platform/payout/concepts/payout-pipeline.mdx +99 -0
- package/content/platform/payout/guides/create-a-payout-account.mdx +59 -0
- package/content/platform/payout/guides/process-a-provider-webhook.mdx +74 -0
- package/content/platform/payout/guides/start-provider-onboarding.mdx +50 -0
- package/content/platform/payout/overview.mdx +86 -0
- package/content/platform/payout/reference/data-models.mdx +61 -0
- package/content/platform/payout/reference/events.mdx +48 -0
- package/content/platform/payout/reference/links.mdx +36 -0
- package/content/platform/payout/reference/service.mdx +53 -0
- package/content/platform/payout/reference/workflows.mdx +32 -0
- package/content/platform/product-edit/concepts/change-actions.mdx +66 -0
- package/content/platform/product-edit/concepts/change-pipeline.mdx +69 -0
- package/content/platform/product-edit/concepts/status-and-auto-confirm.mdx +66 -0
- package/content/platform/product-edit/guides/confirm-or-decline-a-change.mdx +76 -0
- package/content/platform/product-edit/guides/edit-a-product.mdx +74 -0
- package/content/platform/product-edit/guides/request-a-revision.mdx +54 -0
- package/content/platform/product-edit/overview.mdx +85 -0
- package/content/platform/product-edit/reference/data-models.mdx +65 -0
- package/content/platform/product-edit/reference/events.mdx +47 -0
- package/content/platform/product-edit/reference/links.mdx +39 -0
- package/content/platform/product-edit/reference/service.mdx +43 -0
- package/content/platform/product-edit/reference/workflows.mdx +49 -0
- package/content/platform/review/concepts/product-vs-seller-reviews.mdx +63 -0
- package/content/platform/review/concepts/ratings-and-moderation.mdx +64 -0
- package/content/platform/review/concepts/the-review-model.mdx +56 -0
- package/content/platform/review/guides/compute-aggregate-ratings.mdx +57 -0
- package/content/platform/review/guides/create-a-review.mdx +55 -0
- package/content/platform/review/guides/moderate-a-review.mdx +58 -0
- package/content/platform/review/guides/respond-to-a-review.mdx +61 -0
- package/content/platform/review/overview.mdx +87 -0
- package/content/platform/review/reference/data-models.mdx +36 -0
- package/content/platform/review/reference/events.mdx +61 -0
- package/content/platform/review/reference/links.mdx +43 -0
- package/content/platform/review/reference/service.mdx +54 -0
- package/content/platform/review/reference/workflows.mdx +31 -0
- package/content/platform/store/concepts/lifecycle.mdx +62 -0
- package/content/platform/store/concepts/store-entity.mdx +53 -0
- package/content/platform/store/concepts/team.mdx +50 -0
- package/content/platform/store/guides/create-a-store.mdx +55 -0
- package/content/platform/store/guides/manage-the-team.mdx +55 -0
- package/content/platform/store/guides/moderate-a-store.mdx +59 -0
- package/content/platform/store/overview.mdx +86 -0
- package/content/platform/store/reference/data-models.mdx +89 -0
- package/content/platform/store/reference/events.mdx +43 -0
- package/content/platform/store/reference/links.mdx +71 -0
- package/content/platform/store/reference/service.mdx +51 -0
- package/content/platform/store/reference/workflows.mdx +35 -0
- package/content/references/api/admin/commission-rates/create-commission-rate.mdx +1 -1
- package/content/references/api/admin/commission-rates/list-commission-rates.mdx +2 -2
- package/content/references/api/admin/commission-rates/update-commission-rate.mdx +1 -1
- package/content/references/api/admin/offers/batch-create-offers.mdx +3 -3
- package/content/references/api/admin/order-groups/list-order-groups.mdx +1 -1
- package/content/references/api/admin/product-attributes/create-attribute-value.mdx +2 -2
- package/content/references/api/admin/product-attributes/create-product-attribute.mdx +1 -1
- package/content/references/api/admin/product-attributes/update-product-attribute.mdx +1 -1
- package/content/references/api/admin/product-changes/confirm-product-change.mdx +1 -1
- package/content/references/api/admin/products/batch-product-attributes.mdx +1 -1
- package/content/references/api/admin/products/create-product.mdx +1 -1
- package/content/references/api/admin/products/preview-product.mdx +1 -1
- package/content/references/api/admin.mdx +4 -5
- package/content/references/api/conventions.mdx +9 -7
- package/content/references/api/store/carts/add-line-item.mdx +1 -1
- package/content/references/api/store/offers/list-offers.mdx +1 -1
- package/content/references/api/store/order-groups/list-order-groups.mdx +1 -1
- package/content/references/api/store.mdx +4 -13
- package/content/references/api/vendor/members/accept-member-invite.mdx +1 -1
- package/content/references/api/vendor/offers/batch-create-offers.mdx +4 -0
- package/content/references/api/vendor/offers/batch-offer-inventory-items.mdx +2 -0
- package/content/references/api/vendor/offers/create-offer.mdx +13 -1
- package/content/references/api/vendor/offers/list-offers.mdx +4 -0
- package/content/references/api/vendor/offers/retrieve-offer.mdx +4 -0
- package/content/references/api/vendor/offers/update-offer.mdx +12 -0
- package/content/references/api/vendor/payout-accounts/create-onboarding.mdx +1 -1
- package/content/references/api/vendor/products/batch-product-attributes.mdx +1 -1
- package/content/references/api/vendor/products/create-product-variant.mdx +1 -1
- package/content/references/api/vendor/products/create-product.mdx +1 -1
- package/content/references/api/vendor/products/delete-product.mdx +1 -1
- package/content/references/api/vendor/products/update-product.mdx +1 -1
- package/content/references/api/vendor/sellers/create-seller.mdx +2 -2
- package/content/references/api/vendor/sellers/list-sellers.mdx +1 -1
- package/content/references/api/vendor.mdx +6 -5
- package/content/references/configuration.mdx +16 -33
- package/content/references/overview.mdx +34 -52
- package/content/references/panel-extensions/create-page.mdx +194 -0
- package/content/references/panel-extensions/custom-fields.mdx +256 -0
- package/content/references/panel-extensions/overview.mdx +102 -0
- package/content/references/panel-extensions/widgets.mdx +212 -0
- package/content/resources/ai/mcp.mdx +2 -2
- package/content/resources/ai/overview.mdx +21 -16
- package/content/resources/ai/skills.mdx +67 -0
- package/content/resources/best-practices/api-routes.mdx +55 -43
- package/content/resources/best-practices/custom-fields.mdx +116 -92
- package/content/resources/best-practices/frontend.mdx +62 -50
- package/content/resources/best-practices/module-links.mdx +48 -34
- package/content/resources/best-practices/modules.mdx +53 -27
- package/content/resources/best-practices/overview.mdx +45 -17
- package/content/resources/best-practices/subscribers-and-jobs.mdx +37 -24
- package/content/resources/best-practices/types.mdx +38 -23
- package/content/resources/best-practices/workflows.mdx +33 -21
- package/content/resources/customization/custom-fields.mdx +15 -15
- package/content/resources/customization/extend-a-workflow.mdx +7 -4
- package/content/resources/customization/extending-panels.mdx +55 -52
- package/content/resources/deployment/medusa-cloud.mdx +21 -20
- package/content/resources/deployment/self-host.mdx +123 -0
- package/content/resources/integrations/overview.mdx +38 -0
- package/content/resources/integrations/stripe-connect.mdx +39 -38
- package/content/resources/tutorials/add-a-block.mdx +25 -18
- package/content/resources/tutorials/add-a-widget.mdx +32 -23
- package/content/resources/tutorials/add-order-detail-button.mdx +33 -20
- package/content/resources/tutorials/attributes-and-variant-axes.mdx +28 -27
- package/content/resources/tutorials/build-a-block.mdx +26 -15
- package/content/resources/tutorials/custom-api-route.mdx +32 -20
- package/content/resources/tutorials/custom-panel-page.mdx +21 -12
- package/content/resources/tutorials/customize-navigation.mdx +30 -23
- package/content/resources/tutorials/extend-forms-and-tables.mdx +36 -28
- package/content/resources/tutorials/extend-onboarding.mdx +38 -35
- package/content/resources/tutorials/master-products-and-offers.mdx +28 -23
- package/content/telemetry.mdx +3 -3
- package/content/user-guide/admin/attributes/how-tos/create-an-attribute.mdx +64 -0
- package/content/user-guide/admin/attributes/how-tos/manage-possible-values.mdx +40 -0
- package/content/user-guide/admin/attributes/overview.mdx +22 -0
- package/content/user-guide/admin/commissions/how-tos/create-a-commission-rule.mdx +63 -0
- package/content/user-guide/admin/commissions/how-tos/edit-the-global-commission.mdx +48 -0
- package/content/user-guide/admin/commissions/how-tos/manage-a-commission-rule.mdx +45 -0
- package/content/user-guide/admin/commissions/overview.mdx +25 -0
- package/content/user-guide/admin/overview.mdx +20 -12
- package/content/user-guide/admin/product-requests/how-tos/review-a-new-product.mdx +58 -0
- package/content/user-guide/admin/product-requests/how-tos/review-a-product-edit.mdx +48 -0
- package/content/user-guide/admin/product-requests/overview.mdx +25 -0
- package/content/user-guide/vendor/offers/how-tos/create-an-offer.mdx +59 -0
- package/content/user-guide/vendor/offers/how-tos/update-prices-and-stock.mdx +40 -0
- package/content/user-guide/vendor/offers/overview.mdx +22 -0
- package/content/user-guide/vendor/onboarding.mdx +79 -0
- package/content/user-guide/vendor/orders/how-tos/fulfill-an-order.mdx +49 -0
- package/content/user-guide/vendor/orders/how-tos/mark-an-order-as-delivered.mdx +33 -0
- package/content/user-guide/vendor/orders/how-tos/process-a-return.mdx +42 -0
- package/content/user-guide/vendor/orders/how-tos/refund-an-order.mdx +38 -0
- package/content/user-guide/vendor/orders/how-tos/ship-an-order.mdx +40 -0
- package/content/user-guide/vendor/orders/overview.mdx +31 -0
- package/content/user-guide/vendor/overview.mdx +23 -12
- package/content/user-guide/vendor/products/how-tos/edit-a-product.mdx +44 -0
- package/content/user-guide/vendor/products/how-tos/submit-a-product.mdx +63 -0
- package/content/user-guide/vendor/products/overview.mdx +22 -0
- package/llms.txt +176 -142
- package/package.json +1 -1
- package/content/learn/concepts.mdx +0 -84
- package/content/learn/installation.mdx +0 -117
- package/content/learn/mirakl-alternative.mdx +0 -86
- package/content/migration/from-1-x-to-2-0.mdx +0 -152
- package/content/migration/from-2-0-to-2-1.mdx +0 -105
- package/content/migration/overview.mdx +0 -58
- package/content/references/api/store/search/search.mdx +0 -136
- package/content/references/modules/commission.mdx +0 -106
- package/content/references/modules/custom-fields.mdx +0 -45
- package/content/references/modules/media.mdx +0 -55
- package/content/references/modules/offer.mdx +0 -64
- package/content/references/modules/payout.mdx +0 -121
- package/content/references/modules/product-attribute.mdx +0 -111
- package/content/references/modules/product-edit.mdx +0 -80
- package/content/references/modules/search.mdx +0 -112
- package/content/references/modules/seller.mdx +0 -175
- package/content/references/panel-extension-api.mdx +0 -337
- package/content/references/workflows/cart/add-seller-shipping-method-to-cart.mdx +0 -48
- package/content/references/workflows/cart/complete-cart-with-split-orders.mdx +0 -36
- package/content/references/workflows/cart/list-seller-shipping-options-for-cart.mdx +0 -39
- package/content/references/workflows/cart/update-cart-seller-promotions.mdx +0 -42
- package/content/references/workflows/commission/batch-commission-rules.mdx +0 -49
- package/content/references/workflows/commission/create-commission-rates.mdx +0 -41
- package/content/references/workflows/commission/delete-commission-rates.mdx +0 -34
- package/content/references/workflows/commission/refresh-order-commission-lines.mdx +0 -30
- package/content/references/workflows/commission/update-commission-rates.mdx +0 -35
- package/content/references/workflows/media/set-category-images.mdx +0 -41
- package/content/references/workflows/media/set-collection-images.mdx +0 -41
- package/content/references/workflows/member/accept-member-invite.mdx +0 -33
- package/content/references/workflows/member/add-seller-member.mdx +0 -30
- package/content/references/workflows/member/create-member-invites.mdx +0 -34
- package/content/references/workflows/member/delete-member-invite.mdx +0 -24
- package/content/references/workflows/member/remove-seller-member.mdx +0 -28
- package/content/references/workflows/member/resend-member-invite.mdx +0 -28
- package/content/references/workflows/member/update-member-role.mdx +0 -28
- package/content/references/workflows/member/update-member.mdx +0 -35
- package/content/references/workflows/offer/batch-offer-inventory-items.mdx +0 -62
- package/content/references/workflows/offer/create-offers.mdx +0 -65
- package/content/references/workflows/offer/delete-offers.mdx +0 -35
- package/content/references/workflows/offer/update-offers.mdx +0 -53
- package/content/references/workflows/order/cancel-order-fulfillment.mdx +0 -34
- package/content/references/workflows/order/confirm-claim-request.mdx +0 -25
- package/content/references/workflows/order/confirm-exchange-request.mdx +0 -25
- package/content/references/workflows/order/confirm-order-edit-request.mdx +0 -25
- package/content/references/workflows/order/confirm-return-receive.mdx +0 -25
- package/content/references/workflows/order/create-order-fulfillment.mdx +0 -45
- package/content/references/workflows/order-group/get-order-group-detail.mdx +0 -29
- package/content/references/workflows/order-group/get-order-groups-list.mdx +0 -38
- package/content/references/workflows/overview.mdx +0 -72
- package/content/references/workflows/payout/create-onboarding.mdx +0 -36
- package/content/references/workflows/payout/create-payout-account.mdx +0 -33
- package/content/references/workflows/payout/create-payout.mdx +0 -30
- package/content/references/workflows/payout/process-payout-for-webhook.mdx +0 -34
- package/content/references/workflows/product/confirm-products.mdx +0 -48
- package/content/references/workflows/product/create-products.mdx +0 -63
- package/content/references/workflows/product/link-sellers-to-product-category.mdx +0 -40
- package/content/references/workflows/product/link-sellers-to-product.mdx +0 -40
- package/content/references/workflows/product/reject-product.mdx +0 -48
- package/content/references/workflows/product/request-product-change.mdx +0 -48
- package/content/references/workflows/product-attribute/add-product-attributes-to-product.mdx +0 -49
- package/content/references/workflows/product-attribute/create-and-link-product-attributes-to-product.mdx +0 -46
- package/content/references/workflows/product-attribute/create-product-attribute-values.mdx +0 -43
- package/content/references/workflows/product-attribute/create-product-attributes.mdx +0 -56
- package/content/references/workflows/product-attribute/delete-product-attribute-values.mdx +0 -30
- package/content/references/workflows/product-attribute/delete-product-attributes.mdx +0 -30
- package/content/references/workflows/product-attribute/remove-product-attributes-from-product.mdx +0 -29
- package/content/references/workflows/product-attribute/update-product-attribute-values.mdx +0 -44
- package/content/references/workflows/product-attribute/update-product-attributes-on-product.mdx +0 -41
- package/content/references/workflows/product-attribute/update-product-attributes.mdx +0 -48
- package/content/references/workflows/product-attribute/upsert-product-attribute-values.mdx +0 -43
- package/content/references/workflows/product-edit/auto-confirm-product-change.mdx +0 -39
- package/content/references/workflows/product-edit/cancel-product-change.mdx +0 -49
- package/content/references/workflows/product-edit/confirm-product-change.mdx +0 -57
- package/content/references/workflows/product-edit/create-product-change.mdx +0 -72
- package/content/references/workflows/product-edit/reject-product-change.mdx +0 -54
- package/content/references/workflows/product-edit/stage-product-change.mdx +0 -75
- package/content/references/workflows/seller/approve-seller.mdx +0 -36
- package/content/references/workflows/seller/create-seller-account.mdx +0 -59
- package/content/references/workflows/seller/create-seller-defaults.mdx +0 -22
- package/content/references/workflows/seller/create-sellers.mdx +0 -65
- package/content/references/workflows/seller/delete-seller-professional-details.mdx +0 -37
- package/content/references/workflows/seller/delete-sellers.mdx +0 -24
- package/content/references/workflows/seller/invite-seller.mdx +0 -28
- package/content/references/workflows/seller/suspend-seller.mdx +0 -37
- package/content/references/workflows/seller/terminate-seller.mdx +0 -37
- package/content/references/workflows/seller/unsuspend-seller.mdx +0 -36
- package/content/references/workflows/seller/unterminate-seller.mdx +0 -36
- package/content/references/workflows/seller/update-seller-address.mdx +0 -55
- package/content/references/workflows/seller/update-seller-payment-details.mdx +0 -52
- package/content/references/workflows/seller/update-seller-professional-details.mdx +0 -48
- package/content/references/workflows/seller/update-sellers.mdx +0 -57
- package/content/resources/ai/llms.mdx +0 -74
- package/content/resources/integrations/notifications.mdx +0 -39
- package/content/resources/integrations/search.mdx +0 -122
- package/content/resources/tutorials/configure-commissions.mdx +0 -127
- package/content/resources/tutorials/first-marketplace.mdx +0 -45
- package/content/resources/tutorials/handle-product-requests.mdx +0 -80
- package/content/resources/tutorials/import-export-products.mdx +0 -96
- package/content/resources/tutorials/seller-payouts-stripe.mdx +0 -89
- package/content/resources/tutorials/store-setup-checklist.mdx +0 -214
- package/content/tools/api-client.mdx +0 -155
- package/content/tools/cli.mdx +0 -196
- package/content/tools/dashboard-sdk.mdx +0 -35
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Edit a product"
|
|
3
|
+
sidebarTitle: "Edit a product"
|
|
4
|
+
description: "Stage a product change from server code with the edit workflows."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how to route a product edit through the change
|
|
8
|
+
pipeline from your own server code, such as a custom API route or a bulk tool.
|
|
9
|
+
|
|
10
|
+
Instead of writing to a product directly, you stage a `ProductChange`. Mercur
|
|
11
|
+
exposes high-level edit workflows that diff your update against the current
|
|
12
|
+
product and stage only the fields that actually changed.
|
|
13
|
+
|
|
14
|
+
## Update product fields
|
|
15
|
+
|
|
16
|
+
`productEditUpdateProductWorkflow` diffs the `update` payload against the product
|
|
17
|
+
and stages an `UPDATE` action per changed field.
|
|
18
|
+
|
|
19
|
+
```ts title="src/api/custom/edit/route.ts"
|
|
20
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
21
|
+
import { productEditUpdateProductWorkflow } from "@mercurjs/core/workflows"
|
|
22
|
+
|
|
23
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
24
|
+
const { result } = await productEditUpdateProductWorkflow(req.scope).run({
|
|
25
|
+
input: {
|
|
26
|
+
product_id: req.params.id,
|
|
27
|
+
created_by: req.auth_context?.actor_id,
|
|
28
|
+
update: { title: "Updated title", material: "Cotton" },
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
res.status(201).json({ product_change: result })
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
<Note>
|
|
37
|
+
If a product already has a `pending` change, staging another one is rejected.
|
|
38
|
+
Only one active change per product is allowed. Resolve or cancel the open
|
|
39
|
+
change first.
|
|
40
|
+
</Note>
|
|
41
|
+
|
|
42
|
+
## Stage actions directly
|
|
43
|
+
|
|
44
|
+
For finer control (variants, attributes, mixed operations), stage the actions
|
|
45
|
+
yourself with `stageProductChangeWorkflow`:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { stageProductChangeWorkflow } from "@mercurjs/core/workflows"
|
|
49
|
+
|
|
50
|
+
await stageProductChangeWorkflow(container).run({
|
|
51
|
+
input: {
|
|
52
|
+
product_id: "prod_123",
|
|
53
|
+
created_by: "user_123",
|
|
54
|
+
actions: [
|
|
55
|
+
{ product_id: "prod_123", action: "UPDATE", details: { field: "subtitle", value: "New" } },
|
|
56
|
+
{ product_id: "prod_123", action: "VARIANT_REMOVE", details: { variant_id: "variant_123" } },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Auto-confirm
|
|
63
|
+
|
|
64
|
+
Both workflows run auto-confirm after staging: with review off the change
|
|
65
|
+
applies immediately, with review on it stays `pending`. Pass `auto_confirm: true`
|
|
66
|
+
to `stageProductChangeWorkflow` to force immediate application regardless of the
|
|
67
|
+
review setting.
|
|
68
|
+
|
|
69
|
+
<Tip>
|
|
70
|
+
Dedicated helpers exist for common shapes, such as
|
|
71
|
+
`productEditUpdateVariantsWorkflow`, `productEditUpdateAttributesWorkflow`, and
|
|
72
|
+
`productEditDeleteProductWorkflow`. Each stages the right action types for you.
|
|
73
|
+
See the [Workflows reference](/platform/product-edit/reference/workflows).
|
|
74
|
+
</Tip>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Request a revision"
|
|
3
|
+
sidebarTitle: "Request a revision"
|
|
4
|
+
description: "Send a product submission back to the vendor from server code."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how to ask a vendor to rework a submission instead of
|
|
8
|
+
approving or rejecting it outright.
|
|
9
|
+
|
|
10
|
+
A revision request doesn't mutate the product. It records a `CHANGE_REQUESTED`
|
|
11
|
+
action in the audit trail carrying your message, and emits
|
|
12
|
+
`product.change-requested` so the vendor is notified. The product stays with the
|
|
13
|
+
vendor to revise and resubmit.
|
|
14
|
+
|
|
15
|
+
## Run the workflow
|
|
16
|
+
|
|
17
|
+
`requestProductChangeWorkflow` validates that the product is in `proposed`,
|
|
18
|
+
records the audit action, and emits the event.
|
|
19
|
+
|
|
20
|
+
```ts title="src/api/custom/request-revision/route.ts"
|
|
21
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
22
|
+
import { requestProductChangeWorkflow } from "@mercurjs/core/workflows"
|
|
23
|
+
|
|
24
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
25
|
+
await requestProductChangeWorkflow(req.scope).run({
|
|
26
|
+
input: {
|
|
27
|
+
product_id: req.params.id,
|
|
28
|
+
actor_id: req.auth_context?.actor_id,
|
|
29
|
+
message: "Please add a size guide and sharper photos.",
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
res.sendStatus(200)
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
<Note>
|
|
38
|
+
The request is only valid while the product is `proposed`. The workflow
|
|
39
|
+
validates the product status first and fails otherwise.
|
|
40
|
+
</Note>
|
|
41
|
+
|
|
42
|
+
## Where the message goes
|
|
43
|
+
|
|
44
|
+
The `message` is stored in two places for durability: the `CHANGE_REQUESTED`
|
|
45
|
+
action's `details.message`, and the parent change's `external_note` (the
|
|
46
|
+
vendor-facing note). Because the audit change is created already `confirmed`, the
|
|
47
|
+
request is a permanent entry in the product's history.
|
|
48
|
+
|
|
49
|
+
<Tip>
|
|
50
|
+
Subscribe to `product.change-requested` to send the vendor a notification. The
|
|
51
|
+
payload includes the `id` (product), the `message`, and the `actor_id` of the
|
|
52
|
+
operator who asked. See the
|
|
53
|
+
[Event reference](/platform/product-edit/reference/events).
|
|
54
|
+
</Tip>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Product Edit"
|
|
3
|
+
sidebarTitle: "Overview"
|
|
4
|
+
description: "Route every product edit through a reviewable, immutable change pipeline."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use Mercur to keep a full audit trail of every product change and govern your
|
|
8
|
+
master data before it changes.
|
|
9
|
+
|
|
10
|
+
Master-data governance depends on knowing who changed what, and reviewing it
|
|
11
|
+
before it takes effect. The Product Edit domain is that auditable change
|
|
12
|
+
pipeline. Every edit becomes an immutable, attributed `ProductChange` record that
|
|
13
|
+
enters an approval queue, so no change to a shared product is silently written.
|
|
14
|
+
Each record carries typed actions and a status lifecycle, and the trail records
|
|
15
|
+
who changed what and who approved it.
|
|
16
|
+
|
|
17
|
+
<Note>
|
|
18
|
+
**Product Edit ≠ product ownership.** Products are the shared master catalog,
|
|
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.
|
|
21
|
+
</Note>
|
|
22
|
+
|
|
23
|
+
## Key features
|
|
24
|
+
|
|
25
|
+
- **Immutable audit trail:** every edit is an attributed `ProductChange` that is never rewritten, only appended to and resolved.
|
|
26
|
+
- **Typed change actions:** each edit is expressed as `ProductChangeAction` rows such as `UPDATE`, `VARIANT_*`, `ATTRIBUTE_*`, `STATUS_CHANGE`, or `PRODUCT_ADD/DELETE`.
|
|
27
|
+
- **Approval queue:** a change moves `pending` → `confirmed` / `declined` / `canceled`, each through a dedicated workflow.
|
|
28
|
+
- **Deferred application:** actions are applied to the product only on confirmation, then marked `applied`.
|
|
29
|
+
- **Auto-confirm:** when review is off, staged changes confirm and apply immediately.
|
|
30
|
+
- **Revision requests:** operators send a submission back to the vendor as a recorded `CHANGE_REQUESTED` audit action.
|
|
31
|
+
- **One active change per product:** a product can't have two pending changes at once.
|
|
32
|
+
|
|
33
|
+
## Get started
|
|
34
|
+
|
|
35
|
+
Learn how the domain fits together:
|
|
36
|
+
|
|
37
|
+
<CardGroup cols={2}>
|
|
38
|
+
<Card title="The change pipeline" icon="clock-rotate-left" href="/platform/product-edit/concepts/change-pipeline">
|
|
39
|
+
The `ProductChange` record, immutability, and the audit trail.
|
|
40
|
+
</Card>
|
|
41
|
+
<Card title="Change actions" icon="list-check" href="/platform/product-edit/concepts/change-actions">
|
|
42
|
+
The typed actions that make up a change and their `details`.
|
|
43
|
+
</Card>
|
|
44
|
+
<Card title="Status & auto-confirm" icon="arrows-rotate" href="/platform/product-edit/concepts/status-and-auto-confirm">
|
|
45
|
+
The status lifecycle, revision requests, and auto-confirm.
|
|
46
|
+
</Card>
|
|
47
|
+
</CardGroup>
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
Build against the Product Edit domain in your own code:
|
|
52
|
+
|
|
53
|
+
<CardGroup cols={2}>
|
|
54
|
+
<Card title="Edit a product" icon="pen" href="/platform/product-edit/guides/edit-a-product">
|
|
55
|
+
Stage a product change from server code.
|
|
56
|
+
</Card>
|
|
57
|
+
<Card title="Confirm or decline" icon="gavel" href="/platform/product-edit/guides/confirm-or-decline-a-change">
|
|
58
|
+
Resolve a pending change in code.
|
|
59
|
+
</Card>
|
|
60
|
+
<Card title="Request a revision" icon="rotate-left" href="/platform/product-edit/guides/request-a-revision">
|
|
61
|
+
Send a submission back to the vendor.
|
|
62
|
+
</Card>
|
|
63
|
+
</CardGroup>
|
|
64
|
+
|
|
65
|
+
## Resources
|
|
66
|
+
|
|
67
|
+
Data models, workflows, service methods, and events for the Product Edit domain:
|
|
68
|
+
|
|
69
|
+
<CardGroup cols={2}>
|
|
70
|
+
<Card title="Data models" icon="table" href="/platform/product-edit/reference/data-models">
|
|
71
|
+
The `ProductChange` and `ProductChangeAction` entities.
|
|
72
|
+
</Card>
|
|
73
|
+
<Card title="Links" icon="link" href="/platform/product-edit/reference/links">
|
|
74
|
+
How the Product Edit domain links to other modules.
|
|
75
|
+
</Card>
|
|
76
|
+
<Card title="Workflows" icon="diagram-project" href="/platform/product-edit/reference/workflows">
|
|
77
|
+
Create, confirm, decline, cancel, and stage workflows.
|
|
78
|
+
</Card>
|
|
79
|
+
<Card title="Service" icon="gear" href="/platform/product-edit/reference/service">
|
|
80
|
+
Module service methods for working with records directly.
|
|
81
|
+
</Card>
|
|
82
|
+
<Card title="Events" icon="bell" href="/platform/product-edit/reference/events">
|
|
83
|
+
Events emitted as changes move through the pipeline.
|
|
84
|
+
</Card>
|
|
85
|
+
</CardGroup>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Data models"
|
|
3
|
+
sidebarTitle: "Data models"
|
|
4
|
+
description: "The data models owned by the Product Edit domain."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Product Edit domain is owned by the **Product Edit module**
|
|
8
|
+
(`MercurModules.PRODUCT_EDIT`). This reference lists its data models and their
|
|
9
|
+
fields.
|
|
10
|
+
|
|
11
|
+
## ProductChange
|
|
12
|
+
|
|
13
|
+
Table `product_change`, id prefix `prodch`. A single reviewable edit to one
|
|
14
|
+
product.
|
|
15
|
+
|
|
16
|
+
| Field | Type | Notes |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `id` | text | Primary key |
|
|
19
|
+
| `product_id` | text | The product this change targets (indexed) |
|
|
20
|
+
| `status` | enum | `ProductChangeStatus`, default `pending` (indexed) |
|
|
21
|
+
| `internal_note` | text | Nullable; operator-only note |
|
|
22
|
+
| `external_note` | text | Nullable; vendor-facing note |
|
|
23
|
+
| `created_by` | text | Nullable; actor who staged the change |
|
|
24
|
+
| `confirmed_by` / `confirmed_at` | text / dateTime | Nullable; set on confirm |
|
|
25
|
+
| `declined_by` / `declined_at` | text / dateTime | Nullable; set on decline |
|
|
26
|
+
| `declined_reason` | text | Nullable |
|
|
27
|
+
| `canceled_by` / `canceled_at` | text / dateTime | Nullable; set on cancel |
|
|
28
|
+
| `requires_action_by` / `requires_action_at` | text / dateTime | Nullable |
|
|
29
|
+
| `requires_action_reason` | text | Nullable |
|
|
30
|
+
| `metadata` | json | Nullable |
|
|
31
|
+
|
|
32
|
+
Relations: `actions` (one-to-many `ProductChangeAction`, cascade-deleted with the
|
|
33
|
+
change).
|
|
34
|
+
|
|
35
|
+
<Note>
|
|
36
|
+
The `status` enum has four values: `pending`, `confirmed`, `declined`, and
|
|
37
|
+
`canceled`. A revision request is recorded as a `CHANGE_REQUESTED` audit action
|
|
38
|
+
rather than a distinct status.
|
|
39
|
+
</Note>
|
|
40
|
+
|
|
41
|
+
## ProductChangeAction
|
|
42
|
+
|
|
43
|
+
Table `product_change_action`, id prefix `prodchact`. A single typed operation
|
|
44
|
+
inside a change.
|
|
45
|
+
|
|
46
|
+
| Field | Type | Notes |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| `id` | text | Primary key |
|
|
49
|
+
| `product_id` | text | The product the action targets (indexed) |
|
|
50
|
+
| `product_change_id` | text | Nullable FK to the parent change (`ON DELETE SET NULL`, indexed) |
|
|
51
|
+
| `ordering` | autoincrement | Deterministic apply order (indexed) |
|
|
52
|
+
| `action` | text | A `ProductChangeActionType` value |
|
|
53
|
+
| `details` | json | Default `{}`; the operation payload |
|
|
54
|
+
| `internal_note` | text | Nullable |
|
|
55
|
+
| `applied` | boolean | Default `false`; set `true` once written to the product |
|
|
56
|
+
|
|
57
|
+
## Enums
|
|
58
|
+
|
|
59
|
+
`ProductChangeStatus`: `pending`, `confirmed`, `declined`, `canceled`.
|
|
60
|
+
|
|
61
|
+
`ProductChangeActionType`: `UPDATE`, `STATUS_CHANGE`, `VARIANT_ADD`,
|
|
62
|
+
`VARIANT_UPDATE`, `VARIANT_REMOVE`, `ATTRIBUTE_ADD`, `ATTRIBUTE_UPDATE`,
|
|
63
|
+
`ATTRIBUTE_REMOVE`, `PRODUCT_ADD`, `PRODUCT_DELETE`, `CHANGE_REQUESTED`.
|
|
64
|
+
|
|
65
|
+
Both enums are exported from `@mercurjs/types`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Event reference"
|
|
3
|
+
sidebarTitle: "Events"
|
|
4
|
+
description: "Events emitted by the Product Edit domain, for subscribers and side effects."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Product Edit domain emits events as changes move through the pipeline.
|
|
8
|
+
Subscribe to them to run side effects instead of polling. Use them to notify a
|
|
9
|
+
vendor, sync external systems, or kick off follow-up workflows.
|
|
10
|
+
|
|
11
|
+
```ts title="src/subscribers/product-change-confirmed.ts"
|
|
12
|
+
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
13
|
+
|
|
14
|
+
export default async function productChangeConfirmedHandler({
|
|
15
|
+
event,
|
|
16
|
+
container,
|
|
17
|
+
}: SubscriberArgs<{ id: string }>) {
|
|
18
|
+
const changeId = event.data.id
|
|
19
|
+
// ...notify the vendor, sync search, etc.
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const config: SubscriberConfig = {
|
|
23
|
+
event: "product-change.confirmed",
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Change events
|
|
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>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Links to other modules"
|
|
3
|
+
sidebarTitle: "Links"
|
|
4
|
+
description: "How the Product Edit domain links to other modules across the marketplace."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Modules in Mercur never reference each other directly. They connect through
|
|
8
|
+
**module links**. Once a link is defined, you retrieve related records with
|
|
9
|
+
`query.graph` using the link alias.
|
|
10
|
+
|
|
11
|
+
## Product
|
|
12
|
+
|
|
13
|
+
The Product Edit domain links to the Product module so a product's change
|
|
14
|
+
history hangs off the product itself.
|
|
15
|
+
|
|
16
|
+
| Linked module | Relationship |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| **Product** | A product has many changes (`product_change.product_id`, read-only). Exposed as `product.changes`. |
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
const { data: products } = await query.graph({
|
|
22
|
+
entity: "product",
|
|
23
|
+
fields: ["id", "title", "changes.status", "changes.actions.action"],
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
<Note>
|
|
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>
|
|
33
|
+
|
|
34
|
+
## Actor references
|
|
35
|
+
|
|
36
|
+
The `created_by`, `confirmed_by`, `declined_by`, and `canceled_by` fields hold
|
|
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`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Service reference"
|
|
3
|
+
sidebarTitle: "Service"
|
|
4
|
+
description: "The Product Edit module service methods for working with records directly."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Product Edit module exposes a service you can resolve from the Medusa
|
|
8
|
+
container to read and write records directly, without going through a workflow.
|
|
9
|
+
Use it inside custom services, subscribers, or scheduled jobs.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { MercurModules } from "@mercurjs/types"
|
|
13
|
+
|
|
14
|
+
const productChangeModuleService = container.resolve(MercurModules.PRODUCT_EDIT)
|
|
15
|
+
|
|
16
|
+
const [changes, count] = await productChangeModuleService.listAndCountProductChanges({
|
|
17
|
+
status: "pending",
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Generated methods
|
|
22
|
+
|
|
23
|
+
Each data model gets a standard set of auto-generated methods. For
|
|
24
|
+
`ProductChange`:
|
|
25
|
+
|
|
26
|
+
| Method | Description |
|
|
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 |
|
|
34
|
+
|
|
35
|
+
The same set exists for `ProductChangeAction`: `createProductChangeActions`,
|
|
36
|
+
`listProductChangeActions`, `updateProductChangeActions`, and so on.
|
|
37
|
+
|
|
38
|
+
<Warning>
|
|
39
|
+
Prefer [workflows](/platform/product-edit/reference/workflows) for anything with
|
|
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.
|
|
43
|
+
</Warning>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Workflows"
|
|
3
|
+
sidebarTitle: "Workflows"
|
|
4
|
+
description: "Product change workflows, service methods, and events."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This reference lists the workflows for the Product Edit domain. Import them from
|
|
8
|
+
`@mercurjs/core/workflows` and run them against the Medusa container.
|
|
9
|
+
|
|
10
|
+
## Lifecycle workflows
|
|
11
|
+
|
|
12
|
+
| Workflow | Input | Purpose |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| `createProductChangeWorkflow` | `{ changes[], additional_data? }` | Create pending changes (rejects if one is already pending) |
|
|
15
|
+
| `stageProductChangeWorkflow` | `{ product_id, actions[], created_by?, internal_note?, external_note?, auto_confirm? }` | Create a change with actions, then run auto-confirm |
|
|
16
|
+
| `confirmProductChangeWorkflow` | `{ ids[], confirmed_by?, internal_note?, external_note? }` | Mark `confirmed` and apply pending actions |
|
|
17
|
+
| `rejectProductChangeWorkflow` | `{ id, declined_by?, declined_reason? }` | Move a `pending` change to `declined` |
|
|
18
|
+
| `cancelProductChangeWorkflow` | `{ id, canceled_by? }` | Move a `pending` change to `canceled` |
|
|
19
|
+
| `autoConfirmProductChangeWorkflow` | `{ change_id, confirmed_by?, force? }` | Confirm when review is off, or when `force` is set |
|
|
20
|
+
|
|
21
|
+
## Apply workflows
|
|
22
|
+
|
|
23
|
+
| Workflow | Input | Purpose |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `applyProductChangeActionsWorkflow` | `{ change_ids[] }` | Bucket not-yet-applied actions and dispatch them to product/variant workflows |
|
|
26
|
+
| `applyProductAttributeChangeActionsWorkflow` | `{ product_id, add[], remove[], update[] }` | Apply the attribute batch for a change |
|
|
27
|
+
|
|
28
|
+
## Edit helpers
|
|
29
|
+
|
|
30
|
+
High-level workflows that diff your input and stage the right actions for you.
|
|
31
|
+
|
|
32
|
+
| Workflow | Input | Purpose |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `productEditUpdateProductWorkflow` | `{ product_id, update, created_by? }` | Diff and stage `UPDATE` actions per changed field |
|
|
35
|
+
| `productEditUpdateVariantsWorkflow` | `{ product_id, ... }` | Stage `VARIANT_*` actions |
|
|
36
|
+
| `productEditUpdateAttributesWorkflow` | `{ product_id, ... }` | Stage `ATTRIBUTE_*` actions |
|
|
37
|
+
| `productEditDeleteProductWorkflow` | `{ product_id, ... }` | Stage a `PRODUCT_DELETE` action |
|
|
38
|
+
|
|
39
|
+
## Audit-trail workflows
|
|
40
|
+
|
|
41
|
+
| Workflow | Input | Purpose |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `recordProductAuditChangeWorkflow` | `{ actor_id?, changes[] }` | Record already-`confirmed` audit changes (actions stored `applied`) |
|
|
44
|
+
| `requestProductChangeWorkflow` | `{ product_id, message?, actor_id? }` | Record a `CHANGE_REQUESTED` revision request on a `proposed` product |
|
|
45
|
+
|
|
46
|
+
To work with records directly instead of through a workflow, see the
|
|
47
|
+
[Service reference](/platform/product-edit/reference/service). To run side effects
|
|
48
|
+
when a change resolves, see the
|
|
49
|
+
[Event reference](/platform/product-edit/reference/events).
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Product vs seller reviews"
|
|
3
|
+
sidebarTitle: "Product vs seller reviews"
|
|
4
|
+
description: "The reference discriminator and the links that anchor each review."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page covers how one review model serves two targets and how each review is
|
|
8
|
+
anchored to the rest of the marketplace.
|
|
9
|
+
|
|
10
|
+
## Reference
|
|
11
|
+
|
|
12
|
+
The `reference` field on the `Review` model decides what a review is about. It's
|
|
13
|
+
an enum with two values, `product` and `seller`, and it works together with the
|
|
14
|
+
review's link to the target record. There is no polymorphic id column on the
|
|
15
|
+
model itself; the target is resolved through a module link.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// A product review
|
|
19
|
+
{ reference: "product", reference_id: "prod_123", rating: 5 }
|
|
20
|
+
|
|
21
|
+
// A seller review
|
|
22
|
+
{ reference: "seller", reference_id: "sel_123", rating: 4 }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
When a review is created, the `reference` value selects which link is written:
|
|
26
|
+
`reference: "product"` links the review to a product, and `reference: "seller"`
|
|
27
|
+
links it to a seller. Reading a review back, you follow the matching relation
|
|
28
|
+
(`review.product` or `review.seller`) to reach its target.
|
|
29
|
+
|
|
30
|
+
<Note>
|
|
31
|
+
Products are the shared master catalog, not seller-owned. A **product** review
|
|
32
|
+
rates the master product; a **seller** review rates the store. They are
|
|
33
|
+
independent. A customer can leave both for the same order.
|
|
34
|
+
</Note>
|
|
35
|
+
|
|
36
|
+
## Order & customer links
|
|
37
|
+
|
|
38
|
+
Beyond its target, every review is anchored to the order that earned it and the
|
|
39
|
+
customer who wrote it. Creating a review writes two more links, one to the
|
|
40
|
+
`Order` and one to the `Customer`, so a review always has a verifiable purchase
|
|
41
|
+
behind it.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
// resolved through the customer link when listing a customer's own reviews
|
|
45
|
+
const { data } = await query.graph({
|
|
46
|
+
entity: "customer_customer_review_review",
|
|
47
|
+
fields: ["review.*"],
|
|
48
|
+
filters: { customer_id: "cus_123" },
|
|
49
|
+
})
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## One review per target, per order
|
|
53
|
+
|
|
54
|
+
Because a review is tied to an order, the create flow enforces that a customer
|
|
55
|
+
can leave **at most one review per target per order**. Submitting a second review
|
|
56
|
+
for the same `reference` and `reference_id` on the same order is rejected. The
|
|
57
|
+
order must also belong to the customer submitting the review.
|
|
58
|
+
|
|
59
|
+
<Tip>
|
|
60
|
+
A single order can still produce several reviews, one per distinct target. For
|
|
61
|
+
example, a customer may review the master product *and* the store that
|
|
62
|
+
fulfilled it from the same order.
|
|
63
|
+
</Tip>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Ratings & moderation"
|
|
3
|
+
sidebarTitle: "Ratings & moderation"
|
|
4
|
+
description: "The review status lifecycle, store responses, and aggregate ratings."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page covers how a review moves from submission to a public rating, and how
|
|
8
|
+
per-product and per-seller averages are computed.
|
|
9
|
+
|
|
10
|
+
## Status
|
|
11
|
+
|
|
12
|
+
A review's state is held in the `status` field of the `Review` model. A review
|
|
13
|
+
moves through three statuses:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
┌──────────┐ publish ┌────────────┐
|
|
17
|
+
│ pending │───────────►│ published │
|
|
18
|
+
└────┬─────┘ └────────────┘
|
|
19
|
+
│ reject
|
|
20
|
+
▼
|
|
21
|
+
┌────────────┐
|
|
22
|
+
│ rejected │
|
|
23
|
+
└────────────┘
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Status | Meaning |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `pending` | Submitted, awaiting moderation. The default on creation |
|
|
29
|
+
| `published` | Approved and visible on the storefront |
|
|
30
|
+
| `rejected` | Declined by a moderator |
|
|
31
|
+
|
|
32
|
+
A review is created as `pending`. Moderation moves it to `published` or
|
|
33
|
+
`rejected` by updating the `status` field. See
|
|
34
|
+
[Moderate a review](/platform/review/guides/moderate-a-review).
|
|
35
|
+
|
|
36
|
+
## Store responses
|
|
37
|
+
|
|
38
|
+
A store can attach a single public response to any of its reviews. The response
|
|
39
|
+
lives in the `seller_note` field and is added through a dedicated respond flow,
|
|
40
|
+
which refuses to overwrite an existing response.
|
|
41
|
+
|
|
42
|
+
<Note>
|
|
43
|
+
Responding is separate from moderation. A store adds its `seller_note`, while
|
|
44
|
+
the `status` transition (`published` / `rejected`) stays an operator decision.
|
|
45
|
+
</Note>
|
|
46
|
+
|
|
47
|
+
## Aggregate ratings
|
|
48
|
+
|
|
49
|
+
The module service computes average ratings on demand rather than storing a
|
|
50
|
+
denormalized column. `getAvgRating` returns the average for a single product or
|
|
51
|
+
seller, and `getProductsWithRating` / `getSellersWithRating` return records with
|
|
52
|
+
their average rating joined in for list views.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
const service = container.resolve(MercurModules.REVIEW)
|
|
56
|
+
|
|
57
|
+
const avg = await service.getAvgRating("seller", "sel_123")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
<Tip>
|
|
61
|
+
Because averages are computed at query time, they always reflect the current
|
|
62
|
+
set of reviews. There's no cache to invalidate when a review is added, removed,
|
|
63
|
+
or moderated.
|
|
64
|
+
</Tip>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "The review model"
|
|
3
|
+
sidebarTitle: "The review model"
|
|
4
|
+
description: "The single review entity, its rating, notes, and moderation status."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This page covers the review record and the fields that make up a rating.
|
|
8
|
+
|
|
9
|
+
## Review
|
|
10
|
+
|
|
11
|
+
A review is a customer's rating of a single target, either a product or a seller.
|
|
12
|
+
It's represented by the `Review` data model (table `review`, id prefix `rev`). It
|
|
13
|
+
holds the numeric rating, an optional customer note, an optional store response,
|
|
14
|
+
and the moderation status.
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
const { result } = await createReviewWorkflow(container).run({
|
|
18
|
+
input: {
|
|
19
|
+
order_id: "order_123",
|
|
20
|
+
reference: "product",
|
|
21
|
+
reference_id: "prod_123",
|
|
22
|
+
rating: 5,
|
|
23
|
+
customer_note: "Exactly as described, fast shipping.",
|
|
24
|
+
customer_id: "cus_123",
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Every review carries the same shape regardless of what it targets:
|
|
30
|
+
|
|
31
|
+
| Field | Purpose |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `rating` | The numeric score the customer gave |
|
|
34
|
+
| `reference` | Whether the review is about a `product` or a `seller` |
|
|
35
|
+
| `customer_note` | The customer's optional free-text note |
|
|
36
|
+
| `seller_note` | The store's optional public response |
|
|
37
|
+
| `status` | The moderation state: `pending`, `published`, or `rejected` |
|
|
38
|
+
| `display_id` | A human-readable auto-incrementing number |
|
|
39
|
+
|
|
40
|
+
<Note>
|
|
41
|
+
There is no separate table for product reviews and seller reviews. A single
|
|
42
|
+
`Review` row is discriminated by its `reference` field. See
|
|
43
|
+
[Product vs seller reviews](/platform/review/concepts/product-vs-seller-reviews).
|
|
44
|
+
</Note>
|
|
45
|
+
|
|
46
|
+
## Notes
|
|
47
|
+
|
|
48
|
+
A review separates the two sides of the conversation into two nullable text
|
|
49
|
+
fields. `customer_note` is written by the customer when they submit the review;
|
|
50
|
+
`seller_note` is the store's single response, added later through the respond
|
|
51
|
+
flow. Both are searchable so operators can find reviews by their content.
|
|
52
|
+
|
|
53
|
+
<Tip>
|
|
54
|
+
A store can respond **once**. The respond flow refuses to overwrite an existing
|
|
55
|
+
`seller_note`. To change a response, clear it first.
|
|
56
|
+
</Tip>
|