fix(medusa): default sales channel for store variant endpoints (#4556)
* add changeset * include default sales channel when querying variant endpoints * make parameter optional * update default values * add integraiton tests
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(medusa): include default sales channel for store/variant endpoints if no other channel is selected
|
||||||
@@ -10,7 +10,10 @@ const adminSeeder = require("../../../../helpers/admin-seeder")
|
|||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
const { simpleProductFactory } = require("../../../../factories")
|
const {
|
||||||
|
simpleProductFactory,
|
||||||
|
simpleSalesChannelFactory,
|
||||||
|
} = require("../../../../factories")
|
||||||
|
|
||||||
const adminHeaders = { headers: { Authorization: "Bearer test_token" } }
|
const adminHeaders = { headers: { Authorization: "Bearer test_token" } }
|
||||||
|
|
||||||
@@ -21,6 +24,10 @@ describe("Get variant", () => {
|
|||||||
const productId = "test-product"
|
const productId = "test-product"
|
||||||
const variantId = "test-variant"
|
const variantId = "test-variant"
|
||||||
let invItem
|
let invItem
|
||||||
|
let salesChannelService
|
||||||
|
let salesChannelLocationService
|
||||||
|
let location
|
||||||
|
let inventoryService
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||||
@@ -52,8 +59,16 @@ describe("Get variant", () => {
|
|||||||
const productVariantInventoryService = appContainer.resolve(
|
const productVariantInventoryService = appContainer.resolve(
|
||||||
"productVariantInventoryService"
|
"productVariantInventoryService"
|
||||||
)
|
)
|
||||||
const inventoryService = appContainer.resolve("inventoryService")
|
inventoryService = appContainer.resolve("inventoryService")
|
||||||
|
salesChannelService = appContainer.resolve("salesChannelService")
|
||||||
|
salesChannelLocationService = appContainer.resolve(
|
||||||
|
"salesChannelLocationService"
|
||||||
|
)
|
||||||
|
const stockLocationService = appContainer.resolve("stockLocationService")
|
||||||
|
|
||||||
|
location = await stockLocationService.create({
|
||||||
|
name: "test-location",
|
||||||
|
})
|
||||||
await simpleProductFactory(
|
await simpleProductFactory(
|
||||||
dbConnection,
|
dbConnection,
|
||||||
{
|
{
|
||||||
@@ -95,4 +110,34 @@ describe("Get variant", () => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("sets availability correctly", async () => {
|
||||||
|
const salesChannel = await simpleSalesChannelFactory(dbConnection, {
|
||||||
|
is_default: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await salesChannelService.addProducts(salesChannel.id, [productId])
|
||||||
|
|
||||||
|
await salesChannelLocationService.associateLocation(
|
||||||
|
salesChannel.id,
|
||||||
|
location.id
|
||||||
|
)
|
||||||
|
|
||||||
|
await inventoryService.createInventoryLevel({
|
||||||
|
inventory_item_id: invItem.id,
|
||||||
|
location_id: location.id,
|
||||||
|
stocked_quantity: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(`/store/variants/${variantId}`)
|
||||||
|
|
||||||
|
expect(response.data).toEqual({
|
||||||
|
variant: expect.objectContaining({
|
||||||
|
purchasable: true,
|
||||||
|
inventory_quantity: 10,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ describe("List Variants", () => {
|
|||||||
name: "test-location",
|
name: "test-location",
|
||||||
})
|
})
|
||||||
|
|
||||||
const salesChannel = await simpleSalesChannelFactory(dbConnection, {})
|
const salesChannel = await simpleSalesChannelFactory(dbConnection, {
|
||||||
|
is_default: true,
|
||||||
|
})
|
||||||
|
|
||||||
const product = await simpleProductFactory(dbConnection, {
|
const product = await simpleProductFactory(dbConnection, {
|
||||||
variants: [{ id: variantId }],
|
variants: [{ id: variantId }],
|
||||||
@@ -125,5 +127,20 @@ describe("List Variants", () => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("sets availability correctly", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(`/store/variants?ids=${variantId}`)
|
||||||
|
|
||||||
|
expect(response.data).toEqual({
|
||||||
|
variants: [
|
||||||
|
expect.objectContaining({
|
||||||
|
purchasable: true,
|
||||||
|
inventory_quantity: 10,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { FlagRouter } from "@medusajs/utils"
|
|
||||||
import { NextFunction, Request, Response } from "express"
|
import { NextFunction, Request, Response } from "express"
|
||||||
|
|
||||||
|
import { FlagRouter } from "@medusajs/utils"
|
||||||
import SalesChannelFeatureFlag from "../../loaders/feature-flags/sales-channels"
|
import SalesChannelFeatureFlag from "../../loaders/feature-flags/sales-channels"
|
||||||
import { SalesChannelService } from "../../services"
|
import { SalesChannelService } from "../../services"
|
||||||
|
|
||||||
@@ -8,11 +9,13 @@ import { SalesChannelService } from "../../services"
|
|||||||
* @param context Object of options
|
* @param context Object of options
|
||||||
* @param context.attachChannelAsArray Whether to attach the default sales channel as an array or just a string
|
* @param context.attachChannelAsArray Whether to attach the default sales channel as an array or just a string
|
||||||
*/
|
*/
|
||||||
export function withDefaultSalesChannel({
|
export function withDefaultSalesChannel(
|
||||||
attachChannelAsArray,
|
{
|
||||||
}: {
|
attachChannelAsArray,
|
||||||
attachChannelAsArray?: boolean
|
}: {
|
||||||
}): (req: Request, res: Response, next: NextFunction) => Promise<void> {
|
attachChannelAsArray: boolean
|
||||||
|
} = { attachChannelAsArray: false }
|
||||||
|
): (req: Request, res: Response, next: NextFunction) => Promise<void> {
|
||||||
return async (req: Request, _, next: NextFunction) => {
|
return async (req: Request, _, next: NextFunction) => {
|
||||||
const featureFlagRouter = req.scope.resolve(
|
const featureFlagRouter = req.scope.resolve(
|
||||||
"featureFlagRouter"
|
"featureFlagRouter"
|
||||||
@@ -38,6 +41,7 @@ export function withDefaultSalesChannel({
|
|||||||
: defaultSalesChannel.id
|
: defaultSalesChannel.id
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
// noop
|
||||||
} finally {
|
} finally {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default (app, featureFlagRouter: FlagRouter) => {
|
|||||||
|
|
||||||
route.get(
|
route.get(
|
||||||
"/:id",
|
"/:id",
|
||||||
withDefaultSalesChannel({}),
|
withDefaultSalesChannel(),
|
||||||
transformStoreQuery(StoreGetProductsProductParams, {
|
transformStoreQuery(StoreGetProductsProductParams, {
|
||||||
defaultRelations: defaultStoreProductsRelations,
|
defaultRelations: defaultStoreProductsRelations,
|
||||||
defaultFields: defaultStoreProductsFields,
|
defaultFields: defaultStoreProductsFields,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { StoreGetVariantsVariantParams } from "./get-variant"
|
|||||||
import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params"
|
import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params"
|
||||||
import { validateProductVariantSalesChannelAssociation } from "../../../middlewares/publishable-api-key/validate-variant-sales-channel-association"
|
import { validateProductVariantSalesChannelAssociation } from "../../../middlewares/publishable-api-key/validate-variant-sales-channel-association"
|
||||||
import { validateSalesChannelParam } from "../../../middlewares/publishable-api-key/validate-sales-channel-param"
|
import { validateSalesChannelParam } from "../../../middlewares/publishable-api-key/validate-sales-channel-param"
|
||||||
|
import { withDefaultSalesChannel } from "../../../middlewares/with-default-sales-channel"
|
||||||
|
|
||||||
const route = Router()
|
const route = Router()
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ export default (app) => {
|
|||||||
|
|
||||||
route.get(
|
route.get(
|
||||||
"/",
|
"/",
|
||||||
|
withDefaultSalesChannel(),
|
||||||
transformStoreQuery(StoreGetVariantsParams, {
|
transformStoreQuery(StoreGetVariantsParams, {
|
||||||
defaultRelations: defaultStoreVariantRelations,
|
defaultRelations: defaultStoreVariantRelations,
|
||||||
allowedRelations: allowedStoreVariantRelations,
|
allowedRelations: allowedStoreVariantRelations,
|
||||||
@@ -26,6 +28,7 @@ export default (app) => {
|
|||||||
)
|
)
|
||||||
route.get(
|
route.get(
|
||||||
"/:id",
|
"/:id",
|
||||||
|
withDefaultSalesChannel(),
|
||||||
transformStoreQuery(StoreGetVariantsVariantParams, {
|
transformStoreQuery(StoreGetVariantsVariantParams, {
|
||||||
defaultRelations: defaultStoreVariantRelations,
|
defaultRelations: defaultStoreVariantRelations,
|
||||||
allowedRelations: allowedStoreVariantRelations,
|
allowedRelations: allowedStoreVariantRelations,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { IsInt, IsOptional, IsString } from "class-validator"
|
|||||||
|
|
||||||
import { FilterableProductVariantProps } from "../../../../types/product-variant"
|
import { FilterableProductVariantProps } from "../../../../types/product-variant"
|
||||||
import { IsType } from "../../../../utils/validators/is-type"
|
import { IsType } from "../../../../utils/validators/is-type"
|
||||||
|
import { MedusaError } from "@medusajs/utils"
|
||||||
import { NumericalComparisonOperator } from "../../../../types/common"
|
import { NumericalComparisonOperator } from "../../../../types/common"
|
||||||
import { PriceSelectionParams } from "../../../../types/price-selection"
|
import { PriceSelectionParams } from "../../../../types/price-selection"
|
||||||
import { Type } from "class-transformer"
|
import { Type } from "class-transformer"
|
||||||
@@ -154,6 +155,7 @@ export default async (req, res) => {
|
|||||||
"cart_id",
|
"cart_id",
|
||||||
"region_id",
|
"region_id",
|
||||||
"currency_code",
|
"currency_code",
|
||||||
|
"sales_channel_id",
|
||||||
])
|
])
|
||||||
|
|
||||||
if (validated.ids) {
|
if (validated.ids) {
|
||||||
|
|||||||
Reference in New Issue
Block a user