Browse Source

feat(core): Pass Promotion instance to condition & action functions

Fixes #1787
Michael Bromley 3 years ago
parent
commit
e70bb66c96

+ 37 - 7
packages/core/src/config/promotion/promotion-action.ts

@@ -8,7 +8,7 @@ import {
     ConfigurableOperationDef,
     ConfigurableOperationDefOptions,
 } from '../../common/configurable-operation';
-import { PromotionState } from '../../entity';
+import { Promotion, PromotionState } from '../../entity';
 import { OrderItem } from '../../entity/order-item/order-item.entity';
 import { OrderLine } from '../../entity/order-line/order-line.entity';
 import { Order } from '../../entity/order/order.entity';
@@ -76,6 +76,7 @@ export type ExecutePromotionItemActionFn<T extends ConfigArgs, U extends Array<P
     orderLine: OrderLine,
     args: ConfigArgValues<T>,
     state: ConditionState<U>,
+    promotion: Promotion,
 ) => number | Promise<number>;
 
 /**
@@ -91,6 +92,7 @@ export type ExecutePromotionOrderActionFn<T extends ConfigArgs, U extends Array<
     order: Order,
     args: ConfigArgValues<T>,
     state: ConditionState<U>,
+    promotion: Promotion,
 ) => number | Promise<number>;
 
 /**
@@ -110,6 +112,7 @@ export type ExecutePromotionShippingActionFn<
     order: Order,
     args: ConfigArgValues<T>,
     state: ConditionState<U>,
+    promotion: Promotion,
 ) => number | Promise<number>;
 
 /**
@@ -125,6 +128,7 @@ type PromotionActionSideEffectFn<T extends ConfigArgs> = (
     ctx: RequestContext,
     order: Order,
     args: ConfigArgValues<T>,
+    promotion: Promotion,
 ) => void | Promise<void>;
 
 /**
@@ -274,13 +278,23 @@ export abstract class PromotionAction<
     abstract execute(...arg: any[]): number | Promise<number>;
 
     /** @internal */
-    onActivate(ctx: RequestContext, order: Order, args: ConfigArg[]): void | Promise<void> {
-        return this.onActivateFn?.(ctx, order, this.argsArrayToHash(args));
+    onActivate(
+        ctx: RequestContext,
+        order: Order,
+        args: ConfigArg[],
+        promotion: Promotion,
+    ): void | Promise<void> {
+        return this.onActivateFn?.(ctx, order, this.argsArrayToHash(args), promotion);
     }
 
     /** @internal */
-    onDeactivate(ctx: RequestContext, order: Order, args: ConfigArg[]): void | Promise<void> {
-        return this.onDeactivateFn?.(ctx, order, this.argsArrayToHash(args));
+    onDeactivate(
+        ctx: RequestContext,
+        order: Order,
+        args: ConfigArg[],
+        promotion: Promotion,
+    ): void | Promise<void> {
+        return this.onDeactivateFn?.(ctx, order, this.argsArrayToHash(args), promotion);
     }
 }
 
@@ -322,6 +336,7 @@ export class PromotionItemAction<
         orderLine: OrderLine,
         args: ConfigArg[],
         state: PromotionState,
+        promotion: Promotion,
     ) {
         const actionState = this.conditions
             ? pick(
@@ -335,6 +350,7 @@ export class PromotionItemAction<
             orderLine,
             this.argsArrayToHash(args),
             actionState as ConditionState<U>,
+            promotion,
         );
     }
 }
@@ -371,14 +387,26 @@ export class PromotionOrderAction<
     }
 
     /** @internal */
-    execute(ctx: RequestContext, order: Order, args: ConfigArg[], state: PromotionState) {
+    execute(
+        ctx: RequestContext,
+        order: Order,
+        args: ConfigArg[],
+        state: PromotionState,
+        promotion: Promotion,
+    ) {
         const actionState = this.conditions
             ? pick(
                   state,
                   this.conditions.map(c => c.code),
               )
             : {};
-        return this.executeFn(ctx, order, this.argsArrayToHash(args), actionState as ConditionState<U>);
+        return this.executeFn(
+            ctx,
+            order,
+            this.argsArrayToHash(args),
+            actionState as ConditionState<U>,
+            promotion,
+        );
     }
 }
 
@@ -407,6 +435,7 @@ export class PromotionShippingAction<
         order: Order,
         args: ConfigArg[],
         state: PromotionState,
+        promotion: Promotion,
     ) {
         const actionState = this.conditions
             ? pick(
@@ -420,6 +449,7 @@ export class PromotionShippingAction<
             order,
             this.argsArrayToHash(args),
             actionState as ConditionState<U>,
+            promotion,
         );
     }
 }

