From 343703af0f17ac557fb284efd07569c1d99dcbe9 Mon Sep 17 00:00:00 2001 From: vanpho93 Date: Mon, 30 Jan 2023 16:41:50 +0700 Subject: [PATCH 1/2] feat: update coupon trigger parameter schema Signed-off-by: vanpho93 --- .../src/preStartup.js | 11 ++++++++++- .../src/simpleSchemas.js | 19 ++++++++++++++++--- .../api-plugin-promotions-offers/src/index.js | 5 +++-- .../src/mutations/createPromotion.js | 2 ++ .../src/mutations/createPromotion.test.js | 11 +++++++++++ 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/api-plugin-promotions-coupons/src/preStartup.js b/packages/api-plugin-promotions-coupons/src/preStartup.js index 06aacf3e9b2..8a59a5ae2e1 100644 --- a/packages/api-plugin-promotions-coupons/src/preStartup.js +++ b/packages/api-plugin-promotions-coupons/src/preStartup.js @@ -1,5 +1,6 @@ import _ from "lodash"; import SimpleSchema from "simpl-schema"; +import { CouponTriggerCondition, CouponTriggerParameters } from "./simpleSchemas.js"; /** * @summary This is a preStartup function that is called before the app starts up. @@ -7,7 +8,15 @@ import SimpleSchema from "simpl-schema"; * @returns {undefined} */ export default async function preStartupPromotionCoupon(context) { - const { simpleSchemas: { Cart, Promotion }, promotions: pluginPromotions } = context; + const { simpleSchemas: { Cart, Promotion, RuleExpression }, promotions: pluginPromotions } = context; + + CouponTriggerCondition.extend({ + conditions: RuleExpression + }); + + CouponTriggerParameters.extend({ + conditions: RuleExpression + }); // because we're reusing the offer trigger, we need to promotion-discounts plugin to be installed first const offerTrigger = pluginPromotions.triggers.find((trigger) => trigger.key === "offers"); diff --git a/packages/api-plugin-promotions-coupons/src/simpleSchemas.js b/packages/api-plugin-promotions-coupons/src/simpleSchemas.js index 825fee4cfe7..957c2000de1 100644 --- a/packages/api-plugin-promotions-coupons/src/simpleSchemas.js +++ b/packages/api-plugin-promotions-coupons/src/simpleSchemas.js @@ -1,9 +1,22 @@ import SimpleSchema from "simpl-schema"; +export const CouponTriggerCondition = new SimpleSchema({ + conditions: { + type: Object + } +}); + export const CouponTriggerParameters = new SimpleSchema({ - name: String, - couponCode: { - type: String + conditions: { + type: Object + }, + inclusionRules: { + type: CouponTriggerCondition, + optional: true + }, + exclusionRules: { + type: CouponTriggerCondition, + optional: true } }); diff --git a/packages/api-plugin-promotions-offers/src/index.js b/packages/api-plugin-promotions-offers/src/index.js index 7b228dea862..c1ef574d440 100644 --- a/packages/api-plugin-promotions-offers/src/index.js +++ b/packages/api-plugin-promotions-offers/src/index.js @@ -3,7 +3,7 @@ import triggers from "./triggers/index.js"; import enhancers from "./enhancers/index.js"; import facts from "./facts/index.js"; import { promotionOfferFacts, registerPromotionOfferFacts } from "./registration.js"; -import { ConditionRule } from "./simpleSchemas.js"; +import { ConditionRule, RuleExpression } from "./simpleSchemas.js"; import preStartupPromotionOffer from "./preStartup.js"; const require = createRequire(import.meta.url); @@ -32,7 +32,8 @@ export default async function register(app) { }, promotionOfferFacts: facts, simpleSchemas: { - ConditionRule + ConditionRule, + RuleExpression } }); } diff --git a/packages/api-plugin-promotions/src/mutations/createPromotion.js b/packages/api-plugin-promotions/src/mutations/createPromotion.js index fc08a30fe9f..cc1c1cfa910 100644 --- a/packages/api-plugin-promotions/src/mutations/createPromotion.js +++ b/packages/api-plugin-promotions/src/mutations/createPromotion.js @@ -1,4 +1,5 @@ import Random from "@reactioncommerce/random"; +import ReactionError from "@reactioncommerce/reaction-error"; import validateActionParams from "./validateActionParams.js"; import validateTriggerParams from "./validateTriggerParams.js"; @@ -16,6 +17,7 @@ export default async function createPromotion(context, promotion) { const [firstTrigger] = promotion.triggers; // currently support only one trigger const { triggerKey } = firstTrigger; const trigger = promotions.triggers.find((tr) => tr.key === triggerKey); + if (!trigger) throw new ReactionError("invalid-params", `No trigger found with key ${triggerKey}`); promotion.triggerType = trigger.type; } promotion.state = "created"; diff --git a/packages/api-plugin-promotions/src/mutations/createPromotion.test.js b/packages/api-plugin-promotions/src/mutations/createPromotion.test.js index 4e4fde994b5..3ad3c0f46f3 100644 --- a/packages/api-plugin-promotions/src/mutations/createPromotion.test.js +++ b/packages/api-plugin-promotions/src/mutations/createPromotion.test.js @@ -153,3 +153,14 @@ test("will insert a record if it passes validation", async () => { expect(error).toBeUndefined(); } }); + +test("should throw error when triggerKey is not valid", async () => { + const promotion = _.cloneDeep(CreateOrderPromotion); + promotion.triggers[0].triggerKey = "invalid"; + try { + await createPromotion(mockContext, promotion); + } catch (error) { + expect(error.error).toEqual("invalid-params"); + expect(error.message).toEqual("No trigger found with key invalid"); + } +}); From 1d8309831592962643abcb4dcc5c4e913943a716 Mon Sep 17 00:00:00 2001 From: vanpho93 Date: Wed, 1 Feb 2023 13:38:44 +0700 Subject: [PATCH 2/2] feat: add name field to coupon Signed-off-by: vanpho93 --- .../src/mutations/createStandardCoupon.js | 2 + .../mutations/createStandardCoupon.test.js | 9 ++-- .../src/schemas/schema.graphql | 45 ++----------------- .../src/simpleSchemas.js | 1 + 4 files changed, 12 insertions(+), 45 deletions(-) diff --git a/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.js b/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.js index 6c898fd27b6..05ded1f4e83 100644 --- a/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.js +++ b/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.js @@ -7,6 +7,7 @@ import { Coupon } from "../simpleSchemas.js"; const inputSchema = new SimpleSchema({ shopId: String, promotionId: String, + name: String, code: String, canUseInStore: Boolean, maxUsageTimesPerUser: { @@ -50,6 +51,7 @@ export default async function createStandardCoupon(context, input) { const now = new Date(); const coupon = { _id: Random.id(), + name: input.name, code: input.code, shopId, promotionId, diff --git a/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.test.js b/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.test.js index d486c8889eb..ad1fd7af620 100644 --- a/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.test.js +++ b/packages/api-plugin-promotions-coupons/src/mutations/createStandardCoupon.test.js @@ -12,7 +12,7 @@ test("throws if validation check fails", async () => { }); test("throws error when coupon code already created", async () => { - const input = { code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; + const input = { name: "test", code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; const coupon = { _id: "123", code: "CODE", promotionId: "promotionId" }; const promotion = { _id: "promotionId" }; mockContext.collections = { @@ -40,7 +40,7 @@ test("throws error when coupon code already created", async () => { }); test("throws error when promotion does not exist", async () => { - const input = { code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; + const input = { name: "test", code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; mockContext.collections = { Coupons: { findOne: jest.fn().mockResolvedValueOnce(Promise.resolve(null)) @@ -59,7 +59,7 @@ test("throws error when promotion does not exist", async () => { test("throws error when coupon code already exists in promotion window", async () => { const now = new Date(); - const input = { code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; + const input = { name: "test", code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; const promotion = { _id: "123", startDate: now, endDate: now }; const existsPromotion = { _id: "1234", startDate: now, endDate: now }; const coupon = { _id: "123", code: "CODE", promotionId: "123" }; @@ -86,7 +86,7 @@ test("throws error when coupon code already exists in promotion window", async ( test("should insert a new coupon and return the created results", async () => { const now = new Date(); - const input = { code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; + const input = { name: "test", code: "CODE", shopId: "123", promotionId: "123", canUseInStore: true }; const promotion = { _id: "123", endDate: now }; mockContext.collections = { @@ -112,6 +112,7 @@ test("should insert a new coupon and return the created results", async () => { coupon: { _id: "123", canUseInStore: true, + name: "test", code: "CODE", createdAt: jasmine.any(Date), expirationDate: now, diff --git a/packages/api-plugin-promotions-coupons/src/schemas/schema.graphql b/packages/api-plugin-promotions-coupons/src/schemas/schema.graphql index 75780164f0c..ea943c7c465 100644 --- a/packages/api-plugin-promotions-coupons/src/schemas/schema.graphql +++ b/packages/api-plugin-promotions-coupons/src/schemas/schema.graphql @@ -11,6 +11,9 @@ type Coupon { "The coupon owner ID" userId: ID + "The coupon name" + name: String! + "The coupon code" code: String! @@ -64,48 +67,8 @@ input CreateStandardCouponInput { "The promotion ID" promotionId: ID! - "The coupon code" - code: String! - - "Can use this coupon in the store" - canUseInStore: Boolean! - - "The number of times this coupon can be used per user" - maxUsageTimesPerUser: Int - - "The number of times this coupon can be used" - maxUsageTimes: Int -} - -input CouponQueryInput { - "The unique ID of the coupon" - _id: String! - - "The unique ID of the shop" - shopId: String! -} - -input CouponFilter { - "The expiration date of the coupon" - expirationDate: Date - - "The related promotion ID" - promotionId: ID - - "The coupon code" - code: String - "The coupon name" - userId: ID -} - -"The input for the createStandardCoupon mutation" -input CreateStandardCouponInput { - "The shop ID" - shopId: ID! - - "The promotion ID" - promotionId: ID! + name: String! "The coupon code" code: String! diff --git a/packages/api-plugin-promotions-coupons/src/simpleSchemas.js b/packages/api-plugin-promotions-coupons/src/simpleSchemas.js index 957c2000de1..e3a0b6c9deb 100644 --- a/packages/api-plugin-promotions-coupons/src/simpleSchemas.js +++ b/packages/api-plugin-promotions-coupons/src/simpleSchemas.js @@ -22,6 +22,7 @@ export const CouponTriggerParameters = new SimpleSchema({ export const Coupon = new SimpleSchema({ _id: String, + name: String, code: String, shopId: String, promotionId: String,