feat(medusa,core-flows,types): adds batch operations to price list prices (#7077)

what:

- adds batch operations to price list prices

RESOLVES CORE-1969
RESOLVES CORE-1970
This commit is contained in:
Riqwan Thamir
2024-04-17 15:36:09 +00:00
committed by GitHub
parent 08dc861dc1
commit 8d356217bd
35 changed files with 735 additions and 630 deletions
@@ -1,38 +0,0 @@
import { createPriceListPricesWorkflow } from "@medusajs/core-flows"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../../../../types/routing"
import { getPriceList } from "../../../../queries"
import {
adminPriceListRemoteQueryFields,
defaultAdminPriceListFields,
} from "../../../../query-config"
import { AdminPostPriceListsPriceListPricesBatchAddReq } from "../../../../validators"
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListPricesBatchAddReq>,
res: MedusaResponse
) => {
const { prices } = req.validatedBody
const id = req.params.id
const workflow = createPriceListPricesWorkflow(req.scope)
const { errors } = await workflow.run({
input: { data: [{ id, prices }] },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const priceList = await getPriceList({
id,
container: req.scope,
remoteQueryFields: adminPriceListRemoteQueryFields,
apiFields: defaultAdminPriceListFields,
})
res.status(200).json({ price_list: priceList })
}
@@ -1,37 +0,0 @@
import { removePriceListPricesWorkflow } from "@medusajs/core-flows"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../../../../types/routing"
import { getPriceList } from "../../../../queries"
import {
adminPriceListRemoteQueryFields,
defaultAdminPriceListFields,
} from "../../../../query-config"
import { AdminPostPriceListsPriceListPricesBatchRemoveReq } from "../../../../validators"
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListPricesBatchRemoveReq>,
res: MedusaResponse
) => {
const { ids } = req.validatedBody
const id = req.params.id
const workflow = removePriceListPricesWorkflow(req.scope)
const { errors } = await workflow.run({
input: { ids },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const priceList = await getPriceList({
id,
container: req.scope,
remoteQueryFields: adminPriceListRemoteQueryFields,
apiFields: defaultAdminPriceListFields,
})
res.status(200).json({ price_list: priceList })
}
@@ -0,0 +1,70 @@
import { batchPriceListPricesWorkflow } from "@medusajs/core-flows"
import { promiseAll } from "@medusajs/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../../../types/routing"
import { fetchPriceListPriceIdsForProduct } from "../../../helpers"
import { listPrices } from "../../../queries"
import { adminPriceListPriceRemoteQueryFields } from "../../../query-config"
import { AdminBatchPriceListPricesType } from "../../../validators"
export const POST = async (
req: AuthenticatedMedusaRequest<AdminBatchPriceListPricesType>,
res: MedusaResponse
) => {
const id = req.params.id
const {
create = [],
update = [],
delete: deletePriceIds = [],
product_id: productIds = [],
} = req.validatedBody
const productPriceIds = await fetchPriceListPriceIdsForProduct(
id,
productIds,
req.scope
)
const priceIdsToDelete = [...deletePriceIds, ...productPriceIds]
const workflow = batchPriceListPricesWorkflow(req.scope)
const { result, errors } = await workflow.run({
input: {
data: {
id,
create,
update,
delete: priceIdsToDelete,
},
},
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const [created, updated] = await promiseAll([
listPrices(
result.created.map((c) => c.id),
req.scope,
adminPriceListPriceRemoteQueryFields
),
listPrices(
result.updated.map((c) => c.id),
req.scope,
adminPriceListPriceRemoteQueryFields
),
])
res.status(200).json({
created,
updated,
deleted: {
ids: priceIdsToDelete,
object: "price",
deleted: true,
},
})
}
@@ -1,38 +0,0 @@
import { updatePriceListPricesWorkflow } from "@medusajs/core-flows"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../../../../types/routing"
import { getPriceList } from "../../../../queries"
import {
adminPriceListRemoteQueryFields,
defaultAdminPriceListFields,
} from "../../../../query-config"
import { AdminPostPriceListPriceBatchUpdate } from "../../../../validators"
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostPriceListPriceBatchUpdate>,
res: MedusaResponse
) => {
const { prices } = req.validatedBody
const id = req.params.id
const workflow = updatePriceListPricesWorkflow(req.scope)
const { errors } = await workflow.run({
input: { data: [{ id, prices }] },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const priceList = await getPriceList({
id,
container: req.scope,
remoteQueryFields: adminPriceListRemoteQueryFields,
apiFields: defaultAdminPriceListFields,
})
res.status(200).json({ price_list: priceList })
}
@@ -6,37 +6,31 @@ import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../types/routing"
import { getPriceList } from "../queries"
import {
adminPriceListRemoteQueryFields,
defaultAdminPriceListFields,
} from "../query-config"
import { AdminPostPriceListsPriceListReq } from "../validators"
import { fetchPriceList } from "../helpers"
import { AdminUpdatePriceListType } from "../validators"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const id = req.params.id
const priceList = await getPriceList({
id,
container: req.scope,
remoteQueryFields: adminPriceListRemoteQueryFields,
apiFields: req.retrieveConfig.select!,
})
const price_list = await fetchPriceList(
req.params.id,
req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ price_list: priceList })
res.status(200).json({ price_list })
}
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListReq>,
req: AuthenticatedMedusaRequest<AdminUpdatePriceListType>,
res: MedusaResponse
) => {
const id = req.params.id
const workflow = updatePriceListsWorkflow(req.scope)
const { errors } = await workflow.run({
input: { price_lists_data: [{ id, ...req.validatedBody }] },
input: { price_lists_data: [{ ...req.validatedBody, id }] },
throwOnError: false,
})
@@ -44,14 +38,13 @@ export const POST = async (
throw errors[0].error
}
const priceList = await getPriceList({
const price_list = await fetchPriceList(
id,
container: req.scope,
remoteQueryFields: adminPriceListRemoteQueryFields,
apiFields: defaultAdminPriceListFields,
})
req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ price_list: priceList })
res.status(200).json({ price_list })
}
export const DELETE = async (
@@ -0,0 +1,79 @@
import { MedusaContainer } from "@medusajs/types"
import {
buildPriceListRules,
buildPriceSetPricesForCore,
ContainerRegistrationKeys,
isPresent,
MedusaError,
remoteQueryObjectFromString,
} from "@medusajs/utils"
export const fetchPriceList = async (
id: string,
scope: MedusaContainer,
fields: string[]
) => {
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "price_lists",
variables: {
filters: { id },
},
fields,
})
const [priceList] = await remoteQuery(queryObject)
if (!isPresent(priceList)) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Price list with id: ${id} was not found`
)
}
return transformPriceList(priceList)
}
export const transformPriceList = (priceList) => {
priceList.rules = buildPriceListRules(priceList.price_list_rules)
priceList.prices = buildPriceSetPricesForCore(priceList.prices)
delete priceList.price_list_rules
return priceList
}
export const fetchPriceListPriceIdsForProduct = async (
priceListId: string,
productIds: string[],
scope: MedusaContainer
): Promise<string[]> => {
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const priceSetIds: string[] = []
const variants = await remoteQuery(
remoteQueryObjectFromString({
entryPoint: "variants",
variables: { filters: { product_id: productIds } },
fields: ["price_set.id"],
})
)
for (const variant of variants) {
if (variant.price_set?.id) {
priceSetIds.push(variant.price_set.id)
}
}
const productPrices = await remoteQuery(
remoteQueryObjectFromString({
entryPoint: "prices",
variables: {
filters: { price_set_id: priceSetIds, price_list_id: priceListId },
},
fields: ["id"],
})
)
return productPrices.map((price) => price.id)
}
@@ -1,15 +1,15 @@
import { transformBody, transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { authenticate } from "../../../utils/authenticate-middleware"
import { validateAndTransformBody } from "../../utils/validate-body"
import { validateAndTransformQuery } from "../../utils/validate-query"
import * as QueryConfig from "./query-config"
import {
AdminBatchPriceListPrices,
AdminCreatePriceList,
AdminGetPriceListParams,
AdminGetPriceListPricesParams,
AdminGetPriceListsParams,
AdminGetPriceListsPriceListParams,
AdminPostPriceListPriceBatchUpdate,
AdminPostPriceListsPriceListPricesBatchAddReq,
AdminPostPriceListsPriceListPricesBatchRemoveReq,
AdminPostPriceListsPriceListReq,
AdminPostPriceListsReq,
AdminUpdatePriceList,
} from "./validators"
export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
@@ -22,9 +22,9 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
method: ["GET"],
matcher: "/admin/price-lists",
middlewares: [
transformQuery(
validateAndTransformQuery(
AdminGetPriceListsParams,
QueryConfig.adminListTransformQueryConfig
QueryConfig.listPriceListQueryConfig
),
],
},
@@ -32,37 +32,43 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
method: ["GET"],
matcher: "/admin/price-lists/:id",
middlewares: [
transformQuery(
AdminGetPriceListsPriceListParams,
QueryConfig.adminRetrieveTransformQueryConfig
validateAndTransformQuery(
AdminGetPriceListParams,
QueryConfig.retrivePriceListQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/admin/price-lists",
middlewares: [transformBody(AdminPostPriceListsReq)],
},
{
method: ["POST"],
matcher: "/admin/price-lists/:id",
middlewares: [transformBody(AdminPostPriceListsPriceListReq)],
},
{
method: ["POST"],
matcher: "/admin/price-lists/:id/prices/batch/add",
middlewares: [transformBody(AdminPostPriceListsPriceListPricesBatchAddReq)],
},
{
method: ["POST"],
matcher: "/admin/price-lists/:id/prices/batch/remove",
middlewares: [
transformBody(AdminPostPriceListsPriceListPricesBatchRemoveReq),
validateAndTransformBody(AdminCreatePriceList),
validateAndTransformQuery(
AdminGetPriceListPricesParams,
QueryConfig.retrivePriceListQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/admin/price-lists/:id/prices/batch/update",
middlewares: [transformBody(AdminPostPriceListPriceBatchUpdate)],
matcher: "/admin/price-lists/:id",
middlewares: [
validateAndTransformBody(AdminUpdatePriceList),
validateAndTransformQuery(
AdminGetPriceListPricesParams,
QueryConfig.retrivePriceListQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/admin/price-lists/:id/prices/batch",
middlewares: [
validateAndTransformBody(AdminBatchPriceListPrices),
validateAndTransformQuery(
AdminGetPriceListPricesParams,
QueryConfig.listPriceListPriceQueryConfig
),
],
},
]
@@ -7,14 +7,15 @@ import { AdminPriceListRemoteQueryDTO } from "../types"
export * from "./get-price-list"
export * from "./list-price-lists"
export * from "./list-prices"
export function buildPriceListResponse(
priceLists,
apiFields
): AdminPriceListRemoteQueryDTO[] {
for (const priceList of priceLists) {
priceList.rules = buildPriceListRules(priceList.price_list_rules || [])
priceList.prices = buildPriceSetPricesForCore(priceList.prices || [])
priceList.rules = buildPriceListRules(priceList.price_list_rules)
priceList.prices = buildPriceSetPricesForCore(priceList.prices)
}
return priceLists.map((priceList) => cleanResponseData(priceList, apiFields))
@@ -4,17 +4,14 @@ import {
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { AdminPriceListRemoteQueryDTO } from "../types"
import { buildPriceListResponse } from "./"
export async function listPriceLists({
container,
remoteQueryFields,
apiFields,
variables,
}: {
container: MedusaContainer
remoteQueryFields: string[]
apiFields: string[]
variables: Record<string, any>
}): Promise<[AdminPriceListRemoteQueryDTO[], number]> {
const remoteQuery = container.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
@@ -26,11 +23,5 @@ export async function listPriceLists({
const { rows: priceLists, metadata } = await remoteQuery(queryObject)
if (!metadata.count) {
return [[], 0]
}
const sanitizedPriceLists = buildPriceListResponse(priceLists, apiFields)
return [sanitizedPriceLists, metadata.count]
return [priceLists, metadata.count]
}
@@ -0,0 +1,22 @@
import { MedusaContainer } from "@medusajs/types"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
export const listPrices = (
ids: string[],
scope: MedusaContainer,
fields: string[]
) => {
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "price",
variables: {
filters: { id: ids },
},
fields,
})
return remoteQuery(queryObject)
}
@@ -2,6 +2,20 @@ export enum PriceListRelations {
PRICES = "prices",
}
export const adminPriceListPriceRemoteQueryFields = [
"id",
"currency_code",
"amount",
"min_quantity",
"max_quantity",
"created_at",
"deleted_at",
"updated_at",
"price_set.variant.id",
"price_rules.value",
"price_rules.rule_type.rule_attribute",
]
export const adminPriceListRemoteQueryFields = [
"id",
"type",
@@ -13,56 +27,27 @@ export const adminPriceListRemoteQueryFields = [
"created_at",
"updated_at",
"deleted_at",
"prices.id",
"prices.currency_code",
"prices.amount",
"prices.min_quantity",
"prices.max_quantity",
"prices.created_at",
"prices.deleted_at",
"prices.updated_at",
"prices.price_set.variant.id",
"prices.price_rules.value",
"prices.price_rules.rule_type.rule_attribute",
"price_list_rules.price_list_rule_values.value",
"price_list_rules.rule_type.rule_attribute",
...adminPriceListPriceRemoteQueryFields.map((field) => `prices.${field}`),
]
export const defaultAdminPriceListFields = [
"id",
"type",
"description",
"title",
"status",
"starts_at",
"ends_at",
"rules",
"created_at",
"updated_at",
"prices.amount",
"prices.id",
"prices.currency_code",
"prices.amount",
"prices.min_quantity",
"prices.max_quantity",
"prices.variant_id",
"prices.rules",
]
export const retrivePriceListPriceQueryConfig = {
defaults: adminPriceListPriceRemoteQueryFields,
isList: false,
}
export const defaultAdminPriceListRelations = []
export const allowedAdminPriceListRelations = [PriceListRelations.PRICES]
export const adminListTransformQueryConfig = {
defaultLimit: 50,
defaultFields: defaultAdminPriceListFields,
defaultRelations: defaultAdminPriceListRelations,
allowedRelations: allowedAdminPriceListRelations,
export const listPriceListPriceQueryConfig = {
...retrivePriceListPriceQueryConfig,
isList: true,
}
export const adminRetrieveTransformQueryConfig = {
defaultFields: defaultAdminPriceListFields,
defaultRelations: defaultAdminPriceListRelations,
allowedRelations: allowedAdminPriceListRelations,
export const retrivePriceListQueryConfig = {
defaults: adminPriceListRemoteQueryFields,
isList: false,
}
export const listPriceListQueryConfig = {
...retrivePriceListQueryConfig,
isList: true,
}
@@ -1,42 +1,43 @@
import { createPriceListsWorkflow } from "@medusajs/core-flows"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../types/routing"
import { listPriceLists } from "./queries"
import {
adminPriceListRemoteQueryFields,
defaultAdminPriceListFields,
} from "./query-config"
import { AdminPostPriceListsReq } from "./validators"
import { fetchPriceList, transformPriceList } from "./helpers"
import { AdminCreatePriceListType } from "./validators"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const { limit, offset } = req.validatedQuery
const [priceLists, count] = await listPriceLists({
container: req.scope,
apiFields: req.listConfig.select!,
remoteQueryFields: adminPriceListRemoteQueryFields,
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "price_list",
variables: {
filters: req.filterableFields,
order: req.listConfig.order,
skip: req.listConfig.skip,
take: req.listConfig.take,
...req.remoteQueryConfig.pagination,
},
fields: req.remoteQueryConfig.fields,
})
const { rows: priceLists, metadata } = await remoteQuery(queryObject)
res.json({
count,
price_lists: priceLists,
count: metadata.count,
price_lists: priceLists.map((priceList) => transformPriceList(priceList)),
offset,
limit,
})
}
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostPriceListsReq>,
req: AuthenticatedMedusaRequest<AdminCreatePriceListType>,
res: MedusaResponse
) => {
const workflow = createPriceListsWorkflow(req.scope)
@@ -49,16 +50,11 @@ export const POST = async (
throw errors[0].error
}
const [[priceList]] = await listPriceLists({
container: req.scope,
apiFields: defaultAdminPriceListFields,
remoteQueryFields: adminPriceListRemoteQueryFields,
variables: {
filters: { id: result[0].id },
skip: 0,
take: 1,
},
})
const price_list = await fetchPriceList(
result[0].id,
req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ price_list: priceList })
res.status(200).json({ price_list })
}
@@ -1,151 +1,77 @@
import { PriceListStatus, PriceListType } from "@medusajs/types"
import { Transform, Type } from "class-transformer"
import {
IsArray,
IsEnum,
IsInt,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { FindParams } from "../../../types/common"
import { transformOptionalDate } from "../../../utils/validators/date-transform"
import { z } from "zod"
import { createFindParams, createSelectParams } from "../../utils/validators"
export class AdminGetPriceListsParams extends FindParams {}
export class AdminGetPriceListsPriceListParams extends FindParams {}
export const AdminGetPriceListPricesParams = createSelectParams()
export const AdminGetPriceListsParams = createFindParams({
offset: 0,
limit: 50,
})
export class AdminPostPriceListsReq {
@IsString()
title: string
export const AdminGetPriceListParams = createFindParams({
offset: 0,
limit: 50,
})
@IsString()
description: string
export const AdminCreatePriceListPrice = z.object({
currency_code: z.string(),
amount: z.number(),
variant_id: z.string(),
min_quantity: z.number().optional(),
max_quantity: z.number().optional(),
rules: z.record(z.string(), z.string()).optional(),
})
@IsOptional()
@Transform(transformOptionalDate)
starts_at?: string
export type AdminCreatePriceListPriceType = z.infer<
typeof AdminCreatePriceListPrice
>
@IsOptional()
@Transform(transformOptionalDate)
ends_at?: string
export const AdminUpdatePriceListPrice = z.object({
id: z.string(),
currency_code: z.string().optional(),
amount: z.number().optional(),
variant_id: z.string(),
min_quantity: z.number().optional(),
max_quantity: z.number().optional(),
rules: z.record(z.string(), z.string()).optional(),
})
@IsOptional()
@IsEnum(PriceListStatus)
status?: PriceListStatus
export type AdminUpdatePriceListPriceType = z.infer<
typeof AdminUpdatePriceListPrice
>
@IsEnum(PriceListType)
type: PriceListType
export const AdminBatchPriceListPrices = z.object({
create: z.array(AdminCreatePriceListPrice).optional(),
update: z.array(AdminUpdatePriceListPrice).optional(),
delete: z.array(z.string()).optional(),
product_id: z.array(z.string()).optional(),
})
@IsArray()
@Type(() => AdminPriceListPricesCreateReq)
@ValidateNested({ each: true })
prices: AdminPriceListPricesCreateReq[]
export type AdminBatchPriceListPricesType = z.infer<
typeof AdminBatchPriceListPrices
>
@IsOptional()
@IsObject()
rules?: Record<string, string[]>
}
export const AdminCreatePriceList = z.object({
title: z.string(),
description: z.string(),
starts_at: z.string().optional(),
ends_at: z.string().optional(),
status: z.nativeEnum(PriceListStatus).optional(),
type: z.nativeEnum(PriceListType).optional(),
rules: z.record(z.string(), z.array(z.string())).optional(),
prices: z.array(AdminCreatePriceListPrice).optional(),
})
export class AdminPriceListPricesCreateReq {
@IsString()
currency_code: string
export type AdminCreatePriceListType = z.infer<typeof AdminCreatePriceList>
@IsInt()
amount: number
export const AdminUpdatePriceList = z.object({
title: z.string().optional(),
description: z.string().optional(),
starts_at: z.string().optional(),
ends_at: z.string().optional(),
status: z.nativeEnum(PriceListStatus).optional(),
type: z.nativeEnum(PriceListType).optional(),
rules: z.record(z.string(), z.array(z.string())).optional(),
})
@IsString()
variant_id: string
@IsOptional()
@IsInt()
min_quantity?: number
@IsOptional()
@IsInt()
max_quantity?: number
@IsOptional()
@IsObject()
rules?: Record<string, string>
}
export class AdminPostPriceListsPriceListReq {
@IsString()
@IsOptional()
title?: string
@IsString()
@IsOptional()
description?: string
@IsOptional()
@Transform(transformOptionalDate)
starts_at?: string
@IsOptional()
@Transform(transformOptionalDate)
ends_at?: string
@IsOptional()
@IsEnum(PriceListStatus)
status?: PriceListStatus
@IsOptional()
@IsEnum(PriceListType)
type?: PriceListType
@IsOptional()
@IsArray()
prices: AdminPriceListPricesCreateReq[]
@IsOptional()
@IsObject()
rules?: Record<string, string[]>
}
export class AdminPostPriceListsPriceListPricesBatchAddReq {
@IsOptional()
@IsArray()
prices: AdminPriceListPricesCreateReq[]
}
export class AdminPostPriceListPriceBatchUpdate {
@IsOptional()
@IsArray()
prices: AdminPostPriceListPriceUpdate[]
}
export class AdminPostPriceListsPriceListPricesBatchRemoveReq {
@IsArray()
@IsString({ each: true })
ids: string[]
}
export class AdminPostPriceListPriceUpdate {
@IsString()
id: string
@IsString()
variant_id: string
@IsOptional()
@IsString()
currency_code?: string
@IsOptional()
@IsInt()
amount?: number
@IsOptional()
@IsInt()
min_quantity?: number
@IsOptional()
@IsInt()
max_quantity?: number
@IsOptional()
@IsObject()
rules?: Record<string, string>
}
export type AdminUpdatePriceListType = z.infer<typeof AdminUpdatePriceList>