feat: Cart SalesChannel link + clean-up (#6418)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/core-flows": patch
|
||||||
|
"@medusajs/link-modules": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: Cart SalesChannel link
|
||||||
+60
-19
@@ -1,5 +1,9 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
import { ICartModuleService, IRegionModuleService } from "@medusajs/types"
|
import {
|
||||||
|
ICartModuleService,
|
||||||
|
IRegionModuleService,
|
||||||
|
ISalesChannelModuleService,
|
||||||
|
} from "@medusajs/types"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||||
import { useApi } from "../../../../environment-helpers/use-api"
|
import { useApi } from "../../../../environment-helpers/use-api"
|
||||||
@@ -17,6 +21,7 @@ describe("POST /store/carts", () => {
|
|||||||
let shutdownServer
|
let shutdownServer
|
||||||
let cartModuleService: ICartModuleService
|
let cartModuleService: ICartModuleService
|
||||||
let regionModuleService: IRegionModuleService
|
let regionModuleService: IRegionModuleService
|
||||||
|
let scModuleService: ISalesChannelModuleService
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||||
@@ -25,6 +30,7 @@ describe("POST /store/carts", () => {
|
|||||||
appContainer = getContainer()
|
appContainer = getContainer()
|
||||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||||
regionModuleService = appContainer.resolve(ModuleRegistrationName.REGION)
|
regionModuleService = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||||
|
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@@ -45,34 +51,54 @@ describe("POST /store/carts", () => {
|
|||||||
await db.teardown()
|
await db.teardown()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should create a cart", async () => {
|
it("should create and update a cart", async () => {
|
||||||
const region = await regionModuleService.create({
|
const region = await regionModuleService.create({
|
||||||
name: "US",
|
name: "US",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const salesChannel = await scModuleService.create({
|
||||||
|
name: "Webshop",
|
||||||
|
})
|
||||||
|
|
||||||
const api = useApi() as any
|
const api = useApi() as any
|
||||||
const response = await api.post(`/store/carts`, {
|
|
||||||
|
const created = await api.post(`/store/carts`, {
|
||||||
email: "tony@stark.com",
|
email: "tony@stark.com",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
region_id: region.id,
|
region_id: region.id,
|
||||||
|
sales_channel_id: salesChannel.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
expect(created.status).toEqual(200)
|
||||||
expect(response.data.cart).toEqual(
|
expect(created.data.cart).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: response.data.cart.id,
|
id: created.data.cart.id,
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
email: "tony@stark.com",
|
email: "tony@stark.com",
|
||||||
region: expect.objectContaining({
|
region: expect.objectContaining({
|
||||||
id: region.id,
|
id: region.id,
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
}),
|
}),
|
||||||
|
sales_channel_id: salesChannel.id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const updated = await api.post(`/store/carts/${created.data.cart.id}`, {
|
||||||
|
email: "tony@stark-industries.com",
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(updated.status).toEqual(200)
|
||||||
|
expect(updated.data.cart).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: updated.data.cart.id,
|
||||||
|
currency_code: "usd",
|
||||||
|
email: "tony@stark-industries.com",
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use any region", async () => {
|
it("should create cart with any region", async () => {
|
||||||
await regionModuleService.create({
|
await regionModuleService.create({
|
||||||
name: "US",
|
name: "US",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
@@ -97,7 +123,7 @@ describe("POST /store/carts", () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use region currency code", async () => {
|
it("should create cart with region currency code", async () => {
|
||||||
await regionModuleService.create({
|
await regionModuleService.create({
|
||||||
name: "US",
|
name: "US",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
@@ -132,34 +158,49 @@ describe("POST /store/carts", () => {
|
|||||||
).rejects.toThrow()
|
).rejects.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should create a cart", async () => {
|
it("should get cart", async () => {
|
||||||
const region = await regionModuleService.create({
|
const region = await regionModuleService.create({
|
||||||
name: "US",
|
name: "US",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
})
|
})
|
||||||
|
|
||||||
await regionModuleService.create({
|
const salesChannel = await scModuleService.create({
|
||||||
name: "Europe",
|
name: "Webshop",
|
||||||
currency_code: "eur",
|
})
|
||||||
|
|
||||||
|
const cart = await cartModuleService.create({
|
||||||
|
currency_code: "usd",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
unit_price: 1000,
|
||||||
|
quantity: 1,
|
||||||
|
title: "Test item",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
region_id: region.id,
|
||||||
|
sales_channel_id: salesChannel.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
const api = useApi() as any
|
const api = useApi() as any
|
||||||
const response = await api.post(`/store/carts`, {
|
const response = await api.get(`/store/carts/${cart.id}`)
|
||||||
email: "tony@stark.com",
|
|
||||||
currency_code: "usd",
|
|
||||||
region_id: region.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
expect(response.status).toEqual(200)
|
||||||
expect(response.data.cart).toEqual(
|
expect(response.data.cart).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: response.data.cart.id,
|
id: cart.id,
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
email: "tony@stark.com",
|
items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
unit_price: 1000,
|
||||||
|
quantity: 1,
|
||||||
|
title: "Test item",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
region: expect.objectContaining({
|
region: expect.objectContaining({
|
||||||
id: region.id,
|
id: region.id,
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
}),
|
}),
|
||||||
|
sales_channel_id: salesChannel.id,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
|
||||||
import { ICartModuleService } from "@medusajs/types"
|
|
||||||
import path from "path"
|
|
||||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
|
||||||
import { useApi } from "../../../../environment-helpers/use-api"
|
|
||||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
|
||||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
|
||||||
|
|
||||||
describe("GET /store/:id", () => {
|
|
||||||
let dbConnection
|
|
||||||
let appContainer
|
|
||||||
let shutdownServer
|
|
||||||
let cartModuleService: ICartModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
|
||||||
dbConnection = await initDb({ cwd, env } as any)
|
|
||||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
|
||||||
appContainer = getContainer()
|
|
||||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.shutdown()
|
|
||||||
await shutdownServer()
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.teardown()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should get cart", async () => {
|
|
||||||
const cart = await cartModuleService.create({
|
|
||||||
currency_code: "usd",
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
unit_price: 1000,
|
|
||||||
quantity: 1,
|
|
||||||
title: "Test item",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
const api = useApi() as any
|
|
||||||
const response = await api.get(`/store/carts/${cart.id}`)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.cart).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: cart.id,
|
|
||||||
currency_code: "usd",
|
|
||||||
items: expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
unit_price: 1000,
|
|
||||||
quantity: 1,
|
|
||||||
title: "Test item",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
|
||||||
import { ICartModuleService } from "@medusajs/types"
|
|
||||||
import path from "path"
|
|
||||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
|
||||||
import { useApi } from "../../../../environment-helpers/use-api"
|
|
||||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
|
||||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
|
||||||
|
|
||||||
describe("POST /store/carts/:id", () => {
|
|
||||||
let dbConnection
|
|
||||||
let appContainer
|
|
||||||
let shutdownServer
|
|
||||||
let cartModuleService: ICartModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
|
||||||
dbConnection = await initDb({ cwd, env } as any)
|
|
||||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
|
||||||
appContainer = getContainer()
|
|
||||||
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.shutdown()
|
|
||||||
await shutdownServer()
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.teardown()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should create a cart", async () => {
|
|
||||||
const api = useApi() as any
|
|
||||||
|
|
||||||
const cart = await cartModuleService.create({
|
|
||||||
currency_code: "usd",
|
|
||||||
})
|
|
||||||
|
|
||||||
const response = await api.post(`/store/carts/${cart.id}`, {
|
|
||||||
email: "tony@stark.com",
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.cart).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: cart.id,
|
|
||||||
currency_code: "usd",
|
|
||||||
email: "tony@stark.com",
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
ICartModuleService,
|
||||||
|
IRegionModuleService,
|
||||||
|
ISalesChannelModuleService,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import path from "path"
|
||||||
|
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||||
|
import { getContainer } from "../../../environment-helpers/use-container"
|
||||||
|
import { initDb, useDb } from "../../../environment-helpers/use-db"
|
||||||
|
|
||||||
|
jest.setTimeout(50000)
|
||||||
|
|
||||||
|
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||||
|
|
||||||
|
describe("Cart links", () => {
|
||||||
|
let dbConnection
|
||||||
|
let appContainer
|
||||||
|
let shutdownServer
|
||||||
|
let cartModuleService: ICartModuleService
|
||||||
|
let scModuleService: ISalesChannelModuleService
|
||||||
|
let remoteQuery
|
||||||
|
let regionModule: IRegionModuleService
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
dbConnection = await initDb({ cwd, env } as any)
|
||||||
|
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||||
|
appContainer = getContainer()
|
||||||
|
cartModuleService = appContainer.resolve(ModuleRegistrationName.CART)
|
||||||
|
scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL)
|
||||||
|
regionModule = appContainer.resolve(ModuleRegistrationName.REGION)
|
||||||
|
remoteQuery = appContainer.resolve("remoteQuery")
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
await shutdownServer()
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
// @ts-ignore
|
||||||
|
await regionModule.createDefaultCountriesAndCurrencies()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should query carts, sales channels, regions with remote query", async () => {
|
||||||
|
const region = await regionModule.create({
|
||||||
|
name: "Region",
|
||||||
|
currency_code: "usd",
|
||||||
|
})
|
||||||
|
|
||||||
|
const salesChannel = await scModuleService.create({
|
||||||
|
name: "Webshop",
|
||||||
|
})
|
||||||
|
|
||||||
|
const cart = await cartModuleService.create({
|
||||||
|
email: "tony@stark.com",
|
||||||
|
currency_code: "usd",
|
||||||
|
region_id: region.id,
|
||||||
|
sales_channel_id: salesChannel.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
const carts = await remoteQuery({
|
||||||
|
cart: {
|
||||||
|
fields: ["id"],
|
||||||
|
sales_channel: {
|
||||||
|
fields: ["id"],
|
||||||
|
},
|
||||||
|
region: {
|
||||||
|
fields: ["id"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const salesChannels = await remoteQuery({
|
||||||
|
sales_channel: {
|
||||||
|
fields: ["id"],
|
||||||
|
carts: {
|
||||||
|
fields: ["id"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const regions = await remoteQuery({
|
||||||
|
region: {
|
||||||
|
fields: ["id"],
|
||||||
|
carts: {
|
||||||
|
fields: ["id"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(carts).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: cart.id,
|
||||||
|
sales_channel: expect.objectContaining({ id: salesChannel.id }),
|
||||||
|
region: expect.objectContaining({ id: region.id }),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(salesChannels).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: salesChannel.id,
|
||||||
|
carts: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: cart.id }),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(regions).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: region.id,
|
||||||
|
carts: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: cart.id }),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -37,9 +37,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
featureFlags: {
|
featureFlags: {
|
||||||
medusa_v2: enableMedusaV2,
|
medusa_v2: enableMedusaV2,
|
||||||
workflows: {
|
|
||||||
[Workflows.CreateCart]: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
modules: {
|
modules: {
|
||||||
[Modules.AUTH]: {
|
[Modules.AUTH]: {
|
||||||
|
|||||||
@@ -1,238 +0,0 @@
|
|||||||
import {
|
|
||||||
TransactionStepsDefinition,
|
|
||||||
WorkflowManager,
|
|
||||||
} from "@medusajs/orchestration"
|
|
||||||
import { CartWorkflow } from "@medusajs/types"
|
|
||||||
|
|
||||||
import { Workflows } from "../../definitions"
|
|
||||||
import {
|
|
||||||
AddressHandlers,
|
|
||||||
CartHandlers,
|
|
||||||
CommonHandlers,
|
|
||||||
CustomerHandlers,
|
|
||||||
RegionHandlers,
|
|
||||||
SalesChannelHandlers,
|
|
||||||
} from "../../handlers"
|
|
||||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
enum CreateCartActions {
|
|
||||||
setContext = "setContext",
|
|
||||||
attachLineItems = "attachLineItems",
|
|
||||||
attachToSalesChannel = "attachToSalesChannel",
|
|
||||||
findRegion = "findRegion",
|
|
||||||
findSalesChannel = "findSalesChannel",
|
|
||||||
createCart = "createCart",
|
|
||||||
findOrCreateAddresses = "findOrCreateAddresses",
|
|
||||||
findOrCreateCustomer = "findOrCreateCustomer",
|
|
||||||
removeCart = "removeCart",
|
|
||||||
removeAddresses = "removeAddresses",
|
|
||||||
}
|
|
||||||
|
|
||||||
const workflowAlias = "cart"
|
|
||||||
const getWorkflowInput = (alias = workflowAlias) => ({
|
|
||||||
inputAlias: workflowAlias,
|
|
||||||
invoke: {
|
|
||||||
from: workflowAlias,
|
|
||||||
alias,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const workflowSteps: TransactionStepsDefinition = {
|
|
||||||
next: [
|
|
||||||
{
|
|
||||||
action: CreateCartActions.findOrCreateCustomer,
|
|
||||||
noCompensation: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: CreateCartActions.findSalesChannel,
|
|
||||||
noCompensation: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: CreateCartActions.setContext,
|
|
||||||
noCompensation: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: CreateCartActions.findRegion,
|
|
||||||
noCompensation: true,
|
|
||||||
next: {
|
|
||||||
action: CreateCartActions.findOrCreateAddresses,
|
|
||||||
noCompensation: true,
|
|
||||||
next: {
|
|
||||||
action: CreateCartActions.createCart,
|
|
||||||
next: [
|
|
||||||
{
|
|
||||||
action: CreateCartActions.attachLineItems,
|
|
||||||
noCompensation: true,
|
|
||||||
},
|
|
||||||
{ action: CreateCartActions.attachToSalesChannel },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlers = new Map([
|
|
||||||
[
|
|
||||||
CreateCartActions.findOrCreateCustomer,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
getWorkflowInput(
|
|
||||||
CustomerHandlers.findOrCreateCustomer.aliases.Customer
|
|
||||||
),
|
|
||||||
CustomerHandlers.findOrCreateCustomer
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.findSalesChannel,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
getWorkflowInput(
|
|
||||||
SalesChannelHandlers.findSalesChannel.aliases.SalesChannel
|
|
||||||
),
|
|
||||||
SalesChannelHandlers.findSalesChannel
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.setContext,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
getWorkflowInput(CommonHandlers.setContext.aliases.Context),
|
|
||||||
CommonHandlers.setContext
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.findRegion,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
getWorkflowInput(RegionHandlers.findRegion.aliases.Region),
|
|
||||||
RegionHandlers.findRegion
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.findOrCreateAddresses,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
{
|
|
||||||
invoke: [
|
|
||||||
getWorkflowInput(
|
|
||||||
AddressHandlers.findOrCreateAddresses.aliases.Addresses
|
|
||||||
).invoke,
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findRegion,
|
|
||||||
alias: AddressHandlers.findOrCreateAddresses.aliases.Region,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
AddressHandlers.findOrCreateAddresses
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.createCart,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
{
|
|
||||||
invoke: [
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findSalesChannel,
|
|
||||||
alias: CartHandlers.createCart.aliases.SalesChannel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findRegion,
|
|
||||||
alias: CartHandlers.createCart.aliases.Region,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: CreateCartActions.setContext,
|
|
||||||
alias: CartHandlers.createCart.aliases.Context,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findOrCreateCustomer,
|
|
||||||
alias: CartHandlers.createCart.aliases.Customer,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findOrCreateAddresses,
|
|
||||||
alias: CartHandlers.createCart.aliases.Addresses,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
CartHandlers.createCart
|
|
||||||
),
|
|
||||||
compensate: pipe(
|
|
||||||
{
|
|
||||||
invoke: [
|
|
||||||
{
|
|
||||||
from: CreateCartActions.createCart,
|
|
||||||
alias: CartHandlers.removeCart.aliases.Cart,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
CartHandlers.removeCart
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.attachLineItems,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
{
|
|
||||||
invoke: [
|
|
||||||
getWorkflowInput(
|
|
||||||
CartHandlers.attachLineItemsToCart.aliases.LineItems
|
|
||||||
).invoke,
|
|
||||||
{
|
|
||||||
from: CreateCartActions.createCart,
|
|
||||||
alias: CartHandlers.attachLineItemsToCart.aliases.Cart,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
CartHandlers.attachLineItemsToCart
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
CreateCartActions.attachToSalesChannel,
|
|
||||||
{
|
|
||||||
invoke: pipe(
|
|
||||||
{
|
|
||||||
invoke: [
|
|
||||||
{
|
|
||||||
from: CreateCartActions.createCart,
|
|
||||||
alias: CartHandlers.attachCartToSalesChannel.aliases.Cart,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findSalesChannel,
|
|
||||||
alias: CartHandlers.attachCartToSalesChannel.aliases.SalesChannel,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
CartHandlers.attachCartToSalesChannel
|
|
||||||
),
|
|
||||||
compensate: pipe(
|
|
||||||
{
|
|
||||||
invoke: [
|
|
||||||
{
|
|
||||||
from: CreateCartActions.findSalesChannel,
|
|
||||||
alias:
|
|
||||||
CartHandlers.detachCartFromSalesChannel.aliases.SalesChannel,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
CartHandlers.detachCartFromSalesChannel
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
])
|
|
||||||
|
|
||||||
WorkflowManager.register(Workflows.CreateCart, workflowSteps, handlers)
|
|
||||||
|
|
||||||
type CreateCartWorkflowOutput = Record<any, any>
|
|
||||||
|
|
||||||
export const createCart = exportWorkflow<
|
|
||||||
CartWorkflow.CreateCartWorkflowInputDTO,
|
|
||||||
CreateCartWorkflowOutput
|
|
||||||
>(Workflows.CreateCart, CreateCartActions.createCart)
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
export * from "./create-cart"
|
|
||||||
export * from "./steps"
|
export * from "./steps"
|
||||||
export * from "./workflows"
|
export * from "./workflows"
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import {
|
|||||||
} from "@medusajs/workflows-sdk"
|
} from "@medusajs/workflows-sdk"
|
||||||
import { createCartsStep, findOneOrAnyRegionStep } from "../steps"
|
import { createCartsStep, findOneOrAnyRegionStep } from "../steps"
|
||||||
|
|
||||||
type WorkflowInput = CreateCartWorkflowInputDTO
|
|
||||||
|
|
||||||
export const createCartWorkflowId = "create-cart"
|
export const createCartWorkflowId = "create-cart"
|
||||||
export const createCartWorkflow = createWorkflow(
|
export const createCartWorkflow = createWorkflow(
|
||||||
createCartWorkflowId,
|
createCartWorkflowId,
|
||||||
(input: WorkflowData<WorkflowInput>): WorkflowData<CartDTO[]> => {
|
(
|
||||||
|
input: WorkflowData<CreateCartWorkflowInputDTO>
|
||||||
|
): WorkflowData<CartDTO[]> => {
|
||||||
const region = findOneOrAnyRegionStep({
|
const region = findOneOrAnyRegionStep({
|
||||||
regionId: input.region_id,
|
regionId: input.region_id,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
|
||||||
import { Modules } from "@medusajs/modules-sdk"
|
|
||||||
|
|
||||||
type HandlerInputData = {
|
|
||||||
cart: {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
sales_channel: {
|
|
||||||
sales_channel_id: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Aliases {
|
|
||||||
Cart = "cart",
|
|
||||||
SalesChannel = "sales_channel",
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function attachCartToSalesChannel({
|
|
||||||
container,
|
|
||||||
data,
|
|
||||||
}: WorkflowArguments<HandlerInputData>): Promise<void> {
|
|
||||||
const featureFlagRouter = container.resolve("featureFlagRouter")
|
|
||||||
const remoteLink = container.resolve("remoteLink")
|
|
||||||
|
|
||||||
if (!featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const cart = data[Aliases.Cart]
|
|
||||||
const salesChannel = data[Aliases.SalesChannel]
|
|
||||||
|
|
||||||
await remoteLink.create({
|
|
||||||
[Modules.CART]: {
|
|
||||||
cart_id: cart.id,
|
|
||||||
},
|
|
||||||
[Modules.SALES_CHANNEL]: {
|
|
||||||
sales_channel_id: salesChannel.sales_channel_id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
attachCartToSalesChannel.aliases = Aliases
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import { CartWorkflow } from "@medusajs/types"
|
|
||||||
import { SalesChannelFeatureFlag } from "@medusajs/utils"
|
|
||||||
|
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
type HandlerInputData = {
|
|
||||||
line_items: {
|
|
||||||
items?: CartWorkflow.CreateLineItemInputDTO[]
|
|
||||||
}
|
|
||||||
cart: {
|
|
||||||
id: string
|
|
||||||
customer_id: string
|
|
||||||
region_id: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Aliases {
|
|
||||||
LineItems = "line_items",
|
|
||||||
Cart = "cart",
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function attachLineItemsToCart({
|
|
||||||
container,
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
}: WorkflowArguments<HandlerInputData>): Promise<void> {
|
|
||||||
const { manager } = context
|
|
||||||
|
|
||||||
const featureFlagRouter = container.resolve("featureFlagRouter")
|
|
||||||
const lineItemService = container.resolve("lineItemService")
|
|
||||||
const cartService = container.resolve("cartService")
|
|
||||||
|
|
||||||
const lineItemServiceTx = lineItemService.withTransaction(manager)
|
|
||||||
const cartServiceTx = cartService.withTransaction(manager)
|
|
||||||
let lineItems = data[Aliases.LineItems].items
|
|
||||||
const cart = data[Aliases.Cart]
|
|
||||||
|
|
||||||
if (lineItems?.length) {
|
|
||||||
const generateInputData = lineItems.map((item) => ({
|
|
||||||
variantId: item.variant_id,
|
|
||||||
quantity: item.quantity,
|
|
||||||
}))
|
|
||||||
|
|
||||||
lineItems = await lineItemServiceTx.generate(generateInputData, {
|
|
||||||
region_id: cart.region_id,
|
|
||||||
customer_id: cart.customer_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
await cartServiceTx.addOrUpdateLineItems(cart.id, lineItems, {
|
|
||||||
validateSalesChannels: featureFlagRouter.isFeatureEnabled(
|
|
||||||
SalesChannelFeatureFlag.key
|
|
||||||
),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attachLineItemsToCart.aliases = Aliases
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import { AddressDTO, CustomerDTO, RegionDTO, legacy_CartDTO } from "@medusajs/types"
|
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
enum Aliases {
|
|
||||||
SalesChannel = "SalesChannel",
|
|
||||||
Addresses = "addresses",
|
|
||||||
Customer = "customer",
|
|
||||||
Region = "region",
|
|
||||||
Context = "context",
|
|
||||||
}
|
|
||||||
|
|
||||||
type HandlerInputData = {
|
|
||||||
sales_channel: {
|
|
||||||
sales_channel_id?: string
|
|
||||||
}
|
|
||||||
addresses: {
|
|
||||||
shipping_address?: AddressDTO
|
|
||||||
shipping_address_id: string
|
|
||||||
billing_address?: AddressDTO
|
|
||||||
billing_address_id: string
|
|
||||||
}
|
|
||||||
customer: {
|
|
||||||
customer?: CustomerDTO
|
|
||||||
customer_id?: string
|
|
||||||
email?: string
|
|
||||||
}
|
|
||||||
region: {
|
|
||||||
region?: RegionDTO
|
|
||||||
region_id: string
|
|
||||||
}
|
|
||||||
context: {
|
|
||||||
context: Record<any, any>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HandlerOutputData = {
|
|
||||||
cart: legacy_CartDTO
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createCart({
|
|
||||||
container,
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
}: WorkflowArguments<HandlerInputData>): Promise<HandlerOutputData> {
|
|
||||||
const { manager } = context
|
|
||||||
|
|
||||||
const cartService = container.resolve("cartService")
|
|
||||||
const cartServiceTx = cartService.withTransaction(manager)
|
|
||||||
|
|
||||||
return await cartServiceTx.create({
|
|
||||||
...data[Aliases.SalesChannel],
|
|
||||||
...data[Aliases.Addresses],
|
|
||||||
...data[Aliases.Customer],
|
|
||||||
...data[Aliases.Region],
|
|
||||||
...data[Aliases.Context],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
createCart.aliases = Aliases
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import { MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
|
||||||
import { Modules } from "@medusajs/modules-sdk"
|
|
||||||
|
|
||||||
type HandlerInputData = {
|
|
||||||
cart: {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
sales_channel: {
|
|
||||||
sales_channel_id: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Aliases {
|
|
||||||
Cart = "cart",
|
|
||||||
SalesChannel = "sales_channel",
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function detachCartFromSalesChannel({
|
|
||||||
container,
|
|
||||||
data,
|
|
||||||
}: WorkflowArguments<HandlerInputData>): Promise<void> {
|
|
||||||
const featureFlagRouter = container.resolve("featureFlagRouter")
|
|
||||||
const remoteLink = container.resolve("remoteLink")
|
|
||||||
|
|
||||||
if (!featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const cart = data[Aliases.Cart]
|
|
||||||
const salesChannel = data[Aliases.SalesChannel]
|
|
||||||
|
|
||||||
await remoteLink.dismiss({
|
|
||||||
[Modules.CART]: {
|
|
||||||
cart_id: cart.id,
|
|
||||||
},
|
|
||||||
[Modules.SALES_CHANNEL]: {
|
|
||||||
sales_channel_id: salesChannel.sales_channel_id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
detachCartFromSalesChannel.aliases = Aliases
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
export * from "./attach-line-items-to-cart"
|
|
||||||
export * from "./create-cart"
|
|
||||||
export * from "./remove-cart"
|
|
||||||
export * from "./retrieve-cart"
|
|
||||||
export * from "./attach-cart-to-sales-channel"
|
|
||||||
export * from "./detach-cart-from-sales-channel"
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
enum Aliases {
|
|
||||||
Cart = "cart",
|
|
||||||
}
|
|
||||||
|
|
||||||
type HandlerInputData = {
|
|
||||||
cart: {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeCart({
|
|
||||||
container,
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
}: WorkflowArguments<HandlerInputData>): Promise<void> {
|
|
||||||
const { manager } = context
|
|
||||||
|
|
||||||
const cartService = container.resolve("cartService")
|
|
||||||
|
|
||||||
const cartServiceTx = cartService.withTransaction(manager)
|
|
||||||
const cart = data[Aliases.Cart]
|
|
||||||
|
|
||||||
await cartServiceTx.delete(cart.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
removeCart.aliases = Aliases
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { legacy_CartDTO } from "@medusajs/types"
|
|
||||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
type HandlerInputData = {
|
|
||||||
cart: {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
config: {
|
|
||||||
retrieveConfig: {
|
|
||||||
select: string[]
|
|
||||||
relations: string[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Aliases {
|
|
||||||
Cart = "cart",
|
|
||||||
Config = "config",
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function retrieveCart({
|
|
||||||
container,
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
}: WorkflowArguments<HandlerInputData>): Promise<legacy_CartDTO> {
|
|
||||||
const { manager } = context
|
|
||||||
|
|
||||||
const cartService = container.resolve("cartService")
|
|
||||||
|
|
||||||
const cartServiceTx = cartService.withTransaction(manager)
|
|
||||||
|
|
||||||
const retrieved = await cartServiceTx.retrieve(
|
|
||||||
data[Aliases.Cart].id,
|
|
||||||
data[Aliases.Config].retrieveConfig
|
|
||||||
)
|
|
||||||
|
|
||||||
return retrieved
|
|
||||||
}
|
|
||||||
|
|
||||||
retrieveCart.aliases = Aliases
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
export * as AddressHandlers from "./address"
|
export * as AddressHandlers from "./address"
|
||||||
export * as CartHandlers from "./cart"
|
|
||||||
export * as CommonHandlers from "./common"
|
export * as CommonHandlers from "./common"
|
||||||
export * as CustomerHandlers from "./customer"
|
export * as CustomerHandlers from "./customer"
|
||||||
export * as InventoryHandlers from "./inventory"
|
export * as InventoryHandlers from "./inventory"
|
||||||
|
|||||||
@@ -1,60 +1,26 @@
|
|||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
import { LINKS } from "../links"
|
|
||||||
|
|
||||||
export const CartSalesChannel: ModuleJoinerConfig = {
|
export const CartSalesChannel: ModuleJoinerConfig = {
|
||||||
serviceName: LINKS.CartSalesChannel,
|
|
||||||
isLink: true,
|
isLink: true,
|
||||||
databaseConfig: {
|
isReadOnlyLink: true,
|
||||||
tableName: "cart_sales_channel",
|
|
||||||
idPrefix: "cartsc",
|
|
||||||
},
|
|
||||||
alias: [
|
|
||||||
{
|
|
||||||
name: "cart_sales_channel",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "cart_sales_channels",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
primaryKeys: ["id", "cart_id", "sales_channel_id"],
|
|
||||||
relationships: [
|
|
||||||
{
|
|
||||||
serviceName: Modules.CART,
|
|
||||||
primaryKey: "id",
|
|
||||||
foreignKey: "cart_id",
|
|
||||||
alias: "cart",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
serviceName: Modules.SALES_CHANNEL,
|
|
||||||
primaryKey: "id",
|
|
||||||
foreignKey: "sales_channel_id",
|
|
||||||
alias: "sales_channel",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
extends: [
|
extends: [
|
||||||
{
|
{
|
||||||
serviceName: Modules.CART,
|
serviceName: Modules.CART,
|
||||||
fieldAlias: {
|
|
||||||
sales_channel: "sales_channel_link.sales_channel",
|
|
||||||
},
|
|
||||||
relationship: {
|
relationship: {
|
||||||
serviceName: LINKS.CartSalesChannel,
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
primaryKey: "cart_id",
|
primaryKey: "id",
|
||||||
foreignKey: "id",
|
foreignKey: "sales_channel_id",
|
||||||
alias: "sales_channel_link",
|
alias: "sales_channel",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: Modules.SALES_CHANNEL,
|
serviceName: Modules.SALES_CHANNEL,
|
||||||
fieldAlias: {
|
|
||||||
carts: "cart_link.cart",
|
|
||||||
},
|
|
||||||
relationship: {
|
relationship: {
|
||||||
serviceName: LINKS.CartSalesChannel,
|
serviceName: Modules.CART,
|
||||||
primaryKey: "sales_channel_id",
|
primaryKey: "sales_channel_id",
|
||||||
foreignKey: "id",
|
foreignKey: "id",
|
||||||
alias: "cart_link",
|
alias: "carts",
|
||||||
isList: true,
|
isList: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,12 +28,6 @@ export const LINKS = {
|
|||||||
Modules.SALES_CHANNEL,
|
Modules.SALES_CHANNEL,
|
||||||
"sales_channel_id"
|
"sales_channel_id"
|
||||||
),
|
),
|
||||||
CartSalesChannel: composeLinkName(
|
|
||||||
Modules.CART,
|
|
||||||
"cart_id",
|
|
||||||
Modules.SALES_CHANNEL,
|
|
||||||
"sales_channel_id"
|
|
||||||
),
|
|
||||||
OrderSalesChannel: composeLinkName(
|
OrderSalesChannel: composeLinkName(
|
||||||
"orderService",
|
"orderService",
|
||||||
"order_id",
|
"order_id",
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ import { updateCartsWorkflow } from "@medusajs/core-flows"
|
|||||||
import { UpdateCartDataDTO } from "@medusajs/types"
|
import { UpdateCartDataDTO } from "@medusajs/types"
|
||||||
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
|
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
|
||||||
|
|
||||||
import { defaultStoreCartRemoteQueryObject } from "../query-config"
|
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||||
|
import { defaultStoreCartFields } from "../query-config"
|
||||||
|
|
||||||
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||||
const remoteQuery = req.scope.resolve("remoteQuery")
|
const remoteQuery = req.scope.resolve("remoteQuery")
|
||||||
|
|
||||||
const variables = { id: req.params.id }
|
const variables = { id: req.params.id }
|
||||||
|
|
||||||
const query = {
|
const query = remoteQueryObjectFromString({
|
||||||
cart: {
|
entryPoint: "cart",
|
||||||
...defaultStoreCartRemoteQueryObject,
|
fields: defaultStoreCartFields,
|
||||||
},
|
})
|
||||||
}
|
|
||||||
|
|
||||||
const [cart] = await remoteQuery(query, { cart: variables })
|
const [cart] = await remoteQuery(query, { cart: variables })
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,36 @@ export const defaultStoreCartFields = [
|
|||||||
"email",
|
"email",
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
"deleted_at",
|
"items.id",
|
||||||
|
"items.created_at",
|
||||||
|
"items.updated_at",
|
||||||
|
"items.title",
|
||||||
|
"items.quantity",
|
||||||
|
"items.unit_price",
|
||||||
|
"shipping_address.id",
|
||||||
|
"shipping_address.first_name",
|
||||||
|
"shipping_address.last_name",
|
||||||
|
"shipping_address.address_1",
|
||||||
|
"shipping_address.address_2",
|
||||||
|
"shipping_address.city",
|
||||||
|
"shipping_address.postal_code",
|
||||||
|
"shipping_address.country_code",
|
||||||
|
"shipping_address.region_code",
|
||||||
|
"shipping_address.phone",
|
||||||
|
"billing_address.id",
|
||||||
|
"billing_address.first_name",
|
||||||
|
"billing_address.last_name",
|
||||||
|
"billing_address.address_1",
|
||||||
|
"billing_address.address_2",
|
||||||
|
"billing_address.city",
|
||||||
|
"billing_address.postal_code",
|
||||||
|
"billing_address.country_code",
|
||||||
|
"billing_address.region_code",
|
||||||
|
"billing_address.phone",
|
||||||
|
"region.id",
|
||||||
|
"region.name",
|
||||||
|
"region.currency_code",
|
||||||
|
"sales_channel_id",
|
||||||
]
|
]
|
||||||
|
|
||||||
export const defaultStoreCartRelations = [
|
export const defaultStoreCartRelations = [
|
||||||
@@ -15,54 +44,18 @@ export const defaultStoreCartRelations = [
|
|||||||
"shipping_methods",
|
"shipping_methods",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const allowedRelations = [
|
||||||
|
"items",
|
||||||
|
"region",
|
||||||
|
"shipping_address",
|
||||||
|
"billing_address",
|
||||||
|
"shipping_methods",
|
||||||
|
"sales_channel",
|
||||||
|
]
|
||||||
|
|
||||||
export const retrieveTransformQueryConfig = {
|
export const retrieveTransformQueryConfig = {
|
||||||
defaultFields: defaultStoreCartFields,
|
defaultFields: defaultStoreCartFields,
|
||||||
defaultRelations: defaultStoreCartRelations,
|
defaultRelations: defaultStoreCartRelations,
|
||||||
|
allowedRelations: defaultStoreCartRelations,
|
||||||
isList: false,
|
isList: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultStoreCartRemoteQueryObject = {
|
|
||||||
fields: defaultStoreCartFields,
|
|
||||||
items: {
|
|
||||||
fields: [
|
|
||||||
"id",
|
|
||||||
"created_at",
|
|
||||||
"updated_at",
|
|
||||||
"deleted_at",
|
|
||||||
"title",
|
|
||||||
"quantity",
|
|
||||||
"unit_price",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
shipping_address: {
|
|
||||||
fields: [
|
|
||||||
"id",
|
|
||||||
"first_name",
|
|
||||||
"last_name",
|
|
||||||
"address_1",
|
|
||||||
"address_2",
|
|
||||||
"city",
|
|
||||||
"postal_code",
|
|
||||||
"country_code",
|
|
||||||
"region_code",
|
|
||||||
"phone",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
billing_address: {
|
|
||||||
fields: [
|
|
||||||
"id",
|
|
||||||
"first_name",
|
|
||||||
"last_name",
|
|
||||||
"address_1",
|
|
||||||
"address_2",
|
|
||||||
"city",
|
|
||||||
"postal_code",
|
|
||||||
"country_code",
|
|
||||||
"region_code",
|
|
||||||
"phone",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
region: {
|
|
||||||
fields: ["id", "name", "currency_code"],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createCartWorkflow } from "@medusajs/core-flows"
|
import { createCartWorkflow } from "@medusajs/core-flows"
|
||||||
import { CreateCartDTO } from "@medusajs/types"
|
import { CreateCartDTO } from "@medusajs/types"
|
||||||
|
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||||
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
|
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
|
||||||
import { defaultStoreCartRemoteQueryObject } from "../carts/query-config"
|
import { defaultStoreCartFields } from "../carts/query-config"
|
||||||
|
|
||||||
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
|
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||||
const workflow = createCartWorkflow(req.scope)
|
const workflow = createCartWorkflow(req.scope)
|
||||||
@@ -19,11 +20,10 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
|
|||||||
|
|
||||||
const variables = { id: result[0].id }
|
const variables = { id: result[0].id }
|
||||||
|
|
||||||
const query = {
|
const query = remoteQueryObjectFromString({
|
||||||
cart: {
|
entryPoint: "cart",
|
||||||
...defaultStoreCartRemoteQueryObject,
|
fields: defaultStoreCartFields,
|
||||||
},
|
})
|
||||||
}
|
|
||||||
|
|
||||||
const [cart] = await remoteQuery(query, { cart: variables })
|
const [cart] = await remoteQuery(query, { cart: variables })
|
||||||
|
|
||||||
|
|||||||
@@ -205,9 +205,8 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
return createdCart
|
return createdCart
|
||||||
})
|
})
|
||||||
// }
|
|
||||||
|
|
||||||
cart = await cartService.retrieveWithTotals(cart!.id, {
|
cart = await cartService.retrieveWithTotals(cart.id, {
|
||||||
select: defaultStoreCartFields,
|
select: defaultStoreCartFields,
|
||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
|
||||||
import { MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
|
|
||||||
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
|
|
||||||
|
|
||||||
export const featureFlag = [SalesChannelFeatureFlag.key, MedusaV2Flag.key]
|
|
||||||
|
|
||||||
export class CartSalesChannelsLink1698160215000 implements MigrationInterface {
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS "cart_sales_channel"
|
|
||||||
(
|
|
||||||
"id" character varying NOT NULL,
|
|
||||||
"cart_id" character varying NOT NULL,
|
|
||||||
"sales_channel_id" character varying NOT NULL,
|
|
||||||
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
|
||||||
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
|
||||||
"deleted_at" TIMESTAMP WITH TIME ZONE,
|
|
||||||
CONSTRAINT "cart_sales_channel_pk" PRIMARY KEY ("cart_id", "sales_channel_id"),
|
|
||||||
CONSTRAINT "cart_sales_channel_cart_id_unique" UNIQUE ("cart_id")
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS "IDX_id_cart_sales_channel" ON "cart_sales_channel" ("id");
|
|
||||||
|
|
||||||
insert into "cart_sales_channel" (id, cart_id, sales_channel_id)
|
|
||||||
(select 'cartsc_' || substr(md5(random()::text), 0, 27), id, sales_channel_id from "cart" WHERE sales_channel_id IS NOT NULL);
|
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS "cart" DROP CONSTRAINT IF EXISTS "FK_a2bd3c26f42e754b9249ba78fd6";
|
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS "store" DROP CONSTRAINT IF EXISTS "FK_61b0f48cccbb5f41c750bac7286";
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`
|
|
||||||
UPDATE "cart" SET "sales_channel_id" = "cart_sales_channel"."sales_channel_id"
|
|
||||||
FROM "cart_sales_channel"
|
|
||||||
WHERE "cart"."id" = "cart_sales_channel"."cart_id";
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS "cart_sales_channel";
|
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS "cart" ADD CONSTRAINT "FK_a2bd3c26f42e754b9249ba78fd6" FOREIGN KEY ("sales_channel_id") REFERENCES "sales_channel"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
|
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS "store" ADD CONSTRAINT "FK_61b0f48cccbb5f41c750bac7286" FOREIGN KEY ("default_sales_channel_id") REFERENCES "sales_channel"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { BeforeInsert, Column, Index, PrimaryColumn } from "typeorm"
|
|
||||||
import { MedusaV2Flag, SalesChannelFeatureFlag } from "@medusajs/utils"
|
|
||||||
|
|
||||||
import { generateEntityId } from "../utils"
|
|
||||||
import { SoftDeletableEntity } from "../interfaces"
|
|
||||||
import { FeatureFlagEntity } from "../utils/feature-flag-decorators"
|
|
||||||
|
|
||||||
@FeatureFlagEntity([MedusaV2Flag.key, SalesChannelFeatureFlag.key])
|
|
||||||
export class CartSalesChannel extends SoftDeletableEntity {
|
|
||||||
@Column()
|
|
||||||
id: string
|
|
||||||
|
|
||||||
@Index("cart_sales_channel_cart_id_unique", {
|
|
||||||
unique: true,
|
|
||||||
})
|
|
||||||
@PrimaryColumn()
|
|
||||||
cart_id: string
|
|
||||||
|
|
||||||
@PrimaryColumn()
|
|
||||||
sales_channel_id: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @apiIgnore
|
|
||||||
*/
|
|
||||||
@BeforeInsert()
|
|
||||||
private beforeInsert(): void {
|
|
||||||
this.id = generateEntityId(this.id, "cartsc")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { RemoteQueryFunction } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
FlagRouter,
|
FlagRouter,
|
||||||
isDefined,
|
isDefined,
|
||||||
@@ -45,6 +46,11 @@ import {
|
|||||||
SalesChannel,
|
SalesChannel,
|
||||||
ShippingMethod,
|
ShippingMethod,
|
||||||
} from "../models"
|
} from "../models"
|
||||||
|
import { AddressRepository } from "../repositories/address"
|
||||||
|
import { CartRepository } from "../repositories/cart"
|
||||||
|
import { LineItemRepository } from "../repositories/line-item"
|
||||||
|
import { PaymentSessionRepository } from "../repositories/payment-session"
|
||||||
|
import { ShippingMethodRepository } from "../repositories/shipping-method"
|
||||||
import {
|
import {
|
||||||
CartCreateProps,
|
CartCreateProps,
|
||||||
CartUpdateProps,
|
CartUpdateProps,
|
||||||
@@ -59,16 +65,8 @@ import {
|
|||||||
TotalField,
|
TotalField,
|
||||||
WithRequiredProperty,
|
WithRequiredProperty,
|
||||||
} from "../types/common"
|
} from "../types/common"
|
||||||
import { buildQuery, isString, setMetadata } from "../utils"
|
|
||||||
|
|
||||||
import { Modules, RemoteLink } from "@medusajs/modules-sdk"
|
|
||||||
import { RemoteQueryFunction } from "@medusajs/types"
|
|
||||||
import { AddressRepository } from "../repositories/address"
|
|
||||||
import { CartRepository } from "../repositories/cart"
|
|
||||||
import { LineItemRepository } from "../repositories/line-item"
|
|
||||||
import { PaymentSessionRepository } from "../repositories/payment-session"
|
|
||||||
import { ShippingMethodRepository } from "../repositories/shipping-method"
|
|
||||||
import { PaymentSessionInput } from "../types/payment"
|
import { PaymentSessionInput } from "../types/payment"
|
||||||
|
import { buildQuery, isString, setMetadata } from "../utils"
|
||||||
import { validateEmail } from "../utils/is-email"
|
import { validateEmail } from "../utils/is-email"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -101,7 +99,6 @@ type InjectedDependencies = {
|
|||||||
productVariantInventoryService: ProductVariantInventoryService
|
productVariantInventoryService: ProductVariantInventoryService
|
||||||
pricingService: PricingService
|
pricingService: PricingService
|
||||||
remoteQuery: RemoteQueryFunction
|
remoteQuery: RemoteQueryFunction
|
||||||
remoteLink: RemoteLink
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TotalsConfig = {
|
type TotalsConfig = {
|
||||||
@@ -144,7 +141,6 @@ class CartService extends TransactionBaseService {
|
|||||||
protected readonly lineItemAdjustmentService_: LineItemAdjustmentService
|
protected readonly lineItemAdjustmentService_: LineItemAdjustmentService
|
||||||
protected readonly featureFlagRouter_: FlagRouter
|
protected readonly featureFlagRouter_: FlagRouter
|
||||||
protected remoteQuery_: RemoteQueryFunction
|
protected remoteQuery_: RemoteQueryFunction
|
||||||
protected remoteLink_: RemoteLink
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
protected readonly productVariantInventoryService_: ProductVariantInventoryService
|
protected readonly productVariantInventoryService_: ProductVariantInventoryService
|
||||||
protected readonly pricingService_: PricingService
|
protected readonly pricingService_: PricingService
|
||||||
@@ -176,7 +172,6 @@ class CartService extends TransactionBaseService {
|
|||||||
featureFlagRouter,
|
featureFlagRouter,
|
||||||
storeService,
|
storeService,
|
||||||
remoteQuery,
|
remoteQuery,
|
||||||
remoteLink,
|
|
||||||
productVariantInventoryService,
|
productVariantInventoryService,
|
||||||
pricingService,
|
pricingService,
|
||||||
}: InjectedDependencies) {
|
}: InjectedDependencies) {
|
||||||
@@ -211,7 +206,6 @@ class CartService extends TransactionBaseService {
|
|||||||
this.productVariantInventoryService_ = productVariantInventoryService
|
this.productVariantInventoryService_ = productVariantInventoryService
|
||||||
this.pricingService_ = pricingService
|
this.pricingService_ = pricingService
|
||||||
this.remoteQuery_ = remoteQuery
|
this.remoteQuery_ = remoteQuery
|
||||||
this.remoteLink_ = remoteLink
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -500,14 +494,7 @@ class CartService extends TransactionBaseService {
|
|||||||
data.sales_channel_id
|
data.sales_channel_id
|
||||||
)
|
)
|
||||||
|
|
||||||
await this.remoteLink_.create({
|
cart.sales_channel_id = salesChannel.id
|
||||||
[Modules.CART]: {
|
|
||||||
cart_id: cart.id,
|
|
||||||
},
|
|
||||||
[Modules.SALES_CHANNEL]: {
|
|
||||||
sales_channel_id: salesChannel.id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.eventBus_
|
await this.eventBus_
|
||||||
@@ -1287,33 +1274,7 @@ class CartService extends TransactionBaseService {
|
|||||||
|
|
||||||
await this.onSalesChannelChange(cart, data.sales_channel_id)
|
await this.onSalesChannelChange(cart, data.sales_channel_id)
|
||||||
|
|
||||||
/**
|
cart.sales_channel_id = salesChannel.id
|
||||||
* TODO: remove this once update cart workflow is build
|
|
||||||
* since this will be handled in a handler by the workflow
|
|
||||||
*/
|
|
||||||
if (this.featureFlagRouter_.isFeatureEnabled(MedusaV2Flag.key)) {
|
|
||||||
if (cart.sales_channel_id) {
|
|
||||||
await this.remoteLink_.dismiss({
|
|
||||||
[Modules.CART]: {
|
|
||||||
cart_id: cart.id,
|
|
||||||
},
|
|
||||||
[Modules.SALES_CHANNEL]: {
|
|
||||||
sales_channel_id: cart.sales_channel_id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.remoteLink_.create({
|
|
||||||
[Modules.CART]: {
|
|
||||||
cart_id: cart.id,
|
|
||||||
},
|
|
||||||
[Modules.SALES_CHANNEL]: {
|
|
||||||
sales_channel_id: salesChannel.id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
cart.sales_channel_id = salesChannel.id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDefined(data.discounts) && data.discounts.length) {
|
if (isDefined(data.discounts) && data.discounts.length) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
Filter,
|
Filter,
|
||||||
Index,
|
Index,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
|
OnInit,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
OptionalProps,
|
OptionalProps,
|
||||||
PrimaryKey,
|
PrimaryKey,
|
||||||
@@ -71,7 +72,7 @@ export default class Region {
|
|||||||
this.id = generateEntityId(this.id, "reg")
|
this.id = generateEntityId(this.id, "reg")
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeCreate()
|
@OnInit()
|
||||||
onInit() {
|
onInit() {
|
||||||
this.id = generateEntityId(this.id, "reg")
|
this.id = generateEntityId(this.id, "reg")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import { DALUtils, generateEntityId } from "@medusajs/utils"
|
import { DALUtils, generateEntityId } from "@medusajs/utils"
|
||||||
|
|
||||||
|
import { DAL } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
Entity,
|
Entity,
|
||||||
Filter,
|
Filter,
|
||||||
Index,
|
Index,
|
||||||
|
OnInit,
|
||||||
OptionalProps,
|
OptionalProps,
|
||||||
PrimaryKey,
|
PrimaryKey,
|
||||||
Property,
|
Property,
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import { DAL } from "@medusajs/types"
|
|
||||||
|
|
||||||
type SalesChannelOptionalProps = "is_disabled" | DAL.EntityDateColumns
|
type SalesChannelOptionalProps = "is_disabled" | DAL.EntityDateColumns
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ export default class SalesChannel {
|
|||||||
this.id = generateEntityId(this.id, "sc")
|
this.id = generateEntityId(this.id, "sc")
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeCreate()
|
@OnInit()
|
||||||
onInit() {
|
onInit() {
|
||||||
this.id = generateEntityId(this.id, "sc")
|
this.id = generateEntityId(this.id, "sc")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,7 @@ import {
|
|||||||
SalesChannelDTO,
|
SalesChannelDTO,
|
||||||
UpdateSalesChannelDTO,
|
UpdateSalesChannelDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import { MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
|
||||||
InjectTransactionManager,
|
|
||||||
MedusaContext,
|
|
||||||
ModulesSdkUtils,
|
|
||||||
} from "@medusajs/utils"
|
|
||||||
|
|
||||||
import { SalesChannel } from "@models"
|
import { SalesChannel } from "@models"
|
||||||
|
|
||||||
@@ -61,7 +57,6 @@ export default class SalesChannelModuleService<
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<SalesChannelDTO>
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
|
||||||
async create(
|
async create(
|
||||||
data: CreateSalesChannelDTO | CreateSalesChannelDTO[],
|
data: CreateSalesChannelDTO | CreateSalesChannelDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -88,7 +83,6 @@ export default class SalesChannelModuleService<
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<SalesChannelDTO>
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
|
||||||
async update(
|
async update(
|
||||||
data: UpdateSalesChannelDTO | UpdateSalesChannelDTO[],
|
data: UpdateSalesChannelDTO | UpdateSalesChannelDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user