From edd35631f722009bdcb2439ff8c2326025425d33 Mon Sep 17 00:00:00 2001 From: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Fri, 7 Oct 2022 09:12:25 +0200 Subject: [PATCH] fix(medusa): Add sales channel to order on creation (#2374) --- .changeset/nasty-ligers-travel.md | 5 + .../__tests__/store/cart/ff-sales-channels.js | 163 ++++++++++++++++++ packages/medusa/src/services/order.ts | 13 ++ 3 files changed, 181 insertions(+) create mode 100644 .changeset/nasty-ligers-travel.md create mode 100644 integration-tests/api/__tests__/store/cart/ff-sales-channels.js diff --git a/.changeset/nasty-ligers-travel.md b/.changeset/nasty-ligers-travel.md new file mode 100644 index 0000000000..b81d1f8dac --- /dev/null +++ b/.changeset/nasty-ligers-travel.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +fix(medusa): Add sales channel to order on creation diff --git a/integration-tests/api/__tests__/store/cart/ff-sales-channels.js b/integration-tests/api/__tests__/store/cart/ff-sales-channels.js new file mode 100644 index 0000000000..c0d92f51d2 --- /dev/null +++ b/integration-tests/api/__tests__/store/cart/ff-sales-channels.js @@ -0,0 +1,163 @@ +const path = require("path") + +const startServerWithEnvironment = + require("../../../../helpers/start-server-with-environment").default +const { useApi } = require("../../../../helpers/use-api") +const { useDb } = require("../../../../helpers/use-db") + +const { + simpleCartFactory, + simpleRegionFactory, + simpleShippingOptionFactory, + simpleCustomShippingOptionFactory, + simpleProductFactory, + simplePriceListFactory, + simpleDiscountFactory, +} = require("../../../factories") +const { IdMap } = require("medusa-test-utils") + +jest.setTimeout(30000) + +const customerData = { + email: "medusa@test.dk", + password: "medusatest", + first_name: "medusa", + last_name: "medusa", +} + +describe("[MEDUSA_FF_SALES_CHANNELS] /store/carts", () => { + let medusaProcess + let dbConnection + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + const [process, connection] = await startServerWithEnvironment({ + cwd, + env: { MEDUSA_FF_SALES_CHANNELS: true }, + verbose: false, + }) + dbConnection = connection + medusaProcess = process + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + + medusaProcess.kill() + }) + + describe("POST /store/carts/:id", () => { + let product + + beforeEach(async () => { + await simpleRegionFactory(dbConnection, { + id: "test-region", + currency_code: "usd", + countries: ["us"], + tax_rate: 20, + name: "region test", + }) + + product = await simpleProductFactory(dbConnection, { + sales_channels: [ + { + id: "sales-channel", + name: "Sales channel", + description: "Sales channel", + is_disabled: false, + }, + { + id: "default-sales-channel", + name: "Main sales channel", + description: "Main sales channel", + is_default: true, + is_disabled: false, + }, + ], + }) + }) + + afterEach(async () => { + const db = useDb() + return await db.teardown() + }) + + it("should assign sales channel to order on cart completion", async () => { + const api = useApi() + + const customerRes = await api.post("/store/customers", customerData, { + withCredentials: true, + }) + + const createCartRes = await api.post("/store/carts", { + region_id: "test-region", + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + ], + sales_channel_id: "sales-channel", + }) + + const cart = createCartRes.data.cart + + await api.post(`/store/carts/${cart.id}`, { + customer_id: customerRes.data.customer.id, + }) + + await api.post(`/store/carts/${cart.id}/payment-sessions`) + + const createdOrder = await api.post( + `/store/carts/${cart.id}/complete-cart` + ) + + expect(createdOrder.data.type).toEqual("order") + expect(createdOrder.status).toEqual(200) + expect(createdOrder.data.data).toEqual( + expect.objectContaining({ + sales_channel_id: "sales-channel", + }) + ) + }) + + it("should assign default sales channel to order on cart completion", async () => { + const api = useApi() + + const customerRes = await api.post("/store/customers", customerData, { + withCredentials: true, + }) + + const createCartRes = await api.post("/store/carts", { + region_id: "test-region", + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + ], + }) + + const cart = createCartRes.data.cart + + await api.post(`/store/carts/${cart.id}`, { + customer_id: customerRes.data.customer.id, + }) + + await api.post(`/store/carts/${cart.id}/payment-sessions`) + + const createdOrder = await api.post( + `/store/carts/${cart.id}/complete-cart` + ) + + expect(createdOrder.data.type).toEqual("order") + expect(createdOrder.status).toEqual(200) + expect(createdOrder.data.data).toEqual( + expect.objectContaining({ + sales_channel_id: "default-sales-channel", + }) + ) + }) + }) +}) diff --git a/packages/medusa/src/services/order.ts b/packages/medusa/src/services/order.ts index edea864cf8..ce2aa5449a 100644 --- a/packages/medusa/src/services/order.ts +++ b/packages/medusa/src/services/order.ts @@ -1,6 +1,7 @@ import { MedusaError } from "medusa-core-utils" import { Brackets, EntityManager } from "typeorm" import { TransactionBaseService } from "../interfaces" +import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels" import { Address, ClaimOrder, @@ -26,6 +27,7 @@ import { import { UpdateOrderInput } from "../types/orders" import { CreateShippingMethodDto } from "../types/shipping-options" import { buildQuery, setMetadata } from "../utils" +import { FlagRouter } from "../utils/flag-router" import CartService from "./cart" import CustomerService from "./customer" import DiscountService from "./discount" @@ -61,6 +63,7 @@ type InjectedDependencies = { draftOrderService: DraftOrderService inventoryService: InventoryService eventBusService: EventBusService + featureFlagRouter: FlagRouter } class OrderService extends TransactionBaseService { @@ -103,6 +106,7 @@ class OrderService extends TransactionBaseService { protected readonly draftOrderService_: DraftOrderService protected readonly inventoryService_: InventoryService protected readonly eventBus_: EventBusService + protected readonly featureFlagRouter_: FlagRouter constructor({ manager, @@ -123,6 +127,7 @@ class OrderService extends TransactionBaseService { draftOrderService, inventoryService, eventBusService, + featureFlagRouter, }: InjectedDependencies) { // eslint-disable-next-line prefer-rest-params super(arguments[0]) @@ -145,6 +150,7 @@ class OrderService extends TransactionBaseService { this.addressRepository_ = addressRepository this.draftOrderService_ = draftOrderService this.inventoryService_ = inventoryService + this.featureFlagRouter_ = featureFlagRouter } /** @@ -574,6 +580,13 @@ class OrderService extends TransactionBaseService { metadata: cart.metadata || {}, } as Partial + if ( + cart.sales_channel_id && + this.featureFlagRouter_.isFeatureEnabled(SalesChannelFeatureFlag.key) + ) { + toCreate.sales_channel_id = cart.sales_channel_id + } + if (cart.type === "draft_order") { const draft = await this.draftOrderService_ .withTransaction(manager)