docs: revise commerce modules overview pages (#10738)

* revise API Key Module overview

* revise auth module

* support ref sidebar items

* remove examples

* revise cart module

* revise currency

* revise customer module

* revise fulfillment module

* revise inventory module

* revise order module

* revise payment

* revise pricing module

* revise product module

* revise promotion module

* revise region module

* revise sales channel module

* revise stock location module

* revise store module

* revise tax module

* revise user module

* lint content + fix snippets
This commit is contained in:
Shahed Nasser authored and GitHub committed 2024-12-26 10:32:16 +02:00
1 parent c8f9938865
commit ebca8fed28
112 files changed
+9465 -7731

No files matched your search

@@ -1,257 +0,0 @@
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: `Examples of the Sales Channel Module`,
}
# {metadata.title}
In this guide, you’ll find common examples of how you can use the Sales Channel Module in your application.
<Note>
You should only use the Sales Channel Module's main service when implementing complex customizations. For common cases, check out [available workflows instead](../../../medusa-workflows-reference/page.mdx).
</Note>
## Create a Sales Channel
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function POST(
request: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const salesChannelModuleService =
request.scope.resolve(Modules.SALES_CHANNEL)
const salesChannel = await salesChannelModuleService.createSalesChannels({
name: "B2B",
})
res.json({
sales_channel: salesChannel,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeSalesChannelModule } from "@medusajs/medusa/sales-channel"
export async function POST(request: Request) {
const salesChannelModuleService = await initializeSalesChannelModule()
const salesChannel = await salesChannelModuleService.createSalesChannels({
name: "B2B",
})
return NextResponse.json({ sales_channel: salesChannel })
}
```
</CodeTab>
</CodeTabs>
---
## List Sales Channels
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function GET(
request: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const salesChannelModuleService =
request.scope.resolve(Modules.SALES_CHANNEL)
res.json({
sales_channels: salesChannelModuleService.listSalesChannels(),
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeSalesChannelModule } from "@medusajs/medusa/sales-channel"
export async function GET(request: Request) {
const salesChannelModuleService = await initializeSalesChannelModule()
const salesChannels = await salesChannelModuleService.listSalesChannels()
return NextResponse.json({ sales_channels: salesChannels })
}
```
</CodeTab>
</CodeTabs>
---
## Retrieve a Sales Channel by its ID
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function GET(
request: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const salesChannelModuleService =
request.scope.resolve(Modules.SALES_CHANNEL)
const salesChannel = await salesChannelModuleService.retrieveSalesChannel(
"sc_123"
)
res.json({
sales_channel: salesChannel,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeSalesChannelModule } from "@medusajs/medusa/sales-channel"
export async function GET(request: Request) {
const salesChannelModuleService = await initializeSalesChannelModule()
const salesChannel = await salesChannelModuleService.retrieveSalesChannel(
"sc_123"
)
return NextResponse.json({ sales_channel: salesChannel })
}
```
</CodeTab>
</CodeTabs>
---
## Update a Sales Channel
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function POST(
request: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const salesChannelModuleService =
request.scope.resolve(Modules.SALES_CHANNEL)
const salesChannel = await salesChannelModuleService.updateSalesChannels({
id: "sc_123",
description: "Sales channel for B2B customers",
})
res.json({
sales_channel: salesChannel,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeSalesChannelModule } from "@medusajs/medusa/sales-channel"
export async function POST(request: Request) {
const salesChannelModuleService = await initializeSalesChannelModule()
const salesChannel = await salesChannelModuleService.updateSalesChannels({
id: "sc_123",
description: "Sales channel for B2B customers",
})
return NextResponse.json({ sales_channel: salesChannel })
}
```
</CodeTab>
</CodeTabs>
---
## Delete a Sales Channel
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function DELETE(
request: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const salesChannelModuleService =
request.scope.resolve(Modules.SALES_CHANNEL)
await salesChannelModuleService.deleteSalesChannels("sc_123")
res.status(200)
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeSalesChannelModule } from "@medusajs/medusa/sales-channel"
export async function DELETE(request: Request) {
const salesChannelModuleService = await initializeSalesChannelModule()
await salesChannelModuleService.deleteSalesChannels("sc_123")
}
```
</CodeTab>
</CodeTabs>
---
## More Examples
The [Sales Channel Module's main service reference](/references/sales-channel) provides a reference to all the methods available for use with examples for each.
@@ -45,8 +45,8 @@ To retrieve the API keys associated with a sales channel with [Query](!docs!/lea
const { data: salesChannels } = await query.graph({
entity: "sales_channel",
fields: [
"publishable_api_keys.*"
]
"publishable_api_keys.*",
],
})
// salesChannels.publishable_api_keys
@@ -63,8 +63,8 @@ import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data: salesChannels } = useQueryGraphStep({
entity: "sales_channel",
fields: [
"publishable_api_keys.*"
]
"publishable_api_keys.*",
],
})
// salesChannels.publishable_api_keys
@@ -134,8 +134,8 @@ To retrieve the carts of a sales channel with [Query](!docs!/learn/fundamentals/
const { data: salesChannels } = await query.graph({
entity: "sales_channel",
fields: [
"carts.*"
]
"carts.*",
],
})
// salesChannels.carts
@@ -152,8 +152,8 @@ import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data: salesChannels } = useQueryGraphStep({
entity: "sales_channel",
fields: [
"carts.*"
]
"carts.*",
],
})
// salesChannels.carts
@@ -179,8 +179,8 @@ To retrieve the orders of a sales channel with [Query](!docs!/learn/fundamentals
const { data: salesChannels } = await query.graph({
entity: "sales_channel",
fields: [
"orders.*"
]
"orders.*",
],
})
// salesChannels.orders
@@ -197,8 +197,8 @@ import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data: salesChannels } = useQueryGraphStep({
entity: "sales_channel",
fields: [
"orders.*"
]
"orders.*",
],
})
// salesChannels.orders
@@ -228,8 +228,8 @@ To retrieve the products of a sales channel with [Query](!docs!/learn/fundamenta
const { data: salesChannels } = await query.graph({
entity: "sales_channel",
fields: [
"products.*"
]
"products.*",
],
})
// salesChannels.products
@@ -246,8 +246,8 @@ import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data: salesChannels } = useQueryGraphStep({
entity: "sales_channel",
fields: [
"products.*"
]
"products.*",
],
})
// salesChannels.products
@@ -321,8 +321,8 @@ To retrieve the stock locations of a sales channel with [Query](!docs!/learn/fun
const { data: salesChannels } = await query.graph({
entity: "sales_channel",
fields: [
"stock_locations.*"
]
"stock_locations.*",
],
})
// salesChannels.stock_locations
@@ -339,8 +339,8 @@ import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data: salesChannels } = useQueryGraphStep({
entity: "sales_channel",
fields: [
"stock_locations.*"
]
"stock_locations.*",
],
})
// salesChannels.stock_locations
@@ -6,68 +6,15 @@ export const metadata = {
# {metadata.title}
The Sales Channel Module provides sales-channel-related features in your Medusa and Node.js applications.
In this section of the documentation, you will find resources to learn more about the Sales Channel Module and how to use it in your application.
## How to Use Sales Channel Module's Service
Medusa has sales channel related features available out-of-the-box through the Sales Channel Module. A [module](!docs!/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in commerce modules, such as this Sales Channel Module.
You can use the Sales Channel Module's main service by resolving from the Medusa container the resource `Modules.SALES_CHANNEL`.
<Note>
For example:
Learn more about why modules are isolated in [this documentation](!docs!/learn/fundamentals/modules/isolation).
<CodeTabs groupId="resource-type">
<CodeTab label="Workflow Step" value="workflow-step">
```ts title="src/workflows/hello-world/step1.ts"
import { createStep } from "@medusajs/framework/workflows-sdk"
import { Modules } from "@medusajs/framework/utils"
const step1 = createStep("step-1", async (_, { container }) => {
const salesChannelModuleService =
container.resolve(Modules.SALES_CHANNEL)
const salesChannels = await salesChannelModuleService.listSalesChannels()
})
```
</CodeTab>
<CodeTab label="API Route" value="api-route">
```ts title="src/api/store/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function GET(
request: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const salesChannelModuleService =
request.scope.resolve(Modules.SALES_CHANNEL)
res.json({
sales_channels: await salesChannelModuleService.listSalesChannels(),
})
}
```
</CodeTab>
<CodeTab label="Subscriber" value="subscribers">
```ts title="src/subscribers/custom-handler.ts"
import { SubscriberArgs } from "@medusajs/framework"
import { Modules } from "@medusajs/framework/utils"
export default async function subscriberHandler({ container }: SubscriberArgs) {
const salesChannelModuleService =
container.resolve(Modules.SALES_CHANNEL)
const salesChannels = await salesChannelModuleService.listSalesChannels()
}
```
</CodeTab>
</CodeTabs>
---
</Note>
## What's a Sales Channel?
@@ -81,31 +28,151 @@ Some use case examples for using a sales channel:
---
## Features
## Sales Channel Features
### Sales Channel Management
- [Sales Channel Management](/references/sales-channel/models/SalesChannel): Manage sales channels in your store. Each sales channel has different meta information such as name or description, allowing you to easily differentiate between sales channels.
- [Product Availability](./links-to-other-modules/page.mdx): Medusa uses the Product and Sales Channel modules to allow merchants to specify a product's availability per sales channel.
- [Cart and Order Scoping](./links-to-other-modules/page.mdx): Carts, available through the Cart Module, are scoped to a sales channel. Paired with the product availability feature, you benefit from more features like allowing only products available in sales channel in a cart.
- [Inventory Availability Per Sales Channel](./links-to-other-modules/page.mdx): Medusa links sales channels to stock locations, allowing you to retrieve available inventory of products based on the specified sales channel.
Manage sales channels in your store. Each sales channel has different meta information such as name or description, allowing you to easily differentiate between sales channels.
---
```ts
const salesChannels = await salesChannelModuleService.createSalesChannels([
{
name: "B2B",
## How to Use Sales Channel Module's Service
In your Medusa application, you build flows around commerce modules. A flow is built as a [Workflow](!docs!/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism.
You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package.
For example:
export const highlights = [
["12", "Modules.SALES_CHANNEL", "Resolve the module in a step."]
]
```ts title="src/workflows/create-sales-channel.ts" highlights={highlights}
import {
createWorkflow,
WorkflowResponse,
createStep,
StepResponse,
} from "@medusajs/framework/workflows-sdk"
import { Modules } from "@medusajs/framework/utils"
const createSalesChannelStep = createStep(
"create-sales-channel",
async ({}, { container }) => {
const salesChannelModuleService = container.resolve(Modules.SALES_CHANNEL)
const salesChannels = await salesChannelModuleService.createSalesChannels([
{
name: "B2B",
},
{
name: "Mobile App",
},
])
return new StepResponse({ salesChannels }, salesChannels.map((sc) => sc.id))
},
{
name: "Mobile App",
},
])
async (salesChannelIds, { container }) => {
if (!salesChannelIds) {
return
}
const salesChannelModuleService = container.resolve(Modules.SALES_CHANNEL)
await salesChannelModuleService.deleteSalesChannels(
salesChannelIds
)
}
)
export const createSalesChannelWorkflow = createWorkflow(
"create-sales-channel",
() => {
const { salesChannels } = createSalesChannelStep()
return new WorkflowResponse({
salesChannels,
})
}
)
```
### Product Availability
You can then execute the workflow in your custom API routes, scheduled jobs, or subscribers:
Medusa uses the Product and Sales Channel modules to allow merchants to specify a product's availability per sales channel.
<CodeTabs group="resource-types">
<CodeTab label="API Route" value="api-route">
```ts title="src/api/workflow/route.ts" highlights={[["11"], ["12"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import type {
MedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { createSalesChannelWorkflow } from "../../workflows/create-sales-channel"
For example, B2B customers viewing products only see products in the B2B sales channel.
export async function GET(
req: MedusaRequest,
res: MedusaResponse
) {
const { result } = await createSalesChannelWorkflow(req.scope)
.run()
### Cart and Order Scoping
res.send(result)
}
```
Carts, available through the Cart Module, are scoped to a sales channel. Paired with the product availability feature, you benefit from more features like allowing only products available in sales channel in a cart.
</CodeTab>
<CodeTab label="Subscriber" value="subscriber">
```ts title="src/subscribers/user-created.ts" highlights={[["11"], ["12"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import {
type SubscriberConfig,
type SubscriberArgs,
} from "@medusajs/framework"
import { createSalesChannelWorkflow } from "../workflows/create-sales-channel"
Orders are also scoped to a sales channel due to the relation between the Sales Channel and Order modules.
export default async function handleUserCreated({
event: { data },
container,
}: SubscriberArgs<{ id: string }>) {
const { result } = await createSalesChannelWorkflow(container)
.run()
console.log(result)
}
export const config: SubscriberConfig = {
event: "user.created",
}
```
</CodeTab>
<CodeTab label="Scheduled Job" value="scheduled-job">
```ts title="src/jobs/run-daily.ts" highlights={[["7"], ["8"]]}
import { MedusaContainer } from "@medusajs/framework/types"
import { createSalesChannelWorkflow } from "../workflows/create-sales-channel"
export default async function myCustomJob(
container: MedusaContainer
) {
const { result } = await createSalesChannelWorkflow(container)
.run()
console.log(result)
}
export const config = {
name: "run-once-a-day",
schedule: `0 0 * * *`,
}
```
</CodeTab>
</CodeTabs>
Learn more about workflows in [this documentation](!docs!/learn/fundamentals/workflows).
---
<CommerceModuleSections name="Sales Channel" />