From 680dfcdad3cacbdf2950b1038cb713bb543f4dda Mon Sep 17 00:00:00 2001 From: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:42:11 +0100 Subject: [PATCH] feat(core-flow, medusa): Create cart with Sales Channel (#6427) --- .../__tests__/cart/store/carts.spec.ts | 15 ++++++ .../cart/steps/find-sales-channel.ts | 34 ++++++++++++ .../src/definition/cart/steps/index.ts | 2 +- .../definition/cart/workflows/create-carts.ts | 53 ++++++++++++------- packages/medusa/src/api-v2/middlewares.ts | 4 +- 5 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 packages/core-flows/src/definition/cart/steps/find-sales-channel.ts diff --git a/integration-tests/plugins/__tests__/cart/store/carts.spec.ts b/integration-tests/plugins/__tests__/cart/store/carts.spec.ts index e91eb226e5..fba57c7767 100644 --- a/integration-tests/plugins/__tests__/cart/store/carts.spec.ts +++ b/integration-tests/plugins/__tests__/cart/store/carts.spec.ts @@ -225,6 +225,21 @@ describe("Store Carts API", () => { ).rejects.toThrow() }) + it("should throw if sales channel is disabled", async () => { + const api = useApi() as any + + const salesChannel = await scModuleService.create({ + name: "Webshop", + is_disabled: true, + }) + + await expect( + api.post(`/store/carts`, { + sales_channel_id: salesChannel.id, + }) + ).rejects.toThrow() + }) + describe("compensation", () => { it("should delete created customer if cart-creation fails", async () => { expect.assertions(2) diff --git a/packages/core-flows/src/definition/cart/steps/find-sales-channel.ts b/packages/core-flows/src/definition/cart/steps/find-sales-channel.ts new file mode 100644 index 0000000000..5dcc9f60b2 --- /dev/null +++ b/packages/core-flows/src/definition/cart/steps/find-sales-channel.ts @@ -0,0 +1,34 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { ISalesChannelModuleService, SalesChannelDTO } from "@medusajs/types" +import { MedusaError } from "@medusajs/utils" +import { StepResponse, createStep } from "@medusajs/workflows-sdk" + +interface StepInput { + salesChannelId?: string +} + +export const findSalesChannelStepId = "find-sales-channel" +export const findSalesChannelStep = createStep( + findSalesChannelStepId, + async (data: StepInput, { container }) => { + const salesChannelService = container.resolve( + ModuleRegistrationName.SALES_CHANNEL + ) + + let salesChannel: SalesChannelDTO | undefined + if (data.salesChannelId) { + salesChannel = await salesChannelService.retrieve(data.salesChannelId) + } else { + // TODO: Find default sales channel from store + } + + if (salesChannel?.is_disabled) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Unable to assign cart to disabled Sales Channel: ${salesChannel.name}` + ) + } + + return new StepResponse(salesChannel) + } +) diff --git a/packages/core-flows/src/definition/cart/steps/index.ts b/packages/core-flows/src/definition/cart/steps/index.ts index 2803a6a741..d2b4329db5 100644 --- a/packages/core-flows/src/definition/cart/steps/index.ts +++ b/packages/core-flows/src/definition/cart/steps/index.ts @@ -1,5 +1,5 @@ export * from "./create-carts" export * from "./find-one-or-any-region" export * from "./find-or-create-customer" +export * from "./find-sales-channel" export * from "./update-carts" - diff --git a/packages/core-flows/src/definition/cart/workflows/create-carts.ts b/packages/core-flows/src/definition/cart/workflows/create-carts.ts index 724a51e3d6..6900ee85a6 100644 --- a/packages/core-flows/src/definition/cart/workflows/create-carts.ts +++ b/packages/core-flows/src/definition/cart/workflows/create-carts.ts @@ -2,41 +2,54 @@ import { CartDTO, CreateCartWorkflowInputDTO } from "@medusajs/types" import { WorkflowData, createWorkflow, + parallelize, transform, } from "@medusajs/workflows-sdk" import { createCartsStep, findOneOrAnyRegionStep, findOrCreateCustomerStep, + findSalesChannelStep, } from "../steps" export const createCartWorkflowId = "create-cart" export const createCartWorkflow = createWorkflow( createCartWorkflowId, (input: WorkflowData): WorkflowData => { - const region = findOneOrAnyRegionStep({ - regionId: input.region_id, - }) + const [salesChannel, region, customerData] = parallelize( + findSalesChannelStep({ + salesChannelId: input.sales_channel_id, + }), + findOneOrAnyRegionStep({ + regionId: input.region_id, + }), + findOrCreateCustomerStep({ + customerId: input.customer_id, + email: input.email, + }) + ) - const customerData = findOrCreateCustomerStep({ - customerId: input.customer_id, - email: input.email, - }) + const cartInput = transform( + { input, region, customerData, salesChannel }, + (data) => { + const data_ = { + ...data.input, + currency_code: data.input.currency_code ?? data.region.currency_code, + region_id: data.region.id, + } - const cartInput = transform({ input, region, customerData }, (data) => { - const data_ = { - ...data.input, - currency_code: data.input.currency_code ?? data.region.currency_code, - region_id: data.region.id, + if (data.customerData.customer?.id) { + data_.customer_id = data.customerData.customer.id + data_.email = data.input?.email ?? data.customerData.customer.email + } + + if (data.salesChannel?.id) { + data_.sales_channel_id = data.salesChannel.id + } + + return data_ } - - if (data.customerData.customer?.id) { - data_.customer_id = data.customerData.customer.id - data_.email = data.input?.email ?? data.customerData.customer.email - } - - return data_ - }) + ) // TODO: Add line items diff --git a/packages/medusa/src/api-v2/middlewares.ts b/packages/medusa/src/api-v2/middlewares.ts index 18d4287cc6..8ead6492b3 100644 --- a/packages/medusa/src/api-v2/middlewares.ts +++ b/packages/medusa/src/api-v2/middlewares.ts @@ -2,15 +2,15 @@ import { MiddlewaresConfig } from "../loaders/helpers/routing/types" import { adminCampaignRoutesMiddlewares } from "./admin/campaigns/middlewares" import { adminCustomerGroupRoutesMiddlewares } from "./admin/customer-groups/middlewares" import { adminCustomerRoutesMiddlewares } from "./admin/customers/middlewares" +import { adminInviteRoutesMiddlewares } from "./admin/invites/middlewares" import { adminPromotionRoutesMiddlewares } from "./admin/promotions/middlewares" import { adminRegionRoutesMiddlewares } from "./admin/regions/middlewares" +import { adminUserRoutesMiddlewares } from "./admin/users/middlewares" import { adminWorkflowsExecutionsMiddlewares } from "./admin/workflows-executions/middlewares" import { authRoutesMiddlewares } from "./auth/middlewares" import { storeCartRoutesMiddlewares } from "./store/carts/middlewares" import { storeCustomerRoutesMiddlewares } from "./store/customers/middlewares" -import { adminUserRoutesMiddlewares } from "./admin/users/middlewares" import { storeRegionRoutesMiddlewares } from "./store/regions/middlewares" -import { adminInviteRoutesMiddlewares } from "./admin/invites/middlewares" export const config: MiddlewaresConfig = { routes: [