feat(dashboard,types,promotion,medusa): hide fields on promotions depending on templates (#7746)

**what:**

- hides different fields depending on the chosen template
- remove operator values API
- fixes to edit promotion rules
- make currency optional for promotion

RESOLVES CORE-2297
This commit is contained in:
Riqwan Thamir authored and GitHub committed 2024-06-18 16:47:42 +00:00
1 parent 1451112f08
commit 0d04c548f5
24 files changed
+523 -389

No files matched your search

@@ -33,9 +33,11 @@ export const GET = async (
})
const [promotion] = await remoteQuery(queryObject)
const ruleAttributes = getRuleAttributesMap(
promotion?.type || req.query.promotion_type
)[ruleType]
const ruleAttributes = getRuleAttributesMap({
promotionType: promotion?.type || req.query.promotion_type,
applicationMethodType:
promotion?.application_method?.type || req.query.application_method_type,
})[ruleType]
const promotionRules: any[] = []
if (dasherizedRuleType === RuleType.RULES) {
@@ -48,7 +50,6 @@ export const GET = async (
const transformedRules: AdminGetPromotionRulesRes = []
const disguisedRules = ruleAttributes.filter((attr) => !!attr.disguised)
const requiredRules = ruleAttributes.filter((attr) => !!attr.required)
for (const disguisedRule of disguisedRules) {
const getValues = () => {
@@ -65,18 +66,22 @@ export const GET = async (
return []
}
transformedRules.push({
id: undefined,
attribute: disguisedRule.id,
attribute_label: disguisedRule.label,
field_type: disguisedRule.field_type,
hydrate: disguisedRule.hydrate || false,
operator: RuleOperator.EQ,
operator_label: operatorsMap[RuleOperator.EQ].label,
values: getValues(),
disguised: true,
required: true,
})
const required = disguisedRule.required ?? true
const applicationMethod = promotion?.application_method
const recordValue = applicationMethod?.[disguisedRule.id]
if (required || recordValue) {
transformedRules.push({
...disguisedRule,
id: undefined,
attribute: disguisedRule.id,
attribute_label: disguisedRule.label,
operator: RuleOperator.EQ,
operator_label: operatorsMap[RuleOperator.EQ].label,
value: undefined,
values: getValues(),
})
}
continue
}
@@ -125,36 +130,15 @@ export const GET = async (
if (!currentRuleAttribute.hydrate) {
transformedRules.push({
...currentRuleAttribute,
...promotionRule,
attribute_label: currentRuleAttribute.label,
field_type: currentRuleAttribute.field_type,
operator_label:
operatorsMap[promotionRule.operator]?.label || promotionRule.operator,
disguised: false,
required: currentRuleAttribute.required || false,
})
}
}
if (requiredRules.length && !transformedRules.length) {
for (const requiredRule of requiredRules) {
transformedRules.push({
id: undefined,
attribute: requiredRule.value,
attribute_label: requiredRule.label,
operator: RuleOperator.EQ,
field_type: requiredRule.field_type,
operator_label: operatorsMap[RuleOperator.EQ].label,
values: [],
disguised: true,
required: true,
hydrate: false,
})
continue
}
}
res.json({
rules: transformedRules,
})
@@ -14,7 +14,10 @@ export const GET = async (
validateRuleType(ruleType)
const attributes =
getRuleAttributesMap(req.query.promotion_type as string)[ruleType] || []
getRuleAttributesMap({
promotionType: req.query.promotion_type as string,
applicationMethodType: req.query.application_method_type as string,
})[ruleType] || []
res.json({
attributes,
@@ -1,14 +0,0 @@
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../types/routing"
import { operatorsMap } from "../utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
res.json({
operators: Object.values(operatorsMap),
})
}
@@ -13,6 +13,13 @@ import {
} from "../../../utils"
import { AdminGetPromotionRuleParamsType } from "../../../validators"
/*
This endpoint returns all the potential values for rules (promotion rules, target rules and buy rules)
given an attribute of a rule. The response for different rule_attributes are returned uniformly
as an array of labels and values.
Eg. If the rule_attribute requested is "currency_code" for "rules" rule type, we return currencies
from the currency module.
*/
export const GET = async (
req: AuthenticatedMedusaRequest<AdminGetPromotionRuleParamsType>,
res: MedusaResponse
@@ -21,6 +28,7 @@ export const GET = async (
rule_type: ruleType,
rule_attribute_id: ruleAttributeId,
promotion_type: promotionType,
application_method_type: applicationMethodType,
} = req.params
const queryConfig = ruleQueryConfigurations[ruleAttributeId]
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
@@ -33,7 +41,12 @@ export const GET = async (
}
validateRuleType(ruleType)
validateRuleAttribute(promotionType, ruleType, ruleAttributeId)
validateRuleAttribute({
promotionType,
ruleType,
ruleAttributeId,
applicationMethodType,
})
const { rows } = await remoteQuery(
remoteQueryObjectFromString({
@@ -1,4 +1,9 @@
import { PromotionType } from "@medusajs/utils"
import {
ApplicationMethodType,
PromotionType,
RuleOperator,
} from "@medusajs/utils"
import { operatorsMap } from "./operators-map"
export enum DisguisedRule {
APPLY_TO_QUANTITY = "apply_to_quantity",
@@ -7,21 +12,13 @@ export enum DisguisedRule {
}
const ruleAttributes = [
{
id: DisguisedRule.CURRENCY_CODE,
value: DisguisedRule.CURRENCY_CODE,
label: "Currency Code",
field_type: "select",
required: true,
disguised: true,
hydrate: true,
},
{
id: "customer_group",
value: "customer.groups.id",
label: "Customer Group",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "region",
@@ -29,6 +26,7 @@ const ruleAttributes = [
label: "Region",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "country",
@@ -36,6 +34,7 @@ const ruleAttributes = [
label: "Country",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "sales_channel",
@@ -43,6 +42,7 @@ const ruleAttributes = [
label: "Sales Channel",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
]
@@ -53,6 +53,7 @@ const commonAttributes = [
label: "Product",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "product_category",
@@ -60,6 +61,7 @@ const commonAttributes = [
label: "Product Category",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "product_collection",
@@ -67,6 +69,7 @@ const commonAttributes = [
label: "Product Collection",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "product_type",
@@ -74,6 +77,7 @@ const commonAttributes = [
label: "Product Type",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
{
id: "product_tag",
@@ -81,9 +85,21 @@ const commonAttributes = [
label: "Product Tag",
required: false,
field_type: "multiselect",
operators: Object.values(operatorsMap),
},
]
const currencyRule = {
id: DisguisedRule.CURRENCY_CODE,
value: DisguisedRule.CURRENCY_CODE,
label: "Currency Code",
field_type: "select",
required: true,
disguised: true,
hydrate: true,
operators: [operatorsMap[RuleOperator.EQ]],
}
const buyGetBuyRules = [
{
id: DisguisedRule.BUY_RULES_MIN_QUANTITY,
@@ -92,6 +108,7 @@ const buyGetBuyRules = [
field_type: "number",
required: true,
disguised: true,
operators: [operatorsMap[RuleOperator.EQ]],
},
]
@@ -103,16 +120,29 @@ const buyGetTargetRules = [
field_type: "number",
required: true,
disguised: true,
operators: [operatorsMap[RuleOperator.EQ]],
},
]
export const getRuleAttributesMap = (promotionType?: string) => {
export const getRuleAttributesMap = ({
promotionType,
applicationMethodType,
}: {
promotionType?: string
applicationMethodType?: string
}) => {
const map = {
rules: [...ruleAttributes],
"target-rules": [...commonAttributes],
"buy-rules": [...commonAttributes],
}
if (applicationMethodType === ApplicationMethodType.FIXED) {
map["rules"].push({ ...currencyRule })
} else {
map["rules"].push({ ...currencyRule, required: false })
}
if (promotionType === PromotionType.BUYGET) {
map["buy-rules"].push(...buyGetBuyRules)
map["target-rules"].push(...buyGetTargetRules)
@@ -1,12 +1,21 @@
import { MedusaError } from "@medusajs/utils"
import { getRuleAttributesMap } from "./rule-attributes-map"
export function validateRuleAttribute(
promotionType: string | undefined,
ruleType: string,
export function validateRuleAttribute(attributes: {
promotionType: string | undefined
ruleType: string
ruleAttributeId: string
) {
const ruleAttributes = getRuleAttributesMap(promotionType)[ruleType] || []
applicationMethodType?: string
}) {
const { promotionType, ruleType, ruleAttributeId, applicationMethodType } =
attributes
const ruleAttributes =
getRuleAttributesMap({
promotionType,
applicationMethodType,
})[ruleType] || []
const ruleAttribute = ruleAttributes.find((obj) => obj.id === ruleAttributeId)
if (!ruleAttribute) {
@@ -49,6 +49,7 @@ export type AdminGetPromotionRuleParamsType = z.infer<
>
export const AdminGetPromotionRuleParams = z.object({
promotion_type: z.string().optional(),
application_method_type: z.string().optional(),
})
export type AdminGetPromotionRuleTypeParamsType = z.infer<
@@ -57,6 +58,7 @@ export type AdminGetPromotionRuleTypeParamsType = z.infer<
export const AdminGetPromotionRuleTypeParams = createSelectParams().merge(
z.object({
promotion_type: z.string().optional(),
application_method_type: z.string().optional(),
})
)
@@ -105,7 +107,7 @@ export const AdminCreateApplicationMethod = z
.object({
description: z.string().optional(),
value: z.number(),
currency_code: z.string(),
currency_code: z.string().optional().nullable(),
max_quantity: z.number().optional().nullable(),
type: z.nativeEnum(ApplicationMethodType),
target_type: z.nativeEnum(ApplicationMethodTargetType),
@@ -125,7 +127,7 @@ export const AdminUpdateApplicationMethod = z
description: z.string().optional(),
value: z.number().optional(),
max_quantity: z.number().optional().nullable(),
currency_code: z.string().optional(),
currency_code: z.string().optional().nullable(),
type: z.nativeEnum(ApplicationMethodType).optional(),
target_type: z.nativeEnum(ApplicationMethodTargetType).optional(),
allocation: z.nativeEnum(ApplicationMethodAllocation).optional(),