diff --git a/.changeset/sunny-buckets-chew.md b/.changeset/sunny-buckets-chew.md
new file mode 100644
index 0000000000..2234112446
--- /dev/null
+++ b/.changeset/sunny-buckets-chew.md
@@ -0,0 +1,7 @@
+---
+"@medusajs/dashboard": minor
+"@medusajs/types": minor
+"@medusajs/medusa": minor
+---
+
+fix(dashboard,medusa,types): improve performance for price list prices retrieval
diff --git a/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts b/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts
index 06b9c3e2ed..56890f708b 100644
--- a/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts
+++ b/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts
@@ -14,6 +14,7 @@ medusaIntegrationTestRunner({
env: {},
testSuite: ({ dbConnection, getContainer, api }) => {
let pricelist1
+ let pricelist1Prices
let pricelist2
let region1
let product1
@@ -93,6 +94,10 @@ medusaIntegrationTestRunner({
)
).data.price_list
+ pricelist1Prices = await api
+ .get(`/admin/price-lists/${pricelist1.id}/prices`, adminHeaders)
+ .then((res) => res.data.prices)
+
pricelist2 = (
await api.post(
"/admin/price-lists",
@@ -134,7 +139,7 @@ medusaIntegrationTestRunner({
})
const response = await api.post(
- "/admin/price-lists",
+ "/admin/price-lists?fields=prices.*,prices.price_set.*,prices.price_set.variant.*",
payload,
adminHeaders
)
@@ -189,34 +194,12 @@ medusaIntegrationTestRunner({
status: pricelist1.status,
starts_at: pricelist1.starts_at,
ends_at: pricelist1.ends_at,
- prices: expect.arrayContaining([
- expect.objectContaining({
- id: expect.any(String),
- amount: 100,
- currency_code: "usd",
- // BREAKING: Min and max quantity are returned as string
- min_quantity: 1,
- max_quantity: 100,
- variant_id: product1.variants[0].id,
- created_at: expect.any(String),
- updated_at: expect.any(String),
- // BREAKING: `variant` and `variants` are not returned as part of the prices
- }),
- expect.objectContaining({
- id: expect.any(String),
- amount: 80,
- currency_code: "usd",
- min_quantity: 101,
- max_quantity: 500,
- variant_id: product1.variants[0].id,
- created_at: expect.any(String),
- updated_at: expect.any(String),
- }),
- ]),
created_at: expect.any(String),
updated_at: expect.any(String),
})
)
+ // BREAKING: Prices are not returned as part of the price list if not specified in fields
+ expect(response.data.price_list).not.toHaveProperty("prices")
})
it("returns a list of price lists", async () => {
@@ -367,22 +350,6 @@ medusaIntegrationTestRunner({
status: "draft",
starts_at: "2022-09-01T00:00:00.000Z",
ends_at: "2022-12-31T00:00:00.000Z",
- prices: expect.arrayContaining([
- expect.objectContaining({
- amount: 100,
- currency_code: "usd",
- id: expect.any(String),
- max_quantity: 100,
- min_quantity: 1,
- }),
- expect.objectContaining({
- amount: 80,
- currency_code: "usd",
- id: expect.any(String),
- max_quantity: 500,
- min_quantity: 101,
- }),
- ]),
rules: {
"customer.groups.id": [customerGroup1.id],
},
@@ -393,11 +360,12 @@ medusaIntegrationTestRunner({
})
it("updates the amount and currency of a price in the price list", async () => {
+ const priceToUpdate = pricelist1Prices.find((p) => p.amount === 80)
const payload = {
// BREAKING: Updates of prices happen through the batch endpoint, and doing it through the price list update endpoint is no longer supported
update: [
{
- id: pricelist1.prices.find((p) => p.amount === 80).id,
+ id: priceToUpdate.id,
amount: 250,
currency_code: "eur",
variant_id: product1.variants[0].id,
@@ -411,27 +379,29 @@ medusaIntegrationTestRunner({
adminHeaders
)
const response = await api.get(
- `/admin/price-lists/${pricelist1.id}`,
+ `/admin/price-lists/${pricelist1.id}/prices`,
adminHeaders
)
expect(response.status).toEqual(200)
- expect(response.data.price_list.prices).toEqual([
- expect.objectContaining({
- amount: 100,
- currency_code: "usd",
- id: expect.any(String),
- max_quantity: 100,
- min_quantity: 1,
- }),
- expect.objectContaining({
- amount: 250,
- currency_code: "eur",
- id: expect.any(String),
- max_quantity: 500,
- min_quantity: 101,
- }),
- ])
+ expect(response.data.prices).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ amount: 100,
+ currency_code: "usd",
+ id: expect.any(String),
+ max_quantity: 100,
+ min_quantity: 1,
+ }),
+ expect.objectContaining({
+ amount: 250,
+ currency_code: "eur",
+ id: expect.any(String),
+ max_quantity: 500,
+ min_quantity: 101,
+ }),
+ ])
+ )
})
})
@@ -470,13 +440,13 @@ medusaIntegrationTestRunner({
adminHeaders
)
const response = await api.get(
- `/admin/price-lists/${pricelist1.id}`,
+ `/admin/price-lists/${pricelist1.id}/prices`,
adminHeaders
)
expect(response.status).toEqual(200)
- expect(response.data.price_list.prices.length).toEqual(5)
- expect(response.data.price_list.prices).toEqual(
+ expect(response.data.prices.length).toEqual(5)
+ expect(response.data.prices).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
@@ -484,7 +454,12 @@ medusaIntegrationTestRunner({
currency_code: "usd",
min_quantity: 1,
max_quantity: 100,
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
expect.objectContaining({
id: expect.any(String),
@@ -492,13 +467,23 @@ medusaIntegrationTestRunner({
currency_code: "usd",
min_quantity: 101,
max_quantity: 500,
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
expect.objectContaining({
id: expect.any(String),
amount: 45,
currency_code: "usd",
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
min_quantity: 1001,
max_quantity: 2000,
}),
@@ -506,7 +491,12 @@ medusaIntegrationTestRunner({
id: expect.any(String),
amount: 35,
currency_code: "usd",
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
min_quantity: 2001,
max_quantity: 3000,
}),
@@ -514,7 +504,12 @@ medusaIntegrationTestRunner({
id: expect.any(String),
amount: 25,
currency_code: "usd",
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
min_quantity: 3001,
max_quantity: 4000,
}),
@@ -551,13 +546,13 @@ medusaIntegrationTestRunner({
)
const response = await api.get(
- `/admin/price-lists/${pricelist1.id}`,
+ `/admin/price-lists/${pricelist1.id}/prices`,
adminHeaders
)
expect(response.status).toEqual(200)
- expect(response.data.price_list.prices.length).toEqual(2)
- expect(response.data.price_list.prices).toEqual(
+ expect(response.data.prices.length).toEqual(2)
+ expect(response.data.prices).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
@@ -565,7 +560,12 @@ medusaIntegrationTestRunner({
currency_code: "usd",
min_quantity: 1,
max_quantity: 100,
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
expect.objectContaining({
id: expect.any(String),
@@ -573,7 +573,12 @@ medusaIntegrationTestRunner({
currency_code: "usd",
min_quantity: 101,
max_quantity: 500,
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
])
)
@@ -605,13 +610,13 @@ medusaIntegrationTestRunner({
adminHeaders
)
const response = await api.get(
- `/admin/price-lists/${pricelist1.id}`,
+ `/admin/price-lists/${pricelist1.id}/prices`,
adminHeaders
)
expect(response.status).toEqual(200)
- expect(response.data.price_list.prices.length).toEqual(4)
- expect(response.data.price_list.prices).toEqual(
+ expect(response.data.prices.length).toEqual(4)
+ expect(response.data.prices).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
@@ -619,7 +624,12 @@ medusaIntegrationTestRunner({
currency_code: "usd",
min_quantity: 1,
max_quantity: 100,
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
expect.objectContaining({
id: expect.any(String),
@@ -627,20 +637,40 @@ medusaIntegrationTestRunner({
currency_code: "usd",
min_quantity: 101,
max_quantity: 500,
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
expect.objectContaining({
id: expect.any(String),
amount: 100,
currency_code: "eur",
- rules: { region_id: region1.id },
- variant_id: product1.variants[0].id,
+ price_rules: expect.arrayContaining([
+ expect.objectContaining({
+ attribute: "region_id",
+ value: region1.id,
+ }),
+ ]),
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
expect.objectContaining({
id: expect.any(String),
amount: 200,
currency_code: "eur",
- variant_id: product1.variants[0].id,
+ price_set: expect.objectContaining({
+ id: expect.any(String),
+ variant: {
+ id: product1.variants[0].id,
+ },
+ }),
}),
])
)
@@ -680,41 +710,48 @@ medusaIntegrationTestRunner({
)
const response = await api.get(
- `/admin/price-lists/${pricelist1.id}`,
+ `/admin/price-lists/${pricelist1.id}/prices`,
adminHeaders
)
expect(response.status).toEqual(200)
- expect(response.data.price_list.prices.length).toEqual(0)
+ expect(response.data.prices.length).toEqual(0)
})
})
describe("DELETE /admin/price-lists/:id/prices/batch", () => {
// BREAKING: The batch method signature changed
it("Deletes several prices associated with a price list", async () => {
+ const priceToDelete = pricelist1Prices.find((p) => p.amount === 100)
await api.post(
`/admin/price-lists/${pricelist1.id}/prices/batch`,
{
- delete: [pricelist1.prices[0].id],
+ delete: [priceToDelete.id],
},
adminHeaders
)
const response = await api.get(
- `/admin/price-lists/${pricelist1.id}`,
+ `/admin/price-lists/${pricelist1.id}/prices`,
adminHeaders
)
expect(response.status).toEqual(200)
- expect(response.data.price_list.prices).toEqual([
- expect.objectContaining({
- amount: 80,
- currency_code: "usd",
- min_quantity: 101,
- max_quantity: 500,
- variant_id: product1.variants[0].id,
- }),
- ])
+ expect(response.data.prices).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ amount: 80,
+ currency_code: "usd",
+ min_quantity: 101,
+ max_quantity: 500,
+ price_set: expect.objectContaining({
+ variant: expect.objectContaining({
+ id: product1.variants[0].id,
+ }),
+ }),
+ }),
+ ])
+ )
})
})
diff --git a/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts
index 645f1e88ff..43a1d8000f 100644
--- a/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts
+++ b/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts
@@ -99,7 +99,10 @@ medusaIntegrationTestRunner({
},
])
- let response = await api.get(`/admin/price-lists`, adminHeaders)
+ let response = await api.get(
+ `/admin/price-lists?fields=prices.*,prices.price_rules.*,prices.price_set.*,prices.price_set.variant.*`,
+ adminHeaders
+ )
expect(response.status).toEqual(200)
expect(response.data.count).toEqual(1)
@@ -130,9 +133,16 @@ medusaIntegrationTestRunner({
updated_at: expect.any(String),
deleted_at: null,
price_set_id: expect.any(String),
+ price_list_id: expect.any(String),
+ title: null,
rules: {
region_id: region.id,
},
+ rules_count: 1,
+ raw_amount: expect.objectContaining({
+ value: "5000",
+ precision: 20,
+ }),
},
],
},
@@ -258,7 +268,7 @@ medusaIntegrationTestRunner({
])
let response = await api.get(
- `/admin/price-lists/${priceList.id}`,
+ `/admin/price-lists/${priceList.id}?fields=prices.*,prices.price_rules.*,prices.price_set.*,prices.price_set.variant.*`,
adminHeaders
)
@@ -288,8 +298,15 @@ medusaIntegrationTestRunner({
variant_id: variant.id,
created_at: expect.any(String),
updated_at: expect.any(String),
+ price_list_id: expect.any(String),
price_set_id: expect.any(String),
deleted_at: null,
+ rules_count: 1,
+ raw_amount: expect.objectContaining({
+ value: "5000",
+ precision: 20,
+ }),
+ title: null,
rules: {
region_id: region.id,
},
@@ -355,7 +372,7 @@ medusaIntegrationTestRunner({
}
const response = await api.post(
- `admin/price-lists`,
+ `admin/price-lists?fields=prices.*,prices.price_rules.*,prices.price_set.*,prices.price_set.variant.*`,
data,
adminHeaders
)
@@ -388,6 +405,12 @@ medusaIntegrationTestRunner({
updated_at: expect.any(String),
deleted_at: null,
price_set_id: expect.any(String),
+ rules_count: 1,
+ raw_amount: expect.objectContaining({
+ value: "400",
+ precision: 20,
+ }),
+ title: null,
rules: {
region_id: region.id,
},
diff --git a/packages/admin/dashboard/src/hooks/api/price-lists.tsx b/packages/admin/dashboard/src/hooks/api/price-lists.tsx
index 1a4e2ac4fc..ccceaa32ad 100644
--- a/packages/admin/dashboard/src/hooks/api/price-lists.tsx
+++ b/packages/admin/dashboard/src/hooks/api/price-lists.tsx
@@ -14,7 +14,12 @@ import { customerGroupsQueryKeys } from "./customer-groups"
import { productsQueryKeys } from "./products"
const PRICE_LISTS_QUERY_KEY = "price-lists" as const
+const PRICE_LIST_PRICES_QUERY_KEY = "price-list-prices" as const
+
export const priceListsQueryKeys = queryKeysFactory(PRICE_LISTS_QUERY_KEY)
+export const priceListPricesQueryKeys = queryKeysFactory(
+ PRICE_LIST_PRICES_QUERY_KEY
+)
export const usePriceList = (
id: string,
@@ -31,7 +36,7 @@ export const usePriceList = (
) => {
const { data, ...rest } = useQuery({
queryFn: () => sdk.admin.priceList.retrieve(id, query),
- queryKey: priceListsQueryKeys.detail(id),
+ queryKey: priceListsQueryKeys.detail(id, query),
...options,
})
@@ -124,6 +129,25 @@ export const useDeletePriceList = (
})
}
+export const usePriceListPrices = (
+ id: string,
+ query?: HttpTypes.AdminPriceListPriceListParams,
+ options?: UseQueryOptions<
+ HttpTypes.AdminPriceListPriceListResponse,
+ FetchError,
+ HttpTypes.AdminPriceListPriceListResponse,
+ QueryKey
+ >
+) => {
+ const { data, ...rest } = useQuery({
+ queryFn: () => sdk.admin.priceList.prices(id, query),
+ queryKey: priceListPricesQueryKeys.detail(id, query),
+ ...options,
+ })
+
+ return { ...data, ...rest }
+}
+
export const useBatchPriceListPrices = (
id: string,
query?: HttpTypes.AdminPriceListParams,
@@ -141,6 +165,9 @@ export const useBatchPriceListPrices = (
queryKey: priceListsQueryKeys.detail(id),
})
queryClient.invalidateQueries({ queryKey: productsQueryKeys.lists() })
+ queryClient.invalidateQueries({
+ queryKey: priceListPricesQueryKeys.detail(id),
+ })
options?.onSuccess?.(data, variables, context)
},
diff --git a/packages/admin/dashboard/src/routes/price-lists/price-list-detail/components/price-list-general-section/price-list-general-section.tsx b/packages/admin/dashboard/src/routes/price-lists/price-list-detail/components/price-list-general-section/price-list-general-section.tsx
index 05df8606a5..d3158e8bf2 100644
--- a/packages/admin/dashboard/src/routes/price-lists/price-list-detail/components/price-list-general-section/price-list-general-section.tsx
+++ b/packages/admin/dashboard/src/routes/price-lists/price-list-detail/components/price-list-general-section/price-list-general-section.tsx
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"
import { ActionMenu } from "../../../../../components/common/action-menu"
import { useDeletePriceListAction } from "../../../common/hooks/use-delete-price-list-action"
import { getPriceListStatus } from "../../../common/utils"
+import { usePriceListPrices } from "../../../../../hooks/api"
type PriceListGeneralSectionProps = {
priceList: HttpTypes.AdminPriceList
@@ -15,8 +16,13 @@ export const PriceListGeneralSection = ({
priceList,
}: PriceListGeneralSectionProps) => {
const { t } = useTranslation()
-
- const overrideCount = priceList.prices?.length || 0
+ const {
+ count: overrideCount,
+ isLoading,
+ error,
+ } = usePriceListPrices(priceList.id, {
+ limit: 1,
+ })
const { color, text } = getPriceListStatus(t, priceList)
@@ -77,9 +83,11 @@ export const PriceListGeneralSection = ({
{t("priceLists.fields.priceOverrides.label")}
-
- {overrideCount || "-"}
-
+ {!isLoading && !error && (
+
+ {overrideCount || "-"}
+
+ )}
)
diff --git a/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/price-count-cell.tsx b/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/price-count-cell.tsx
new file mode 100644
index 0000000000..72a2a386e5
--- /dev/null
+++ b/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/price-count-cell.tsx
@@ -0,0 +1,19 @@
+import { usePriceListPrices } from "../../../../../hooks/api/price-lists"
+import { PlaceholderCell } from "../../../../../components/table/table-cells/common/placeholder-cell"
+import { TextCell } from "../../../../../components/table/table-cells/common/text-cell"
+
+type PriceCountCellProps = {
+ priceListId: string
+}
+
+export const PriceCountCell = ({ priceListId }: PriceCountCellProps) => {
+ const { count, isLoading } = usePriceListPrices(priceListId, {
+ limit: 1,
+ })
+
+ if (isLoading) {
+ return
+ }
+
+ return 0 ? count.toString() : "-"} />
+}
diff --git a/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/use-pricing-table-columns.tsx b/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/use-pricing-table-columns.tsx
index d301d577db..0d2a53e50c 100644
--- a/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/use-pricing-table-columns.tsx
+++ b/packages/admin/dashboard/src/routes/price-lists/price-list-list/components/price-list-list-table/use-pricing-table-columns.tsx
@@ -4,12 +4,10 @@ import { useMemo } from "react"
import { useTranslation } from "react-i18next"
import { StatusCell } from "../../../../../components/table/table-cells/common/status-cell"
-import {
- TextCell,
- TextHeader,
-} from "../../../../../components/table/table-cells/common/text-cell"
+import { TextHeader } from "../../../../../components/table/table-cells/common/text-cell"
import { getPriceListStatus } from "../../../common/utils"
import { PriceListListTableActions } from "./price-list-list-table-actions"
+import { PriceCountCell } from "./price-count-cell"
const columnHelper = createColumnHelper()
@@ -30,9 +28,10 @@ export const usePricingTableColumns = () => {
return {text}
},
}),
- columnHelper.accessor("prices", {
+ columnHelper.display({
+ id: "price_overrides",
header: t("priceLists.fields.priceOverrides.header"),
- cell: (info) => ,
+ cell: ({ row }) => ,
}),
columnHelper.display({
id: "actions",
diff --git a/packages/admin/dashboard/src/routes/price-lists/price-list-prices-add/price-list-prices-add.tsx b/packages/admin/dashboard/src/routes/price-lists/price-list-prices-add/price-list-prices-add.tsx
index f883114b03..9a527e7101 100644
--- a/packages/admin/dashboard/src/routes/price-lists/price-list-prices-add/price-list-prices-add.tsx
+++ b/packages/admin/dashboard/src/routes/price-lists/price-list-prices-add/price-list-prices-add.tsx
@@ -7,7 +7,10 @@ import { PriceListPricesAddForm } from "./components/price-list-prices-add-form"
export const PriceListProductsAdd = () => {
const { id } = useParams<{ id: string }>()
- const { price_list, isPending, isError, error } = usePriceList(id!)
+ const { price_list, isPending, isError, error } = usePriceList(id!, {
+ fields:
+ "*prices,prices.price_set.variant.id,prices.price_rules.attribute,prices.price_rules.value",
+ })
const { currencies, regions, pricePreferences, isReady } =
usePriceListCurrencyData()
diff --git a/packages/admin/dashboard/src/routes/price-lists/price-list-prices-edit/price-list-prices-edit.tsx b/packages/admin/dashboard/src/routes/price-lists/price-list-prices-edit/price-list-prices-edit.tsx
index 60c8e87c1c..12746c4f87 100644
--- a/packages/admin/dashboard/src/routes/price-lists/price-list-prices-edit/price-list-prices-edit.tsx
+++ b/packages/admin/dashboard/src/routes/price-lists/price-list-prices-edit/price-list-prices-edit.tsx
@@ -10,7 +10,9 @@ export const PriceListPricesEdit = () => {
const [searchParams] = useSearchParams()
const ids = searchParams.get("ids[]")
- const { price_list, isLoading, isError, error } = usePriceList(id!)
+ const { price_list, isLoading, isError, error } = usePriceList(id!, {
+ fields: "*prices,prices.price_set.variant.id,prices.price_rules.attribute,prices.price_rules.value",
+ })
const productIds = ids?.split(",")
const {
diff --git a/packages/core/js-sdk/src/admin/price-list.ts b/packages/core/js-sdk/src/admin/price-list.ts
index b83a386b55..b605979457 100644
--- a/packages/core/js-sdk/src/admin/price-list.ts
+++ b/packages/core/js-sdk/src/admin/price-list.ts
@@ -19,24 +19,24 @@ export class PriceList {
* This method retrieves a price list. It sends a request to the
* [Get Price List](https://docs.medusajs.com/v2/api/admin#price-lists_getpricelistsid)
* API route.
- *
+ *
* @param id - The price list's ID.
* @param query - Configure the fields to retrieve in the price list.
* @param headers - Headers to pass in the request
* @returns The price list's details.
- *
+ *
* @example
* To retrieve a price list by its ID:
- *
+ *
* ```ts
* sdk.admin.priceList.retrieve("plist_123")
* .then(({ price_list }) => {
* console.log(price_list)
* })
* ```
- *
+ *
* To specify the fields and relations to retrieve:
- *
+ *
* ```ts
* sdk.admin.priceList.retrieve("plist_123", {
* fields: "id,*prices"
@@ -45,7 +45,7 @@ export class PriceList {
* console.log(price_list)
* })
* ```
- *
+ *
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/v2/api/store#select-fields-and-relations).
*/
async retrieve(
@@ -64,27 +64,27 @@ export class PriceList {
}
/**
- * This method retrieves a paginated list of price lists. It sends a request to the
+ * This method retrieves a paginated list of price lists. It sends a request to the
* [List Price Lists](https://docs.medusajs.com/v2/api/admin#price-lists_getpricelists) API route.
- *
+ *
* @param query - Filters and pagination configurations.
* @param headers - Headers to pass in the request.
* @returns The paginated list of price lists.
- *
+ *
* @example
* To retrieve the list of price lists:
- *
+ *
* ```ts
* sdk.admin.priceList.list()
* .then(({ price_lists, count, limit, offset }) => {
* console.log(price_lists)
* })
* ```
- *
+ *
* To configure the pagination, pass the `limit` and `offset` query parameters.
- *
+ *
* For example, to retrieve only 10 items and skip 10 items:
- *
+ *
* ```ts
* sdk.admin.priceList.list({
* limit: 10,
@@ -94,10 +94,10 @@ export class PriceList {
* console.log(price_lists)
* })
* ```
- *
+ *
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
* in each price list:
- *
+ *
* ```ts
* sdk.admin.priceList.list({
* fields: "id,*prices"
@@ -106,7 +106,7 @@ export class PriceList {
* console.log(price_lists)
* })
* ```
- *
+ *
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/v2/api/store#select-fields-and-relations).
*/
async list(
@@ -127,12 +127,12 @@ export class PriceList {
* This method creates a price list. It sends a request to the
* [Create Price List](https://docs.medusajs.com/v2/api/admin#price-lists_postpricelists)
* API route.
- *
+ *
* @param body - The details of the price list to create.
* @param query - Configure the fields to retrieve in the price list.
* @param headers - Headers to pass in the request
* @returns The price list's details.
- *
+ *
* @example
* sdk.admin.priceList.create({
* title: "My Price List",
@@ -170,16 +170,16 @@ export class PriceList {
}
/**
- * This method updates a price list. It sends a request to the
+ * This method updates a price list. It sends a request to the
* [Update Price List](https://docs.medusajs.com/v2/api/admin#price-lists_postpricelistsid)
* API route.
- *
+ *
* @param id - The price list's ID.
* @param body - The data to update in the price list.
* @param query - Configure the fields to retrieve in the price list.
* @param headers - Headers to pass in the request
* @returns The price list's details.
- *
+ *
* @example
* sdk.admin.priceList.update("plist_123", {
* title: "My Price List",
@@ -209,11 +209,11 @@ export class PriceList {
* This method deletes a price list. It sends a request to the
* [Delete Price List](https://docs.medusajs.com/v2/api/admin#price-lists_deletepricelistsid)
* API route.
- *
+ *
* @param id - The price list's ID.
* @param headers - Headers to pass in the request
* @returns The deletion's details.
- *
+ *
* @example
* sdk.admin.priceList.delete("plist_123")
* .then(({ deleted }) => {
@@ -234,13 +234,13 @@ export class PriceList {
* This method manages the prices of a price list to create, update, or delete them.
* It sends a request to the [Manage Prices](https://docs.medusajs.com/v2/api/admin#price-lists_postpricelistsidpricesbatch)
* API route.
- *
+ *
* @param id - The price list's ID.
* @param body - The prices to create, update, or delete.
* @param query - Configure the fields to retrieve in the price list.
* @param headers - Headers to pass in the request
* @returns The price list's details.
- *
+ *
* @example
* sdk.admin.priceList.batchPrices("plist_123", {
* create: [{
@@ -279,17 +279,47 @@ export class PriceList {
)
}
+ /**
+ * This method retrieves the prices of a price list. It sends a request to the
+ * [Get Prices](https://docs.medusajs.com/v2/api/admin#price-lists_getpricelistsidprices)
+ * API route.
+ *
+ * @param id - The price list's ID.
+ * @param query - Configure the fields to retrieve in the price list.
+ * @param headers - Headers to pass in the request
+ * @returns The price list's prices.
+ *
+ * @example
+ * sdk.admin.priceList.prices("plist_123")
+ * .then(({ prices }) => {
+ * console.log(prices)
+ * })
+ */
+ async prices(
+ id: string,
+ query?: HttpTypes.AdminPriceListPriceListParams,
+ headers?: ClientHeaders
+ ) {
+ return this.client.fetch(
+ `/admin/price-lists/${id}/prices`,
+ {
+ method: "GET",
+ headers,
+ query,
+ }
+ )
+ }
/**
* This method removes products from a price list. It sends a request to the
* [Remove Product](https://docs.medusajs.com/v2/api/admin#price-lists_postpricelistsidproducts)
* API route.
- *
+ *
* @param id - The price list's ID.
* @param body - The details of the products to remove.
* @param query - Configure the fields to retrieve in the price list.
* @param headers - Headers to pass in the request
* @returns The price list's details.
- *
+ *
* @example
* sdk.admin.priceList.linkProducts("plist_123", {
* remove: ["prod_123"]
diff --git a/packages/core/types/src/http/price-list/admin/queries.ts b/packages/core/types/src/http/price-list/admin/queries.ts
index 937bf50411..09ea08965c 100644
--- a/packages/core/types/src/http/price-list/admin/queries.ts
+++ b/packages/core/types/src/http/price-list/admin/queries.ts
@@ -32,3 +32,7 @@ export interface AdminPriceListListParams
}
export interface AdminPriceListParams extends SelectParams {}
+
+export interface AdminPriceListPriceListParams
+ extends FindParams,
+ BaseFilterable {}
diff --git a/packages/core/types/src/http/price-list/admin/responses.ts b/packages/core/types/src/http/price-list/admin/responses.ts
index e78292a2b5..c3738f4b0b 100644
--- a/packages/core/types/src/http/price-list/admin/responses.ts
+++ b/packages/core/types/src/http/price-list/admin/responses.ts
@@ -38,3 +38,8 @@ export interface AdminPriceListBatchResponse {
deleted: boolean
}
}
+
+export interface AdminPriceListPriceListResponse
+ extends PaginatedResponse<{
+ prices: AdminPrice[]
+ }> {}
diff --git a/packages/medusa/src/api/admin/price-lists/[id]/prices/batch/route.ts b/packages/medusa/src/api/admin/price-lists/[id]/prices/batch/route.ts
index 4a74ae6d1c..3bc7071a5c 100644
--- a/packages/medusa/src/api/admin/price-lists/[id]/prices/batch/route.ts
+++ b/packages/medusa/src/api/admin/price-lists/[id]/prices/batch/route.ts
@@ -4,7 +4,7 @@ import {
MedusaResponse,
} from "@medusajs/framework/http"
import { listPrices } from "../../../queries"
-import { adminPriceListPriceRemoteQueryFields } from "../../../query-config"
+import { adminPriceListPriceQueryFields } from "../../../query-config"
import { BatchMethodRequest, HttpTypes } from "@medusajs/framework/types"
import {
AdminCreatePriceListPriceType,
@@ -44,12 +44,12 @@ export const POST = async (
listPrices(
result.created.map((c) => c.id),
req.scope,
- adminPriceListPriceRemoteQueryFields
+ adminPriceListPriceQueryFields
),
listPrices(
result.updated.map((c) => c.id),
req.scope,
- adminPriceListPriceRemoteQueryFields
+ adminPriceListPriceQueryFields
),
])
diff --git a/packages/medusa/src/api/admin/price-lists/[id]/prices/route.ts b/packages/medusa/src/api/admin/price-lists/[id]/prices/route.ts
new file mode 100644
index 0000000000..0f00214058
--- /dev/null
+++ b/packages/medusa/src/api/admin/price-lists/[id]/prices/route.ts
@@ -0,0 +1,26 @@
+import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/framework"
+import { HttpTypes } from "@medusajs/types"
+import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
+
+export const GET = async (
+ req: AuthenticatedMedusaRequest,
+ res: MedusaResponse
+) => {
+ const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
+ const result = await query.graph({
+ entity: "price",
+ fields: req.queryConfig.fields,
+ filters: {
+ ...req.filterableFields,
+ price_list_id: req.params.id,
+ },
+ pagination: req.queryConfig.pagination,
+ })
+
+ res.status(200).json({
+ prices: result.data,
+ count: result.metadata?.count ?? 0,
+ offset: result.metadata?.skip ?? 0,
+ limit: result.metadata?.take ?? 0,
+ })
+}
diff --git a/packages/medusa/src/api/admin/price-lists/middlewares.ts b/packages/medusa/src/api/admin/price-lists/middlewares.ts
index 26331e7677..30e3a9a7ad 100644
--- a/packages/medusa/src/api/admin/price-lists/middlewares.ts
+++ b/packages/medusa/src/api/admin/price-lists/middlewares.ts
@@ -10,6 +10,7 @@ import {
AdminCreatePriceList,
AdminCreatePriceListPrice,
AdminGetPriceListParams,
+ AdminGetPriceListPriceParams,
AdminGetPriceListPricesParams,
AdminGetPriceListsParams,
AdminRemoveProductsPriceList,
@@ -44,7 +45,7 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
middlewares: [
validateAndTransformBody(AdminCreatePriceList),
validateAndTransformQuery(
- AdminGetPriceListPricesParams,
+ AdminGetPriceListsParams,
QueryConfig.retrivePriceListQueryConfig
),
],
@@ -55,7 +56,7 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
middlewares: [
validateAndTransformBody(AdminUpdatePriceList),
validateAndTransformQuery(
- AdminGetPriceListPricesParams,
+ AdminGetPriceListParams,
QueryConfig.retrivePriceListQueryConfig
),
],
@@ -71,6 +72,16 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
),
],
},
+ {
+ method: ["GET"],
+ matcher: "/admin/price-lists/:id/prices",
+ middlewares: [
+ validateAndTransformQuery(
+ AdminGetPriceListPricesParams,
+ QueryConfig.listPriceListPriceQueryConfig
+ ),
+ ],
+ },
{
method: ["POST"],
matcher: "/admin/price-lists/:id/prices/batch",
@@ -82,7 +93,7 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
createBatchBody(AdminCreatePriceListPrice, AdminUpdatePriceListPrice)
),
validateAndTransformQuery(
- AdminGetPriceListPricesParams,
+ AdminGetPriceListPriceParams,
QueryConfig.listPriceListPriceQueryConfig
),
],
diff --git a/packages/medusa/src/api/admin/price-lists/query-config.ts b/packages/medusa/src/api/admin/price-lists/query-config.ts
index 9c34e6fc6c..7b1511617a 100644
--- a/packages/medusa/src/api/admin/price-lists/query-config.ts
+++ b/packages/medusa/src/api/admin/price-lists/query-config.ts
@@ -2,7 +2,8 @@ export enum PriceListRelations {
PRICES = "prices",
}
-export const adminPriceListPriceRemoteQueryFields = [
+// Note: renamed to avoid referencing remoteQuery which is legacy
+export const adminPriceListPriceQueryFields = [
"id",
"currency_code",
"amount",
@@ -29,11 +30,10 @@ export const adminPriceListRemoteQueryFields = [
"deleted_at",
"price_list_rules.value",
"price_list_rules.attribute",
- ...adminPriceListPriceRemoteQueryFields.map((field) => `prices.${field}`),
]
export const retrivePriceListPriceQueryConfig = {
- defaults: adminPriceListPriceRemoteQueryFields,
+ defaults: adminPriceListPriceQueryFields,
isList: false,
}
diff --git a/packages/medusa/src/api/admin/price-lists/validators.ts b/packages/medusa/src/api/admin/price-lists/validators.ts
index 7da286727f..c5af548322 100644
--- a/packages/medusa/src/api/admin/price-lists/validators.ts
+++ b/packages/medusa/src/api/admin/price-lists/validators.ts
@@ -7,7 +7,12 @@ import {
} from "../../utils/validators"
import { applyAndAndOrOperators } from "../../utils/common-validators"
-export const AdminGetPriceListPricesParams = createSelectParams()
+export const AdminGetPriceListPriceParams = createSelectParams()
+
+export const AdminGetPriceListPricesParams = createFindParams({
+ offset: 0,
+ limit: 50,
+})
export const AdminGetPriceListsParamsFields = z.object({
q: z.string().optional(),