feat(medusa): filter shipping options by location (#8511)

what:

- filters shipping options by location ID

RESOLVES CC-328
This commit is contained in:
Riqwan Thamir authored and GitHub committed 2024-08-08 14:40:02 +00:00
1 parent d4c5f6593d
commit a7cace90e0
4 files changed
+118 -22

No files matched your search

@@ -43,9 +43,7 @@ medusaIntegrationTestRunner({
location = ( location = (
await api.post( await api.post(
`/admin/stock-locations`, `/admin/stock-locations`,
{ { name: "Test location" },
name: "Test location",
},
adminHeaders adminHeaders
) )
).data.stock_location ).data.stock_location
@@ -53,10 +51,15 @@ medusaIntegrationTestRunner({
location = ( location = (
await api.post( await api.post(
`/admin/stock-locations/${location.id}/fulfillment-sets?fields=*fulfillment_sets`, `/admin/stock-locations/${location.id}/fulfillment-sets?fields=*fulfillment_sets`,
{ { name: "Test", type: "test-type" },
name: "Test", adminHeaders
type: "test-type", )
}, ).data.stock_location
location2 = (
await api.post(
`/admin/stock-locations`,
{ name: "Test location 2" },
adminHeaders adminHeaders
) )
).data.stock_location ).data.stock_location
@@ -91,6 +94,46 @@ medusaIntegrationTestRunner({
).data.region ).data.region
}) })
describe("GET /admin/shipping-options", () => {
it("should filters options by stock_location_id", async () => {
const shippingOptionPayload = {
name: "Test shipping option",
service_zone_id: fulfillmentSet.service_zones[0].id,
shipping_profile_id: shippingProfile.id,
provider_id: "manual_test-provider",
price_type: "flat",
type: {
label: "Test type",
description: "Test description",
code: "test-code",
},
prices: [{ currency_code: "usd", amount: 1000 }],
}
const {
data: { shipping_option: shippingOption },
} = await api.post(
`/admin/shipping-options`,
shippingOptionPayload,
adminHeaders
)
const shippingOptions = await api.get(
`/admin/shipping-options?stock_location_id=${location.id}`,
adminHeaders
)
expect(shippingOptions.data.shipping_options).toHaveLength(1)
const shippingOptions2 = await api.get(
`/admin/shipping-options?stock_location_id=${location2.id}`,
adminHeaders
)
expect(shippingOptions2.data.shipping_options).toHaveLength(0)
})
})
describe("POST /admin/shipping-options", () => { describe("POST /admin/shipping-options", () => {
it("should throw error when required params are missing", async () => { it("should throw error when required params are missing", async () => {
const shippingOptionPayload = { const shippingOptionPayload = {
@@ -1,4 +1,13 @@
import { MiddlewareRoute } from "@medusajs/framework" import { MiddlewareRoute } from "@medusajs/framework"
import { maybeApplyLinkFilter } from "../../utils/maybe-apply-link-filter"
import { validateAndTransformBody } from "../../utils/validate-body"
import { validateAndTransformQuery } from "../../utils/validate-query"
import { createBatchBody } from "../../utils/validators"
import {
listTransformQueryConfig,
retrieveRuleTransformQueryConfig,
retrieveTransformQueryConfig,
} from "./query-config"
import { import {
AdminCreateShippingOption, AdminCreateShippingOption,
AdminCreateShippingOptionRule, AdminCreateShippingOptionRule,
@@ -8,14 +17,6 @@ import {
AdminUpdateShippingOption, AdminUpdateShippingOption,
AdminUpdateShippingOptionRule, AdminUpdateShippingOptionRule,
} from "./validators" } from "./validators"
import {
listTransformQueryConfig,
retrieveRuleTransformQueryConfig,
retrieveTransformQueryConfig,
} from "./query-config"
import { validateAndTransformBody } from "../../utils/validate-body"
import { validateAndTransformQuery } from "../../utils/validate-query"
import { createBatchBody } from "../../utils/validators"
export const adminShippingOptionRoutesMiddlewares: MiddlewareRoute[] = [ export const adminShippingOptionRoutesMiddlewares: MiddlewareRoute[] = [
{ {
@@ -26,6 +27,12 @@ export const adminShippingOptionRoutesMiddlewares: MiddlewareRoute[] = [
AdminGetShippingOptionsParams, AdminGetShippingOptionsParams,
listTransformQueryConfig listTransformQueryConfig
), ),
maybeApplyLinkFilter({
entryPoint: "location_fulfillment_set",
resourceId: "fulfillment_set_id",
filterableField: "stock_location_id",
filterByField: "service_zone.fulfillment_set_id",
}),
], ],
}, },
{ {
@@ -27,6 +27,7 @@ export const AdminGetShippingOptionsParams = createFindParams({
service_zone_id: z.union([z.string(), z.array(z.string())]).optional(), service_zone_id: z.union([z.string(), z.array(z.string())]).optional(),
shipping_profile_id: z.union([z.string(), z.array(z.string())]).optional(), shipping_profile_id: z.union([z.string(), z.array(z.string())]).optional(),
provider_id: z.union([z.string(), z.array(z.string())]).optional(), provider_id: z.union([z.string(), z.array(z.string())]).optional(),
stock_location_id: z.union([z.string(), z.array(z.string())]).optional(),
shipping_option_type_id: z shipping_option_type_id: z
.union([z.string(), z.array(z.string())]) .union([z.string(), z.array(z.string())])
.optional(), .optional(),
@@ -10,6 +10,7 @@ export function maybeApplyLinkFilter({
entryPoint, entryPoint,
resourceId, resourceId,
filterableField, filterableField,
filterByField = "id",
}) { }) {
return async (req: MedusaRequest, _, next: NextFunction) => { return async (req: MedusaRequest, _, next: NextFunction) => {
const filterableFields = req.filterableFields const filterableFields = req.filterableFields
@@ -37,21 +38,65 @@ export function maybeApplyLinkFilter({
}) })
const resources = await remoteQuery(queryObject) const resources = await remoteQuery(queryObject)
let existingFilters = filterableFields[filterByField] as
| string[]
| string
| undefined
let existingIdFilters = filterableFields.id as string[] | string | undefined if (existingFilters) {
if (existingIdFilters) { if (typeof existingFilters === "string") {
if (typeof existingIdFilters === "string") { existingFilters = [existingFilters]
existingIdFilters = [existingIdFilters]
} }
filterableFields.id = arrayIntersection( filterableFields[filterByField] = arrayIntersection(
existingIdFilters, existingFilters,
resources.map((p) => p[resourceId]) resources.map((p) => p[resourceId])
) )
} else { } else {
filterableFields.id = resources.map((p) => p[resourceId]) filterableFields[filterByField] = resources.map((p) => p[resourceId])
} }
req.filterableFields = transformFilterableFields(filterableFields)
return next() return next()
} }
} }
/*
Transforms an object key string into nested objects
before = {
"test.something.another": []
}
after = {
test: {
something: {
another: []
}
}
}
*/
function transformFilterableFields(filterableFields: Record<string, unknown>) {
const result = {};
for (const key of Object.keys(filterableFields)) {
const value = filterableFields[key];
const keys = key.split(".");
let current = result;
// Iterate over the keys, creating nested objects as needed
for (let i = 0; i < keys.length; i++) {
const part = keys[i];
current[part] ??= {};
if (i === keys.length - 1) {
// If its the last key, assign the value
current[part] = value;
break;
}
current = current[part];
}
}
return result;
}