+ 6 - 4
packages/core/src/config/promotion/promotion-condition.ts

@@ -7,6 +7,7 @@ import {
     ConfigurableOperationDef,
     ConfigurableOperationDefOptions,
 } from '../../common/configurable-operation';
+import { Promotion } from '../../entity/index';
 import { Order } from '../../entity/order/order.entity';
 
 export type PromotionConditionState = Record<string, unknown>;
@@ -31,6 +32,7 @@ export type CheckPromotionConditionFn<T extends ConfigArgs, R extends CheckPromo
     ctx: RequestContext,
     order: Order,
     args: ConfigArgValues<T>,
+    promotion: Promotion,
 ) => R | Promise<R>;
 
 /**
@@ -44,7 +46,7 @@ export type CheckPromotionConditionFn<T extends ConfigArgs, R extends CheckPromo
 export interface PromotionConditionConfig<
     T extends ConfigArgs,
     C extends string,
-    R extends CheckPromotionConditionResult
+    R extends CheckPromotionConditionResult,
 > extends ConfigurableOperationDefOptions<T> {
     code: C;
     check: CheckPromotionConditionFn<T, R>;
@@ -64,7 +66,7 @@ export interface PromotionConditionConfig<
 export class PromotionCondition<
     T extends ConfigArgs = ConfigArgs,
     C extends string = string,
-    R extends CheckPromotionConditionResult = any
+    R extends CheckPromotionConditionResult = any,
 > extends ConfigurableOperationDef<T> {
     /**
      * @description
@@ -92,7 +94,7 @@ export class PromotionCondition<
      * This is the function which contains the conditional logic to decide whether
      * a Promotion should apply to an Order. See {@link CheckPromotionConditionFn}.
      */
-    async check(ctx: RequestContext, order: Order, args: ConfigArg[]): Promise<R> {
-        return this.checkFn(ctx, order, this.argsArrayToHash(args));
+    async check(ctx: RequestContext, order: Order, args: ConfigArg[], promotion: Promotion): Promise<R> {
+        return this.checkFn(ctx, order, this.argsArrayToHash(args), promotion);
     }
 }

+ 11 - 6
packages/core/src/entity/promotion/promotion.entity.ts

@@ -135,19 +135,19 @@ export class Promotion extends AdjustmentSource implements ChannelAware, SoftDel
                 if (this.isOrderItemArg(args)) {
                     const { orderItem, orderLine } = args;
                     amount += Math.round(
-                        await promotionAction.execute(ctx, orderItem, orderLine, action.args, state),
+                        await promotionAction.execute(ctx, orderItem, orderLine, action.args, state, this),
                     );
                 }
             } else if (promotionAction instanceof PromotionOrderAction) {
                 if (this.isOrderArg(args)) {
                     const { order } = args;
-                    amount += Math.round(await promotionAction.execute(ctx, order, action.args, state));
+                    amount += Math.round(await promotionAction.execute(ctx, order, action.args, state, this));
                 }
             } else if (promotionAction instanceof PromotionShippingAction) {
                 if (this.isShippingArg(args)) {
                     const { shippingLine, order } = args;
                     amount += Math.round(
-                        await promotionAction.execute(ctx, shippingLine, order, action.args, state),
+                        await promotionAction.execute(ctx, shippingLine, order, action.args, state, this),
                     );
                 }
             }
@@ -178,7 +178,12 @@ export class Promotion extends AdjustmentSource implements ChannelAware, SoftDel
             if (!promotionCondition) {
                 return false;
             }
-            const applicableOrConditionState = await promotionCondition.check(ctx, order, condition.args);
+            const applicableOrConditionState = await promotionCondition.check(
+                ctx,
+                order,
+                condition.args,
+                this,
+            );
             if (!applicableOrConditionState) {
                 return false;
             }
@@ -192,14 +197,14 @@ export class Promotion extends AdjustmentSource implements ChannelAware, SoftDel
     async activate(ctx: RequestContext, order: Order) {
         for (const action of this.actions) {
             const promotionAction = this.allActions[action.code];
-            await promotionAction.onActivate(ctx, order, action.args);
+            await promotionAction.onActivate(ctx, order, action.args, this);
         }
     }
 
     async deactivate(ctx: RequestContext, order: Order) {
         for (const action of this.actions) {
             const promotionAction = this.allActions[action.code];
-            await promotionAction.onDeactivate(ctx, order, action.args);
+            await promotionAction.onDeactivate(ctx, order, action.args, this);
         }
     }