docs: edits and fixes to commerce module docs (#7468)

Apply edits and fixes to the commerce modules docs
This commit is contained in:
Shahed Nasser
2024-05-29 14:08:06 +03:00
committed by GitHub
parent 130de74d6d
commit 2c5ba408d4
160 changed files with 6400 additions and 3790 deletions

View File

@@ -69,18 +69,18 @@ export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const customerService: ICustomerModuleService =
const customerModuleService: ICustomerModuleService =
req.scope.resolve(ModuleRegistrationName.CUSTOMER)
const customer = await customerService.retrieve(
req.auth.actor_id
const customer = await customerModuleService.retrieve(
req.auth_context.actor_id
)
// ...
}
```
In the route handler, you resolve the `CustomerService`, then use it to retrieve the logged-in customer, if available.
In the route handler, you resolve the Customer Module's main service, then use it to retrieve the logged-in customer, if available.
---
@@ -106,13 +106,15 @@ export const GET = async (
ModuleRegistrationName.USER
)
const user = await userService.retrieve(req.auth.actor_id)
const user = await userService.retrieve(
req.auth_context.actor_id
)
// ...
}
```
In the route handler, you resolve the `UserService`, and then use it to retrieve the logged-in admin user.
In the route handler, you resolve the User Module's main service, and then use it to retrieve the logged-in admin user.
---

View File

@@ -0,0 +1,29 @@
export const metadata = {
title: `API Key Concepts`,
}
# {metadata.title}
In this document, youll learn how about the different types of API keys, and their expiration and verification.
## API Key Types
There are two types of API keys:
- `publishable`: A public key used in client applications, such as a storefront.
- `secret`: A secret key used for authentication and verification purposes, such as an admin users authentication token or a password reset token.
The API keys type is stored in the `type` field of the [ApiKey data model](/references/api-key/models/ApiKey).
---
## API Key Expiration
An API key expires when its revoked using the [revoke method of the modules main service](/references/api-key/revoke).
The associated token is no longer usable or verifiable.
---
## Token Verification
To verify a token received as an input or in a request, use the [authenticate method of the modules main service](/references/api-key/authenticate) which validates the token against all non-expired tokens.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the API Key Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -120,19 +120,27 @@ In this guide, youll find common examples of how you can use the API Key Modu
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
AuthenticatedMedusaRequest,
MedusaResponse
} from "@medusajs/medusa"
import { IApiKeyModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
ModuleRegistrationName
} from "@medusajs/modules-sdk"
export async function POST(
request: MedusaRequest,
request: AuthenticatedMedusaRequest,
res: MedusaResponse
) {
const apiKeyModuleService: IApiKeyModuleService =
request.scope.resolve(ModuleRegistrationName.API_KEY)
const revokedKey = await apiKeyModuleService.revoke(
request.params.id
request.params.id,
{
revoked_by: request.auth_context.actor_id
}
)
res.json({
@@ -154,6 +162,7 @@ In this guide, youll find common examples of how you can use the API Key Modu
type ContextType = {
params: {
id: string
user_id: string
}
}
@@ -163,7 +172,12 @@ In this guide, youll find common examples of how you can use the API Key Modu
) {
const apiKeyModuleService = await initializeApiKeyModule()
const revokedKey = await apiKeyModuleService.revoke(params.id)
const revokedKey = await apiKeyModuleService.revoke(
params.id,
{
revoked_by: params.user_id
}
)
return NextResponse.json({
api_key: revokedKey,
@@ -176,7 +190,7 @@ In this guide, youll find common examples of how you can use the API Key Modu
---
## Verify Token
## Verify or Authenticate Token
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
@@ -194,7 +208,7 @@ In this guide, youll find common examples of how you can use the API Key Modu
request.scope.resolve(ModuleRegistrationName.API_KEY)
const authenticatedToken =
await apiKeyModuleService.authenticate(request.params.id)
await apiKeyModuleService.authenticate(request.params.token)
res.json({
is_authenticated: !!authenticatedToken,
@@ -214,7 +228,7 @@ In this guide, youll find common examples of how you can use the API Key Modu
type ContextType = {
params: {
id: string
token: string
}
}
@@ -225,7 +239,7 @@ In this guide, youll find common examples of how you can use the API Key Modu
const apiKeyModuleService = await initializeApiKeyModule()
const authenticatedToken =
await apiKeyModuleService.authenticate(request.params.id)
await apiKeyModuleService.authenticate(request.params.token)
return NextResponse.json({
is_authenticated: !!authenticatedToken,
@@ -244,19 +258,25 @@ In this guide, youll find common examples of how you can use the API Key Modu
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
AuthenticatedMedusaRequest,
MedusaResponse
} from "@medusajs/medusa"
import { IApiKeyModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function POST(
request: MedusaRequest,
request: AuthenticatedMedusaRequest,
res: MedusaResponse
) {
const apiKeyModuleService: IApiKeyModuleService =
request.scope.resolve(ModuleRegistrationName.API_KEY)
const revokedKey = await apiKeyModuleService.revoke(
request.params.id
request.params.id,
{
revoked_by: request.auth_context.actor_id
}
)
const newKey = await apiKeyModuleService.create({
@@ -284,6 +304,7 @@ In this guide, youll find common examples of how you can use the API Key Modu
type ContextType = {
params: {
id: string
user_id: string
}
}
@@ -293,7 +314,9 @@ In this guide, youll find common examples of how you can use the API Key Modu
) {
const apiKeyModuleService = await initializeApiKeyModule()
const revokedKey = await apiKeyModuleService.revoke(params.id)
const revokedKey = await apiKeyModuleService.revoke(params.id, {
revoked_by: params.user_id
})
const newKey = await apiKeyModuleService.create({
title: revokedKey.title,
@@ -314,4 +337,4 @@ In this guide, youll find common examples of how you can use the API Key Modu
## More Examples
The [module interface reference](/references/api-key) provides a reference to all the methods available for use with examples for each.
The [API Key Module's main service reference](/references/api-key) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,8 +8,6 @@ export const metadata = {
The API Key Module is the `@medusajs/api-key` NPM package that provides API-key-related features in your Medusa and Node.js applications.
---
## Features
### API Key Types and Management
@@ -54,7 +52,9 @@ if (!authenticatedToken) {
Revoke keys to disable their use permenantly.
```ts
const revokedKey = await apiKeyModuleService.revoke("apk_1")
const revokedKey = await apiKeyModuleService.revoke("apk_1", {
revoked_by: "user_123"
})
```
### Roll API Keys
@@ -62,7 +62,9 @@ const revokedKey = await apiKeyModuleService.revoke("apk_1")
Roll API keys by revoking a key then re-creating it.
```ts
const revokedKey = await apiKeyModuleService.revoke("apk_1")
const revokedKey = await apiKeyModuleService.revoke("apk_1", {
revoked_by: "user_123"
})
const newKey = await apiKeyModuleService.create({
title: revokedKey.title,
@@ -75,14 +77,16 @@ const newKey = await apiKeyModuleService.create({
## Configure API Key Module
After installing the `@medusajs/api-key` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the API Key Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
apiKey: {
resolve: "@medusajs/api-key",
},
[Modules.API_KEY]: true,
}
```
@@ -141,12 +145,15 @@ For example:
import { IApiKeyModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const apiKeyModuleService: IApiKeyModuleService =
context.container.resolve(
ModuleRegistrationName.API_KEY
)
const apiKeys = await apiKeyModuleService.list()
const step1 = createStep(
"step-1",
async (_, { container }) => {
const apiKeyModuleService: IApiKeyModuleService =
container.resolve(
ModuleRegistrationName.API_KEY
)
const apiKeys = await apiKeyModuleService.list()
})
```

View File

@@ -4,15 +4,13 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the API Key Module and other Commerce Modules.
This document showcases the link modules defined between the API Key Module and other commerce modules.
## Sales Channel Module
You can create a publishable API key and associate it with a sales channel. The Medusa application forms a relation between the `ApiKey` and the `SalesChannel` data models.
You can create a publishable API key and associate it with a sales channel. Medusa defines a link module that builds a relation between the `ApiKey` and the `SalesChannel` data models.
![A diagram showcasing an example of how resources from the API Key and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1710170465/Medusa%20Resources/api-key-sales-channel_ylpl6t.jpg)
![A diagram showcasing an example of how data models from the API Key and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709812064/Medusa%20Resources/sales-channel-api-key_zmqi2l.jpg)
This is useful to avoid passing the sales channel's ID as a parameter of every request, and instead pass the publishable API key in the header of any request to the Store API route.

View File

@@ -1,50 +0,0 @@
export const metadata = {
title: `API Key Tokens`,
}
# {metadata.title}
In this document, youll learn how the API Key module generates, revokes, and verifies tokens.
## API Key Types
There are two types of API keys:
- `publishable`: A public key used in client applications, such as a storefront.
- `secret`: A secret key used for authentication and verification purposes, such as an admin users authentication token or a password reset token.
The API keys type is stored in the `type` field of the `ApiKey` data model.
---
## Publishable Token Generation
When you create a publishable API key, its token is generated using [the `randomBytes` method of Node.jss crypto package](https://nodejs.org/docs/latest-v18.x/api/crypto.html#cryptorandombytessize-callback). The token is `32` characters long and is hex-encoded. Its stored in the `token` field of the `ApiKey` data model.
---
## Secret Token Generation
When you create a secret API key, three tokens are generated:
- A token thats `32` characters long and hex-encoded. Its generated using the `randomBytes` method of Node.jss crypto package.
- A salt token thats `15` characters long and hex-encoded. Its also generated using the `randomBytes` method.
- A hashed token is generated from the token and salt token using [the `scrypt` method of Node.jss crypto package](https://nodejs.org/docs/latest-v18.x/api/crypto.html#x509tostring). Its `64` characters long and hex-encoded.
The salt and hashed tokens are stored in the `ApiKey` data models `salt` and `token` fields, respectively.
---
## API Key Expiration
An API key expires when its revoked using the `revoke` method of the modules main service. The method sets the API keys `revoked_at` and `revoked_by` fields accordingly.
The associated token is no longer usable or verifiable.
---
## Token Verification
To verify a token received as an input or in a request, the `authenticate` method of the modules main service goes through all non-expired API keys. It recalculates the hash token using the supplied token and the API keys `salt` field.
If the calculated hashed token matches the one in the database, the token is considered verified.

View File

@@ -12,7 +12,7 @@ In this document, you'll learn about how the Auth Provider is used in an authent
## How to Authenticate a User
To authenticate a user, you use the `authenticate` method of the Auth Module's main service (`IAuthModuleService`). For example:
To authenticate a user, you use the [authenticate method of the Auth Module's main service](/references/auth/authenticate) (`IAuthModuleService`). For example:
```ts
const data = await authModuleService.authenticate(
@@ -24,13 +24,7 @@ const data = await authModuleService.authenticate(
)
```
This method calls the `authenticate` method of the specified provider and returns its data.
<Note>
Learn about the parameters and return type of the `IAuthModuleService`'s `authenticate` method in [this reference](/references/auth/authenticate).
</Note>
This method calls the `authenticate` method of the provider specified in the first parameter and returns its data.
---
@@ -51,7 +45,7 @@ Then, the user is authenticated successfully, and their authentication details a
<Note>
Learn more about the `authIdentity` in [this guide](../persisting-auth-user/page.mdx#what-is-an-authuser).
Check out the [AuthIdentity](/references/auth/models/AuthIdentity) reference for the expected fields in `authIdentity`.
</Note>
@@ -65,8 +59,8 @@ If the `authenticate` method returns the following object:
```ts
data = {
success: true,
location: "https://....",
success: true,
location: "https://....",
}
```
@@ -78,7 +72,7 @@ It means the authentication process requires the user to perform an action with
Providers handling this authentication flow must implement the `validateCallback` method. It implements the logic to validate the authentication with the third-party service.
So, once the user performs the required action, the third-party service must redirect to an API route that uses the `validateCallback` method of the `IAuthModuleService`. The method calls the specified providers `validateCallback` method passing it the authentication details it received in the second parameter:
So, once the user performs the required action, the third-party service must redirect to an API route that uses the [validateCallback method of the Auth Module's main service](/references/auth/validateCallback). The method calls the specified providers `validateCallback` method passing it the authentication details it received in the second parameter:
```ts
const data = await authModuleService.validateCallback(
@@ -90,13 +84,7 @@ const data = await authModuleService.validateCallback(
)
```
<Note>
Learn more about the parameters and return type of the `IAuthModuleService`'s `validateCallback` method in [this reference](/references/auth/validateCallback).
</Note>
If the authentication is successful, the auth providers `validateCallback` method returns the same data as the basic authentication:
If the authentication is successful, the `validateCallback` method returns the same data as the basic authentication:
```ts
data = {

View File

@@ -6,34 +6,43 @@ export const metadata = {
In this document, youll learn how the Auth Module handles authentication using providers.
## What's an Auth Provider?
## What's an Auth Provider Module?
An auth provider is a TypeScript or JavaScript class used to authenticate customers and users. Each provider implements the authentication logic based on its purpose.
An auth provider module handles authenticating customers and users, either using custom logic or by integrating a third-party service.
For example, the `emailpass` provider authenticates a user using their email and password, whereas the `google` provider authenticates users using their Google account.
For example, the EmailPass Auth Provider Module authenticates a user using their email and password, whereas the Google Auth Provider Module authenticates users using their Google account.
<Note type="check">
Support for the Google Auth Provider Module is coming soon.
</Note>
---
## The Auth Provider Class
## Configure Auth Provider Modules
An auth provider implements the `AbstractAuthModuleProvider` class imported from the `@medusajs/utils` package. The provider must implement the `authenticate` method that authenticates a user.
By default, admin users and customers can login with all installed auth provider moduless.
When you call the `authenticate` method of the Auth Module's main service (`IAuthModuleService`), the method resolves the specified provider and calls its `authenticate` method passing it the second parameter it received:
To limit the auth providers that used for admin users and customers, use the [authMethodsPerActor option](/references/medusa-config#http-authMethodsPerActor-1-3) in Medusa's configurations:
```ts
const data = await authModuleService.authenticate(
"emailpass",
// passed to auth provider
{
```js title="medusa-config.js"
module.exports = {
projectConfig: {
http: {
authMethodsPerActor: {
user: ["google"],
customer: ["emailpass"]
},
// ...
}
)
},
// ...
}
}
```
It also returns the same data returned by the auth provider.
---
<Note>
## How to Create an Auth Provider Module
Learn about the parameters and return type of the `IAuthModuleService`'s `authenticate` method in [this reference](/references/auth/authenticate).
</Note>
Refer to [this guide](/references/auth/provider) to learn how to create an auth provider module.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Auth Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -218,7 +218,7 @@ This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/j
---
## Create Auth User
## Create Auth Identity
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
@@ -275,7 +275,7 @@ This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/j
---
## List Auth Users
## List Auth Identities
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
@@ -322,7 +322,7 @@ This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/j
---
## Update an Auth User
## Update an Auth Identity
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
@@ -392,7 +392,7 @@ This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/j
---
## Delete an Auth User
## Delete an Auth Identity
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
@@ -448,4 +448,4 @@ This example uses the [jsonwebtoken NPM package](https://www.npmjs.com/package/j
## More Examples
The [module interface reference](/references/auth) provides a reference to all the methods available for use with examples for each.
The [Auth Module's main service reference](/references/auth) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,13 +8,11 @@ export const metadata = {
The Auth Module is the `@medusajs/auth` NPM package that provides authentication-related features in your Medusa and Node.js applications.
---
## Features
### Authenticate Users
### Basic User Authentication
With the Auth Module, authenticate users using their credentials.
With the Auth Module, authenticate users using their email and password credentials.
```ts
const { success, authIdentity, error } =
@@ -71,25 +69,22 @@ const { success, authIdentity } =
## Configure Auth Module
After installing the `@medusajs/auth` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Auth Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
auth: {
resolve: "@medusajs/auth",
options: {
providers: [
// ...
],
},
},
[Modules.AUTH]: true,
}
```
### Module Options
{/* ### Module Options
Refer to [this documentation](./module-options/page.mdx) for details on the module's options.
Refer to [this documentation](./module-options/page.mdx) for details on the module's options. */}
---
@@ -103,9 +98,14 @@ For example:
<CodeTab label="API Route" value="api-route">
```ts title="src/api/store/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
MedusaRequest,
MedusaResponse
} from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
ModuleRegistrationName
} from "@medusajs/modules-sdk"
export async function GET(
req: MedusaRequest,
@@ -126,7 +126,9 @@ For example:
```ts title="src/subscribers/custom-handler.ts"
import { SubscriberArgs } from "@medusajs/medusa"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
ModuleRegistrationName
} from "@medusajs/modules-sdk"
export default async function subscriberHandler({
container,
@@ -144,11 +146,15 @@ For example:
```ts title="src/workflows/hello-world/step1.ts"
import { createStep } from "@medusajs/workflows-sdk"
import { IAuthModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
ModuleRegistrationName
} from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const authModuleService: IAuthModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.AUTH
)
const authIdentitys = await authModuleService.list()

View File

@@ -1,58 +0,0 @@
---
sidebar_label: "Persisting Auth User"
---
export const metadata = {
title: `Persisting Auth User Authentication`,
}
# {metadata.title}
In this document, youll learn what the `AuthIdentity` is and how to persist its authentication.
## What is an AuthIdentity?
As explained in the [Auth Provider](../auth-providers/page.mdx) guide, when a user or customer is authenticated, you receive an `authIdentity` object:
```ts
const { success, authIdentity } =
await authModuleService.authenticate("emailpass", {
// ...
})
```
The `authIdentity` object is a record of the `AuthIdentity` data model. It has details about the authenticated user or customer, such as their ID, email, and other details.
<Note>
Learn more about the `AuthIdentity`'s fields in [this reference](/references/auth/models/AuthIdentity).
</Note>
---
## Persisting Authentication
While the Auth Module provides the authentication functionality, it doesnt provide the functionality to persist the authentication, as that depends on your applications requirements.
For example, the Medusa applications authentication route signs the `authIdentity` object into a JSON Web Token (JWT):
```ts
const {
success,
authIdentity,
} = await service.authenticate(auth_provider, authData)
// ...
const {
jwtSecret,
} = req.scope.resolve("configModule").projectConfig.http
const token = jwt.sign(authIdentity, jwtSecret)
```
Then, the token is passed in the header of subsequent requests in the Authorization Bearer header.
An authentication middleware verifies the token and attaches the associated `authIdentity`'s details to the `auth` property of the request object passed to the subsequent middlewares and route.
If the authentication middleware cant verify the token, the user isnt authenticated and theyre asked to login again.

View File

@@ -3,32 +3,14 @@ sidebar_label: "User Creation"
---
export const metadata = {
title: `User Creation with Auth Module`,
title: `User Creation`,
}
# {metadata.title}
In this document, youll learn about the user-creation flow and how to use it with the User Module.
In this document, youll learn about creating a user with the User Module after authentication.
## Auth User Creation in Authentication Flow
In the [Auth Provider](../auth-providers/page.mdx) documentation, you learned about the authentication flows supported by the Auth Module. These flows are used when an `AuthIdentity` is already available for the specified authentication data, such as email/password credentials.
However, the `emailpass` and `google` providers support creating an `AuthIdentity` if none exists. If an email is provided that doesnt have an `AuthIdentity` associated with it (checked via its `entity_id` field) for the specified provider (checked via its `provider` field), a new `AuthIdentity` is created for that email and provider.
![Diagram showcasing the AuthIdentity creation part of the authentication flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1711441638/Medusa%20Resources/auth-user-creation_gmahvl.jpg)
So, by default, your authentication flow supports both sign-in and sign-up flows.
<Note title="Tip">
This step actually occurs at different points of the authentication flow for each of the providers. For the `emailpass` provider, it occurs before checking that the password is correct. For the `google` provider, you must go through the full authentication flow to retrieve the user details, such as email, from Google.
</Note>
---
## Creating a User in the User Module
## Creating a User using the User Module
The User Module provides user and invite management functionalities. However, it doesnt provide authentication functionalities or store any related data.

View File

@@ -8,7 +8,7 @@ In this document, youll get an overview of the main concepts of a cart.
## Shipping and Billing Addresses
A cart has a shipping and billing address. Both of these addresses are represented by the `Address` data model.
A cart has a shipping and billing address. Both of these addresses are represented by the [Address data model](/references/cart/models/Address).
![A diagram showcasing the relation between the Cart and Address data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1711532392/Medusa%20Resources/cart-addresses_ls6qmv.jpg)
@@ -16,13 +16,13 @@ A cart has a shipping and billing address. Both of these addresses are represent
## Line Items
A line item, represented by the `LineItem` data model, is a product added to the cart. A cart has multiple line items.
A line item, represented by the `LineItem` data model, is a product variant added to the cart. A cart has multiple line items.
A line item stores some of the products fields, such as the `product_title` and `product_description`. It also stores data related to the items quantity and price.
A line item stores some of the product variants fields, such as the `product_title` and `product_description`. It also stores data related to the items quantity and price.
<Note>
A product can be from the [Product Module](../../product/page.mdx) but can also be a custom item used only in this cart.
A product variant can be from the [Product Module](../../product/page.mdx) but can also be a custom item used only in this cart.
</Note>
@@ -30,16 +30,14 @@ A product can be from the [Product Module](../../product/page.mdx) but can also
## Shipping Methods
A shipping method, represented by the `ShippingMethod` data model, is the method used to fulfill the items in the cart after the order is placed. A cart can have more than one shipping method.
A shipping method, represented by the [ShippingMethod data model](/references/cart/models/ShippingMethod), is used to fulfill the items in the cart after the order is placed. A cart can have more than one shipping method.
If the shipping method is created from a shipping option, typically available through the Fulfillment Module, its ID is stored in the `shipping_option_id`.
If the shipping method is created from a shipping option, available through the [Fulfillment Module](../../fulfillment/page.mdx), its ID is stored in the `shipping_option_id`.
A shipping method can also be a custom method associated with this cart only.
### data Field
When fulfilling the order after its placed, you may use a third-party fulfillment provider that requires additional custom data to be passed along from the checkout process.
After an order is placed, you may use a third-party fulfillment provider to fulfill its shipments. If the fulfillment provider requires additional custom data to be passed along from the checkout process, you can add this data in the `ShippingMethod`'s `data` field.
The `ShippingMethod` data model has a `data` field. It's an object used to store custom data relevant later for fulfillment.
In the Medusa application, it's the `data` is passed to the Fulfillment Module when fulfilling items.
The `data` field is an object used to store custom data relevant later for fulfillment.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Cart Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -448,7 +448,7 @@ In this guide, youll find common examples of how you can use the Cart Module
const cartModuleService: ICartModuleService =
req.scope.resolve(ModuleRegistrationName.CART)
await cartModuleService.deleteLineItems(["cali_123"])
await cartModuleService.deleteShippingMethods(["casm_123"])
res.status(200)
}
@@ -482,4 +482,4 @@ In this guide, youll find common examples of how you can use the Cart Module
## More Examples
The [module interface reference](/references/cart) provides a reference to all the methods available for use with examples for each.
The [Cart Module's main service reference](/references/cart) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,8 +8,6 @@ export const metadata = {
The Cart Module is the `@medusajs/cart` NPM package that provides cart-related features in your Medusa and Node.js applications.
---
## Features
### Cart Management
@@ -67,14 +65,16 @@ When used with their respective modules and other commerce modules, you benefit
## Configure Cart Module
After installing the `@medusajs/cart` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Cart Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
cart: {
resolve: "@medusajs/cart",
},
[Modules.CART]: true,
}
```
@@ -134,11 +134,14 @@ For example:
import { ICartModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const cartModuleService: ICartModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.CART
)
const carts = await cartModuleService.list()
})
```

View File

@@ -14,17 +14,26 @@ In this document, youll learn how a promotion is applied to a carts line i
An adjustment line indicates a change to an item or a shipping methods amount. Its used to apply promotions or discounts on a cart.
The `LineItemAdjustment` data model represents adjustment lines for a line item, and the `ShippingMethodAdjustment` data model represents adjustment lines for a shipping method.
The `LineItemAdjustment` data model represents changes on a line item, and the `ShippingMethodAdjustment` data model represents changes on a shipping method.
![A diagram showcasing the relations between other data models and adjustment line models](https://res.cloudinary.com/dza7lstvk/image/upload/v1711534248/Medusa%20Resources/cart-adjustments_k4sttb.jpg)
The `amount` field of the adjustment line indicates the amount to be discounted from the original amount. Also, the ID of the applied promotion can be stored in the `promotion_id` field of the adjustment line.
The `amount` field of the adjustment line indicates the amount to be discounted from the original amount. Also, the ID of the applied promotion is stored in the `promotion_id` field of the adjustment line.
---
## Discountable Option
The `LineItem` data model has an `is_discountable` field that indicates whether promotions can be applied to the line item. Its enabled by default.
When disabled, a promotion cant be applied to a line item. In the context of the Promotion Module, the promotion isnt applied to the line item even if it matches its rules.
---
## Promotion Actions
When using the Cart and Promotion modules together, such as in the Medusa application, use the `computeActions` method of the Promotion Modules main service. It retrieves the actions of line items and shipping methods.
When using the Cart and Promotion modules together, use the [computeActions method of the Promotion Modules main service](/references/promotion/computeActions). It retrieves the actions of line items and shipping methods.
<Note>
@@ -90,12 +99,6 @@ const actions = await promotionModuleService.computeActions(
The `computeActions` method accepts the existing adjustments of line items and shipping methods to compute the actions accurately.
<Note>
Learn more about the `computeActions` method in [this reference](/references/promotion/computeActions).
</Note>
Then, use the returned `addItemAdjustment` and `addShippingMethodAdjustment` actions to set the carts line item and the shipping methods adjustments.
```ts
@@ -121,12 +124,4 @@ await cartModuleService.setShippingMethodAdjustments(
action.action === "addShippingMethodAdjustment"
) as AddShippingMethodAdjustment[]
)
```
---
## Discountable Option
The `LineItem` data model has an `is_discountable` field that indicates whether promotions can be applied to the line item. Its enabled by default.
When disabled, a promotion cant be applied to a line item. In the context of the Promotion Module, the promotion isnt applied to the line item even if it matches its rules.
```

View File

@@ -4,36 +4,50 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the Cart Module and other Commerce Modules.
This document showcases the link modules defined between the Cart Module and other commerce modules.
## Customer Module
A cart is scoped to the customer using it. The Medusa application forms a relation between the `Cart` and `Customer` data models.
A cart is scoped to the customer using it. Medusa defines a link module that builds a relationship between the `Cart` and `Customer` data models.
![A diagram showcasing an example of how resources from the Cart and Customer modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537276/Medusa%20Resources/cart-customer_pnjvuw.jpg)
![A diagram showcasing an example of how data models from the Cart and Customer modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537276/Medusa%20Resources/cart-customer_pnjvuw.jpg)
---
## Payment Module
The Payment Module allows you to associate payments with a cart. The Medusa application forms a relation between the `Cart` and `PaymentCollection` data models.
The Payment Module allows you to associate payments with a cart. Medusa defines a link module that builds a relationship between the `Cart` and `PaymentCollection` data models.
![A diagram showcasing an example of how resources from the Cart and Payment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537849/Medusa%20Resources/cart-payment_ixziqm.jpg)
![A diagram showcasing an example of how data models from the Cart and Payment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537849/Medusa%20Resources/cart-payment_ixziqm.jpg)
---
## Product Module
A cart's line item is associated with a product and its variant. Medusa defines a link module that builds a relationship between the `Cart`, `Product`, and `ProductVariant` data models.
![A diagram showcasing an example of how data models from the Cart and Product modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716546229/Medusa%20Resources/cart-product_x82x9j.jpg)
---
## Promotion Module
A promotion can be applied on line items and shipping methods of a cart. The Medusa application forms a relation between the `Cart` and `Promotion` data models.
A promotion can be applied on line items and shipping methods of a cart. Medusa defines a link module that builds a relationship between the `Cart`, `LineItemAdjustment`, and `Promotion` data models.
![A diagram showcasing an example of how resources from the Cart and Promotion modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538015/Medusa%20Resources/cart-promotion_kuh9vm.jpg)
![A diagram showcasing an example of how data models from the Cart and Promotion modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538015/Medusa%20Resources/cart-promotion_kuh9vm.jpg)
---
## Region Module
A cart is scoped to a region. Medusa defines a link module that builds a relationship between the `Cart` and `Region` data models.
![A diagram showcasing an example of how data models from the Cart and Region modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716543714/Medusa%20Resources/customer-region_rtmymb.jpg)
---
## Sales Channel Module
A cart is scoped to a sales channel. The Medusa application forms a relation between the `Cart` and `SalesChannel` data models.
A cart is scoped to a sales channel. Medusa defines a link module that builds a relationship between the `Cart` and `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Cart and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538159/Medusa%20Resources/cart-sales-channel_n2oi0v.jpg)
![A diagram showcasing an example of how data models from the Cart and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538159/Medusa%20Resources/cart-sales-channel_n2oi0v.jpg)

View File

@@ -8,7 +8,7 @@ In this document, youll learn about tax lines in a cart and how to retrieve t
## What are Tax Lines?
A tax line indicates the tax rate of a line item or a shipping method. The `LineItemTaxLine` data model represents a line items tax line, and the `ShippingMethodTaxLine` data model represents a shipping methods tax line.
A tax line indicates the tax rate of a line item or a shipping method. The [LineItemTaxLine data model](/references/cart/models/LineItemTaxLine) represents a line items tax line, and the [ShippingMethodTaxLine data model](/references/cart/models/ShippingMethodTaxLine) represents a shipping methods tax line.
![A diagram showcasing the relation between other data models and the tax line models](https://res.cloudinary.com/dza7lstvk/image/upload/v1711534431/Medusa%20Resources/cart-tax-lines_oheaq6.jpg)
@@ -34,7 +34,7 @@ The following diagram is a simplified showcase of how a subtotal is calculated f
## Retrieving Tax Lines
When using the Cart and Tax modules together, such as in the Medusa application, you can use the `getTaxLines` method of the Tax Modules main service. It retrieves the tax lines for a carts line items and shipping methods.
When using the Cart and Tax modules together, you can use the `getTaxLines` method of the Tax Modules main service. It retrieves the tax lines for a carts line items and shipping methods.
```ts
// retrieve the cart

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Currency Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -55,7 +55,7 @@ In this guide, youll find common examples of how you can use the Currency Mod
---
## Retrieve a Currency by its ID
## Retrieve a Currency by its Code
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
@@ -108,4 +108,4 @@ In this guide, youll find common examples of how you can use the Currency Mod
## More Examples
The [Currency Module interface reference](/references/currency) provides a reference to all the methods available for use with examples for each.
The [Currency Module's main service reference](/references/currency) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,23 +8,19 @@ export const metadata = {
The Currency Module is the `@medusajs/currency` NPM package that provides currency-related features in your Medusa and Node.js applications.
---
## Features
### Currency Retrieval
List and retrieve currencies stored in your application.
By default, the module, on application start, adds currencies defined in [this file](https://github.com/medusajs/medusa/blob/develop/packages/utils/src/defaults/currencies.ts) to the database.
```ts
const currency = await currencyModuleService.retrieve("usd")
```
### Support Currencies in Modules
Other commerce modules use currency codes in their models or operations. You can use the Currency Module to retrieve a currency code and its details.
Other commerce modules use currency codes in their data models or operations. You can use the Currency Module to retrieve a currency code and its details.
An example with the Region Module:
@@ -39,14 +35,16 @@ const currency = await currencyModuleService.retrieve(
## Configure Currency Module
After installing the `@medusajs/currency` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Currency Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
currency: {
resolve: "@medusajs/currency",
},
[Modules.CURRENCY]: true,
}
```
@@ -105,9 +103,11 @@ For example:
import { ICurrencyModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const currencyModuleService: ICurrencyModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.CURRENCY
)

View File

@@ -0,0 +1,13 @@
export const metadata = {
title: `Relations between Currency Module and Other Modules`,
}
# {metadata.title}
This document showcases the link modules defined between the Currency Module and other commerce modules.
## Store Module
A store has a default currency. Medusa defines a link module that builds a relationship between the `Store` and `Currency` data models.
![A diagram showcasing an example of how resources from the Stock Location and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1716798146/Medusa%20Resources/store-currency_wzftwh.jpg)

View File

@@ -8,7 +8,7 @@ In this document, youll learn how registered and unregistered accounts are di
## `has_account` field
The `Customer` data model has a `has_account` field, which is a boolean that indicates whether a customer is registerd.
The [Customer data model](/references/customer/models/Customer) has a `has_account` field, which is a boolean that indicates whether a customer is registerd.
When a guest customer places an order, a new `Customer` record is created with `has_account` set to `false`.
@@ -20,4 +20,4 @@ When this or another guest customer registers an account with the same email, a
The above behavior means that two `Customer` records may exist of the same email. However, the main difference is the `has_account` fields value.
So, there can only be one guest customer (having `has_account=false`) and one registered customer (having `has_account=true`) with the same email. If another customer tries to create an account with the same email, theyll get an error that an account with this email already exists.
So, there can only be one guest customer (having `has_account=false`) and one registered customer (having `has_account=true`) with the same email.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Customer Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -233,4 +233,4 @@ In this guide, youll find common examples of how you can use the Customer Mod
## More Examples
The [module interface reference](/references/customer) provides a reference to all the methods available for use with examples for each.
The [Customer Module's main service reference](/references/customer) provides a reference to all the methods available for use with examples for each.

View File

@@ -42,14 +42,16 @@ await customerModuleService.addCustomerToGroup({
## Configure Customer Module
After installing the `@medusajs/customer` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Customer Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
customer: {
resolve: "@medusajs/customer",
},
[Modules.CUSTOMER]: true,
}
```
@@ -108,9 +110,11 @@ For example:
import { ICustomerModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const customerModuleService: ICustomerModuleService =
context.container.resolve(ModuleRegistrationName.PRODUCT)
container.resolve(ModuleRegistrationName.CUSTOMER)
const customers = await customerModuleService.list()
})

View File

@@ -4,13 +4,19 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the Customer Module and other Commerce Modules.
This document showcases the link modules defined between the Customer Module and other commerce modules.
## Cart Module
A customer has a cart to purchase items from the store. The Medusa application forms a relation between the `Customer` and the `Cart` data models.
A customer has a cart to purchase items from the store. Medusa defines a link module that builds a relationship between the `Customer` and the `Cart` data models.
![A diagram showcasing an example of how resources from the Customer and Cart modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709915775/Medusa%20Resources/customer-cart_by5e7s.jpg)
![A diagram showcasing an example of how data models from the Customer and Cart modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537276/Medusa%20Resources/cart-customer_pnjvuw.jpg)
---
## Order Module
A customer is associated with the orders they place. Medusa defines a link module that builds a relationship between the `Customer` and the `Order` data models.
![A diagram showcasing an example of how data models from the Customer and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716545470/Medusa%20Resources/customer-order_pkla6f.jpg)

View File

@@ -10,7 +10,7 @@ In this document, youll learn about some basic fulfillment concepts.
A fulfillment set is a general form or way of fulfillment. For example, shipping is a form of fulfillment, and pick-up is another form of fulfillment. Each of these can be created as fulfillment sets.
A fulfillment set is represented by the `FulfillmentSet` data model. All other configurations, options, and management features are related to a fulfillment set, in one way or another. So, the first step when using the Fulfillment Module is to create a fulfillment set.
A fulfillment set is represented by the [FulfillmentSet data model](/references/fulfillment/models/FulfillmentSet). All other configurations, options, and management features are related to a fulfillment set, in one way or another.
```ts
const fulfillmentSets = await fulfillmentModuleService.create(
@@ -33,13 +33,11 @@ const fulfillmentSets = await fulfillmentModuleService.create(
A service zone is a collection of geographical zones or areas. Its used to restrict available shipping options to a defined set of locations.
A service zone is represented by the `ServiceZone` data model. Its associated with a fulfillment set, as each service zone is specific to a form of fulfillment. For example, if a customer chooses to pick up items, you can restrict the available shipping options based on their location.
A service zone is represented by the [ServiceZone data model](/references/fulfillment/models/ServiceZone). Its associated with a fulfillment set, as each service zone is specific to a form of fulfillment. For example, if a customer chooses to pick up items, you can restrict the available shipping options based on their location.
A fulfillment set can have multiple service zones, each restricting different locations.
![A diagram showcasing the relation between fulfillment sets, service zones, and geo zones](https://res.cloudinary.com/dza7lstvk/image/upload/v1712329770/Medusa%20Resources/service-zone_awmvfs.jpg)
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712329770/Medusa%20Resources/service-zone_awmvfs.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712329770/Medusa%20Resources/service-zone_awmvfs.jpg)
A service zone can have multiple geographical zones, each represented by the `GeoZone` data model. It holds location-related details to narrow down supported areas, such as country, city, or province code.
A service zone can have multiple geographical zones, each represented by the [GeoZone data model](/references/fulfillment/models/GeoZone). It holds location-related details to narrow down supported areas, such as country, city, or province code.
---
@@ -47,4 +45,4 @@ A service zone can have multiple geographical zones, each represented by the `Ge
A shipping profile defines a type of items that are shipped in a similar manner. For example, a `default` shipping profile is used for all item types, but the `digital` shipping profile is used for digital items that arent shipped and delivered conventionally.
A shipping profile is represented by the `ShippingProfile` data model. It only defines the profiles details, but its associated with the shipping options available for the item type.
A shipping profile is represented by the [ShippingProfile data model](/references/fulfillment/models/ShippingProfile). It only defines the profiles details, but its associated with the shipping options available for the item type.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Fulfillment Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -1,25 +1,27 @@
export const metadata = {
title: `Fulfillment Provider`,
title: `Fulfillment Provider Module`,
}
# {metadata.title}
In this document, youll learn what a fulfillment provider is.
In this document, youll learn what a fulfillment provider module is.
## Whats a Fulfillment Provider?
## Whats a Fulfillment Provider Module?
A fulfillment provider implements the functionality of fulfilling items, typically using a third-party integration. Its represented by the `FulfillmentProvider` data model.
A fulfillment provider module handles fulfilling items, typically using a third-party integration.
---
## How to Create a Fulfillment Provider?
A fulfillment provider is a TypeScript or JavaScript class that extends the `AbstractFulfillmentProviderService` class imported from `@medusajs/utils`. You can create it part of your Medusa application codebase, in a plugin, or in a provider module.
Fulfillment provider modules are stored and represented by the [FulfillmentProvider data model](/references/fulfillment/models/FulfillmentProvider).
---
## Configure Fulfillment Providers
The Fulfillment Module accepts a `providers` option that allows you to register providers in your application. When the Medusa application starts, it registers these modules and adds records of the `FulfillmentProvider` for them.
The Fulfillment Module accepts a `providers` option that allows you to register providers in your application.
Learn more about the `providers` option in [this documentation](../module-options/page.mdx).
---
## How to Create a Fulfillment Provider?
Refer to [this guide](/references/fulfillment/provider) to learn how to create a fulfillment provider module.

View File

@@ -8,7 +8,7 @@ In this document, youll learn about the concepts of item fulfillment.
## Fulfillment Data Model
A fulfillment is the shipping and delivery of one or more items to the customer. Its represented by the `Fulfillment` data model.
A fulfillment is the shipping and delivery of one or more items to the customer. Its represented by the [Fulfillment data model](/references/fulfillment/models/Fulfillment).
---
@@ -18,7 +18,7 @@ A fulfillment is associated with a fulfillment provider that handles all its pro
The fulfillment is also associated with a shipping option of that provider, which determines how the item is shipped.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712331947/Medusa%20Resources/fulfillment-shipping-option_jk9ndp.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331947/Medusa%20Resources/fulfillment-shipping-option_jk9ndp.jpg)
![A diagram showcasing the relation between a fulfillment, fulfillment provider, and shipping option](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331947/Medusa%20Resources/fulfillment-shipping-option_jk9ndp.jpg)
---
@@ -36,7 +36,7 @@ A fulfillment is used to fulfill one or more items. Each item is represented by
The fulfillment item holds details relevant to fulfilling the item, such as barcode, SKU, and quantity to fulfill.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712332114/Medusa%20Resources/fulfillment-item_etzxb0.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712332114/Medusa%20Resources/fulfillment-item_etzxb0.jpg)
![A diagram showcasing the relation between fulfillment and fulfillment items.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712332114/Medusa%20Resources/fulfillment-item_etzxb0.jpg)
---

View File

@@ -14,7 +14,7 @@ In this document, you'll learn about the options of the Fulfillment Module.
## providers
The `providers` option is an array of either fulfillment provider modules, fulfillment plugins, or path to a file that holds a fulfillment provider.
The `providers` option is an array of fulfillment provider modules.
When the Medusa application starts, these providers are registered and can be used to process fulfillments.
@@ -29,6 +29,13 @@ const modules = {
providers: [
{
resolve: `@medusajs/fulfillment-manual`,
options: {
config: {
manual: {
// provider options...
}
}
}
},
],
},
@@ -38,5 +45,6 @@ const modules = {
The `providers` option is an array of objects that accept the following properties:
- `resolve`: A string indicating the package name of the fulfillment provider module or the fulfillment plugin, or the path to the file defining the fulfillment provider.
- `options`: An optional object of options to pass to the fulfillment provider.
- `resolve`: A string indicating either the package name of the fulfillment provider module or the path to it.
- `options`: An optional object of the fulfillment provider module's options. The object must have the following property:
- `config`: An object whose key is the ID of the fulfillment provider, and its value is an object of options to pass to the provider module.

View File

@@ -8,13 +8,11 @@ export const metadata = {
The Fulfillment Module is the `@medusajs/fulfillment` NPM package that provides fulfillment-related features in your Medusa and Node.js applications.
---
## Features
### Fulfillment Management
Create fulfillments and keep track of their statuses, items, and more.
Create fulfillments and keep track of their status, items, and more.
```ts
const fulfillment =
@@ -46,7 +44,6 @@ Use third-party fulfillment providers to provide customers with shipping options
```ts
const shippingOption =
await fulfillmentModuleService.createShippingOptions({
name: "Express shipping",
// ...
provider_id: "webshipper",
})
@@ -109,12 +106,14 @@ const fulfillmentSets = await fulfillmentModuleService.create(
## Configure Fulfillment Module
After installing the `@medusajs/fulfillment` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Fulfillment Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
const modules = {
// ...
fulfillment: {
[Modules.FULFILLMENT]: {
resolve: "@medusajs/fulfillment",
providers: [
// ...
@@ -184,11 +183,14 @@ For example:
import { IFulfillmentModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const fulfillmentModuleService: IFulfillmentModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.FULFILLMENT
)
const fulfillments =
await fulfillmentModuleService.listFulfillments()
})

View File

@@ -4,14 +4,26 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the link modules defined between the Fulfillment Module and other commerce modules.
This document showcases the relation between the Fulfillment Module and other Commerce Modules.
## Order Module
A fulfillment is created for an orders' items. Medusa defines a link module that builds a relationship between the `Fulfillment` and `Order` data models.
![A diagram showcasing an example of how data models from the Fulfillment and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716549903/Medusa%20Resources/order-fulfillment_h0vlps.jpg)
---
## Pricing Module
A shipping option's price is stored as a price set. Medusa defines a link module that builds a relationship between the `PriceSet` and `ShippingOption` data models.
![A diagram showcasing an example of how data models from the Pricing and Fulfillment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716561747/Medusa%20Resources/pricing-fulfillment_spywwa.jpg)
---
## Stock Location Module
When the Fulfillment and Stock Location modules are used together, a fulfillment set can be conditioned to a specific stock location.
A fulfillment set can be conditioned to a specific stock location. Medusa defines a link module that builds a relationship between the `FulfillmentSet` and `StockLocation` data models.
The Medusa application forms a relation between the `FulfillmentSet` and `StockLocation` data models.
![A diagram showcasing an example of how resources from the Fulfillment and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712567101/Medusa%20Resources/fulfillment-stock-location_nlkf7e.jpg)
![A diagram showcasing an example of how data models from the Fulfillment and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712567101/Medusa%20Resources/fulfillment-stock-location_nlkf7e.jpg)

View File

@@ -1,5 +1,5 @@
export const metadata = {
title: `Shipping Options`,
title: `Shipping Option`,
}
# {metadata.title}
@@ -12,21 +12,21 @@ A shipping option is a way of shipping an item. Each fulfillment provider provid
When the customer places their order, they choose a shipping option to be used to fulfill their items.
A shipping option is represented by the `ShippingOption` data model.
A shipping option is represented by the [ShippingOption data model](/references/fulfillment/models/ShippingOption).
---
## Service Zone Restrictions
A shipping option is restricted by a service zone, which specifies in what locations can a shipping option be used.
A shipping option is restricted by a service zone, limiting the locations a shipping option be used in.
For example, a fulfillment provider may have a shipping option that can be used in the United States, and another in Canada.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712330831/Medusa%20Resources/shipping-option-service-zone_pobh6k.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712330831/Medusa%20Resources/shipping-option-service-zone_pobh6k.jpg)
![A diagram showcasing the relation between shipping options and service zones.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712330831/Medusa%20Resources/shipping-option-service-zone_pobh6k.jpg)
Service zones can be more restrictive, such as restricting to certain cities or province codes.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712331186/Medusa%20Resources/shipping-option-service-zone-city_m5sxod.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331186/Medusa%20Resources/shipping-option-service-zone-city_m5sxod.jpg)
![A diagram showcasing the relation between shipping options, service zones, and geo zones](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331186/Medusa%20Resources/shipping-option-service-zone-city_m5sxod.jpg)
---
@@ -34,26 +34,26 @@ Service zones can be more restrictive, such as restricting to certain cities or
You can restrict shipping options by custom rules, such as the items weight or the customers group.
These rules are represented by the `ShippingOptionRule` data model. Its fields define the custom rule:
These rules are represented by the [ShippingOptionRule data model](/references/fulfillment/models/ShippingOptionRule). Its fields define the custom rule:
- `field`: The name of an field or table that the rule applies to. For example, `customer_group`.
- `value`: One or more values.
- `attribute`: The name of a field or table that the rule applies to. For example, `customer_group`.
- `operator`: The operator used in the condition. For example:
- To allow multiple values, use the operator `in`, which validates that the provided values are in the rules values.
- To create a negation condition that considers `value` against the rule, use `nin`, which validates that the provided values arent in the rules values.
- Check out more operators in [this reference](/references/fulfillment/types/fulfillment.RuleOperatorType).
- `value`: One or more values.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712331340/Medusa%20Resources/shipping-option-rule_oosopf.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331340/Medusa%20Resources/shipping-option-rule_oosopf.jpg)
![A diagram showcasing the relation between shipping option and shipping option rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331340/Medusa%20Resources/shipping-option-rule_oosopf.jpg)
A shipping option can have multiple rules. For example, a shipping option is available if the customer belongs to the VIP group and the total weight is less than 2000g.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712331462/Medusa%20Resources/shipping-option-rule-2_ylaqdb.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331462/Medusa%20Resources/shipping-option-rule-2_ylaqdb.jpg)
![A diagram showcasing how a shipping option can have multiple rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331462/Medusa%20Resources/shipping-option-rule-2_ylaqdb.jpg)
---
## Shipping Profile and Types
A shipping option belongs to a type. For example, a shipping options type may be `express`, while another `standard`. The type is represented by the `ShippingOptionType` data model.
A shipping option belongs to a type. For example, a shipping options type may be `express`, while another `standard`. The type is represented by the [ShippingOptionType data model](/references/fulfillment/models/ShippingOptionType).
A shipping option also belongs to a shipping profile, as each shipping profile defines the type of items to be shipped in a similar manner.

View File

@@ -8,7 +8,7 @@ In this document, youll learn about the main concepts in the Inventory Module
## InventoryItem
An inventory item, represented by the `InventoryItem` data model, is a stock-kept item, such as a product, whose inventory can be managed.
An inventory item, represented by the [InventoryItem data model](/references/inventory/models/InventoryItem), is a stock-kept item, such as a product, whose inventory can be managed.
The `InventoryItem` data model mainly holds details related to the underlying stock item, but has relations to other data models that include its inventory details.
@@ -18,7 +18,7 @@ The `InventoryItem` data model mainly holds details related to the underlying st
## InventoryLevel
An inventory level, represented by the `InventoryLevel` data model, holds the inventory and quantity details of an inventory item in a specific location.
An inventory level, represented by the [InventoryLevel data model](/references/inventory/models/InventoryLevel), holds the inventory and quantity details of an inventory item in a specific location.
It has three quantity-related fields:
@@ -28,9 +28,7 @@ It has three quantity-related fields:
### Associated Location
The inventory level's location is determined by the `location_id` field. The Medusa application links the `InventoryLevel` data model with the `StockLocation` data model from the Stock Location Module.
Learn more about this relation in [this guide](../relations-to-other-modules/page.mdx#stock-location-module)
The inventory level's location is determined by the `location_id` field. Medusa links the `InventoryLevel` data model with the `StockLocation` data model from the Stock Location Module.
---

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Inventory Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -318,7 +318,7 @@ In this document, youll find common examples of how you can use the Inventory
res.json({
is_available: await inventoryModuleService.confirmInventory(
request.body.inventory_item_id,
request.body.location_id,
[request.body.location_id],
request.body.required_quantity
),
})
@@ -343,7 +343,7 @@ In this document, youll find common examples of how you can use the Inventory
return NextResponse.json({
is_available: await inventoryModuleService.confirmInventory(
body.inventory_item_id,
body.location_id,
[body.location_id],
body.required_quantity
),
})
@@ -569,4 +569,4 @@ In this document, youll find common examples of how you can use the Inventory
## More Examples
The [module interface reference](/references/inventory-next) provides a reference to all the methods available for use with examples for each.
The [Inventory Module's main service reference](/references/inventory-next) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,7 +8,7 @@ This document explains how the Inventory Module is used within the Medusa applic
## Product Variant Creation
When a product variant is created and its `manage_inventory` field's value is `true`, the Medusa application uses the Inventory Module to create an inventory item associated with that product variant.
When a product variant is created and its `manage_inventory` field's value is `true`, the Medusa application creates an inventory item associated with that product variant.
![A diagram showcasing how the Inventory Module is used in the product variant creation form](https://res.cloudinary.com/dza7lstvk/image/upload/v1709661511/Medusa%20Resources/inventory-product-create_khz2hk.jpg)
@@ -16,7 +16,7 @@ When a product variant is created and its `manage_inventory` field's value is `t
## Add to Cart
When a product variant with `manage_inventory` set to `true` is added to cart, the Medusa application uses the Inventory Module to check whether there's sufficient stocked quantity. If not, an error is thrown and the product variant won't be added to the cart.
When a product variant with `manage_inventory` set to `true` is added to cart, the Medusa application checks whether there's sufficient stocked quantity. If not, an error is thrown and the product variant won't be added to the cart.
![A diagram showcasing how the Inventory Module is used in the add to cart flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709711645/Medusa%20Resources/inventory-cart-flow_achwq9.jpg)
@@ -24,7 +24,7 @@ When a product variant with `manage_inventory` set to `true` is added to cart, t
## Order Placed
When an order is placed, the Medusa application uses the Inventory Module to create a reservation item for each product variant with `manage_inventory` set to `true`. It also sets the `reserved_quantity` of the inventory level associated with the inventory item to the ordered quantity of that item.
When an order is placed, the Medusa application creates a reservation item for each product variant with `manage_inventory` set to `true`.
![A diagram showcasing how the Inventory Module is used in the order placed flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709712005/Medusa%20Resources/inventory-order-placed_qdxqdn.jpg)
@@ -32,11 +32,11 @@ When an order is placed, the Medusa application uses the Inventory Module to cre
## Order Fulfillment
When an item in an order is fulfilled and the associated variant has its `manage_inventory` field set to `true`, the Medusa application uses the Inventory Module to:
When an item in an order is fulfilled and the associated variant has its `manage_inventory` field set to `true`, the Medusa application:
- Subtract the `reserved_quantity` from the `stocked_quantity` in the inventory level associated with the variant's inventory item.
- Reset the `reserved_quantity` to `0`.
- Delete the associated reservation item.
- Subtracts the `reserved_quantity` from the `stocked_quantity` in the inventory level associated with the variant's inventory item.
- Resets the `reserved_quantity` to `0`.
- Deletes the associated reservation item.
![A diagram showcasing how the Inventory Module is used in the order fulfillment flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709712390/Medusa%20Resources/inventory-order-fulfillment_o9wdxh.jpg)
@@ -44,6 +44,6 @@ When an item in an order is fulfilled and the associated variant has its `manage
## Order Return
When an item in an order is returned and the associated variant has its `manage_inventory` field set to `true`, the Medusa application uses the Inventor Module to increment the `stocked_quantity` of the inventory level associated with the inventory item with the returned quantity.
When an item in an order is returned and the associated variant has its `manage_inventory` field set to `true`, the Medusa application increments the `stocked_quantity` of the inventory item's level with the returned quantity.
![A diagram showcasing how the Inventory Module is used in the order return flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709712457/Medusa%20Resources/inventory-order-return_ihftyk.jpg)

View File

@@ -8,12 +8,6 @@ export const metadata = {
The Inventory Module is the `@medusajs/inventory-next` NPM package that provides inventory-related features in your Medusa and Node.js applications.
<Note>
This module is an updated version of the [Inventory Module part of the multi-warehouse feature](../../modules/multiwarehouse/inventory-module.md). In Medusa V2, the previous version of the module will no longer be in use.
</Note>
## Features
### Inventory Items Management
@@ -59,7 +53,7 @@ const reservationItem =
### Check Inventory Availability
Check whether an inventory item has the necessary quantity for purchase. Any reserved quantity is considered unavailable, even if the inventory item's quantity hasn't been adjusted yet.
Check whether an inventory item has the necessary quantity for purchase. Any reserved quantity is considered unavailable.
```ts
const isAvailable =
@@ -74,14 +68,16 @@ const isAvailable =
## Configure Inventory Module
After installing the `@medusajs/inventory-next` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Inventory Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
inventoryService: {
resolve: "@medusajs/inventory-next",
},
[Modules.INVENTORY]: true,
}
```
@@ -142,9 +138,11 @@ For example:
import { IInventoryService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const inventoryModuleService: IInventoryService =
context.container.resolve(ModuleRegistrationName.INVENTORY)
container.resolve(ModuleRegistrationName.INVENTORY)
const inventoryItems =
await inventoryModuleService.list({})

View File

@@ -4,15 +4,13 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the Inventory Module and other Commerce Modules.
This document showcases the link modules defined between the Inventory Module and other commerce modules.
## Product Module
Each product variant has different inventory details. The Medusa application forms a relation between the `ProductVariant` and `InventoryItem` data models.
Each product variant has different inventory details. Medusa defines a link module that builds a relationship between the `ProductVariant` and `InventoryItem` data models.
![A diagram showcasing an example of how resources from the Inventory and Product Module are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709658720/Medusa%20Resources/inventory-product_ejnray.jpg)
![A diagram showcasing an example of how data models from the Inventory and Product Module are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709658720/Medusa%20Resources/inventory-product_ejnray.jpg)
A product variant, whose `manage_inventory` field is enabled, has an associated inventory item. Through that inventory's items relations in the Inventory Module, you can manage and check the variant's inventory quantity.
@@ -22,6 +20,6 @@ A product variant, whose `manage_inventory` field is enabled, has an associated
Reservation items and inventory items are associated with a location. The Medusa application forms a relation between the `ReservationItem` and `StockLocation` data models, and the `InventoryLevel` and `StockLocation` data models.
![A diagram showcasing an example of how resources from the Inventory and Stock Location modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709660383/Medusa%20Resources/inventory-stock-location_yp26k3.jpg)
![A diagram showcasing an example of how data models from the Inventory and Stock Location modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709660383/Medusa%20Resources/inventory-stock-location_yp26k3.jpg)
The stock location provides address details of the location.

View File

@@ -4,27 +4,23 @@ export const metadata = {
# {metadata.title}
In this document, youll learn about orders and their general fields.
## Order Data Model
An order represents a customer purchase in your store. The `Order` data model holds the information about that purchase.
---
In this document, youll learn about orders and related concepts
## Order Items
The items purchased in the order are represented by the `OrderItem` data model. An order can have multiple items.
The items purchased in the order are represented by the [OrderItem data model](/references/order/models/OrderItem). An order can have multiple items.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712304722/Medusa%20Resources/order-order-items_uvckxd.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712304722/Medusa%20Resources/order-order-items_uvckxd.jpg)
![A diagram showcasing the relation between an order and its items.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712304722/Medusa%20Resources/order-order-items_uvckxd.jpg)
Learn more about order items in [this guide](../order-items/page.mdx).
### Items Product Details
The details of the purchased products are represented by the [LineItem data model](/references/order/models/LineItem). Not only does a line item hold the details of the product, but also details related to its price, adjustments due to promotions, and taxes.
---
## Orders Shipping Method
An order has one or more shipping methods used to handle item shipment. Each shipping method is represented by the `ShippingMethod` data model that holds its details.
An order has one or more shipping methods used to handle item shipment. Each shipping method is represented by the [ShippingMethod data model](/references/order/models/ShippingMethod) that holds its details.
### data Field
@@ -32,19 +28,19 @@ When fulfilling the order, you may use a third-party fulfillment provider that r
The `ShippingMethod` data model has a `data` field. Its an object used to store custom data relevant later for fulfillment.
In the Medusa application, the `data` is passed to the Fulfillment Module when fulfilling items.
The Medusa application passes the `data` field to the Fulfillment Module when fulfilling items.
---
## Order Totals
The orders total amounts (including tax total, total after an item is returned, etc…) are represented by the `OrderSummary` data model. An order can have multiple summaries.
The orders total amounts (including tax total, total after an item is returned, etc…) are represented by the [OrderSummary data model](/references/order/models/OrderSummary).
---
## Order Payments
Payments made on an order, whether theyre capture or refund payments, are recorded as transactions represented by the `Transaction` data model.
Payments made on an order, whether theyre capture or refund payments, are recorded as transactions represented by the [Transaction data model](/references/order/models/Transaction).
An order can have multiple transactions. The sum of these transactions must be equal to the order summarys total. Otherwise, theres an outstanding amount.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Order Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -8,11 +8,17 @@ export const metadata = {
In this document, youll learn how to make changes to an order, such as return or exchange an item.
<Note type="soon" title="In Development">
Order Change is still in development.
</Note>
## What's an Order Change?
An order change is modifying the orders items for business purposes. For example, when a customer requests to return an item, or when you suggest exchanging an item with another.
An order change is modifying the orders items for business purposes. For example, when a customer requests to return an item, or when a merchant suggests exchanging an item with another.
Order changes are represented by the `OrderChange` data model.
Order changes are represented by the [OrderChange data model](/references/order/models/OrderChange).
---
@@ -25,7 +31,7 @@ An order change can have multiple underlying actions. For example, to exchange a
- Add the new item to be sent to the customer.
- Fulfill the item and send it to the customer.
Each of these actions is represented by the `OrderChangeAction` data model.
Each of these actions is represented by the [OrderChangeAction data model](/references/order/models/OrderChangeAction).
### Action Name
@@ -269,33 +275,12 @@ The `action` field of the `OrderChangeAction` holds the name of the action to pe
</Table.Body>
</Table>
### Action Chaining
Actions are chained one after the other, similar to the example in the earlier section. This also allows you to cancel or undo some actions.
For example, if you request an order return with `RETURN_ITEM` action, you can later cancel it with the `CANCEL_RETURN` action.
The actions are ordered by the `ordering` field of the `OrderChangeAction` data model.
### Action Amount
The `OrderChangeAction` data model has an `amount` field that indicates a change in the orders amount that this action incurs.
---
## Order Change Confirmation
The `OrderChange` data model has a `status` field that indicates its current status. By default, its pending. At this point, the order changes actions arent applied to the order yet.
To apply these changes to the order, you must confirm the order change. When the order change is confirmed:
To apply these changes to the order, you confirm the order change. When the order change is confirmed:
- The status of the order change is changed to `confirmed`.
- The orders items are changed based on the order changes actions. For example, an item is added, or an existing items quantity is changed.
- The order summary is modified to reflect new changes.
<Note>
If there are changes to the orders total amount due to refunding or capturing payment, they must be added as transactions first. Otherwise, they wont be accounted for when modifying the order summary
</Note>

View File

@@ -1,37 +0,0 @@
export const metadata = {
title: `Order Item`,
}
# {metadata.title}
In this document, youll learn about the order item and the general details it holds.
## OrderItem Data Model
Each item in an order is represented by the `OrderItem` data model. It holds details related to the quantity of the item and the underlying product details.
---
## Order Item Quantity
The `OrderItem` data model has the following quantity fields:
- `quantity`: The quantity ordered.
- `fulfilled_quantity`: The quantity thats been fulfilled.
- `shipped_quantity`: The quantity thats been shipped.
- `return_requested_quantity`: The quantity requested to be returned, but hasnt been received yet.
- `return_received_quantity`: The quantity thats been received from the customer due to a return request.
- `return_dismissed_quantity`: The quantity thats been received from the customer due to a return request, but the items are damaged.
- `written_off_quantity`: The quantity removed from the originally ordered quantity.
---
## Items Product Details
The details of the purchased products are represented by the `LineItem` data model. Not only does a line item hold the details of the product, but also details related to its price, adjustments due to promotions, and taxes.
<Note>
The `LineItem` data model is similar to the Cart Modules `LineItem` data model. So, when using both modules, the data can be copied between the modules as-is.
</Note>

View File

@@ -28,6 +28,6 @@ So, if the orders `version` is `1`, the order changes version is `2`.
Then, once the order change is confirmed and applied to the order, the versions of the order and order summary change to that of the order change.
Order items change depending on the version they were added or modified in, as explained in the earlier section.
![A diagram showcasing how the version of an order changes](https://res.cloudinary.com/dza7lstvk/image/upload/v1712304242/Medusa%20Resources/order-versioning_rsx2rn.jpg)
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712304242/Medusa%20Resources/order-versioning_rsx2rn.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712304242/Medusa%20Resources/order-versioning_rsx2rn.jpg)
Order items change depending on the version they were added or modified in, as explained in the earlier section.

View File

@@ -8,13 +8,11 @@ export const metadata = {
The Order Module is the `@medusajs/order` NPM package that provides order-related features in your Medusa and Node.js applications.
---
## Features
### Order Management
Store and manage your orders by retrieving, creating, canceling, and performing other operations.
Store and manage your orders to retriev, create, cancel, and perform other operations.
```ts
const order = await orderModuleService.create({
@@ -47,9 +45,35 @@ const draftOrder = await orderModuleService.create({
})
```
### Apply Promotions
Apply promotions or discounts to the order's items and shipping methods by adding adjustment lines that are factored into their subtotals.
```ts
const lineAdjustments =
await orderModuleService.addLineItemAdjustments({
item_id: "cali_123",
code: "50OFF",
amount: 500,
})
const shippingAdjustments =
await orderModuleService.addShippingMethodAdjustments({
shipping_method_id: "casm_123",
code: "FREESHIPPING",
amount: 1000,
})
```
### Returns, Exchanges, and Other Order Changes
Orders can be changed to return items from the customer, exchange an item with another, change the quantity of an item, or other changes.
<Note title="In Development" type="soon">
Order Changes are still in development.
</Note>
Orders can be changed to return items from the customer, exchange an item with another, change the quantity of an item, or perform other changes.
Changes are only applied after confirmation, and order history is preserved through versioning.
@@ -74,38 +98,20 @@ await orderModuleService.addOrderAction({
await orderModuleService.confirmOrderChange("ord_123")
```
### Apply Promotions
Apply promotions or discounts to the order's items and shipping methods by adding adjustment lines that are factored into their subtotals.
```ts
const lineAdjustments =
await orderModuleService.addLineItemAdjustments({
item_id: "cali_123",
code: "50OFF",
amount: 500,
})
const shippingAdjustments =
await orderModuleService.addShippingMethodAdjustments({
shipping_method_id: "casm_123",
code: "FREESHIPPING",
amount: 1000,
})
```
---
## Configure Order Module
After installing the `@medusajs/order` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Order Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
order: {
resolve: "@medusajs/order",
},
[Modules.ORDER]: true,
}
```
@@ -150,7 +156,7 @@ For example:
container,
}: SubscriberArgs) {
const orderModuleService: IOrderModuleService =
container.resolve(ModuleRegistrationName.API_KEY)
container.resolve(ModuleRegistrationName.ORDER)
const orders = await orderModuleService.list()
}
@@ -164,10 +170,12 @@ For example:
import { IOrderModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const orderModuleService: IOrderModuleService =
context.container.resolve(
ModuleRegistrationName.API_KEY
container.resolve(
ModuleRegistrationName.ORDER
)
const orders = await orderModuleService.list()
})

View File

@@ -14,17 +14,26 @@ In this document, youll learn how a promotion is applied to an orders item
An adjustment line indicates a change to a line item or a shipping methods amount. Its used to apply promotions or discounts on an order.
The `LineItemAdjustment` data model represents adjustment lines for a line item, and the `ShippingMethodAdjustment` data model represents adjustment lines for a shipping method.
The [LineItemAdjustment data model](/references/order/models/LineItemAdjustment) represents changes on a line item, and the [ShippingMethodAdjustment data model](/references/order/models/ShippingMethodAdjustment) represents changes on a shipping method.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712306017/Medusa%20Resources/order-adjustments_myflir.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712306017/Medusa%20Resources/order-adjustments_myflir.jpg)
![A diagram showcasing the relation between an order, its items and shipping methods, and their adjustment lines](https://res.cloudinary.com/dza7lstvk/image/upload/v1712306017/Medusa%20Resources/order-adjustments_myflir.jpg)
The `amount` field of the adjustment line indicates the amount to be discounted from the original amount. Also, the ID of the applied promotion can be stored in the `promotion_id` field of the adjustment line.
---
## Discountable Option
The `LineItem` data model has an `is_discountable` field that indicates whether promotions can be applied to the line item. Its enabled by default.
When disabled, a promotion cant be applied to a line item. In the context of the Promotion Module, the promotion isnt applied to the line item even if it matches its rules.
---
## Promotion Actions
When using the Order and Promotion modules together, such as in the Medusa application, use the `computeActions` method of the Promotion Modules main service. It retrieves the actions of line items and shipping methods.
When using the Order and Promotion modules together, use the [computeActions method of the Promotion Modules main service](/references/promotion/computeActions). It retrieves the actions of line items and shipping methods.
<Note>
@@ -92,12 +101,6 @@ const actions = await promotionModuleService.computeActions(
The `computeActions` method accepts the existing adjustments of line items and shipping methods to compute the actions accurately.
<Note>
Learn more about the `computeActions` method in [this reference](/references/promotion/computeActions).
</Note>
Then, use the returned `addItemAdjustment` and `addShippingMethodAdjustment` actions to set the orders line items and the shipping methods adjustments.
```ts
@@ -123,12 +126,4 @@ await orderModuleService.setShippingMethodAdjustments(
action.action === "addShippingMethodAdjustment"
) as AddShippingMethodAdjustment[]
)
```
---
## Discountable Option
The `LineItem` data model has an `is_discountable` field that indicates whether promotions can be applied to the line item. Its enabled by default.
When disabled, a promotion cant be applied to a line item. In the context of the Promotion Module, the promotion isnt applied to the line item even if it matches its rules.
```

View File

@@ -4,13 +4,59 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the link modules defined between the Order Module and other commerce modules.
This document showcases the relation between the Order Module and other Commerce Modules.
## Customer Module
An order is associated with the customer that placed it. Medusa defines a link module that builds a relationship between the `Order` and `Customer` data models.
![A diagram showcasing an example of how data models from the Order and Customer modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716545470/Medusa%20Resources/customer-order_pkla6f.jpg)
---
## Fulfillment Module
A fulfillment is created for an orders' items. Medusa defines a link module that builds a relationship between the `Fulfillment` and `Order` data models.
![A diagram showcasing an example of how data models from the Fulfillment and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716549903/Medusa%20Resources/order-fulfillment_h0vlps.jpg)
---
## Payment Module
An order's payment is stored in a payment collection. Medusa defines a link module that builds a relationship between the `Order` and `PaymentCollection` data models.
![A diagram showcasing an example of how data models from the Order and Payment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716554726/Medusa%20Resources/order-payment_ubdwok.jpg)
---
## Product Module
An order's line item is associated with the purchased product and its variant. Medusa defines a link module that builds a relationship between the `LineItem`, `Product`, and `ProductVariant` data models.
![A diagram showcasing an example of how data models from the Order and Product modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716556100/Medusa%20Resources/order-product_l6ylte.jpg)
---
## Promotion Module
An order is associated with the promotion applied on it. Medusa defines a link module that builds a relationship between the `Order` and `Promotion` data models.
![A diagram showcasing an example of how data models from the Order and Promotion modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716555015/Medusa%20Resources/order-promotion_dgjzzd.jpg)
---
## Region Module
An order is associated with the customer's region. Medusa defines a link module that builds a relationship between the `Order` and `Region` data models.
![A diagram showcasing an example of how data models from the Order and Region modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716555119/Medusa%20Resources/order-region_ihkp2u.jpg)
---
## Sales Channel Module
Orders can be scoped to a sales channel. The Medusa application forms a relation between the `Order` and the `SalesChannel` data models.
Orders can be scoped to a sales channel. Medusa defines a link module that builds a relationship between the `Order` and the `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Order and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712315409/Medusa%20Resources/order-sales-channel_dy72gx.jpg)

View File

@@ -12,15 +12,15 @@ In this document, youll learn about tax lines in an order.
## What are Tax Lines?
A tax line indicates the tax rate of a line item or a shipping method. The `LineItemTaxLine` data model represents a line items tax line, and the `ShippingMethodTaxLine` data model represents a shipping methods tax line.
A tax line indicates the tax rate of a line item or a shipping method. The [LineItemTaxLine data model](/references/order/models/LineItemTaxLine) represents a line items tax line, and the [ShippingMethodTaxLine data model](/references/order/models/ShippingMethodTaxLine) represents a shipping methods tax line.
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712307225/Medusa%20Resources/order-tax-lines_sixujd.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712307225/Medusa%20Resources/order-tax-lines_sixujd.jpg)
![A diagram showcasing the relation between orders, items and shipping methods, and tax lines](https://res.cloudinary.com/dza7lstvk/image/upload/v1712307225/Medusa%20Resources/order-tax-lines_sixujd.jpg)
---
## Tax Inclusivity
By default, the tax amount is calculated by taking the tax rate from the line item or shipping methods amount and then added to the item/methods subtotal.
By default, the tax amount is calculated by taking the tax rate from the line item or shipping methods amount and then adding it to the item/methods subtotal.
However, line items and shipping methods have an `is_tax_inclusive` field that, when enabled, indicates that the item or methods price already includes taxes.
@@ -32,4 +32,4 @@ The following diagram is a simplified showcase of how a subtotal is calculated f
</Note>
![https://res.cloudinary.com/dza7lstvk/image/upload/v1712307395/Medusa%20Resources/order-tax-inclusive_oebdnm.jpg](https://res.cloudinary.com/dza7lstvk/image/upload/v1712307395/Medusa%20Resources/order-tax-inclusive_oebdnm.jpg)
![A diagram showcasing how a subtotal is calculated from the tax perspective](https://res.cloudinary.com/dza7lstvk/image/upload/v1712307395/Medusa%20Resources/order-tax-inclusive_oebdnm.jpg)

View File

@@ -6,30 +6,19 @@ export const metadata = {
# {metadata.title}
In this document, youll learn about an orders transactions and usefulness.
In this document, youll learn about an orders transactions and its use.
## What is a Transaction?
A transaction represents any order payment process, such as capturing or refunding an amount. Its represented by the `Transaction` data model.
A transaction represents any order payment process, such as capturing or refunding an amount. Its represented by the [Transaction data model](/references/order/models/Transaction).
The transactions main purpose is to ensure a correct balance between paid and outstanding amounts.
---
## Transaction Reference
The Order Module doesnt provide payment processing functionalities, so it doesnt store payments that can be processed. For that, use the Payment Module or custom logic.
The `Transaction` data model has two fields that determine which data model and record holds the actual payments details:
- `reference`: indicates the tables name in the database. For example, `payment` if youre using the Payment Module.
- `reference_id`: indicates the ID of the record in the table. For example, `pay_123`.
---
## Checking Outstanding Amount
The orders total is stored in the `OrderSummary`'s `total` field. To check the outstanding amount of the order, the transaction amounts of an order are summed. Then:
The orders total is stored in the `OrderSummary`'s `total` field. To check the outstanding amount of the order, its transaction amounts are summed. Then, the following conditions are checked:
<Table>
<Table.Header>
@@ -77,3 +66,14 @@ The orders total is stored in the `OrderSummary`'s `total` field. To check th
</Table.Row>
</Table.Body>
</Table>
---
## Transaction Reference
The Order Module doesnt provide payment processing functionalities, so it doesnt store payments that can be processed. For that, use the Payment Module or custom logic.
The `Transaction` data model has two fields that determine which data model and record holds the actual payments details:
- `reference`: indicates the tables name in the database. For example, `payment` if youre using the Payment Module.
- `reference_id`: indicates the ID of the record in the table. For example, `pay_123`.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Payment Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -374,4 +374,4 @@ In this guide, youll find common examples of how you can use the Payment Modu
## More Examples
The [module interface reference](/references/payment) provides a reference to all the methods available for use with examples for each.
The [Payment Module's main service reference](/references/payment) provides a reference to all the methods available for use with examples for each.

View File

@@ -9,8 +9,6 @@ export const metadata = {
The Payment Module is the `@medusajs/payment` NPM package that provides payment-related features in your Medusa and Node.js applications.
---
## Features
### Add Payment Functionalities to Any Resource
@@ -40,7 +38,7 @@ await paymentModuleService.capturePayment({
### Integrate Third-Party Payment Providers
Use payment providers like Stripe and PayPal to handle and process payments.
Use payment providers like Stripe to handle and process payments.
```ts
const payment =
@@ -74,12 +72,16 @@ await paymentModuleService.processEvent({
## Configure Payment Module
After installing the `@medusajs/payment` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Payment Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
apiKey: {
[Modules.PAYMENT]: {
resolve: "@medusajs/payment",
options: {
// ...
@@ -134,7 +136,7 @@ For example:
container,
}: SubscriberArgs) {
const paymentModuleService: IPaymentModuleService =
container.resolve(ModuleRegistrationName.API_KEY)
container.resolve(ModuleRegistrationName.PAYMENT)
const payment_collections =
await paymentModuleService.listPaymentCollections()
@@ -149,10 +151,12 @@ For example:
import { IPaymentModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const paymentModuleService: IPaymentModuleService =
context.container.resolve(
ModuleRegistrationName.API_KEY
container.resolve(
ModuleRegistrationName.PAYMENT
)
const payment_collections =

View File

@@ -8,7 +8,7 @@ In this document, youll learn what a payment collection is and how to use it
## What's a Payment Collection?
A payment collection stores payment details related to a resource, such as a cart or an order. Its represented by the `PaymentCollection` data model.
A payment collection stores payment details related to a resource, such as a cart or an order. Its represented by the [PaymentCollection data model](/references/payment/models/PaymentCollection).
Every purchase or request for payment starts with a payment collection. The collection holds details necessary to complete the payment, including:
@@ -18,20 +18,20 @@ Every purchase or request for payment starts with a payment collection. The coll
---
## Usage with the Cart Module
The Cart Module provides cart management features. However, it doesnt provide any features related to accepting payment.
With the Payment Module, you can create a payment collection for the cart and handle the payment functionalities.
The Medusa application creates a link between the `PaymentCollection` and `Cart` data models. It also implements the payment flow during checkout as explained in [this documentation](../payment-flow/page.mdx).
![Diagram showcasing the relation between the Payment and Cart modules](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537849/Medusa%20Resources/cart-payment_ixziqm.jpg)
---
## Multiple Payments
The payment collection supports multiple payment sessions and payments. You can use this to accept payments in increments or split payments across payment providers.
![Diagram showcasing how a payment collection can have multiple payment sessions and payments](https://res.cloudinary.com/dza7lstvk/image/upload/v1711554695/Medusa%20Resources/payment-collection-multiple-payments_oi3z3n.jpg)
---
## Usage with the Cart Module
The Cart Module provides cart management features. However, it doesnt provide any features related to accepting payment.
With the Payment Module, you can create a payment collection for the cart and process the payment.
The Medusa application creates a link between the `PaymentCollection` and `Cart` data models. It also implements the payment flow during checkout as explained in [this documentation](../payment-flow/page.mdx).
![Diagram showcasing the relation between the Payment and Cart modules](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537849/Medusa%20Resources/cart-payment_ixziqm.jpg)

View File

@@ -1,16 +1,10 @@
export const metadata = {
title: `Payment Flow`,
title: `Accept Payment Flow`,
}
# {metadata.title}
In this document, youll learn about the payment flow implemented by the Medusa application. This is the recommended flow to follow when accepting a payment for a resource using the Payment Module.
<Note>
The flow described is in the checkout context. However, you can apply it in any use case.
</Note>
In this document, youll learn how to implement an accept-payment flow.
## Flow Overview

View File

@@ -8,7 +8,7 @@ In this document, youll learn what a payment session is.
## What's a Payment Session?
A payment session, represented by the `PaymentSession` data model, is a payment amount to be authorized. Its associated with a payment provider that handles authorizing it.
A payment session, represented by the [PaymentSession data model](/references/payment/modules/PaymentSession), is a payment amount to be authorized. Its associated with a payment provider that handles authorizing it.
A payment collection can have multiple payment sessions. For example, during checkout, when a customer chooses between paying with Stripe or PayPal, each of these payment options is a payment session associated with a payment provider (Stripe or PayPal).
@@ -18,9 +18,9 @@ A payment collection can have multiple payment sessions. For example, during che
## data field
Payment providers may need some additional data to process the payment later. The `PaymentSession` data model has a `data` field used to store that data.
Payment providers may need additional data to process the payment later. The `PaymentSession` data model has a `data` field used to store that data.
For example, for Stripe, you must pass Stripes customer ID when processing the payment. So, when you create a payment session, the Stripe payment provider creates the customer in Stripe and stores the ID in the `data` field.
For example, the customer's ID in Stripe is stored in the `data` field.
---

View File

@@ -8,7 +8,7 @@ In this document, youll learn what a payment is and how it's created, capture
## What's a Payment?
When a payment session is authorized, a payment, represented by the `Payment` data model, is created. This payment is an authorized amount thats later captured or refunded.
When a payment session is authorized, a payment, represented by the [Payment data model](/references/payment/models/Payment), is created. This payment can later be captured or refunded.
A payment carries along many of the data and relations of a payment session:
@@ -20,7 +20,7 @@ A payment carries along many of the data and relations of a payment session:
## Capture Payments
When a payment is captured, a capture, represented by the `Capture` data model, is created. It holds details related to the capture, such as the amount, the capture date, and more.
When a payment is captured, a capture, represented by the [Capture data model](/references/payment/models/Capture), is created. It holds details related to the capture, such as the amount, the capture date, and more.
The payment can also be captured incrementally, each time a capture record is created for that amount.
@@ -30,8 +30,8 @@ The payment can also be captured incrementally, each time a capture record is cr
## Refund Payments
An amount of a payment can be refunded if its already captured. Once its refunded, a refund, represented by the `Refund` data model, is created. It holds details related to the refund, such as the amount, refund date, and more.
When a payment is refunded, a refund, represented by the [Refund data model](/references/payment/models/Refund), is created. It holds details related to the refund, such as the amount, refund date, and more.
A payment can be refunded multiple times, and each time a refund record is created for that refund.
A payment can be refunded multiple times, and each time a refund record is created.
![A diagram showcasing how a payment's multiple refunds are stored](https://res.cloudinary.com/dza7lstvk/image/upload/v1711565555/Medusa%20Resources/payment-refund_lgfvyy.jpg)

View File

@@ -4,9 +4,7 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the Payment Module and other Commerce Modules.
This document showcases the link modules defined between the Payment Module and other commerce modules.
## Cart Module
@@ -16,6 +14,14 @@ Learn more about this relation in [this documentation](../payment-collection/pag
---
## Order Module
An order's payment is stored in a payment collection. Medusa defines a link module that builds a relationship between the `Order` and `PaymentCollection` data models.
![A diagram showcasing an example of how data models from the Order and Payment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716554726/Medusa%20Resources/order-payment_ubdwok.jpg)
---
## Region Module
You can specify for each region which payment providers are available. The Medusa application forms a relation between the `PaymentProvider` and the `Region` data models.

View File

@@ -14,31 +14,12 @@ A webhook event is sent from a third-party payment provider to your application.
## processEvent Method
The Payment Modules main service (`IPaymentModuleService`) provides a `processEvent` method used to handle incoming webhook events from third-party providers. The method delegates the handling to the associated payment provider, which returns the event's details.
The Payment Modules main service (`IPaymentModuleService`) provides a [processEvent method](/references/payment/processEvent) used to handle incoming webhook events from third-party payment services. The method delegates the handling to the associated payment provider, which returns the event's details.
If the event's details indicate that the payment should be authorized, then the `authorizePaymentSession` of the main service is executed on the specified payment session.
If the event's details indicate that the payment should be captured, then the `capturePayment` of the main service is executed on the payment of the specified payment session.
Medusa implements a webhook listener at the `/hooks/payment/[provider]` API route, where `[provider]` is the ID of the provider (for example, `stripe`). You can use that webhook listener in your third-party payment provider's configurations.
![A diagram showcasing the steps of how the processEvent method words](https://res.cloudinary.com/dza7lstvk/image/upload/v1711567415/Medusa%20Resources/payment-webhook_seaocg.jpg)
You can use this method in your webhook listener API routes or endpoints.
If the event's details indicate that the payment should be authorized, then the [authorizePaymentSession method of the main service](/references/payment/authorizePaymentSession) is executed on the specified payment session.
<Note>
Medusa V2 implements a webhook listener at the `/hooks/payment/[provider]` API route, where `[provider]` is the ID of the provider (for example, `stripe`). You can use that webhook listener in your third-party payment provider's configurations.
</Note>
For example:
```ts
await paymentModuleService.processEvent({
provider: "stripe",
payload: {
// webhook event data
},
})
```
Learn more about the methods parameters and return types in [this reference](/references/payment/processEvent).
If the event's details indicate that the payment should be captured, then the [capturePayment method of the main service](/references/payment/capturePayment) is executed on the payment of the specified payment session.

View File

@@ -6,70 +6,46 @@ export const metadata = {
In this document, youll learn about the main concepts in the Pricing Module, and how data is stored and related.
## Price
The `Price` data model represents any price.
Prices can be conditioned by the `min_quantity` and `max_quantity` fields, which are helpful when calculating the price for a specific quantity.
If a price has its `min_quantity` or `max_quantity` fields set, theyre only considered for the price calculation if they have a lower `min_quantity` or a higher `max_quantity` than the quantity specified for calculation.
---
## Price Set
A `PriceSet` represents a collection of prices that are linked to a resource (for example, a product or a shipping option). Each of these prices are represented by the `Price` data module.
A [PriceSet](/references/pricing/models/PriceSet) represents a collection of prices that are linked to a resource (for example, a product or a shipping option). Each of these prices are represented by the [Price data module](/references/pricing/models/Price).
![A diagram showcasing the relation between the price set and price](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648650/Medusa%20Resources/price-set-money-amount_xeees0.jpg)
---
## Prices with Rules
### Rule Type
## Rule Type
Each price within a price set can be applied for different conditions. These conditions are represented as rule types.
A `RuleType` defines custom conditions. Each rule type has a unique `rule_field`, referenced in rule values, such as when setting a rule of a price.
A [RuleType](/references/pricing/models/RuleType) defines custom conditions. A rule type has a unique `rule_attribute` which indicates the field this rule applies on. For example, `region_id`.
### Price Rule
This is referenced when setting a rule of a price. For example:
Each rule of a price within a price set is represented by the `PriceRule` data model, which holds the value of a rule type. The `Price` data model has a `rules_count` field, which indicates how many rules, represented by `PriceRule`, are applied to the price.
export const ruleTypeHighlights = [
["8", "region_id", "Reference a rule type by its `rule_attribute`."],
["8", `"PL"`, "The value of this rule."]
]
![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648772/Medusa%20Resources/price-rule-1_vy8bn9.jpg)
For example, you create a `zip_code` rule type. Then, a price within the price set can have the rule value `10557`, indicating that the price can only be applied within the `10557` zip code.
Each price within the price set can have different values for the same rule type.
For example:
![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648884/Medusa%20Resources/price-rule-2_b6fuyb.jpg)
Each price can have multiple rules applied to it as well.
For example, a price can have the rules `zip_code` and `region_id` applied to it. In this case, the value of each rule is represented by a `PriceRule`.
![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType with multiple rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649296/Medusa%20Resources/price-rule-3_pwpocz.jpg)
### PriceSetRuleType
The `PriceSetRuleType` data model indicates what rules the prices can have within a price set. It creates a relation between the `PriceSet` and `RuleType` entities.
For example, to use the `zip_code` rule type on a price in a price set, the rule type must first be enabled on the price set through the `PriceSetRuleType`.
![A diagram showcasing the relation between the PriceSet, PriceRule, Price, RuleType, and PriceSetRuleType](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649375/Medusa%20Resources/price-set-rule-type_cqqt0u.jpg)
```ts highlights={ruleTypeHighlights}
const priceSet = await pricingModuleService.addPrices({
priceSetId,
prices: [
{
amount: 500,
currency_code: "EUR",
rules: {
region_id: "PL",
},
},
],
})
```
---
## Price List
A `PriceList` is a group of prices only enabled if their rules are satisfied. A price list has optional `start_date` and `end_date` fields, which indicate the date range in which a price list can be applied.
A [PriceList](/references/pricing/models/PriceList) is a group of prices only enabled if their conditions and rules are satisfied. A price list has optional `start_date` and `end_date` fields, which indicate the date range in which a price list can be applied.
Its associated prices are represented by the `Price` data model.
Each rule that can be applied to a price list is represented by the `PriceListRule` data model. The `rules_count` field of a `PriceList` indicates how many rules are applied to it.
Each rule of a price list can have more than one value, representing its values by the `PriceListRuleValue` data model.
![A diagram showcasing the relation between the PriceSet, PriceList, Price, RuleType, and PriceListRuleValue](https://res.cloudinary.com/dza7lstvk/image/upload/v1709641999/Medusa%20Resources/price-list_zd10yd.jpg)
Its associated prices are represented by the `Price` data model.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Pricing Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -11,7 +11,7 @@ In this document, youll find common examples of how you can use the Pricing M
## Create a Price Set
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -47,7 +47,7 @@ In this document, youll find common examples of how you can use the Pricing M
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -89,7 +89,7 @@ In this document, youll find common examples of how you can use the Pricing M
## List Price Sets
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -110,7 +110,7 @@ In this document, youll find common examples of how you can use the Pricing M
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -136,7 +136,7 @@ In this document, youll find common examples of how you can use the Pricing M
## Retrieve a Price Set by its ID
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -159,7 +159,7 @@ In this document, youll find common examples of how you can use the Pricing M
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -196,7 +196,7 @@ In this document, youll find common examples of how you can use the Pricing M
## Create a Rule Type
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -210,16 +210,17 @@ In this document, youll find common examples of how you can use the Pricing M
const pricingModuleService: IPricingModuleService =
request.scope.resolve(ModuleRegistrationName.PRICING)
const priceSet = await pricingModuleService.retrieve(
request.params.id
)
const ruleType = await pricingModuleService.createRuleTypes([{
name: "Customer Group",
rule_attribute: "customer_group_id",
}])
res.json({ price_set: priceSet })
res.json({ rule_type: ruleType })
}
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -228,23 +229,17 @@ In this document, youll find common examples of how you can use the Pricing M
initialize as initializePricingModule,
} from "@medusajs/pricing"
type ContextType = {
params: {
id: string
}
}
export async function GET(
request: Request,
{ params }: ContextType
export async function POST(
request: Request
) {
const pricingModuleService = await initializePricingModule()
const priceSet = await pricingModuleService.retrieve(
params.id
)
const ruleType = await pricingModuleService.createRuleTypes([{
name: "Customer Group",
rule_attribute: "customer_group_id",
}])
return NextResponse.json({ price_set: priceSet })
return NextResponse.json({ rule_type: ruleType })
}
```
@@ -256,7 +251,7 @@ In this document, youll find common examples of how you can use the Pricing M
## Add Prices with Rules
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -288,7 +283,7 @@ In this document, youll find common examples of how you can use the Pricing M
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -326,7 +321,7 @@ In this document, youll find common examples of how you can use the Pricing M
## Create Price List
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -369,7 +364,7 @@ In this document, youll find common examples of how you can use the Pricing M
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -415,7 +410,7 @@ In this document, youll find common examples of how you can use the Pricing M
## Calculate Prices For a Currency
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -445,7 +440,7 @@ In this document, youll find common examples of how you can use the Pricing M
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -486,4 +481,4 @@ In this document, youll find common examples of how you can use the Pricing M
## More Examples
The [module interface reference](/references/pricing) provides a reference to all the methods available for use with examples for each.
The [Pricing Module's main service reference](/references/pricing) provides a reference to all the methods available for use with examples for each.

View File

@@ -12,7 +12,7 @@ The Pricing Module is the `@medusajs/pricing` NPM package that provides pricing-
### Price Management
With the Pricing Module, store the prices of a resource and manage them through the main interface's methods.
With the Pricing Module, store the prices of a resource and manage them through the main service's methods.
Prices are grouped in a price set, allowing you to add more than one price for a resource based on different conditions, such as currency code.
@@ -23,7 +23,6 @@ const priceSet = await pricingModuleService.create({
{
amount: 500,
currency_code: "USD",
rules: {},
},
{
amount: 400,
@@ -87,9 +86,7 @@ const priceList = await pricingModuleService.createPriceLists({
### Price Calculation Strategy
The modules main service provides a `calculatePrices` method to retrieve the best price for a given context.
You can use your custom rules here to find the best price for the specified rule values.
Retrieve the best price in a given context and for the specified rule values.
```ts
const price = await pricingModuleService.calculatePrices(
@@ -107,14 +104,16 @@ const price = await pricingModuleService.calculatePrices(
## Configure Pricing Module
After installing the `@medusajs/pricing` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Pricing Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
pricingService: {
resolve: "@medusajs/pricing",
},
[Modules.PRICING]: true,
}
```
@@ -173,9 +172,11 @@ For example:
import { IPricingModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const pricingModuleService: IPricingModuleService =
context.container.resolve(ModuleRegistrationName.PRICING)
container.resolve(ModuleRegistrationName.PRICING)
const priceSets = await pricingModuleService.list()
})

View File

@@ -1,167 +1,164 @@
import { Tabs, TabsList, TabsTrigger, TabsContent, TabsContentWrapper } from "docs-ui"
import { Tabs, TabsList, TabsTrigger, TabsContent, TabsContentWrapper, TypeList } from "docs-ui"
export const metadata = {
title: `Prices Calculation`,
title: `Prices Calculation Strategy`,
}
# {metadata.title}
In this document, you'll learn how prices are calculated under the hood when you use the `calculatePrices` method of the Pricing Module interface.
In this document, you'll learn how prices are calculated when you use the `calculatePrices` method of the Pricing Module's main service.
## Overview
The `calculatePrices` method accepts the ID of one or more price sets and a context. For each price set, it selects two types of prices that best match the context; one belongs to a price list, and one doesn't.
Then, it returns an array of price objects, each price for every supplied price set ID.
The [calculatePrices method](/references/pricing/calculatePrices) accepts the ID of one or more price sets and a context. It returns a price object with the best matching price for each price set.
---
## Calculation Context
The context is an object passed to the `calculatePrices` method. It must contain at least the `currency_code`. Only prices in the price sets with the same currency code are considered for the price selection.
The context is an object passed as a second parameter to the `calculatePrices` method. It must contain at least the `currency_code`. Only prices in the price sets with the same currency code are considered for the price selection.
For example:
```ts
import {
initialize as initializePricingModule,
} from "@medusajs/pricing"
async function calculatePrice(
priceSetId: string,
currencyCode: string
) {
const pricingModuleService = await initializePricingModule()
const price = await pricingModuleService.calculatePrices(
{ id: [priceSetId] },
{
context: {
currency_code: currencyCode,
},
}
)
}
const price = await pricingModuleService.calculatePrices(
{ id: [priceSetId] },
{
context: {
currency_code: currencyCode,
},
}
)
```
The context object can also contain any custom rules, with the key being the `rule_field` of a rule type and its value being the rule's value.
The context object can also contain any custom rules, with the key being the `rule_attribute` of a rule type and its value being the rule's value.
For example:
```ts
import {
initialize as initializePricingModule,
} from "@medusajs/pricing"
async function calculatePrice(
priceSetId: string,
currencyCode: string
) {
const pricingModuleService = await initializePricingModule()
const price = await pricingModuleService.calculatePrices(
{ id: [priceSetId] },
{
context: {
currency_code: currencyCode,
region_id: "US",
},
}
)
}
const price = await pricingModuleService.calculatePrices(
{ id: [priceSetId] },
{
context: {
currency_code: currencyCode,
region_id: "US",
},
}
)
```
---
## Prices Selection
## Returned Price Object
For each price set, the method selects two prices:
- The calculated price: a price that belongs to a price list. If there are no prices associated with a price list, itll be the same as the original price.
- The original price: a price that doesn't belong to a price list.
- The original price: If the calculated price's price list type is `override`, then the original price will be the same as the calculated price. Otheriwse, a price that doesn't belong to a price list.
### Calculated Price Selection Process
After the original and calculated prices are selected, the method will use them to create a price object for each price set.
![A diagram showcasing the calculated price selection process.](https://res.cloudinary.com/dza7lstvk/image/upload/v1700574799/Medusa%20Docs/Diagrams/calculated-price_vjnx3j.jpg)
The price object has the following properties:
- Find the price sets associated valid price lists. A price list is considered valid if:
- The current date is between its start and end dates.
- The price list's rules satisfy the context's rules.
- If valid price lists are found, the prices within them are sorted by their amount in ascending order. The one having the lowest amount is selected as the calculated price.
- If no valid price list is found, the selected calculated price will be the same as the original price.
### Original Price Selection Process
![A diagram showcasing the original price selection process.](https://res.cloudinary.com/dza7lstvk/image/upload/v1700574800/Medusa%20Docs/Diagrams/original-price_i47fso.jpg)
- If the price list associated with the calculated price is of type `override`, the selected original price is set to the calculated price.
- If no rules are provided in the context other than the `currency_code`, the default price is selected as the original price. The default price is a price having no rules applied to it.
- Otherwise, if a price exists in any price set with the same rules provided in the context, it's selected as the original price.
- If no price exists with the same rules as the context, all prices satisfying any combination of the provided rules are retrieved.
- The prices are sorted in descending order by the associated `Price`'s `rules_count`, the `default_priority` of the rule types, and the `priority` of the associated `PriceRule`. The `priority` field has a higher precedence than the `default_priority`.
- The highest price sorted is selected as the original price since it's considered the best price.
---
## Returned Calculated Price
After the original and calculated prices are selected, the method will use them to create the following price object for each pr
```ts
const price = {
id: priceSetId,
is_calculated_price_price_list:
!!calculatedPrice?.price_list_id,
calculated_amount: parseInt(
calculatedPrice?.amount || ""
) || null,
is_original_price_price_list:
!!originalPrice?.price_list_id,
original_amount: parseInt(
originalPrice?.amount || ""
) || null,
currency_code: calculatedPrice?.currency_code || null,
calculated_price: {
price_id: calculatedPrice?.id || null,
price_list_id: calculatedPrice?.price_list_id || null,
price_list_type: calculatedPrice?.price_list_type || null,
min_quantity: parseInt(
calculatedPrice?.min_quantity || ""
) || null,
max_quantity: parseInt(
calculatedPrice?.max_quantity || ""
) || null,
},
original_price: {
price_id: originalPrice?.id || null,
price_list_id: originalPrice?.price_list_id || null,
price_list_type: originalPrice?.price_list_type || null,
min_quantity: parseInt(
originalPrice?.min_quantity || ""
) || null,
max_quantity: parseInt(
originalPrice?.max_quantity || ""
) || null,
},
}
```
Where:
- `id`: The ID of the price set from which the price was selected.
- `is_calculated_price_price_list`: whether the calculated price belongs to a price list. As mentioned earlier, if no valid price list is found, the calculated price is set to the original price, which doesn't belong to a price list.
- `calculated_amount`: The amount of the calculated price, or `null` if there isn't a calculated price.
- `is_original_price_price_list`: whether the original price belongs to a price list. As mentioned earlier, if the price list of the calculated price is of type `override`, the original price will be the same as the calculated price.
- `original_amount`: The amount of the original price, or `null` if there isn't an original price.
- `currency_code`: The currency code of the calculated price, or `null` if there isn't a calculated price.
- `calculated_price`: An object containing the calculated price's price details and potentially its associated price list.
- `original_price`: An object containing the original price's price details and potentially its associated price list.
The method returns an array of these price objects.
<TypeList
types={[
{
name: "id",
type: "`string`",
description: "The ID of the price set from which the price was selected."
},
{
name: "is_calculated_price_price_list",
type: "`boolean`",
description: "Whether the calculated price belongs to a price list. As mentioned earlier, if no valid price list is found, the calculated price is set to the original price, which doesn't belong to a price list."
},
{
name: "calculated_amount",
type: "`number`",
description: "The amount of the calculated price, or `null` if there isn't a calculated price."
},
{
name: "is_original_price_price_list",
type: "`boolean`",
description: "Whether the original price belongs to a price list. As mentioned earlier, if the price list of the calculated price is of type `override`, the original price will be the same as the calculated price."
},
{
name: "original_amount",
type: "`number`",
description: "The amount of the original price, or `null` if there isn't an original price."
},
{
name: "currency_code",
type: "`string`",
description: "The currency code of the calculated price, or `null` if there isn't a calculated price."
},
{
name: "calculated_price",
type: "`object`",
description: "The calculated price's price details and potentially its associated price list.",
children: [
{
name: "price_id",
type: "`string`",
description: "The ID of the price."
},
{
name: "price_list_id",
type: "`string`",
description: "The ID of the associated price list."
},
{
name: "price_list_type",
type: "`string`",
description: "The price list's type."
},
{
name: "min_quantity",
type: "`number`",
description: "The price's min quantity condition."
},
{
name: "max_quantity",
type: "`number`",
description: "The price's max quantity condition."
}
]
},
{
name: "original_price",
type: "`object`",
description: "The original price's price details and potentially its associated price list.",
children: [
{
name: "price_id",
type: "`string`",
description: "The ID of the price."
},
{
name: "price_list_id",
type: "`string`",
description: "The ID of the associated price list."
},
{
name: "price_list_type",
type: "`string`",
description: "The price list's type."
},
{
name: "min_quantity",
type: "`number`",
description: "The price's min quantity condition."
},
{
name: "max_quantity",
type: "`number`",
description: "The price's max quantity condition."
}
]
}
]}
sectionTitle="Returned Calculated Price"
/>
---
@@ -173,18 +170,18 @@ Consider the following rule types and price sets:
const ruleTypes = await pricingModuleService.createRuleTypes([
{
name: "Region",
rule_field: "region_id",
rule_attribute: "region_id",
},
{
name: "City",
rule_field: "city",
rule_attribute: "city",
},
])
const priceSet = await pricingModuleService.create({
rules: [
{ rule_field: "region_id" },
{ rule_field: "city" },
{ rule_attribute: "region_id" },
{ rule_attribute: "city" },
],
prices: [
//default

View File

@@ -0,0 +1,47 @@
export const metadata = {
title: `Price Rules`,
}
# {metadata.title}
In this document, you'll learn about price rules for price sets and price lists.
## Price Rule
Each rule of a price within a price set is represented by the [PriceRule data model](/references/pricing/models/PriceRule), which holds the value of a rule type. The `Price` data model has a `rules_count` field, which indicates how many rules, represented by `PriceRule`, are applied to the price.
![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648772/Medusa%20Resources/price-rule-1_vy8bn9.jpg)
For example, you create a `zip_code` rule type. Then, a price within the price set can have the rule value `10557`, indicating that the price can only be applied within the `10557` zip code.
Each price within the price set can have different values for the same rule type.
For example:
![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648884/Medusa%20Resources/price-rule-2_b6fuyb.jpg)
Each price can have multiple rules applied to it as well.
For example, a price can have the rules `zip_code` and `region_id` applied to it. In this case, the value of each rule is represented by a `PriceRule`.
![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType with multiple rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649296/Medusa%20Resources/price-rule-3_pwpocz.jpg)
---
## Restrict Price Rules
The [PriceSetRuleType data model](/references/pricing/models/PriceSetRuleType) indicates what rules the prices can have within a price set. It creates a relation between the `PriceSet` and `RuleType` data models.
For example, to use the `zip_code` rule type on a price in a price set, the rule type must first be enabled on the price set through the `PriceSetRuleType`.
![A diagram showcasing the relation between the PriceSet, PriceRule, Price, RuleType, and PriceSetRuleType](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649375/Medusa%20Resources/price-set-rule-type_cqqt0u.jpg)
---
## Price List Rules
Rules that can be applied to a price list are represented by the [PriceListRule data model](/references/pricing/models/PriceListRule). The `rules_count` field of a `PriceList` indicates how many rules are applied to it.
Each rule of a price list can have more than one value, representing its values by the [PriceListRuleValue data model](/references/pricing/models/PriceListRuleValue).
![A diagram showcasing the relation between the PriceSet, PriceList, Price, RuleType, and PriceListRuleValue](https://res.cloudinary.com/dza7lstvk/image/upload/v1709641999/Medusa%20Resources/price-list_zd10yd.jpg)

View File

@@ -4,14 +4,20 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the link modules defined between the Pricing Module and other commerce modules.
This document showcases the relation between the Pricing Module and other Commerce Modules.
## Fulfillment Module
A shipping option's price is stored as a price set. Medusa defines a link module that builds a relationship between the `PriceSet` and `ShippingOption` data models.
![A diagram showcasing an example of how data models from the Pricing and Fulfillment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716561747/Medusa%20Resources/pricing-fulfillment_spywwa.jpg)
---
## Product Module
A product variants prices are stored as prices belonging to a price set. The Medusa application forms a relation between the `ProductVariant` and the `PriceSet`.
A product variants prices are stored as prices belonging to a price set. Medusa defines a link module that builds a relationship between the `ProductVariant` and the `PriceSet`.
![A diagram showcasing an example of how resources from the Pricing and Product Module are linked. The PriceSet is linked to the ProductVariant of the Product Module.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709651039/Medusa%20Resources/pricing-product_m4xaut.jpg)
![A diagram showcasing an example of how data models from the Pricing and Product Module are linked. The PriceSet is linked to the ProductVariant of the Product Module.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709651039/Medusa%20Resources/pricing-product_m4xaut.jpg)
So, when you want to add prices for a product variant, you create a price set and add the prices to it. You can then benefit from adding rules to prices or using the `calculatePrices` method to retrieve the price of a product variant within a specified context.

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Product Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -11,7 +11,7 @@ In this guide, youll find common examples of how you can use the Product Modu
## Create Product
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -51,7 +51,7 @@ In this guide, youll find common examples of how you can use the Product Modu
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -96,7 +96,7 @@ In this guide, youll find common examples of how you can use the Product Modu
## List Products
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -110,14 +110,14 @@ In this guide, youll find common examples of how you can use the Product Modu
const productModuleService: IProductModuleService =
request.scope.resolve(ModuleRegistrationName.PRODUCT)
const data = await productModuleService.list()
const products = await productModuleService.list()
res.json({ products: data })
res.json({ products })
}
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -129,19 +129,21 @@ In this guide, youll find common examples of how you can use the Product Modu
export async function GET(request: Request) {
const productModuleService = await initializeProductModule()
const data = await productModuleService.list()
const products = await productModuleService.list()
return NextResponse.json({ products: data })
return NextResponse.json({ products })
}
```
</CodeTab>
</CodeTabs>
---
## Retrieve a Product by its ID
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -155,16 +157,16 @@ In this guide, youll find common examples of how you can use the Product Modu
const productModuleService: IProductModuleService =
request.scope.resolve(ModuleRegistrationName.PRODUCT)
const data = await productModuleService.list({
id: request.params.id,
})
const product = await productModuleService.retrieve(
request.params.id
)
res.json({ product: data[0] })
res.json({ product })
}
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -180,11 +182,11 @@ In this guide, youll find common examples of how you can use the Product Modu
const { id } = params
const productModuleService = await initializeProductModule()
const data = await productModuleService.list({
id,
})
const product = await productModuleService.retrieve(
id
)
return NextResponse.json({ product: data[0] })
return NextResponse.json({ product })
}
```
@@ -196,7 +198,7 @@ In this guide, youll find common examples of how you can use the Product Modu
## Retrieve a Product by its Handle
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -210,14 +212,16 @@ In this guide, youll find common examples of how you can use the Product Modu
const productModuleService: IProductModuleService =
request.scope.resolve(ModuleRegistrationName.PRODUCT)
const data = await productModuleService.list()
const data = await productModuleService.list({
handle: "shirt"
})
res.json({ products: data })
res.json({ product: data[0] })
}
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -229,59 +233,8 @@ In this guide, youll find common examples of how you can use the Product Modu
export async function GET(request: Request) {
const productModuleService = await initializeProductModule()
const data = await productModuleService.list()
return NextResponse.json({ products: data })
}
```
</CodeTab>
</CodeTabs>
## Retrieve a Product by its ID
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IProductModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export async function GET(
request: MedusaRequest,
res: MedusaResponse
) {
const productModuleService: IProductModuleService =
request.scope.resolve(ModuleRegistrationName.PRODUCT)
const data = await productModuleService.list({
handle: request.params.handle,
})
res.json({ product: data[0] })
}
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
```ts
import { NextResponse } from "next/server"
import {
initialize as initializeProductModule,
} from "@medusajs/product"
export async function GET(
request: Request,
{ params }: { params: Record<string, any> }) {
const { handle } = params
const productModuleService = await initializeProductModule()
const data = await productModuleService.list({
handle,
handle: "shirt"
})
return NextResponse.json({ product: data[0] })
@@ -296,7 +249,7 @@ In this guide, youll find common examples of how you can use the Product Modu
## Retrieve Categories
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -310,14 +263,14 @@ In this guide, youll find common examples of how you can use the Product Modu
const productModuleService: IProductModuleService =
request.scope.resolve(ModuleRegistrationName.PRODUCT)
const data = await productModuleService.listCategories()
const categories = await productModuleService.listCategories()
res.json({ categories: data })
res.json({ categories })
}
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -329,9 +282,9 @@ In this guide, youll find common examples of how you can use the Product Modu
export async function GET(request: Request) {
const productModuleService = await initializeProductModule()
const data = await productModuleService.listCategories()
const categories = await productModuleService.listCategories()
return NextResponse.json({ categories: data })
return NextResponse.json({ categories })
}
```
@@ -343,7 +296,7 @@ In this guide, youll find common examples of how you can use the Product Modu
## Retrieve Category by Handle
<CodeTabs groupId="app-type">
<CodeTab label="medusa" value="Medusa API Router">
<CodeTab value="medusa" label="Medusa API Router">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
@@ -366,7 +319,7 @@ In this guide, youll find common examples of how you can use the Product Modu
```
</CodeTab>
<CodeTab label="nextjs" value="Next.js App Router">
<CodeTab value="nextjs" label="Next.js App Router">
```ts
import { NextResponse } from "next/server"
@@ -397,4 +350,4 @@ In this guide, youll find common examples of how you can use the Product Modu
## More Examples
The [Product Module interface reference](/references/product) provides a reference to all the methods available for use with examples for each.
The [Product Module's main service reference](/references/product) provides a reference to all the methods available for use with examples for each.

View File

@@ -12,7 +12,7 @@ The Product Module is the `@medusajs/product` NPM package that provides product-
### Products Management
With the Product Module, store products and manage them through the main interface methods. Products have custom options, such as color or size, and each variant in the product sets the value for these options.
Store and manage products. Products have custom options, such as color or size, and each variant in the product sets the value for these options.
```ts
const products = await productService.create([
@@ -62,14 +62,16 @@ const products = await productService.update([
## Configure Product Module
After installing the `@medusajs/product` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Product Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
productService: {
resolve: "@medusajs/product",
},
[Modules.PRODUCT]: true,
}
```
@@ -126,9 +128,11 @@ For example:
import { IProductModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const productModuleService: IProductModuleService =
context.container.resolve(ModuleRegistrationName.PRODUCT)
container.resolve(ModuleRegistrationName.PRODUCT)
const products = await productModuleService.list()
})

View File

@@ -4,21 +4,29 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the link modules defined between the Product Module and other commerce modules.
This document showcases the relation between the Product Module and other Commerce Modules.
## Cart Module
{/* TODO add relation to:
A cart's line item is associated with a product and its variant. Medusa defines a link module that builds a relationship between the `Cart`, `Product`, and `ProductVariant` data models.
- shipping profile
![A diagram showcasing an example of how data models from the Cart and Product modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716546229/Medusa%20Resources/cart-product_x82x9j.jpg)
*/}
---
## Order Module
An order's line item is associated with the purchased product and its variant. Medusa defines a link module that builds a relationship between the `LineItem`, `Product`, and `ProductVariant` data models.
![A diagram showcasing an example of how data models from the Order and Product modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716556100/Medusa%20Resources/order-product_l6ylte.jpg)
---
## Pricing Module
A product variants prices are stored as money amounts belonging to a price set. The Medusa application forms a relation between the `ProductVariant` and the `PriceSet` data models.
A product variants prices are stored as money amounts belonging to a price set. Medusa defines a link module that builds a relationship between the `ProductVariant` and the `PriceSet` data models.
![A diagram showcasing an example of how resources from the Pricing and Product Module are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709651464/Medusa%20Resources/product-pricing_vlxsiq.jpg)
![A diagram showcasing an example of how data models from the Pricing and Product Module are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709651464/Medusa%20Resources/product-pricing_vlxsiq.jpg)
So, to add prices for a product variant, create a price set and add the prices as money amounts to it.
@@ -28,17 +36,17 @@ Learn more about the `PriceSet` data model in the [Pricing Concepts](../../prici
## Sales Channel Module
A product can have different availability in different sales channels. The Medusa application forms a relation between the `Product` and `SalesChannel` data models.
A product can have different availability in different sales channels. Medusa defines a link module that builds a relationship between the `Product` and `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Product and Sales Channel modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709651840/Medusa%20Resources/product-sales-channel_t848ik.jpg)
![A diagram showcasing an example of how data models from the Product and Sales Channel modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709651840/Medusa%20Resources/product-sales-channel_t848ik.jpg)
---
## Inventory Module
Each product variant has different inventory details. The Medusa application forms a relation between the `ProductVariant` and `InventoryItem` data models.
Each product variant has different inventory details. Medusa defines a link module that builds a relationship between the `ProductVariant` and `InventoryItem` data models.
![A diagram showcasing an example of how resources from the Product and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709652779/Medusa%20Resources/product-inventory_kmjnud.jpg)
![A diagram showcasing an example of how data models from the Product and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709652779/Medusa%20Resources/product-inventory_kmjnud.jpg)
When the `manage_inventory` field of a product variant is enabled, you can manage the variant's inventory in different locations through this relation.

View File

@@ -8,13 +8,7 @@ In this document, youll learn about promotion actions and how theyre compu
## computeActions Method
The `IPromotionModuleService` has a `computeActions` method that returns an array of actions to perform on a cart when one or more promotions are applied.
<Note>
Refer to [the methods reference](/references/promotion/computeActions) for full details on this methods parameters and return type.
</Note>
The Promotion Module's main service has a [computeActions method](/references/promotion/computeActions) that returns an array of actions to perform on a cart when one or more promotions are applied.
Actions inform you what adjustment must be made to a cart item or shipping method. Each action is an object having the `action` field indicating the type of action.
@@ -38,7 +32,7 @@ export interface AddItemAdjustmentAction {
}
```
When the Medusa application receives this action type, it creates a new record of the `LineItemAdjustment` data model in the Cart Module.
This action means that a new record should be created of the `LineItemAdjustment` data model in the Cart Module.
<Note>
@@ -50,7 +44,7 @@ Refer to [this reference](/references/promotion/interfaces/promotion.AddItemAdju
The `removeItemAdjustment` action indicates that an adjustment must be removed from a line item. For example, remove the $5 discount.
When the Medusa application uses the `computeActions` method, it passes any previous item adjustments in the `items` property of the second parameter.
The `computeActions` method accepts any previous item adjustments in the `items` property of the second parameter.
This action has the following format:
@@ -63,7 +57,7 @@ export interface RemoveItemAdjustmentAction {
}
```
When the Medusa application receives this action type, it removes the `LineItemAdjustment` with the specified ID in the `adjustment_id` property.
This action means that a new record should be removed of the `LineItemAdjustment` with the specified ID in the `adjustment_id` property.
<Note>
@@ -87,7 +81,7 @@ export interface AddShippingMethodAdjustment {
}
```
When the Medusa application receives this action type, it creates a new record of the `ShippingMethodAdjustment` data model in the Cart Module.
This action means that a new record should be created of the `ShippingMethodAdjustment` data model in the Cart Module.
<Note>
@@ -99,7 +93,7 @@ Refer to [this reference](/references/promotion/interfaces/promotion.AddShipping
The `removeShippingMethodAdjustment` action indicates that an adjustment must be removed from a shipping method. For example, remove the free shipping discount.
When the Medusa application uses the `computeActions` method, it passes any previous shipping method adjustments in the `shipping_methods` property of the second parameter.
The `computeActions` method accepts any previous shipping method adjustments in the `shipping_methods` property of the second parameter.
This action has the following format:
@@ -132,8 +126,6 @@ export interface CampaignBudgetExceededAction {
}
```
The Medusa Application considers this an error, so it doesnt apply the promotions on the cart.
<Note>
Refer to [this reference](/references/promotion/interfaces/promotion.CampaignBudgetExceededAction) for details on the objects properties.

View File

@@ -0,0 +1,90 @@
import { Table } from "docs-ui"
export const metadata = {
title: `Application Method`,
}
# {metadata.title}
In this document, you'll learn what an application method is.
## What is an Application Method?
The [ApplicationMethod data model](/references/promotion/models/ApplicationMethod) defines how a promotion is applied:
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>
Field
</Table.HeaderCell>
<Table.HeaderCell>
Purpose
</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`type`
</Table.Cell>
<Table.Cell>
Does the promotion discount a fixed amount or a percentage?
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`target_type`
</Table.Cell>
<Table.Cell>
Is the promotion applied on a cart item, shipping method, or the entire order?
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`allocation`
</Table.Cell>
<Table.Cell>
Is the discounted amount applied on each item or split between the applicable items?
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
## Target Promotion Rules
When the promotion is applied to a cart item or a shipping method, you can restrict which items/shipping methods the promotion is applied to.
The `ApplicationMethod` data model has a collection of `PromotionRule` records to restrict which items or shipping methods the promotion applies to. The `target_rules` field represents this relation.
![A diagram showcasing the target_rules relation between the ApplicationMethod and PromotionRule data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709898273/Medusa%20Resources/application-method-target-rules_hqaymz.jpg)
In this example, the promotion is only applied on products in the cart having the SKU `SHIRT`.
---
## Buy Promotion Rules
When the promotions type is `buyget`, you must specify the “buy X” condition. For example, a cart must have two shirts before the promotion can be applied.
The application method has a collection of `PromotionRule` items to define the “buy X” rule. The `buy_rules` field represents this relation.
![A diagram showcasing the buy_rules relation between the ApplicationMethod and PromotionRule data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709898453/Medusa%20Resources/application-method-buy-rules_djjuhw.jpg)
In this example, the cart must have two products with the SKU `SHIRT` for the promotion to be applied.

View File

@@ -0,0 +1,26 @@
export const metadata = {
title: `Campaign`,
}
# {metadata.title}
In this document, you'll learn about campaigns.
## What is a Campaign?
A [Campaign](/references/promotion/models/Campaign) combines promotions under the same conditions, such as start and end dates.
![A diagram showcasing the relation between the Campaign and Promotion data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709899225/Medusa%20Resources/campagin-promotion_hh3qsi.jpg)
---
## Campaign Limits
Each campaign has a budget represented by the [CampaignBudget data model](/references/promotion/models/CampaignBudget). The budget limits how many times the promotion can be used.
There are two types of budgets:
- `spend`: An amount that, when crossed, the promotion becomes unusable. For example, if the amount limit is set to `$100`, and the total amount of usage of this promotion crosses that threshold, the promotion can no longer be applied.
- `usage`: The number of times that a promotion can be used. For example, if the usage limit is set to `10`, the promotion can be used only 10 times by customers. After that, it can no longer be applied.
![A diagram showcasing the relation between the Campaign and CampaignBudget data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709899463/Medusa%20Resources/campagin-budget_rvqlmi.jpg)

View File

@@ -6,11 +6,11 @@ export const metadata = {
# {metadata.title}
In this document, youll learn about the concepts in the Promotion Module.
In this document, youll learn about the main promotion and rule concepts in the Promotion Module.
## Promotion
## What is a Promotion?
A promotion, represented by the `Promotion` data model, represents a discount applied on cart items, shipping methods, or entire orders.
A promotion, represented by the [Promotion data model](/references/promotion/models/Promotion), represents a discount applied on cart items, shipping methods, or entire orders.
A promotion has two types:
@@ -72,131 +72,27 @@ A promotion has two types:
</Table.Body>
</Table>
### PromotionRule
## PromotionRule
A promotion can be restricted by a set of rules, each rule is represented by the `PromotionRule` data model. For example, you can create a promotion that only customers of the `VIP` customer group can use it.
A promotion can be restricted by a set of rules, each rule is represented by the [PromotionRule data model](/references/promotion/models/PromotionRule). For example, you can create a promotion that only customers of the `VIP` customer group can use.
![A diagram showcasing the relation between Promotion and PromotionRule](https://res.cloudinary.com/dza7lstvk/image/upload/v1709833196/Medusa%20Resources/promotion-promotion-rule_msbx0w.jpg)
A `PromotionRule`'s `field` field indicates the field's name to which this rule is applied. For example, `customer_group_id`. Its value is stored in the `PromotionRuleValue` data model. So, a rule can have multiple values.
A `PromotionRule`'s `attribute` field indicates the field's name to which this rule is applied. For example, `customer_group_id`. Its value is stored in the `PromotionRuleValue` data model. So, a rule can have multiple values.
When testing whether a promotion can be applied to a cart, the rule's `field` field and its values are tested on the cart itself. For example, the cart's customer must be part of the customer group(s) indicated in the promotion rule's value.
When testing whether a promotion can be applied to a cart, the rule's `attribute` field and its values are tested on the cart itself. For example, the cart's customer must be part of the customer group(s) indicated in the promotion rule's value.
### Flexible Rules
---
## Flexible Rules
The `PromotionRule`'s `operator` field adds more flexibility to the rules condition rather than simple equality (`eq`).
For example, to restrict the promotion to only `VIP` and `B2B` customer groups:
- Add a `PromotionRule` with its `field` field set to `customer_group_id` and `operator` field to `in`.
- Add a `PromotionRule` with its `attribute` field set to `customer_group_id` and `operator` field to `in`.
- Add two `PromotionRuleValue` associated with the rule: one with the value `VIP` and the other `B2B`.
![A diagram showcasing the relation between PromotionRule and PromotionRuleValue when a rule has multiple values](https://res.cloudinary.com/dza7lstvk/image/upload/v1709897383/Medusa%20Resources/promotion-promotion-rule-multiple_hctpmt.jpg)
In this case, a customers group must be in the `VIP` and `B2B` set of values to use the promotion.
---
## Application Method
The `ApplicationMethod` data model defines how a promotion is applied:
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>
field
</Table.HeaderCell>
<Table.HeaderCell>
Purpose
</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`type`
</Table.Cell>
<Table.Cell>
Does the promotion discount a fixed amount or a percentage?
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`target_type`
</Table.Cell>
<Table.Cell>
Is the promotion applied on a cart item, shipping method, or the entire order?
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`allocation`
</Table.Cell>
<Table.Cell>
Is the discounted amount applied on each item or split between the applicable items?
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
### Target Promotion Rules
When the promotion is applied to a cart item or a shipping method, you can restrict which items/shipping methods the promotion is applied to.
The `ApplicationMethod` data model has a collection of `PromotionRule` records to restrict which items or shipping methods the promotion applies to. The `target_rules` field represents this relation.
![A diagram showcasing the target_rules relation between the ApplicationMethod and PromotionRule data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709898273/Medusa%20Resources/application-method-target-rules_hqaymz.jpg)
In this example, the promotion is only applied on products in the cart having the SKU `SHIRT`.
### Buy Promotion Rules
When the promotions type is `buyget`, you must specify the “buy X” condition. For example, a cart must have two shirts before the promotion can be applied.
The application method has a collection of `PromotionRule` items to define the “buy X” rule. The `buy_rules` field represents this relation.
![A diagram showcasing the buy_rules relation between the ApplicationMethod and PromotionRule data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709898453/Medusa%20Resources/application-method-buy-rules_djjuhw.jpg)
In this example, the cart must have two products with the SKU `SHIRT` for the promotion to be applied.
---
## Campaign
A `Campaign` combines promotions under the same conditions, such as start and end dates.
![A diagram showcasing the relation between the Campaign and Promotion data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709899225/Medusa%20Resources/campagin-promotion_hh3qsi.jpg)
### Campaign Limits
Each campaign has a budget represented by the `CampaignBudget` data model. The budget limits how many times the promotion can be used.
There are two types of budgets:
- `spend`: An amount that, when crossed, the promotion becomes unusable. For example, if the amount limit is set to `$100`, and the total amount of usage of this promotion crosses that threshold, the promotion can no longer be applied.
- `usage`: The number of times that a promotion can be used. For example, if the usage limit is set to `10`, the promotion can be used only 10 times by customers. After that, it can no longer be applied.
![A diagram showcasing the relation between the Campaign and CampaignBudget data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709899463/Medusa%20Resources/campagin-budget_rvqlmi.jpg)
---
## Full Data Models Diagram
![A diagram showcasing all data models and the relations between them](https://res.cloudinary.com/dza7lstvk/image/upload/v1709900277/Medusa%20Resources/promotion-architecture_an8mzy.jpg)

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Promotion Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -32,6 +32,7 @@ In this document, youll find common examples of how you can use the Promotion
type: "percentage",
target_type: "order",
value: "10",
currency_code: "usd",
},
})
@@ -61,6 +62,7 @@ In this document, youll find common examples of how you can use the Promotion
type: "percentage",
target_type: "order",
value: "10",
currency_code: "usd",
},
})
@@ -96,11 +98,6 @@ In this document, youll find common examples of how you can use the Promotion
campaign_identifier: "G-123445",
starts_at: new Date("2024-05-02"),
ends_at: new Date("2024-07-20"),
promotions: [
{
id: "promo_123",
},
],
}
)
@@ -129,11 +126,6 @@ In this document, youll find common examples of how you can use the Promotion
campaign_identifier: "G-123445",
starts_at: new Date("2024-05-02"),
ends_at: new Date("2024-07-20"),
promotions: [
{
id: "promo_123",
},
],
}
)
@@ -170,10 +162,11 @@ In this document, youll find common examples of how you can use the Promotion
type: "percentage",
target_type: "order",
value: "10",
currency_code: "usd",
},
rules: [
{
field: "customer_group_id",
attribute: "customer_group_id",
operator: "eq",
values: ["VIP"],
},
@@ -205,10 +198,11 @@ In this document, youll find common examples of how you can use the Promotion
type: "percentage",
target_type: "order",
value: "10",
currency_code: "usd",
},
rules: [
{
field: "customer_group_id",
attribute: "customer_group_id",
operator: "eq",
values: ["VIP"],
},
@@ -257,7 +251,7 @@ In this document, youll find common examples of how you can use the Promotion
initialize as initializePromotionModule,
} from "@medusajs/promotion"
export async function POST(request: Request) {
export async function GET(request: Request) {
const promotionModuleService =
await initializePromotionModule()
@@ -274,4 +268,4 @@ In this document, youll find common examples of how you can use the Promotion
## More Examples
The [module interface reference](/references/promotion) provides a reference to all the methods available for use with examples for each.
The [Promotion Module's main service reference](/references/promotion) provides a reference to all the methods available for use with examples for each.

View File

@@ -24,6 +24,7 @@ const promotion = await promotionModuleService.create({
type: "percentage",
target_type: "order",
value: "10",
currency_code: "usd"
},
})
```
@@ -40,10 +41,11 @@ const promotion = await promotionModuleService.create({
type: "percentage",
target_type: "order",
value: "10",
currency_code: "usd"
},
rules: [
{
field: "customer_group_id",
attribute: "customer_group_id",
operator: "eq",
values: ["VIP"],
},
@@ -64,11 +66,6 @@ const campaign = await promotionModuleService.createCampaigns(
campaign_identifier: "G-123445",
starts_at: new Date("2024-05-02"),
ends_at: new Date("2024-07-20"),
promotions: [
{
id: "promo_123",
},
],
}
)
```
@@ -77,14 +74,16 @@ const campaign = await promotionModuleService.createCampaigns(
## Configure Promotion Module
After installing the `@medusajs/promotion` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Promotion Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
promotion: {
resolve: "@medusajs/promotion",
},
[Modules.PROMOTION]: true,
}
```
@@ -143,9 +142,11 @@ For example:
import { IPromotionModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const promotionModuleService: IPromotionModuleService =
context.container.resolve(ModuleRegistrationName.PROMOTION)
container.resolve(ModuleRegistrationName.PROMOTION)
const promotions = await promotionModuleService.list()
})

View File

@@ -4,14 +4,18 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the Promotion Module and other Commerce Modules.
This document showcases the link modules defined between the Promotion Module and other commerce modules.
## Cart Module
When the Cart and Promotion modules are used together, the Medusa application links the `Promotion` data model to the `Cart`, `LineItemAdjustment`, and `ShippingMethodAdjustment` data models of the Cart Module.
A promotion can be applied on line items and shipping methods of a cart. Medusa defines a link module that builds a relationship between the `Cart`, `LineItemAdjustment`, and `Promotion` data models.
![A diagram showcasing an example of how resources from the Promotion and Cart modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709905821/Medusa%20Resources/promotion-cart_z5qklr.jpg)
![A diagram showcasing an example of how data models from the Cart and Promotion modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538015/Medusa%20Resources/cart-promotion_kuh9vm.jpg)
A promotion is linked to a cart when a promotion is applied on the cart. Adjustments on items and shipping methods, represented by the `LineItemAdjustment` and `ShippingMethodAdjustment` data models, are linked to the promotion as well.
---
## Order Module
An order is associated with the promotion applied on it. Medusa defines a link module that builds a relationship between the `Order` and `Promotion` data models.
![A diagram showcasing an example of how data models from the Order and Promotion modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716555015/Medusa%20Resources/order-promotion_dgjzzd.jpg)

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Region Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -263,4 +263,4 @@ In this guide, youll find common examples of how you can use the Region Modul
## More Examples
The [Region Module interface reference](/references/region) provides a reference to all the methods available for use with examples for each.
The [Region Module's main service reference](/references/region) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,8 +8,6 @@ export const metadata = {
The Region Module is the `@medusajs/region` NPM package that provides region-related features in your Medusa and Node.js applications.
---
## What is a Region?
A region represents the area you sell products in. Each region can cover multiple countries, but uses a single currency.
@@ -48,7 +46,7 @@ const regions = await regionModuleService.create([
### Different Settings Per Region
Each region has its own settings, such as what countries belong to a region or its tax settings. When using other commerce modules such as the Tax Module or Payment Module, each region has different tax rates, payment providers, and more.
Each region has its own settings, such as what countries belong to a region or its tax settings. Each region has different tax rates, payment providers, and more provided by other commerce modules.
```ts
const regions = await regionModuleService.create([
@@ -62,7 +60,7 @@ const regions = await regionModuleService.create([
name: "United States of America",
currency_code: "usd",
countries: ["us"],
automatic_taxes: false,
payment_providers: ["stripe"]
},
])
```
@@ -71,14 +69,16 @@ const regions = await regionModuleService.create([
## Configure Region Module
After installing the `@medusajs/region` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Region Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
region: {
resolve: "@medusajs/region",
},
[Modules.REGION]: true,
}
```
@@ -137,9 +137,11 @@ For example:
import { IRegionModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const regionModuleService: IRegionModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.REGION
)

View File

@@ -4,14 +4,28 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the relation between the Region Module and other Commerce Modules.
This document showcases the link modules defined between the Region Module and other commerce modules.
## Cart Module
Carts are associated with a region. The Medusa application forms a relation between the `Region` and the `Cart` data models.
Carts are associated with a region. Medusa defines a link module that builds a relationship between the `Region` and the `Cart` data models.
![A diagram showcasing an example of how resources from the API Key and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711116934/Medusa%20Resources/region-cart_hffaib.jpg)
![A diagram showcasing an example of how resources from the API Key and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716543714/Medusa%20Resources/customer-region_rtmymb.jpg)
The cart then uses the same currency as the region. During checkout, the cart's taxes, payment, and fulfillment providers are available based on the region's settings.
---
## Order Module
An order is associated with the customer's region. Medusa defines a link module that builds a relationship between the `Order` and `Region` data models.
![A diagram showcasing an example of how data models from the Order and Region modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716555119/Medusa%20Resources/order-region_ihkp2u.jpg)
---
## Payment Module
You can specify for each region which payment providers are available. Medusa defines a link module that builds a relationship between the `PaymentProvider` and the `Region` data models.
![A diagram showcasing an example of how resources from the Payment and Region modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711569520/Medusa%20Resources/payment-region_jyo2dz.jpg)

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Sales Channel Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -26,7 +26,7 @@ In this guide, youll find common examples of how you can use the Sales Channe
request.scope.resolve(ModuleRegistrationName.SALES_CHANNEL)
const salesChannel = await salesChannelModuleService.create({
name: request.body.name,
name: "B2B",
})
res.json({
@@ -48,10 +48,9 @@ In this guide, youll find common examples of how you can use the Sales Channe
export async function POST(request: Request) {
const salesChannelModuleService =
await initializeSalesChannelModule()
const body = await request.json()
const salesChannel = await salesChannelModuleService.create({
name: body.name,
name: "B2B",
})
return NextResponse.json({ sales_channel: salesChannel })
@@ -129,7 +128,7 @@ In this guide, youll find common examples of how you can use the Sales Channe
request.scope.resolve(ModuleRegistrationName.SALES_CHANNEL)
const salesChannel = await salesChannelModuleService.retrieve(
request.params.id
"sc_123"
)
res.json({
@@ -148,22 +147,14 @@ In this guide, youll find common examples of how you can use the Sales Channe
initialize as initializeSalesChannelModule,
} from "@medusajs/sales-channel"
type ContextType = {
params: {
id: string
}
}
export async function GET(
request: Request,
{ params }: ContextType
request: Request
) {
const salesChannelModuleService =
await initializeSalesChannelModule()
const body = await request.json()
const salesChannel = await salesChannelModuleService.retrieve(
params.id
"sc_123"
)
return NextResponse.json({ sales_channel: salesChannel })
@@ -193,8 +184,8 @@ In this guide, youll find common examples of how you can use the Sales Channe
request.scope.resolve(ModuleRegistrationName.SALES_CHANNEL)
const salesChannel = await salesChannelModuleService.update({
id: request.params.id,
description: request.body.description,
id: "sc_123",
description: "Sales channel for B2B customers",
})
res.json({
@@ -213,23 +204,15 @@ In this guide, youll find common examples of how you can use the Sales Channe
initialize as initializeSalesChannelModule,
} from "@medusajs/sales-channel"
type ContextType = {
params: {
id: string
}
}
export async function POST(
request: Request,
{ params }: ContextType
request: Request
) {
const salesChannelModuleService =
await initializeSalesChannelModule()
const body = await request.json()
const salesChannel = await salesChannelModuleService.update({
id: params.id,
description: body.description,
id: "sc_123",
description: "Sales channel for B2B customers",
})
return NextResponse.json({ sales_channel: salesChannel })
@@ -258,7 +241,7 @@ In this guide, youll find common examples of how you can use the Sales Channe
const salesChannelModuleService: ISalesChannelModuleService =
request.scope.resolve(ModuleRegistrationName.SALES_CHANNEL)
await salesChannelModuleService.delete(request.params.id)
await salesChannelModuleService.delete("sc_123")
res.status(200)
}
@@ -274,20 +257,13 @@ In this guide, youll find common examples of how you can use the Sales Channe
initialize as initializeSalesChannelModule,
} from "@medusajs/sales-channel"
type ContextType = {
params: {
id: string
}
}
export async function DELETE(
request: Request,
{ params }: ContextType
request: Request
) {
const salesChannelModuleService =
await initializeSalesChannelModule()
await salesChannelModuleService.delete(params.id)
await salesChannelModuleService.delete("sc_123")
}
```
@@ -298,4 +274,4 @@ In this guide, youll find common examples of how you can use the Sales Channe
## More Examples
The [Sales Channel Module interface reference](/references/sales-channel) provides a reference to all the methods available for use with examples for each.
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.

View File

@@ -16,7 +16,7 @@ Some use case examples for using a sales channel:
- Implement a B2B Ecommerce Store.
- Specify different products for each channel you sell in.
- Support Omnichannel in your ecommerce store.
- Support omnichannel in your ecommerce store.
---
@@ -24,9 +24,7 @@ Some use case examples for using a sales channel:
### Sales Channel Management
Store and 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.
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.create([
@@ -41,7 +39,7 @@ const salesChannels = await salesChannelModuleService.create([
### Product Availability
By combining the Product and Sales Channel modules, you can specify a product's availability per sales channel.
Medusa links the Product and Sales Channel modules, allowing merchants to specify a product's availability per sales channel.
For example, B2B customers viewing products only see products in the B2B sales channel.
@@ -55,14 +53,16 @@ Orders are also scoped to a sales channel due to the relation between the Sales
## Configure Sales Channel Module
After installing the `@medusajs/sales-channel` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Sales Channel Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
salesChannel: {
resolve: "@medusajs/sales-channel",
},
[Modules.SALES_CHANNEL]: true,
}
```
@@ -121,11 +121,14 @@ For example:
import { ISalesChannelModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const salesChannelModuleService: ISalesChannelModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.SALES_CHANNEL
)
const salesChannels = await salesChannelModuleService.list()
})
```

View File

@@ -12,7 +12,7 @@ In this document, youll learn what publishable API keys are and how to use th
When using multiple sales channels, youll need to specify the ID of a storefronts sales channel. This ensures that you retrieve the products available in that sales channel and associate the sales channel with the storefronts carts and orders.
The Store API routes accept the sales channels IDs differently. For example, the [List Products API route](https://docs.medusajs.com/api/store#products) accepts the sales channels ID as a query parameter, whereas the [Create Cart API route](https://docs.medusajs.com/api/store#carts_postcart) accepts it in the requests body.
The [Store API routes](!api!/store) accept the sales channels IDs differently depending on the API route's HTTP method. Some accept it as a query parameter whereas others accept it as a request body parameter.
This approach is tedious and error-prone as your storefront scales and as you develop multiple types of storefronts.
@@ -20,59 +20,17 @@ This approach is tedious and error-prone as your storefront scales and as you de
## Introducing Publishable API Keys
The API Key module allows you to create keys for different usages. One of those usages is to create a publishable API key.
A publishable API key, provided by the API Key Module, is a client key scoped to one or more sales channels. When passed in the header of a request, the Medusa application infers the associated sales channels.
A publishable API key is a client key scoped to one or more sales channels. When passed in the header of a request, the Medusa application infers the associated sales channels.
So, instead of the previous approach of manually passing the sales channels ID based on the API route, you always pass the publishable API key in the header of your requests:
So, instead of the approach, indicated in the previous section, of manually passing the sales channels ID based on the API route, you always pass the publishable API key in the header of your requests:
```bash
curl http://localhost:9000/store/products \
x-publishable-api-key: {your_publishable_api_key}
```
The Medusa JS Client and Medusa React both provide the option to pass the publishable API key during initialization:
<CodeTabs groupId="client-id">
<CodeTab label="JS Client" value="js-client">
```ts
const medusa = new Medusa({
maxRetries: 3,
baseUrl: "http://localhost:9000",
publishableApiKey,
})
```
</CodeTab>
<CodeTab label="Medusa React" value="medusa-react">
```tsx
import { MedusaProvider } from "medusa-react"
// define query client...
const App = () => {
return (
<MedusaProvider
queryClientProviderProps={{ client: queryClient }}
baseUrl="http://localhost:9000"
// ...
publishableApiKey={publishableApiKey}
>
<MyStorefront />
</MedusaProvider>
)
}
```
</CodeTab>
</CodeTabs>
Then, all requests using the client/hooks automatically include the publishable API key in the header.
---
## How to Create a Publishable API Key?
To create a publishable API key, either use the Medusa Admin or the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys).
To create a publishable API key, either use the Medusa Admin or the [Admin API Routes](!api!/admin#publishable-api-keys).

View File

@@ -4,25 +4,23 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the link modules defined between the Sales Channel Module and other commerce modules.
This document showcases the relation between the Sales Channel Module and other Commerce Modules.
## API Key Module
## Product Module
A publishable API key allows you to easily specify the sales channel scope in a client request. Medusa defines a link module that builds a relationship between the `ApiKey` and the `SalesChannel` data models.
A product has different availability for different sales channels. The Medusa application forms a relation between the `Product` and the `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Sales Channel and API Key modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709812064/Medusa%20Resources/sales-channel-api-key_zmqi2l.jpg)
A product can be available in more than one sales channel. Then, you can retrieve only the products of a sales channel.
![A diagram showcasing an example of how resources from the Sales Channel and Product modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709809833/Medusa%20Resources/product-sales-channel_ciqj6i.jpg)
Using the API Key Module, you create a publishable key and associate it with a sales channel. Learn more in [this document](../publishable-api-keys/page.mdx)
---
## Cart Module
A cart is associated with the sales channel it's created in. The Medusa application forms a relation between the `Cart` and the `SalesChannel` data models.
A cart is associated with the sales channel it's created in. Medusa defines a link module that builds a relationship between the `Cart` and the `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Sales Channel and Cart modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709811093/Medusa%20Resources/sales-channel-cart_m0hozt.jpg)
![A diagram showcasing an example of how data models from the Cart and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538159/Medusa%20Resources/cart-sales-channel_n2oi0v.jpg)
For example, if a customer adds an item to the cart in a mobile app, the cart is associated with the mobile app's sales channel. However, if a customer adds an item to the cart in a web storefront, the cart is associated with the storefront's sales channel.
@@ -30,20 +28,28 @@ For example, if a customer adds an item to the cart in a mobile app, the cart is
## Order Module
An order is associated with the sales channel it's created in. The Medusa application forms a relation between the `Order` and the `SalesChannel` data models.
An order is associated with the sales channel it's created in. Medusa defines a link module that builds a relationship between the `Order` and the `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Sales Channel and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709810401/Medusa%20Resources/sales-channel-order_ixayla.jpg)
![A diagram showcasing an example of how resources from the Order and Sales Channel modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712315409/Medusa%20Resources/order-sales-channel_dy72gx.jpg)
For example, if an order is created in a mobile app, it'll be associated with its sales channel. If another order is created through a POS system, it'll be associated with the POS's sales channel.
---
## API Key Module
## Product Module
A publishable API key allows you to easily specify the sales channel scope in a client request. The Medusa application forms a relation between the `ApiKey` and the `SalesChannel` data models.
A product has different availability for different sales channels. Medusa defines a link module that builds a relationship between the `Product` and the `SalesChannel` data models.
![A diagram showcasing an example of how resources from the Sales Channel and API Key modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709812064/Medusa%20Resources/sales-channel-api-key_zmqi2l.jpg)
A product can be available in more than one sales channel. Then, you can retrieve only the products of a sales channel.
Using the API Key Module, you create a publishable key and associate it with a sales channel.
![A diagram showcasing an example of how resources from the Sales Channel and Product modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1709809833/Medusa%20Resources/product-sales-channel_ciqj6i.jpg)
Instead of passing the sales channel's ID in every request either in the query or body parameters, you always pass the API key in the header of your requests. The Medusa application then infers the sales channel scope from it.
---
## Stock Location Module
A stock location is associated with a sales channel. This scopes inventory quantities associated with that stock location by the associated sales channel.
Medusa defines a link module that builds a relationship between the `SalesChannel` and `StockLocation` data models.
![A diagram showcasing an example of how resources from the Sales Channel and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716796872/Medusa%20Resources/sales-channel-location_cqrih1.jpg)

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Stock Location Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -27,7 +27,7 @@ In this document, youll find common examples of how you can use the Stock Loc
const stockLocation = await stockLocationModuleService.create(
{
name: request.body.name,
name: "Warehouse 1",
}
)
@@ -50,11 +50,10 @@ In this document, youll find common examples of how you can use the Stock Loc
export async function POST(request: Request) {
const stockLocationModuleService =
await initializeStockLocationModule({})
const body = await request.json()
const stockLocation = await stockLocationModuleService.create(
{
name: body.name,
name: "Warehouse 1",
}
)
@@ -132,17 +131,15 @@ In this document, youll find common examples of how you can use the Stock Loc
const stockLocationModuleService: IStockLocationService =
request.scope.resolve(ModuleRegistrationName.STOCK_LOCATION)
const stockLocation = await stockLocationModuleService.update(
{
id: request.params.id,
address: {
country_code: request.body.country_code,
city: request.body.city,
address_1: request.body.address_1,
postal_code: request.body.postal_code,
},
}
)
const stockLocation = await stockLocationModuleService.update({
id: "sloc_123",
address: {
country_code: "US",
city: "New York City",
address_1: "52 Stone St",
postal_code: "10004",
},
})
res.json({
stock_location: stockLocation,
@@ -160,31 +157,21 @@ In this document, youll find common examples of how you can use the Stock Loc
initialize as initializeStockLocationModule,
} from "@medusajs/stock-location-next"
type ContextType = {
params: {
id: string
}
}
export async function POST(
request: Request,
{ params }: ContextType
request: Request
) {
const stockLocationModuleService =
await initializeStockLocationModule({})
const body = await request.json()
const stockLocation = await stockLocationModuleService.update(
{
id: params.id,
address: {
country_code: body.country_code,
city: body.city,
address_1: body.address_1,
postal_code: body.postal_code,
},
}
)
const stockLocation = await stockLocationModuleService.update({
id: "sloc_123",
address: {
country_code: "us",
city: "New York City",
address_1: "52 Stone St",
postal_code: "10004",
},
})
return NextResponse.json({
stock_location: stockLocation,
@@ -214,7 +201,7 @@ In this document, youll find common examples of how you can use the Stock Loc
const stockLocationModuleService: IStockLocationService =
request.scope.resolve(ModuleRegistrationName.STOCK_LOCATION)
await stockLocationModuleService.delete(request.params.id)
await stockLocationModuleService.delete("sloc_123")
res.status(200)
}
@@ -230,20 +217,13 @@ In this document, youll find common examples of how you can use the Stock Loc
initialize as initializeStockLocationModule,
} from "@medusajs/stock-location-next"
type ContextType = {
params: {
id: string
}
}
export async function DELETE(
request: Request,
{ params }: ContextType
request: Request
) {
const stockLocationModuleService =
await initializeStockLocationModule({})
await stockLocationModuleService.delete(params.id)
await stockLocationModuleService.delete("sloc_123")
}
```
@@ -254,4 +234,4 @@ In this document, youll find common examples of how you can use the Stock Loc
## More Examples
The [module interface reference](/references/stock-location) provides a reference to all the methods available for use with examples for each.
The [Stock Location Module's main service reference](/references/stock-location) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,19 +8,11 @@ export const metadata = {
The Stock Location Module is the `@medusajs/stock-location-next` NPM package that provides stock-location-related features in your Medusa and Node.js applications.
It's mainly useful with the [Inventory Module](../inventory/page.mdx).
<Note>
This module is an updated version of the [Stock Location Module part of the multi-warehouse feature](../../modules/multiwarehouse/stock-location-module.md). In Medusa V2, the previous version of the module will no longer be in use.
</Note>
## Features
### Stock Location Management
Store and manage stock locations. Stock locations can be associated with other models that require a location, such as the [Inventory Module's InventoryLevel](../inventory/concepts/page.mdx#inventory-level).
Store and manage stock locations. Stock locations are associated with data models of other modules that require a location, such as the [Inventory Module's InventoryLevel](../inventory/concepts/page.mdx#inventory-level).
```ts
const stockLocation = await stockLocationModuleService.create(
@@ -32,14 +24,14 @@ const stockLocation = await stockLocationModuleService.create(
### Address Management
A stock location can have detailed address details.
Manage the address of each stock location.
```ts
const stockLocation = await stockLocationModuleService.update(
{
id: "sloc_123",
address: {
country_code: "US",
country_code: "us",
city: "New York City",
address_1: "52 Stone St",
postal_code: "10004",
@@ -52,14 +44,16 @@ const stockLocation = await stockLocationModuleService.update(
## Configure Stock Location Module
After installing the `@medusajs/stock-location` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Stock Location Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
stockLocationService: {
resolve: "@medusajs/stock-location-next",
},
[Modules.STOCK_LOCATION]: true,
}
```
@@ -120,9 +114,11 @@ For example:
import { IStockLocationService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const stockLocationModuleService: IStockLocationService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.STOCK_LOCATION
)

View File

@@ -4,14 +4,30 @@ export const metadata = {
# {metadata.title}
When Commerce Modules are used together in a Medusa application, the Medusa application handles building the relations between these modules.
This document showcases the link modules defined between the Stock Location Module and other commerce modules.
This document showcases the relation between the Stock Location Module and other Commerce Modules.
## Fulfillment Module
A fulfillment set can be conditioned to a specific stock location. Medusa defines a link module that builds a relationship between the `FulfillmentSet` and `StockLocation` data models.
![A diagram showcasing an example of how data models from the Fulfillment and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712567101/Medusa%20Resources/fulfillment-stock-location_nlkf7e.jpg)
---
## Inventory Module
Reservation items and inventory items are associated with a location. The Medusa application forms a relation between the `ReservationItem` and `StockLocation` data models, and the `InventoryLevel` and `StockLocation` data models.
Reservation items and inventory items are associated with a location. Medusa defines a link module that builds a relationship between the `ReservationItem` and `StockLocation` data models, and the `InventoryLevel` and `StockLocation` data models.
![A diagram showcasing an example of how resources from the Stock Location and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709716521/Medusa%20Resources/stock-location-inventory_logsrt.jpg)
![A diagram showcasing an example of how resources from the Stock Location and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709660383/Medusa%20Resources/inventory-stock-location_yp26k3.jpg)
With this relation, stock and reserved quantity is specific to a location, providing you with more flexibility. The location can be as simple as having only a name, and more flexible by adding more address details to it.
---
## Sales Channel Module
A stock location is associated with a sales channel. This scopes inventory quantities associated with that stock location by the associated sales channel.
Medusa defines a link module that builds a relationship between the `SalesChannel` and `StockLocation` data models.
![A diagram showcasing an example of how resources from the Sales Channel and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716796872/Medusa%20Resources/sales-channel-location_cqrih1.jpg)

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Store Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

View File

@@ -243,7 +243,7 @@ In this guide, youll find common examples of how you can use the Store Module
const storeModuleService: IStoreModuleService =
request.scope.resolve(ModuleRegistrationName.STORE)
await storeModuleService.delete(request.params.id)
await storeModuleService.delete("store_123")
res.status(200)
}
@@ -259,19 +259,13 @@ In this guide, youll find common examples of how you can use the Store Module
initialize as initializeStoreModule,
} from "@medusajs/store"
type ContextType = {
params: {
id: string
}
}
export async function DELETE(
request: Request,
{ params }: ContextType
) {
const storeModuleService = await initializeStoreModule()
await storeModuleService.delete(params.id)
await storeModuleService.delete("store_123")
}
```
@@ -282,5 +276,5 @@ In this guide, youll find common examples of how you can use the Store Module
## More Examples
The [Store Module interface reference](/references/store) provides a reference to all the methods available for use with examples for each.
The [Store Module's main service reference](/references/store) provides a reference to all the methods available for use with examples for each.

View File

@@ -8,8 +8,6 @@ export const metadata = {
The Store Module is the `@medusajs/store` NPM package that provides store-related features in your Medusa and Node.js applications.
---
## Features
### Store Management
@@ -28,31 +26,32 @@ const store = await storeModuleService.create({
You can create multiple stores, each having its own configurations.
```ts
const store1 = await storeModuleService.create({
name: "USA Store",
supported_currency_codes: ["usd"],
})
const store2 = storeModuleService.create({
name: "Europe Store",
supported_currency_codes: [
"eur",
],
})
const stores = await storeModuleService.create([
{
name: "USA Store",
supported_currency_codes: ["usd"],
},
{
name: "Europe Store",
supported_currency_codes: ["eur"],
}
])
```
---
## Configure Store Module
After installing the `@medusajs/store` package in your Medusa application, add it to the `modules` object in `medusa-config.js`:
To use the Store Module, enable it in the `modules` object in `medusa-config.js`:
```js title="medusa-config.js"
const { Modules } = require("@medusajs/modules-sdk")
// ...
const modules = {
// ...
store: {
resolve: "@medusajs/store",
},
[Modules.STORE]: true,
}
```
@@ -111,11 +110,14 @@ For example:
import { IStoreModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const step1 = createStep("step-1", async (_, context) => {
const step1 = createStep(
"step-1",
async (_, { container }) => {
const storeModuleService: IStoreModuleService =
context.container.resolve(
container.resolve(
ModuleRegistrationName.STORE
)
const stores = await storeModuleService.list()
})
```

View File

@@ -0,0 +1,13 @@
export const metadata = {
title: `Relations between Store Module and Other Modules`,
}
# {metadata.title}
This document showcases the link modules defined between the Store Module and other commerce modules.
## Currency Module
A store has a default currency. Medusa defines a link module that builds a relationship between the `Store` and `Currency` data models.
![A diagram showcasing an example of how resources from the Stock Location and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1716798146/Medusa%20Resources/store-currency_wzftwh.jpg)

View File

@@ -8,4 +8,10 @@ export const metadata = {
Find in this reference the list of events emitted by the Tax Module.
<Note type="soon">
Events are still in development, so this reference will change in the future.
</Note>
<EventsTable />

Some files were not shown because too many files have changed in this diff Show More