chore(promotion): Improve performances [1] (#12129)
**What** Reduce database queries when possible and use proper data structure and aggregation when possible in order to reduce performance decrease overall
This commit is contained in:
committed by
GitHub
parent
31abba8cde
commit
d87b25203c
@@ -50,6 +50,17 @@ export function getComputedActionsForBuyGet(
|
||||
): PromotionTypes.ComputeActions[] {
|
||||
const computedActions: PromotionTypes.ComputeActions[] = []
|
||||
|
||||
if (!itemsContext) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`"items" should be present as an array in the context to compute actions`
|
||||
)
|
||||
}
|
||||
|
||||
if (!itemsContext?.length) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
const minimumBuyQuantity = MathBN.convert(
|
||||
promotion.application_method?.buy_rules_min_quantity ?? 0
|
||||
)
|
||||
@@ -58,11 +69,11 @@ export function getComputedActionsForBuyGet(
|
||||
itemsContext.map((i) => [i.id, i])
|
||||
)
|
||||
|
||||
if (!itemsContext) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`"items" should be present as an array in the context to compute actions`
|
||||
)
|
||||
if (
|
||||
MathBN.lte(minimumBuyQuantity, 0) ||
|
||||
!promotion.application_method?.buy_rules?.length
|
||||
) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
const eligibleBuyItems = filterItemsByPromotionRules(
|
||||
@@ -70,18 +81,25 @@ export function getComputedActionsForBuyGet(
|
||||
promotion.application_method?.buy_rules
|
||||
)
|
||||
|
||||
if (!eligibleBuyItems.length) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
const eligibleBuyItemQuantity = MathBN.sum(
|
||||
...eligibleBuyItems.map((item) => item.quantity)
|
||||
)
|
||||
|
||||
/*
|
||||
Get the total quantity of items where buy rules apply. If the total sum of eligible items
|
||||
Get the total quantity of items where buy rules apply. If the total sum of eligible items
|
||||
does not match up to the minimum buy quantity set on the promotion, return early.
|
||||
*/
|
||||
if (MathBN.gt(minimumBuyQuantity, eligibleBuyItemQuantity)) {
|
||||
return []
|
||||
return computedActions
|
||||
}
|
||||
|
||||
const eligibleItemsByPromotion: EligibleItem[] = []
|
||||
let accumulatedQuantity = MathBN.convert(0)
|
||||
|
||||
/*
|
||||
Eligibility of a BuyGet promotion can span across line items. Once an item has been chosen
|
||||
as eligible, we can't use this item or its partial remaining quantity when we apply the promotion on
|
||||
@@ -89,35 +107,19 @@ export function getComputedActionsForBuyGet(
|
||||
|
||||
We build the map here to use when we apply promotions on the target items.
|
||||
*/
|
||||
|
||||
for (const eligibleBuyItem of eligibleBuyItems) {
|
||||
const eligibleItemsByPromotion =
|
||||
eligibleBuyItemMap.get(promotion.code!) || []
|
||||
|
||||
const accumulatedQuantity = eligibleItemsByPromotion.reduce(
|
||||
(acc, item) => MathBN.sum(acc, item.quantity),
|
||||
MathBN.convert(0)
|
||||
)
|
||||
|
||||
// If we have reached the minimum buy quantity from the eligible items for this promotion,
|
||||
// we can break early and continue to applying the target items
|
||||
if (MathBN.gte(accumulatedQuantity, minimumBuyQuantity)) {
|
||||
break
|
||||
}
|
||||
|
||||
const eligibleQuantity = MathBN.sum(
|
||||
...eligibleItemsByPromotion
|
||||
.filter((buy) => buy.item_id === eligibleBuyItem.id)
|
||||
.map((b) => b.quantity)
|
||||
)
|
||||
|
||||
const reservableQuantity = MathBN.min(
|
||||
eligibleBuyItem.quantity,
|
||||
MathBN.sub(minimumBuyQuantity, eligibleQuantity)
|
||||
MathBN.sub(minimumBuyQuantity, accumulatedQuantity)
|
||||
)
|
||||
|
||||
// If we have reached the required minimum quantity, we break the loop early
|
||||
if (MathBN.lte(reservableQuantity, 0)) {
|
||||
break
|
||||
continue
|
||||
}
|
||||
|
||||
eligibleItemsByPromotion.push({
|
||||
@@ -128,93 +130,126 @@ export function getComputedActionsForBuyGet(
|
||||
).toNumber(),
|
||||
})
|
||||
|
||||
eligibleBuyItemMap.set(promotion.code!, eligibleItemsByPromotion)
|
||||
accumulatedQuantity = MathBN.add(accumulatedQuantity, reservableQuantity)
|
||||
}
|
||||
|
||||
// Store the eligible buy items for this promotion code in the map
|
||||
eligibleBuyItemMap.set(promotion.code!, eligibleItemsByPromotion)
|
||||
|
||||
// If we couldn't accumulate enough items to meet the minimum buy quantity, return early
|
||||
if (MathBN.lt(accumulatedQuantity, minimumBuyQuantity)) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
// Get the number of target items that should receive the discount
|
||||
const targetQuantity = MathBN.convert(
|
||||
promotion.application_method?.apply_to_quantity ?? 0
|
||||
)
|
||||
|
||||
// If no target quantity is specified, return early
|
||||
if (MathBN.lte(targetQuantity, 0)) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
// Find all items that match the target rules criteria
|
||||
const eligibleTargetItems = filterItemsByPromotionRules(
|
||||
itemsContext,
|
||||
promotion.application_method?.target_rules
|
||||
)
|
||||
|
||||
const targetQuantity = MathBN.convert(
|
||||
promotion.application_method?.apply_to_quantity ?? 0
|
||||
)
|
||||
// If no items match the target rules, return early
|
||||
if (!eligibleTargetItems.length) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
/*
|
||||
In this loop, we build a map of eligible target items and quantity applicable to these items.
|
||||
// Track quantities of items that can't be used as targets because they were used in buy rules
|
||||
const inapplicableQuantityMap = new Map<string, BigNumberInput>()
|
||||
|
||||
Here we remove the quantity we used previously to identify eligible buy items
|
||||
from the eligible target items.
|
||||
|
||||
This is done to prevent applying promotion to the same item we use to qualify the buy rules.
|
||||
*/
|
||||
for (const eligibleTargetItem of eligibleTargetItems) {
|
||||
const inapplicableQuantity = MathBN.sum(
|
||||
...Array.from(eligibleBuyItemMap.values())
|
||||
.flat(1)
|
||||
.filter((buy) => buy.item_id === eligibleTargetItem.id)
|
||||
.map((b) => b.quantity)
|
||||
// Build map of quantities that are ineligible as targets because they were used to satisfy buy rules
|
||||
for (const buyItem of eligibleItemsByPromotion) {
|
||||
const currentValue =
|
||||
inapplicableQuantityMap.get(buyItem.item_id) || MathBN.convert(0)
|
||||
inapplicableQuantityMap.set(
|
||||
buyItem.item_id,
|
||||
MathBN.add(currentValue, buyItem.quantity)
|
||||
)
|
||||
}
|
||||
|
||||
// Track items eligible for receiving the discount and total quantity that can be discounted
|
||||
const targetItemsByPromotion: EligibleItem[] = []
|
||||
let targetableQuantity = MathBN.convert(0)
|
||||
|
||||
// Find items eligible for discount, excluding quantities used in buy rules
|
||||
for (const eligibleTargetItem of eligibleTargetItems) {
|
||||
// Calculate how much of this item's quantity can receive the discount
|
||||
const inapplicableQuantity =
|
||||
inapplicableQuantityMap.get(eligibleTargetItem.id) || MathBN.convert(0)
|
||||
const applicableQuantity = MathBN.sub(
|
||||
eligibleTargetItem.quantity,
|
||||
inapplicableQuantity
|
||||
)
|
||||
|
||||
const fulfillableQuantity = MathBN.min(targetQuantity, applicableQuantity)
|
||||
if (MathBN.lte(applicableQuantity, 0)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate how many more items we need to fulfill target quantity
|
||||
const remainingNeeded = MathBN.sub(targetQuantity, targetableQuantity)
|
||||
const fulfillableQuantity = MathBN.min(remainingNeeded, applicableQuantity)
|
||||
|
||||
// If we have reached the required quantity to target from this item, we
|
||||
// move on to the next item
|
||||
if (MathBN.lte(fulfillableQuantity, 0)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const targetItemsByPromotion =
|
||||
eligibleTargetItemMap.get(promotion.code!) || []
|
||||
|
||||
// Add this item to eligible targets
|
||||
targetItemsByPromotion.push({
|
||||
item_id: eligibleTargetItem.id,
|
||||
quantity: MathBN.min(fulfillableQuantity, targetQuantity).toNumber(),
|
||||
quantity: fulfillableQuantity.toNumber(),
|
||||
})
|
||||
|
||||
eligibleTargetItemMap.set(promotion.code!, targetItemsByPromotion)
|
||||
targetableQuantity = MathBN.add(targetableQuantity, fulfillableQuantity)
|
||||
|
||||
// If we've found enough items to fulfill target quantity, stop looking
|
||||
if (MathBN.gte(targetableQuantity, targetQuantity)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const targetItemsByPromotion =
|
||||
eligibleTargetItemMap.get(promotion.code!) || []
|
||||
// Store eligible target items for this promotion
|
||||
eligibleTargetItemMap.set(promotion.code!, targetItemsByPromotion)
|
||||
|
||||
const targettableQuantity = targetItemsByPromotion.reduce(
|
||||
(sum, item) => MathBN.sum(sum, item.quantity),
|
||||
MathBN.convert(0)
|
||||
)
|
||||
|
||||
// If we were able to match the target requirements across all line items, we return early.
|
||||
if (MathBN.lt(targettableQuantity, targetQuantity)) {
|
||||
return []
|
||||
// If we couldn't find enough eligible target items, return early
|
||||
if (MathBN.lt(targetableQuantity, targetQuantity)) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
// Track remaining quantity to apply discount to and get discount percentage
|
||||
let remainingQtyToApply = MathBN.convert(targetQuantity)
|
||||
const applicablePercentage = promotion.application_method?.value ?? 100
|
||||
|
||||
// Apply discounts to eligible target items
|
||||
for (const targetItem of targetItemsByPromotion) {
|
||||
if (MathBN.lte(remainingQtyToApply, 0)) {
|
||||
break
|
||||
}
|
||||
|
||||
const item = itemsMap.get(targetItem.item_id)!
|
||||
const appliedPromoValue =
|
||||
methodIdPromoValueMap.get(item.id) ?? MathBN.convert(0)
|
||||
const multiplier = MathBN.min(targetItem.quantity, remainingQtyToApply)
|
||||
const applicableAmount = MathBN.mult(
|
||||
MathBN.div(item.subtotal, item.quantity),
|
||||
multiplier
|
||||
)
|
||||
const applicablePercentage = promotion.application_method?.value ?? 100
|
||||
|
||||
// Calculate discount amount based on item price and applicable percentage
|
||||
const pricePerUnit = MathBN.div(item.subtotal, item.quantity)
|
||||
const applicableAmount = MathBN.mult(pricePerUnit, multiplier)
|
||||
const amount = MathBN.mult(applicableAmount, applicablePercentage).div(100)
|
||||
|
||||
const newRemainingQtyToApply = MathBN.sub(remainingQtyToApply, multiplier)
|
||||
|
||||
if (MathBN.lt(newRemainingQtyToApply, 0) || MathBN.lte(amount, 0)) {
|
||||
break
|
||||
} else {
|
||||
remainingQtyToApply = newRemainingQtyToApply
|
||||
if (MathBN.lte(amount, 0)) {
|
||||
continue
|
||||
}
|
||||
|
||||
remainingQtyToApply = MathBN.sub(remainingQtyToApply, multiplier)
|
||||
|
||||
// Check if applying this discount would exceed promotion budget
|
||||
const budgetExceededAction = computeActionForBudgetExceeded(
|
||||
promotion,
|
||||
amount
|
||||
@@ -222,15 +257,16 @@ export function getComputedActionsForBuyGet(
|
||||
|
||||
if (budgetExceededAction) {
|
||||
computedActions.push(budgetExceededAction)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Track total promotional value applied to this item
|
||||
methodIdPromoValueMap.set(
|
||||
item.id,
|
||||
MathBN.add(appliedPromoValue, amount).toNumber()
|
||||
)
|
||||
|
||||
// Add computed discount action
|
||||
computedActions.push({
|
||||
action: ComputedActions.ADD_ITEM_ADJUSTMENT,
|
||||
item_id: item.id,
|
||||
|
||||
@@ -75,17 +75,35 @@ function applyPromotionToItems(
|
||||
allocationOverride?: ApplicationMethodAllocationValues
|
||||
): PromotionTypes.ComputeActions[] {
|
||||
const { application_method: applicationMethod } = promotion
|
||||
|
||||
if (!applicationMethod) {
|
||||
return []
|
||||
}
|
||||
|
||||
const allocation = applicationMethod?.allocation! || allocationOverride
|
||||
const computedActions: PromotionTypes.ComputeActions[] = []
|
||||
const applicableItems = getValidItemsForPromotion(items, promotion)
|
||||
const target = applicationMethod?.target_type
|
||||
|
||||
if (!items?.length || !target) {
|
||||
return []
|
||||
}
|
||||
|
||||
const computedActions: PromotionTypes.ComputeActions[] = []
|
||||
|
||||
const applicableItems = getValidItemsForPromotion(items, promotion)
|
||||
|
||||
if (!applicableItems.length) {
|
||||
return computedActions
|
||||
}
|
||||
|
||||
const isTargetShippingMethod = target === TargetType.SHIPPING_METHODS
|
||||
const isTargetLineItems = target === TargetType.ITEMS
|
||||
const isTargetOrder = target === TargetType.ORDER
|
||||
const promotionValue = applicationMethod?.value ?? 0
|
||||
const maxQuantity = isTargetShippingMethod
|
||||
? 1
|
||||
: applicationMethod?.max_quantity!
|
||||
|
||||
let lineItemsTotal = MathBN.convert(0)
|
||||
|
||||
if (allocation === ApplicationMethodAllocation.ACROSS) {
|
||||
lineItemsTotal = applicableItems.reduce(
|
||||
(acc, item) =>
|
||||
@@ -95,22 +113,27 @@ function applyPromotionToItems(
|
||||
),
|
||||
MathBN.convert(0)
|
||||
)
|
||||
|
||||
if (MathBN.lte(lineItemsTotal, 0)) {
|
||||
return computedActions
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of applicableItems!) {
|
||||
const appliedPromoValue = appliedPromotionsMap.get(item.id) ?? 0
|
||||
const maxQuantity = isTargetShippingMethod
|
||||
? 1
|
||||
: applicationMethod?.max_quantity!
|
||||
for (const item of applicableItems) {
|
||||
if (MathBN.lte(item.subtotal, 0)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (isTargetShippingMethod) {
|
||||
item.quantity = 1
|
||||
}
|
||||
|
||||
const appliedPromoValue = appliedPromotionsMap.get(item.id) ?? 0
|
||||
|
||||
const amount = calculateAdjustmentAmountFromPromotion(
|
||||
item,
|
||||
{
|
||||
value: applicationMethod?.value ?? 0,
|
||||
value: promotionValue,
|
||||
applied_value: appliedPromoValue,
|
||||
max_quantity: maxQuantity,
|
||||
type: applicationMethod?.type!,
|
||||
@@ -130,7 +153,6 @@ function applyPromotionToItems(
|
||||
|
||||
if (budgetExceededAction) {
|
||||
computedActions.push(budgetExceededAction)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -143,9 +165,7 @@ function applyPromotionToItems(
|
||||
amount,
|
||||
code: promotion.code!,
|
||||
})
|
||||
}
|
||||
|
||||
if (isTargetShippingMethod) {
|
||||
} else if (isTargetShippingMethod) {
|
||||
computedActions.push({
|
||||
action: ComputedActions.ADD_SHIPPING_METHOD_ADJUSTMENT,
|
||||
shipping_method_id: item.id,
|
||||
@@ -164,24 +184,39 @@ function getValidItemsForPromotion(
|
||||
| PromotionTypes.ComputeActionContext[TargetType.SHIPPING_METHODS],
|
||||
promotion: PromotionTypes.PromotionDTO
|
||||
) {
|
||||
if (!items?.length || !promotion?.application_method) {
|
||||
return []
|
||||
}
|
||||
|
||||
const isTargetShippingMethod =
|
||||
promotion.application_method?.target_type === TargetType.SHIPPING_METHODS
|
||||
|
||||
return (
|
||||
items?.filter((item) => {
|
||||
const isSubtotalPresent = "subtotal" in item
|
||||
const isQuantityPresent = "quantity" in item
|
||||
const isPromotionApplicableToItem = areRulesValidForContext(
|
||||
promotion?.application_method?.target_rules!,
|
||||
item,
|
||||
ApplicationMethodTargetType.ITEMS
|
||||
)
|
||||
const targetRules = promotion.application_method?.target_rules ?? []
|
||||
const hasTargetRules = targetRules.length > 0
|
||||
|
||||
return (
|
||||
isPromotionApplicableToItem &&
|
||||
(isQuantityPresent || isTargetShippingMethod) &&
|
||||
isSubtotalPresent
|
||||
)
|
||||
}) || []
|
||||
)
|
||||
if (isTargetShippingMethod && !hasTargetRules) {
|
||||
return items.filter(
|
||||
(item) => item && "subtotal" in item && MathBN.gt(item.subtotal, 0)
|
||||
)
|
||||
}
|
||||
|
||||
return items.filter((item) => {
|
||||
if (!item || !("subtotal" in item) || MathBN.lte(item.subtotal, 0)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!isTargetShippingMethod && !("quantity" in item)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!hasTargetRules) {
|
||||
return true
|
||||
}
|
||||
|
||||
return areRulesValidForContext(
|
||||
promotion?.application_method?.target_rules!,
|
||||
item,
|
||||
ApplicationMethodTargetType.ITEMS
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -55,20 +55,44 @@ export function areRulesValidForContext(
|
||||
context: Record<string, any>,
|
||||
contextScope: ApplicationMethodTargetTypeValues
|
||||
): boolean {
|
||||
return rules.every((rule) => {
|
||||
const validRuleValues = rule.values?.map((ruleValue) => ruleValue.value)
|
||||
if (!rules?.length) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!rule.attribute) {
|
||||
const isItemScope = contextScope === ApplicationMethodTargetType.ITEMS
|
||||
const isShippingScope =
|
||||
contextScope === ApplicationMethodTargetType.SHIPPING_METHODS
|
||||
|
||||
return rules.every((rule) => {
|
||||
if (!rule.attribute || !rule.values?.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
const valuesToCheck = pickValueFromObject(
|
||||
fetchRuleAttributeForContext(rule.attribute, contextScope),
|
||||
context
|
||||
)
|
||||
const validRuleValues = rule.values
|
||||
.filter((v) => isString(v.value))
|
||||
.map((v) => v.value as string)
|
||||
|
||||
if (!validRuleValues.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
let ruleAttribute = rule.attribute
|
||||
if (isItemScope) {
|
||||
ruleAttribute = ruleAttribute.replace(
|
||||
`${ApplicationMethodTargetType.ITEMS}.`,
|
||||
""
|
||||
)
|
||||
} else if (isShippingScope) {
|
||||
ruleAttribute = ruleAttribute.replace(
|
||||
`${ApplicationMethodTargetType.SHIPPING_METHODS}.`,
|
||||
""
|
||||
)
|
||||
}
|
||||
|
||||
const valuesToCheck = pickValueFromObject(ruleAttribute, context)
|
||||
|
||||
return evaluateRuleValueCondition(
|
||||
validRuleValues.filter(isString),
|
||||
validRuleValues,
|
||||
rule.operator!,
|
||||
valuesToCheck
|
||||
)
|
||||
@@ -76,83 +100,49 @@ export function areRulesValidForContext(
|
||||
}
|
||||
|
||||
/*
|
||||
The context here can either be either:
|
||||
- a cart context
|
||||
- an item context under a cart
|
||||
- a shipping method context under a cart
|
||||
|
||||
The rule's attributes are set from the perspective of the cart context. For example: items.product.id
|
||||
|
||||
When the context here is item or shipping_method, we need to drop the "items."" or "shipping_method."
|
||||
from the rule attribute string to accurate pick the values from the context.
|
||||
Optimized evaluateRuleValueCondition by using early returns and cleaner approach
|
||||
for evaluating rule conditions.
|
||||
*/
|
||||
function fetchRuleAttributeForContext(
|
||||
ruleAttribute: string,
|
||||
contextScope: ApplicationMethodTargetTypeValues
|
||||
): string {
|
||||
if (contextScope === ApplicationMethodTargetType.ITEMS) {
|
||||
ruleAttribute = ruleAttribute.replace(
|
||||
`${ApplicationMethodTargetType.ITEMS}.`,
|
||||
""
|
||||
)
|
||||
}
|
||||
|
||||
if (contextScope === ApplicationMethodTargetType.SHIPPING_METHODS) {
|
||||
ruleAttribute = ruleAttribute.replace(
|
||||
`${ApplicationMethodTargetType.SHIPPING_METHODS}.`,
|
||||
""
|
||||
)
|
||||
}
|
||||
|
||||
return ruleAttribute
|
||||
}
|
||||
|
||||
export function evaluateRuleValueCondition(
|
||||
ruleValues: string[],
|
||||
operator: string,
|
||||
ruleValuesToCheck: (string | number)[] | (string | number)
|
||||
) {
|
||||
if (!Array.isArray(ruleValuesToCheck)) {
|
||||
ruleValuesToCheck = [ruleValuesToCheck]
|
||||
}
|
||||
): boolean {
|
||||
const valuesToCheck = Array.isArray(ruleValuesToCheck)
|
||||
? ruleValuesToCheck
|
||||
: [ruleValuesToCheck]
|
||||
|
||||
if (!ruleValuesToCheck.length) {
|
||||
if (!valuesToCheck.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ruleValuesToCheck.every((ruleValueToCheck: string | number) => {
|
||||
if (operator === "in" || operator === "eq") {
|
||||
return ruleValues.some((ruleValue) => ruleValue === `${ruleValueToCheck}`)
|
||||
switch (operator) {
|
||||
case "in":
|
||||
case "eq": {
|
||||
const ruleValueSet = new Set(ruleValues)
|
||||
return valuesToCheck.every((val) => ruleValueSet.has(`${val}`))
|
||||
}
|
||||
|
||||
if (operator === "ne") {
|
||||
return ruleValues.some((ruleValue) => ruleValue !== `${ruleValueToCheck}`)
|
||||
case "ne": {
|
||||
const ruleValueSet = new Set(ruleValues)
|
||||
return valuesToCheck.every((val) => !ruleValueSet.has(`${val}`))
|
||||
}
|
||||
|
||||
if (operator === "gt") {
|
||||
return ruleValues.some((ruleValue) =>
|
||||
MathBN.convert(ruleValueToCheck).gt(MathBN.convert(ruleValue))
|
||||
case "gt":
|
||||
return valuesToCheck.every((val) =>
|
||||
ruleValues.some((ruleVal) => MathBN.gt(val, ruleVal))
|
||||
)
|
||||
}
|
||||
|
||||
if (operator === "gte") {
|
||||
return ruleValues.some((ruleValue) =>
|
||||
MathBN.convert(ruleValueToCheck).gte(MathBN.convert(ruleValue))
|
||||
case "gte":
|
||||
return valuesToCheck.every((val) =>
|
||||
ruleValues.some((ruleVal) => MathBN.gte(val, ruleVal))
|
||||
)
|
||||
}
|
||||
|
||||
if (operator === "lt") {
|
||||
return ruleValues.some((ruleValue) =>
|
||||
MathBN.convert(ruleValueToCheck).lt(MathBN.convert(ruleValue))
|
||||
case "lt":
|
||||
return valuesToCheck.every((val) =>
|
||||
ruleValues.some((ruleVal) => MathBN.lt(val, ruleVal))
|
||||
)
|
||||
}
|
||||
|
||||
if (operator === "lte") {
|
||||
return ruleValues.some((ruleValue) =>
|
||||
MathBN.convert(ruleValueToCheck).lte(MathBN.convert(ruleValue))
|
||||
case "lte":
|
||||
return valuesToCheck.every((val) =>
|
||||
ruleValues.some((ruleVal) => MathBN.lte(val, ruleVal))
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user