@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,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Order Group"
|
|
3
|
+
sidebarTitle: "Overview"
|
|
4
|
+
description: "Wrap a multi-seller cart into one shopper-facing order made of independent per-seller orders."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use Order Groups to turn a single customer cart that spans multiple sellers into
|
|
8
|
+
one coherent order for the shopper.
|
|
9
|
+
|
|
10
|
+
A marketplace cart can contain offers from several sellers at once. On checkout,
|
|
11
|
+
Mercur splits that cart into one child order per seller and wraps them in an
|
|
12
|
+
**Order Group**. This is the aggregate the shopper sees as "their order". Each
|
|
13
|
+
child order is then fulfilled, returned, and refunded independently, while the
|
|
14
|
+
group gives you a single handle over the whole purchase.
|
|
15
|
+
|
|
16
|
+
<Note>
|
|
17
|
+
An order group is the `OrderGroup` entity. It lives in the **Seller module**
|
|
18
|
+
(id prefix `og`), not a module of its own. There is no `ORDER_GROUP` module
|
|
19
|
+
key. Resolve its service through `MercurModules.SELLER`.
|
|
20
|
+
</Note>
|
|
21
|
+
|
|
22
|
+
## Key features
|
|
23
|
+
|
|
24
|
+
- **Multi-seller checkout:** one cart with offers from many sellers becomes one group of per-seller orders.
|
|
25
|
+
- **Human-readable id:** an auto-incrementing `display_id` the shopper and operator can reference.
|
|
26
|
+
- **Immutable cart link:** a read-only `cart_id` back to the originating cart. Carts are frozen after checkout.
|
|
27
|
+
- **Computed totals:** `seller_count` and `total` are derived at query time, never stored.
|
|
28
|
+
- **Independent child orders:** fulfillment, returns, and refunds happen per seller order.
|
|
29
|
+
- **Scoped visibility:** admins see every group platform-wide. Vendors see only their slice.
|
|
30
|
+
|
|
31
|
+
## Get started
|
|
32
|
+
|
|
33
|
+
Learn how the domain fits together.
|
|
34
|
+
|
|
35
|
+
<CardGroup cols={2}>
|
|
36
|
+
<Card title="The order group" icon="layer-group" href="/platform/order-group/concepts/the-order-group">
|
|
37
|
+
The aggregate entity, its `display_id`, and the read-only cart link.
|
|
38
|
+
</Card>
|
|
39
|
+
<Card title="Order splitting" icon="scissors" href="/platform/order-group/concepts/order-splitting">
|
|
40
|
+
How a multi-seller cart is split into per-seller child orders.
|
|
41
|
+
</Card>
|
|
42
|
+
<Card title="Computed totals" icon="calculator" href="/platform/order-group/concepts/computed-totals">
|
|
43
|
+
Why `seller_count` and `total` are calculated at query time.
|
|
44
|
+
</Card>
|
|
45
|
+
</CardGroup>
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
Build against Order Groups in your own code.
|
|
50
|
+
|
|
51
|
+
<CardGroup cols={2}>
|
|
52
|
+
<Card title="Retrieve an order group" icon="magnifying-glass" href="/platform/order-group/guides/retrieve-an-order-group">
|
|
53
|
+
Load a group and its aggregated child orders.
|
|
54
|
+
</Card>
|
|
55
|
+
<Card title="List order groups" icon="list" href="/platform/order-group/guides/list-order-groups">
|
|
56
|
+
Page through groups, optionally scoped to a seller.
|
|
57
|
+
</Card>
|
|
58
|
+
<Card title="Split a cart" icon="scissors" href="/platform/order-group/guides/split-a-cart">
|
|
59
|
+
Complete a multi-seller cart into a group of orders.
|
|
60
|
+
</Card>
|
|
61
|
+
</CardGroup>
|
|
62
|
+
|
|
63
|
+
## Resources
|
|
64
|
+
|
|
65
|
+
Data models, links, workflows, service methods, and events for Order Groups.
|
|
66
|
+
|
|
67
|
+
<CardGroup cols={2}>
|
|
68
|
+
<Card title="Data models" icon="table" href="/platform/order-group/reference/data-models">
|
|
69
|
+
The `OrderGroup` entity and its fields.
|
|
70
|
+
</Card>
|
|
71
|
+
<Card title="Links" icon="link" href="/platform/order-group/reference/links">
|
|
72
|
+
How order groups link to carts, orders, sellers, and offers.
|
|
73
|
+
</Card>
|
|
74
|
+
<Card title="Workflows" icon="diagram-project" href="/platform/order-group/reference/workflows">
|
|
75
|
+
Splitting, retrieving, and listing order groups.
|
|
76
|
+
</Card>
|
|
77
|
+
<Card title="Service" icon="gear" href="/platform/order-group/reference/service">
|
|
78
|
+
Seller module methods for working with groups directly.
|
|
79
|
+
</Card>
|
|
80
|
+
<Card title="Events" icon="bell" href="/platform/order-group/reference/events">
|
|
81
|
+
Events emitted as order groups are created.
|
|
82
|
+
</Card>
|
|
83
|
+
</CardGroup>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Data models"
|
|
3
|
+
sidebarTitle: "Data models"
|
|
4
|
+
description: "The data model owned by the Order Group domain."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Order Group domain is owned by the **Seller module**. There is no separate
|
|
8
|
+
order-group module. This reference lists its data model and fields. For the full
|
|
9
|
+
module overview, see the [Order Group overview](/platform/order-group/overview).
|
|
10
|
+
|
|
11
|
+
## OrderGroup
|
|
12
|
+
|
|
13
|
+
Table `order_group`, id prefix `og`. The aggregate over the per-seller orders
|
|
14
|
+
created from a single cart.
|
|
15
|
+
|
|
16
|
+
| Field | Type | Notes |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `id` | text | Primary key (prefix `og`) |
|
|
19
|
+
| `display_id` | integer | Auto-incrementing, human-readable reference |
|
|
20
|
+
| `customer_id` | text | Nullable; who placed the group |
|
|
21
|
+
| `cart_id` | text | The originating cart (read-only link to Cart) |
|
|
22
|
+
| `seller_count` | number | **Computed**: distinct sellers with a child order |
|
|
23
|
+
| `total` | bigNumber | **Computed**: sum of child order totals |
|
|
24
|
+
| `created_at` / `updated_at` | dateTime | Timestamps |
|
|
25
|
+
| `deleted_at` | dateTime | Nullable; soft-delete marker |
|
|
26
|
+
|
|
27
|
+
Relations: `orders` (one-to-many through the `order_group_order` link table),
|
|
28
|
+
`cart` (read-only, via `cart_id`).
|
|
29
|
+
|
|
30
|
+
<Note>
|
|
31
|
+
`seller_count` and `total` are marked `computed()`. They hold no value on the
|
|
32
|
+
row and are aggregated from the group's child orders each time it's read. See
|
|
33
|
+
[Computed totals](/platform/order-group/concepts/computed-totals).
|
|
34
|
+
</Note>
|
|
35
|
+
|
|
36
|
+
<Warning>
|
|
37
|
+
The `cart_id` link is **read-only**. The cart is frozen (`completed_at` is set)
|
|
38
|
+
the moment the split runs, so it's a historical reference and can't be written
|
|
39
|
+
through the group.
|
|
40
|
+
</Warning>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Event reference"
|
|
3
|
+
sidebarTitle: "Events"
|
|
4
|
+
description: "Events emitted by the Order Group domain, for subscribers and side effects."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Order Group domain emits an event when a group is created during checkout.
|
|
8
|
+
Subscribe to it to run side effects such as sending an order confirmation,
|
|
9
|
+
syncing external systems, or kicking off follow-up workflows, instead of polling.
|
|
10
|
+
|
|
11
|
+
```ts title="src/subscribers/order-group-created.ts"
|
|
12
|
+
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
13
|
+
|
|
14
|
+
export default async function orderGroupCreatedHandler({
|
|
15
|
+
event,
|
|
16
|
+
container,
|
|
17
|
+
}: SubscriberArgs<{ id: string }>) {
|
|
18
|
+
const orderGroupId = event.data.id
|
|
19
|
+
// ...send a confirmation, notify sellers, etc.
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const config: SubscriberConfig = {
|
|
23
|
+
event: "order_group.created",
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Order group events
|
|
28
|
+
|
|
29
|
+
| Event | Emitted when | Payload |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `order_group.created` | A cart is split and its parent group is created | `{ id }` |
|
|
32
|
+
|
|
33
|
+
<Note>
|
|
34
|
+
The same checkout split also emits `order.placed` for each child order created.
|
|
35
|
+
Subscribe to `order.placed` when you need to react per seller order, and to
|
|
36
|
+
`order_group.created` when you need the purchase as a whole.
|
|
37
|
+
</Note>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Links to other modules"
|
|
3
|
+
sidebarTitle: "Links"
|
|
4
|
+
description: "How the Order Group domain links to carts, orders, sellers, and offers."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Modules in Mercur never reference each other directly. They connect through
|
|
8
|
+
**module links**. The `OrderGroup` entity (owned by the Seller module) sits at
|
|
9
|
+
the center of a completed multi-seller purchase, linking the cart it came from to
|
|
10
|
+
the per-seller orders it produced. Once a link is defined, you retrieve related
|
|
11
|
+
records with `query.graph` using the link alias.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const { data: groups } = await query.graph({
|
|
15
|
+
entity: "order_group",
|
|
16
|
+
fields: ["id", "display_id", "cart.id", "orders.id", "orders.total"],
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Group links
|
|
21
|
+
|
|
22
|
+
| Linked module | Relationship |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| **Cart** | A group references the one cart it was created from (`order_group.cart_id`, **read-only**). Carts are immutable after checkout. |
|
|
25
|
+
| **Order** | A group has many child orders, one per seller, through the `order_group_order` table. |
|
|
26
|
+
|
|
27
|
+
## Order links
|
|
28
|
+
|
|
29
|
+
The child orders produced by the split carry their own marketplace links:
|
|
30
|
+
|
|
31
|
+
| Linked module | Relationship |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| **Seller** | Each order belongs to one seller (`order_order_seller_seller`); a seller has many orders. |
|
|
34
|
+
| **Offer** | Each order line item links to the offer it was purchased from (`order_line_item` → `offer`, list on the line-item side so one offer can back many order lines). |
|
|
35
|
+
|
|
36
|
+
<Note>
|
|
37
|
+
The `cart_id` link is resolved from the field on the group and can't be written
|
|
38
|
+
through the link itself. The split sets it once, at creation.
|
|
39
|
+
</Note>
|
|
40
|
+
|
|
41
|
+
<Tip>
|
|
42
|
+
To scope a group to a single seller, filter its child orders by
|
|
43
|
+
`orders.seller.id`. The list workflow does exactly this when you pass a
|
|
44
|
+
`sellerId`. See [List order groups](/platform/order-group/guides/list-order-groups).
|
|
45
|
+
</Tip>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Service reference"
|
|
3
|
+
sidebarTitle: "Service"
|
|
4
|
+
description: "The Seller module service and its methods for working with order group records directly."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Order groups are owned by the **Seller module**, so you resolve the same service
|
|
8
|
+
you'd use for stores. Resolve it from the Medusa container to read and write
|
|
9
|
+
`OrderGroup` records directly, without going through a workflow. Use it inside
|
|
10
|
+
custom services, subscribers, or scheduled jobs.
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { MercurModules } from "@mercurjs/types"
|
|
14
|
+
|
|
15
|
+
const sellerModuleService = container.resolve(MercurModules.SELLER)
|
|
16
|
+
|
|
17
|
+
const [orderGroups, count] = await sellerModuleService.listAndCountOrderGroups({
|
|
18
|
+
customer_id: "cus_123",
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
<Note>
|
|
23
|
+
There is no `ORDER_GROUP` module key. The `OrderGroup` model is registered on
|
|
24
|
+
the Seller module, so its service methods live on `MercurModules.SELLER`.
|
|
25
|
+
</Note>
|
|
26
|
+
|
|
27
|
+
## Generated methods
|
|
28
|
+
|
|
29
|
+
The `OrderGroup` model gets the standard set of auto-generated methods:
|
|
30
|
+
|
|
31
|
+
| Method | Description |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `createOrderGroups(data)` | Create one or more order groups |
|
|
34
|
+
| `retrieveOrderGroup(id, config?)` | Retrieve a group by id (with computed `seller_count` / `total`) |
|
|
35
|
+
| `listOrderGroups(filters?, config?)` | List groups matching filters |
|
|
36
|
+
| `listAndCountOrderGroups(filters?, config?)` | List groups with a total count |
|
|
37
|
+
| `updateOrderGroups(data)` | Update one or more groups |
|
|
38
|
+
| `deleteOrderGroups(ids)` | Delete one or more groups |
|
|
39
|
+
|
|
40
|
+
The list, count, and retrieve methods run through the module's order-group
|
|
41
|
+
repository, which aggregates each group's child orders to fill in the computed
|
|
42
|
+
`seller_count` and `total`. Supported filters include `id`, `customer_id`,
|
|
43
|
+
`seller_id`, `status`, `sales_channel_id`, `created_at`, `updated_at`, and `q`.
|
|
44
|
+
|
|
45
|
+
<Warning>
|
|
46
|
+
Prefer [workflows](/platform/order-group/reference/workflows) for reads that
|
|
47
|
+
need aggregated child-order status, and for the checkout split. The service
|
|
48
|
+
returns the group row and its computed totals but does **not** expand child
|
|
49
|
+
orders' payment/fulfillment status, emit events, or run compensation.
|
|
50
|
+
</Warning>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Workflows"
|
|
3
|
+
sidebarTitle: "Workflows"
|
|
4
|
+
description: "Order group workflows, service methods, and events."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This reference lists the workflows, service methods, and events for the Order
|
|
8
|
+
Group domain. Import workflows from `@mercurjs/core/workflows` and run them
|
|
9
|
+
against the Medusa container.
|
|
10
|
+
|
|
11
|
+
## Checkout workflow
|
|
12
|
+
|
|
13
|
+
| Workflow | Input | Purpose |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `completeCartWithSplitOrdersWorkflow` | `{ cart_id }` | Split a multi-seller cart into per-seller orders and create the parent `OrderGroup`. Returns `{ order_group_id }`. Idempotent per cart. |
|
|
16
|
+
|
|
17
|
+
## Read workflows
|
|
18
|
+
|
|
19
|
+
| Workflow | Input | Purpose |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `getOrderGroupDetailWorkflow` | `{ order_group_id, fields }` | Load one group with its child orders and derived per-order payment/fulfillment status |
|
|
22
|
+
| `getOrderGroupsListWorkflow` | `{ fields, variables?, sellerId? }` | List groups with a count; `sellerId` scopes each group's child orders to a seller |
|
|
23
|
+
|
|
24
|
+
<Note>
|
|
25
|
+
The read workflows always expand the group's child `orders`. Heavy relations
|
|
26
|
+
(`payment_collections`, `fulfillments`) are only kept in the response when you
|
|
27
|
+
request a matching field, and are used to derive each order's `payment_status`
|
|
28
|
+
and `fulfillment_status`.
|
|
29
|
+
</Note>
|
|
30
|
+
|
|
31
|
+
## Step
|
|
32
|
+
|
|
33
|
+
| Step | Input | Purpose |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `createOrderGroupStep` | `{ customer_id?, cart_id }` | Create the `OrderGroup` record (used inside the checkout workflow, with a compensating delete) |
|
|
36
|
+
|
|
37
|
+
To work with records directly instead of through a workflow, see the
|
|
38
|
+
[Service reference](/platform/order-group/reference/service). To run side effects
|
|
39
|
+
when a group is created, see the [Event reference](/platform/order-group/reference/events).
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Account lifecycle"
|
|
3
|
+
sidebarTitle: "Account lifecycle"
|
|
4
|
+
description: "Payout account statuses and the webhook-driven transitions between them."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this document, you'll learn about the payout account lifecycle and how its
|
|
8
|
+
status stays in sync with the provider.
|
|
9
|
+
|
|
10
|
+
## Status
|
|
11
|
+
|
|
12
|
+
A payout account's state is held in the `status` field of the `PayoutAccount`
|
|
13
|
+
model, typed by the `PayoutAccountStatus` enum. An account moves through four
|
|
14
|
+
statuses.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
┌──────────┐
|
|
18
|
+
│ PENDING │
|
|
19
|
+
└────┬─────┘
|
|
20
|
+
│ account.activated
|
|
21
|
+
▼
|
|
22
|
+
┌────────────┐ ┌────────┐
|
|
23
|
+
│ RESTRICTED │◄─►│ ACTIVE │
|
|
24
|
+
└────────────┘ └───┬────┘
|
|
25
|
+
│ account.rejected
|
|
26
|
+
▼
|
|
27
|
+
┌──────────┐
|
|
28
|
+
│ REJECTED │
|
|
29
|
+
└──────────┘
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| Status | Meaning |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `PENDING` | Account created, provider onboarding not yet complete. |
|
|
35
|
+
| `ACTIVE` | Fully onboarded. Can receive payouts. |
|
|
36
|
+
| `RESTRICTED` | Provider flagged the account, for example missing KYC. No payouts. |
|
|
37
|
+
| `REJECTED` | Provider permanently disabled the account. |
|
|
38
|
+
|
|
39
|
+
<Note>
|
|
40
|
+
Payouts are only created against an `ACTIVE` account. The module rejects a
|
|
41
|
+
payout for an account in any other status.
|
|
42
|
+
</Note>
|
|
43
|
+
|
|
44
|
+
## Webhook-driven transitions
|
|
45
|
+
|
|
46
|
+
Unlike the store lifecycle, payout account transitions are **not** operator
|
|
47
|
+
actions. They follow the provider. The provider sends a webhook, a subscriber
|
|
48
|
+
resolves it to an action, and `processPayoutForWebhookWorkflow` updates the
|
|
49
|
+
status.
|
|
50
|
+
|
|
51
|
+
| Webhook action | Resulting status |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `account.activated` | `ACTIVE` |
|
|
54
|
+
| `account.restricted` | `RESTRICTED` |
|
|
55
|
+
| `account.rejected` | `REJECTED` |
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// Inside processPayoutForWebhookWorkflow
|
|
59
|
+
when({ input }, ({ input }) => input.action === "account.activated")
|
|
60
|
+
.then(() =>
|
|
61
|
+
updatePayoutAccountStep({ id: input.data!.id, status: PayoutAccountStatus.ACTIVE })
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
<Tip>
|
|
66
|
+
A `RESTRICTED` account is not terminal. Once the seller resolves the
|
|
67
|
+
provider's requirements, the provider emits `account.activated` again and the
|
|
68
|
+
account returns to `ACTIVE`. `REJECTED` is the only permanent state.
|
|
69
|
+
</Tip>
|
|
70
|
+
|
|
71
|
+
## Payout status
|
|
72
|
+
|
|
73
|
+
An individual transfer carries its own `PayoutStatus` (`PENDING` → `PROCESSING`
|
|
74
|
+
→ `PAID`, or `FAILED` / `CANCELED`). Provider webhooks advance it through the
|
|
75
|
+
same workflow. See [The payout pipeline](/platform/payout/concepts/payout-pipeline).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Accounts & onboarding"
|
|
3
|
+
sidebarTitle: "Accounts & onboarding"
|
|
4
|
+
description: "The payout account, its onboarding record, and provider-specific data."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this document, you'll learn how a seller connects to a payment provider and
|
|
8
|
+
where provider-specific data lives.
|
|
9
|
+
|
|
10
|
+
## Payout account
|
|
11
|
+
|
|
12
|
+
A payout account is the seller's connection to the payment provider. It is the
|
|
13
|
+
record funds are transferred to. A payout account is represented by the
|
|
14
|
+
`PayoutAccount` data model (table `payout_account`, id prefix `pacc`). It is
|
|
15
|
+
created for a seller through `createPayoutAccountWorkflow`, which also links the
|
|
16
|
+
account to the store.
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
const { result } = await createPayoutAccountWorkflow(container).run({
|
|
20
|
+
input: {
|
|
21
|
+
seller_id: "sel_123",
|
|
22
|
+
context: { /* forwarded to the provider */ },
|
|
23
|
+
data: { /* forwarded to the provider */ },
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Creating an account is a two-step operation. The module first persists the
|
|
29
|
+
`PayoutAccount`. It then calls the provider to create the connected account and
|
|
30
|
+
stores what the provider returns in the account's `data` field. A seller has
|
|
31
|
+
**exactly one** payout account.
|
|
32
|
+
|
|
33
|
+
<Note>
|
|
34
|
+
A store can only have **one** payout account. `createPayoutAccountWorkflow`
|
|
35
|
+
validates that the seller doesn't already have one before creating it.
|
|
36
|
+
</Note>
|
|
37
|
+
|
|
38
|
+
## Onboarding
|
|
39
|
+
|
|
40
|
+
Before an account can receive funds, the seller usually has to complete
|
|
41
|
+
provider-side setup, such as identity verification, bank details, or KYC. That
|
|
42
|
+
state is held in the `Onboarding` data model (table `onboarding`, id prefix
|
|
43
|
+
`onb`). The record is a one-to-one satellite of the payout account.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
await createOnboardingWorkflow(container).run({
|
|
47
|
+
input: {
|
|
48
|
+
account_id: "pacc_123",
|
|
49
|
+
context: { return_url: "https://store.example.com/settings/payouts" },
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The workflow asks the provider to produce onboarding data (for Stripe Connect,
|
|
55
|
+
an onboarding link) and stores it on the record. Running it again on an account
|
|
56
|
+
that already has an onboarding record **updates** it rather than creating a
|
|
57
|
+
second one.
|
|
58
|
+
|
|
59
|
+
## Provider data
|
|
60
|
+
|
|
61
|
+
The `data` JSON field on `PayoutAccount`, `Onboarding`, and `Payout` is where
|
|
62
|
+
provider-specific values live, such as the Stripe account id, onboarding URLs, or
|
|
63
|
+
transfer references. The module never interprets these fields. It forwards them
|
|
64
|
+
to and from the provider.
|
|
65
|
+
|
|
66
|
+
<Tip>
|
|
67
|
+
`context` carries per-request hints such as an `idempotency_key` or a
|
|
68
|
+
`return_url`, while `data` carries the durable provider payload. Both are
|
|
69
|
+
passed straight through the `IPayoutProvider` interface.
|
|
70
|
+
</Tip>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "The payout pipeline"
|
|
3
|
+
sidebarTitle: "The payout pipeline"
|
|
4
|
+
description: "Capture check, payment capture, daily payout, transfer, and the provider interface."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this document, you'll learn how an authorized payment becomes a transfer to a
|
|
8
|
+
seller, and how the provider interface fits in.
|
|
9
|
+
|
|
10
|
+
## Payout
|
|
11
|
+
|
|
12
|
+
A payout is a single transfer of a seller's earnings for one order. It is
|
|
13
|
+
represented by the `Payout` data model (table `payout`, id prefix `pout`). Its
|
|
14
|
+
`amount` is the order total minus the order's commission lines, and it belongs to
|
|
15
|
+
the seller's `PayoutAccount`.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// createPayoutWorkflow computes the seller's share
|
|
19
|
+
const amount = MathBN.sub(order.total, totalCommission)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The flow is designed to run automatically. Scheduled jobs and event-driven
|
|
23
|
+
subscribers move each order from authorized payment to settled transfer with no
|
|
24
|
+
manual step.
|
|
25
|
+
|
|
26
|
+
<Note>
|
|
27
|
+
The payout **workflows** (`createPayoutWorkflow`, `createPayoutAccountWorkflow`,
|
|
28
|
+
`createOnboardingWorkflow`, `processPayoutForWebhookWorkflow`) and the provider
|
|
29
|
+
**webhook subscriber** ship in `@mercurjs/core`. The **scheduled jobs** that
|
|
30
|
+
drive capture and daily payout are wired up in your project (under
|
|
31
|
+
`apps/api/src/jobs`), along with the `order.capture_requested` and
|
|
32
|
+
`payout.requested` events they emit. The steps below describe that intended
|
|
33
|
+
pipeline and its integration points, not jobs bundled in the core plugin.
|
|
34
|
+
</Note>
|
|
35
|
+
|
|
36
|
+
## 1. Capture check (every 15 min)
|
|
37
|
+
|
|
38
|
+
A scheduled job scans for orders ready for capture. An order qualifies when its
|
|
39
|
+
payment is `authorized`, the seller has an `ACTIVE` payout account, the order
|
|
40
|
+
meets the required fulfillment status (default `fulfilled`), and no payout
|
|
41
|
+
exists yet. As the capture deadline nears (authorization window minus safety
|
|
42
|
+
buffer), it emits `order.capture_requested`. If the authorization already
|
|
43
|
+
expired, it emits `order.authorization_expired`.
|
|
44
|
+
|
|
45
|
+
## 2. Payment capture (event-driven)
|
|
46
|
+
|
|
47
|
+
A subscriber listens for `order.capture_requested` and runs Medusa's
|
|
48
|
+
`capturePaymentWorkflow` to capture the authorized payment. On success, the order
|
|
49
|
+
is marked captured. On failure, it's flagged so it isn't retried.
|
|
50
|
+
|
|
51
|
+
## 3. Daily payout (1 AM UTC)
|
|
52
|
+
|
|
53
|
+
A daily job scans captured orders that haven't been paid out and emits
|
|
54
|
+
`payout.requested` for each one. An order qualifies when its payment is captured,
|
|
55
|
+
no payout exists yet, and the seller's account is `ACTIVE`.
|
|
56
|
+
|
|
57
|
+
## 4. Transfer (event-driven)
|
|
58
|
+
|
|
59
|
+
A subscriber listens for `payout.requested` and runs `createPayoutWorkflow`,
|
|
60
|
+
which loads the order with its seller, payout account, and commission lines,
|
|
61
|
+
computes the seller's share, calls the provider to initiate the transfer, and
|
|
62
|
+
creates a `Payout` record linked to the seller.
|
|
63
|
+
|
|
64
|
+
<Note>
|
|
65
|
+
The order id is used as the payout's `idempotency_key`, so a re-emitted
|
|
66
|
+
`payout.requested` event never produces a duplicate transfer.
|
|
67
|
+
</Note>
|
|
68
|
+
|
|
69
|
+
## The provider interface
|
|
70
|
+
|
|
71
|
+
Every external operation goes through the `IPayoutProvider` contract, and the
|
|
72
|
+
module registers **exactly one** provider. Stripe Connect ships out of the box.
|
|
73
|
+
Any other processor implements the same four methods.
|
|
74
|
+
|
|
75
|
+
| Method | Purpose |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `createPayoutAccount` | Create the connected account with the provider |
|
|
78
|
+
| `createOnboarding` | Produce onboarding data (e.g. a Stripe onboarding link) |
|
|
79
|
+
| `createPayout` | Initiate a transfer to the seller |
|
|
80
|
+
| `getWebhookActionAndData` | Parse a raw webhook into a `PayoutWebhookResult` |
|
|
81
|
+
|
|
82
|
+
<Tip>
|
|
83
|
+
Provider-specific values, such as account ids, onboarding URLs, or transfer
|
|
84
|
+
references, are stored in the `data` JSON fields and never interpreted by the
|
|
85
|
+
module. The same code path works for any provider.
|
|
86
|
+
</Tip>
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
The pipeline's timing is tunable via the payout module options in
|
|
91
|
+
`medusa-config.ts`:
|
|
92
|
+
|
|
93
|
+
| Option | Default | Description |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| `disabled` | `false` | Disable both scheduled jobs |
|
|
96
|
+
| `authorizationWindowMs` | 7 days | How long a payment authorization stays valid |
|
|
97
|
+
| `sellerActionWindowMs` | 72 hours | Time a seller has to fulfill before the order is rejected |
|
|
98
|
+
| `captureSafetyBufferMs` | 24 hours | Margin before authorization expiry to trigger capture |
|
|
99
|
+
| `requiredFulfillmentStatus` | `"fulfilled"` | Minimum fulfillment status before an order is eligible |
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Create a payout account"
|
|
3
|
+
sidebarTitle: "Create a payout account"
|
|
4
|
+
description: "Create a seller's payout account with createPayoutAccountWorkflow."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how to create a payout account for a seller from your
|
|
8
|
+
own server code. This is useful in an onboarding flow or a custom API route.
|
|
9
|
+
|
|
10
|
+
Mercur exposes a `createPayoutAccountWorkflow` that persists the `PayoutAccount`,
|
|
11
|
+
calls the configured provider to create the connected account, and links the
|
|
12
|
+
account to the store. Run it from any place that has access to the Medusa
|
|
13
|
+
container.
|
|
14
|
+
|
|
15
|
+
## Run the workflow
|
|
16
|
+
|
|
17
|
+
```ts title="src/api/custom/payout-account/route.ts"
|
|
18
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
19
|
+
import { createPayoutAccountWorkflow } from "@mercurjs/core/workflows"
|
|
20
|
+
|
|
21
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
22
|
+
const { result } = await createPayoutAccountWorkflow(req.scope).run({
|
|
23
|
+
input: {
|
|
24
|
+
seller_id: req.params.id,
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
res.status(201).json({ payout_account: result })
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The new account starts in `PENDING` and can't receive payouts until the provider
|
|
33
|
+
marks it `ACTIVE`. See [Start onboarding](/platform/payout/guides/start-provider-onboarding).
|
|
34
|
+
|
|
35
|
+
<Note>
|
|
36
|
+
A seller can have **only one** payout account. The workflow validates this
|
|
37
|
+
first and fails if the store already has one.
|
|
38
|
+
</Note>
|
|
39
|
+
|
|
40
|
+
## Forward provider data
|
|
41
|
+
|
|
42
|
+
The workflow accepts `data` and `context` payloads that are passed straight to
|
|
43
|
+
the provider when it creates the connected account. Use them to hand the
|
|
44
|
+
provider anything it needs up front.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
await createPayoutAccountWorkflow(req.scope).run({
|
|
48
|
+
input: {
|
|
49
|
+
seller_id: "sel_123",
|
|
50
|
+
context: { idempotency_key: "sel_123" },
|
|
51
|
+
data: { business_type: "company" },
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
<Warning>
|
|
57
|
+
If the provider call fails after the record is created, the workflow rolls the
|
|
58
|
+
account back so you don't leave a dangling `PayoutAccount` behind.
|
|
59
|
+
</Warning>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Process a provider webhook"
|
|
3
|
+
sidebarTitle: "Process a webhook"
|
|
4
|
+
description: "Turn a provider webhook into account and payout status updates."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how a provider webhook becomes account and payout
|
|
8
|
+
status changes. Mercur already wires this up. A subscriber listens for
|
|
9
|
+
`payout.webhook_received` and drives the update workflow. Understanding the path
|
|
10
|
+
lets you emit the event yourself or extend the flow.
|
|
11
|
+
|
|
12
|
+
## The built-in path
|
|
13
|
+
|
|
14
|
+
The `payout-webhook` subscriber resolves the raw payload to an action through the
|
|
15
|
+
provider, then runs `processPayoutForWebhookWorkflow`:
|
|
16
|
+
|
|
17
|
+
```ts title="src/subscribers/payout-webhook.ts (shipped)"
|
|
18
|
+
const processedEvent = await payoutService.getWebhookActionAndData(input)
|
|
19
|
+
|
|
20
|
+
if (!processedEvent.data) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const wfEngine = container.resolve(Modules.WORKFLOW_ENGINE)
|
|
25
|
+
await wfEngine.run(processPayoutForWebhookWorkflowId, { input: processedEvent })
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`getWebhookActionAndData` delegates to the provider, which parses its own payload
|
|
29
|
+
and returns a `PayoutWebhookResult`. The result is an `action` plus the affected
|
|
30
|
+
`id`.
|
|
31
|
+
|
|
32
|
+
## Run the workflow directly
|
|
33
|
+
|
|
34
|
+
To process an already-parsed result yourself, run the workflow with a
|
|
35
|
+
`PayoutWebhookResult`:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { processPayoutForWebhookWorkflow } from "@mercurjs/core/workflows"
|
|
39
|
+
|
|
40
|
+
await processPayoutForWebhookWorkflow(container).run({
|
|
41
|
+
input: {
|
|
42
|
+
action: "payout.paid",
|
|
43
|
+
data: { id: "pout_123" },
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The workflow branches on `action`, updating the account or the payout:
|
|
49
|
+
|
|
50
|
+
| Action | Effect |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| `account.activated` / `account.restricted` / `account.rejected` | Set account status to `ACTIVE` / `RESTRICTED` / `REJECTED` |
|
|
53
|
+
| `payout.processing` / `payout.paid` / `payout.failed` / `payout.canceled` | Set payout status accordingly |
|
|
54
|
+
|
|
55
|
+
<Note>
|
|
56
|
+
Actions the provider can't map return `not_supported` (or a missing `data.id`),
|
|
57
|
+
and the workflow makes no change. It is safe to hand it every event the provider
|
|
58
|
+
sends.
|
|
59
|
+
</Note>
|
|
60
|
+
|
|
61
|
+
## Emit the event yourself
|
|
62
|
+
|
|
63
|
+
To route a custom provider integration through the same path, emit
|
|
64
|
+
`payout.webhook_received` with the raw payload and let the shipped subscriber
|
|
65
|
+
take over.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const eventBus = container.resolve(Modules.EVENT_BUS)
|
|
69
|
+
|
|
70
|
+
await eventBus.emit({
|
|
71
|
+
name: "payout.webhook_received",
|
|
72
|
+
data: { rawData, headers, data },
|
|
73
|
+
})
|
|
74
|
+
```
|