feat: Completely revamp the pricing module (#7852)
* feat: Completely revamp the pricing module * chore: Update all places to the new pricing interfaces * fix: Remove unnecessary join to itself * chore: Add data migration for existing users * fix: Apply the correct index to price rule
This commit is contained in:
1 parent
1f360a3245
commit
c661180c44
84 files changed
+661
-3725
No files matched your search
@@ -13,7 +13,7 @@ export const adminPriceListPriceRemoteQueryFields = [
|
||||
"updated_at",
|
||||
"price_set.variant.id",
|
||||
"price_rules.value",
|
||||
"price_rules.rule_type.rule_attribute",
|
||||
"price_rules.attribute",
|
||||
]
|
||||
|
||||
export const adminPriceListRemoteQueryFields = [
|
||||
@@ -27,8 +27,8 @@ export const adminPriceListRemoteQueryFields = [
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"price_list_rules.price_list_rule_values.value",
|
||||
"price_list_rules.rule_type.rule_attribute",
|
||||
"price_list_rules.value",
|
||||
"price_list_rules.attribute",
|
||||
...adminPriceListPriceRemoteQueryFields.map((field) => `prices.${field}`),
|
||||
]
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export const refetchRuleType = async (
|
||||
ruleTypeId: string,
|
||||
scope: MedusaContainer,
|
||||
fields: string[]
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "rule_type",
|
||||
variables: {
|
||||
filters: { id: ruleTypeId },
|
||||
},
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
const ruleTypes = await remoteQuery(queryObject)
|
||||
return ruleTypes[0]
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
||||
import { validateAndTransformBody } from "../../utils/validate-body"
|
||||
import { validateAndTransformQuery } from "../../utils/validate-query"
|
||||
import * as QueryConfig from "./query-config"
|
||||
import {
|
||||
AdminCreatePricingRuleType,
|
||||
AdminGetPricingRuleTypeParams,
|
||||
AdminGetPricingRuleTypesParams,
|
||||
AdminUpdatePricingRuleType,
|
||||
} from "./validators"
|
||||
|
||||
export const adminPricingRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
{
|
||||
method: ["GET"],
|
||||
matcher: "/admin/pricing/rule-types",
|
||||
middlewares: [
|
||||
validateAndTransformQuery(
|
||||
AdminGetPricingRuleTypesParams,
|
||||
QueryConfig.listTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/pricing/rule-types",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminCreatePricingRuleType),
|
||||
validateAndTransformQuery(
|
||||
AdminGetPricingRuleTypeParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["GET"],
|
||||
matcher: "/admin/pricing/rule-types/:id",
|
||||
middlewares: [
|
||||
validateAndTransformQuery(
|
||||
AdminGetPricingRuleTypeParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/pricing/rule-types/:id",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminUpdatePricingRuleType),
|
||||
validateAndTransformQuery(
|
||||
AdminGetPricingRuleTypeParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["DELETE"],
|
||||
matcher: "/admin/pricing/rule-types/:id",
|
||||
middlewares: [],
|
||||
},
|
||||
]
|
||||
@@ -1,16 +0,0 @@
|
||||
export const defaultAdminPricingRuleTypeFields = [
|
||||
"id",
|
||||
"name",
|
||||
"rule_attribute",
|
||||
"default_priority",
|
||||
]
|
||||
|
||||
export const retrieveTransformQueryConfig = {
|
||||
defaults: defaultAdminPricingRuleTypeFields,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const listTransformQueryConfig = {
|
||||
...retrieveTransformQueryConfig,
|
||||
isList: true,
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import {
|
||||
deletePricingRuleTypesWorkflow,
|
||||
updatePricingRuleTypesWorkflow,
|
||||
} from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../types/routing"
|
||||
import {
|
||||
AdminGetPricingRuleTypeParamsType,
|
||||
AdminUpdatePricingRuleTypeType,
|
||||
} from "../../validators"
|
||||
import { refetchRuleType } from "../../helpers"
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest<AdminGetPricingRuleTypeParamsType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const ruleType = await refetchRuleType(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
if (!ruleType) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`RuleType with id: ${req.params.id} was not found`
|
||||
)
|
||||
}
|
||||
|
||||
res.status(200).json({ rule_type: ruleType })
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminUpdatePricingRuleTypeType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const workflow = updatePricingRuleTypesWorkflow(req.scope)
|
||||
await workflow.run({
|
||||
input: {
|
||||
data: [{ ...req.validatedBody, id: req.params.id }],
|
||||
},
|
||||
})
|
||||
|
||||
const ruleType = await refetchRuleType(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({
|
||||
rule_type: ruleType,
|
||||
})
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const id = req.params.id
|
||||
const workflow = deletePricingRuleTypesWorkflow(req.scope)
|
||||
|
||||
await workflow.run({
|
||||
input: { ids: [id] },
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
id,
|
||||
object: "rule_type",
|
||||
deleted: true,
|
||||
})
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import { createPricingRuleTypesWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
import {
|
||||
AdminCreatePricingRuleTypeType,
|
||||
AdminGetPricingRuleTypesParamsType,
|
||||
} from "../validators"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { refetchRuleType } from "../helpers"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest<AdminGetPricingRuleTypesParamsType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "rule_type",
|
||||
variables: {
|
||||
filters: req.filterableFields,
|
||||
...req.remoteQueryConfig.pagination,
|
||||
},
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const { rows: rule_types, metadata } = await remoteQuery(queryObject)
|
||||
|
||||
res.json({
|
||||
rule_types: rule_types,
|
||||
count: metadata.count,
|
||||
offset: metadata.skip,
|
||||
limit: metadata.take,
|
||||
})
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminCreatePricingRuleTypeType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const workflow = createPricingRuleTypesWorkflow(req.scope)
|
||||
const ruleTypesData = [req.validatedBody]
|
||||
|
||||
const { result } = await workflow.run({
|
||||
input: { data: ruleTypesData },
|
||||
})
|
||||
|
||||
const ruleType = await refetchRuleType(
|
||||
result[0].id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({
|
||||
rule_type: ruleType,
|
||||
})
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { z } from "zod"
|
||||
import { createFindParams, createSelectParams } from "../../utils/validators"
|
||||
|
||||
export type AdminGetPricingRuleTypeParamsType = z.infer<
|
||||
typeof AdminGetPricingRuleTypeParams
|
||||
>
|
||||
export const AdminGetPricingRuleTypeParams = createSelectParams()
|
||||
|
||||
export type AdminGetPricingRuleTypesParamsType = z.infer<
|
||||
typeof AdminGetPricingRuleTypesParams
|
||||
>
|
||||
export const AdminGetPricingRuleTypesParams = createFindParams({
|
||||
limit: 100,
|
||||
offset: 0,
|
||||
}).merge(
|
||||
z.object({
|
||||
rule_attribute: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
$and: z.lazy(() => AdminGetPricingRuleTypesParams.array()).optional(),
|
||||
$or: z.lazy(() => AdminGetPricingRuleTypesParams.array()).optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export type AdminCreatePricingRuleTypeType = z.infer<
|
||||
typeof AdminCreatePricingRuleType
|
||||
>
|
||||
export const AdminCreatePricingRuleType = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
rule_attribute: z.string(),
|
||||
default_priority: z.number(),
|
||||
})
|
||||
.strict()
|
||||
|
||||
export type AdminUpdatePricingRuleTypeType = z.infer<
|
||||
typeof AdminUpdatePricingRuleType
|
||||
>
|
||||
export const AdminUpdatePricingRuleType = z
|
||||
.object({
|
||||
name: z.string().optional(),
|
||||
rule_attribute: z.string().optional(),
|
||||
default_priority: z.number().optional(),
|
||||
})
|
||||
.strict()
|
||||
@@ -92,7 +92,7 @@ export const buildRules = (price: PriceDTO) => {
|
||||
const rules: Record<string, string> = {}
|
||||
|
||||
for (const priceRule of price.price_rules || []) {
|
||||
const ruleAttribute = priceRule.rule_type?.rule_attribute
|
||||
const ruleAttribute = priceRule.attribute
|
||||
|
||||
if (ruleAttribute) {
|
||||
rules[ruleAttribute] = priceRule.value
|
||||
|
||||
@@ -23,7 +23,7 @@ export const defaultAdminProductsVariantFields = [
|
||||
"barcode",
|
||||
"*prices",
|
||||
"prices.price_rules.value",
|
||||
"prices.price_rules.rule_type.rule_attribute",
|
||||
"prices.price_rules.attribute",
|
||||
"*options",
|
||||
]
|
||||
|
||||
@@ -85,7 +85,7 @@ export const defaultAdminProductFields = [
|
||||
"*variants",
|
||||
"*variants.prices",
|
||||
"variants.prices.price_rules.value",
|
||||
"variants.prices.price_rules.rule_type.rule_attribute",
|
||||
"variants.prices.price_rules.attribute",
|
||||
"*variants.options",
|
||||
"*sales_channels",
|
||||
]
|
||||
|
||||
@@ -14,7 +14,6 @@ import { adminInviteRoutesMiddlewares } from "./admin/invites/middlewares"
|
||||
import { adminOrderRoutesMiddlewares } from "./admin/orders/middlewares"
|
||||
import { adminPaymentRoutesMiddlewares } from "./admin/payments/middlewares"
|
||||
import { adminPriceListsRoutesMiddlewares } from "./admin/price-lists/middlewares"
|
||||
import { adminPricingRoutesMiddlewares } from "./admin/pricing/middlewares"
|
||||
import { adminProductCategoryRoutesMiddlewares } from "./admin/product-categories/middlewares"
|
||||
import { adminProductTypeRoutesMiddlewares } from "./admin/product-types/middlewares"
|
||||
import { adminProductTagRoutesMiddlewares } from "./admin/product-tags/middlewares"
|
||||
@@ -81,7 +80,6 @@ export const config: MiddlewaresConfig = {
|
||||
...adminPriceListsRoutesMiddlewares,
|
||||
...adminInventoryRoutesMiddlewares,
|
||||
...adminCollectionRoutesMiddlewares,
|
||||
...adminPricingRoutesMiddlewares,
|
||||
...adminShippingOptionRoutesMiddlewares,
|
||||
...adminDraftOrderRoutesMiddlewares,
|
||||
...adminSalesChannelRoutesMiddlewares,
|
||||
|
||||
Reference in new issue
Block a user