-
Notifications
You must be signed in to change notification settings - Fork 2.2k
chore: clean-up tasks related to removing appEvents from all meteor code
#5692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a45b635
d12f1c3
fcb748f
72369f9
10d012d
32b96fd
6cb2014
fd24bcb
f6b1d0a
809b700
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| import SimpleSchema from "simpl-schema"; | ||
| import Random from "@reactioncommerce/random"; | ||
| import ReactionError from "@reactioncommerce/reaction-error"; | ||
| import getCart from "../util/getCart.js"; | ||
|
|
||
| const inputSchema = new SimpleSchema({ | ||
| cartId: String, | ||
| discountCode: String, | ||
| shopId: String, | ||
| token: { | ||
| type: String, | ||
| optional: true | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * @method applyDiscountCodeToCart | ||
| * @summary Applies a discount code to a cart | ||
| * @param {Object} context - an object containing the per-request state | ||
| * @param {Object} input - an object of all mutation arguments that were sent by the client | ||
| * @param {Object} input.cartId - Cart to add discount to | ||
| * @param {Object} input.discountCode - Discount code to add to cart | ||
| * @param {String} input.shopId - Shop cart belongs to | ||
| * @param {String} [input.token] - Cart token, if anonymous | ||
| * @returns {Promise<Object>} An object with the updated cart with the applied discount | ||
| */ | ||
| export default async function applyDiscountCodeToCart(context, input) { | ||
| inputSchema.validate(input); | ||
|
|
||
| const { cartId, discountCode, shopId, token } = input; | ||
| const { collections, userHasPermission, userId } = context; | ||
| const { Cart, Discounts } = collections; | ||
|
|
||
| let userCount = 0; | ||
| let orderCount = 0; | ||
| let cart = await getCart(context, shopId, cartId, { cartToken: token, throwIfNotFound: false }); | ||
|
|
||
| // If we didn't find a cart, it means it belongs to another user, | ||
| // not the currently logged in user. | ||
| // Check to make sure current user has admin permission. | ||
| if (!cart) { | ||
| cart = await Cart.findOne({ _id: cartId }); | ||
| if (!cart) { | ||
| throw new ReactionError("not-found", "Cart not found"); | ||
| } | ||
|
|
||
| if (!userHasPermission(["owner", "admin", "discounts/apply"], shopId)) { | ||
| throw new ReactionError("access-denied", "Access Denied"); | ||
| } | ||
| } | ||
|
|
||
| const objectToApplyDiscount = cart; | ||
|
|
||
| const discount = await Discounts.findOne({ code: discountCode }); | ||
| if (!discount) throw new ReactionError("not-found", `No discount found for code ${discountCode}`); | ||
|
|
||
| const { conditions } = discount; | ||
| let accountLimitExceeded = false; | ||
| let discountLimitExceeded = false; | ||
|
|
||
| // existing usage count | ||
| if (discount.transactions) { | ||
| const users = Array.from(discount.transactions, (trans) => trans.userId); | ||
| const transactionCount = new Map([...new Set(users)].map((userX) => [userX, users.filter((userY) => userY === userX).length])); | ||
| const orders = Array.from(discount.transactions, (trans) => trans.cartId); | ||
| userCount = transactionCount.get(userId); | ||
| orderCount = orders.length; | ||
| } | ||
| // check limits | ||
| if (conditions) { | ||
| if (conditions.accountLimit) accountLimitExceeded = conditions.accountLimit <= userCount; | ||
| if (conditions.redemptionLimit) discountLimitExceeded = conditions.redemptionLimit <= orderCount; | ||
| } | ||
|
|
||
| // validate basic limit handling | ||
| if (accountLimitExceeded === true || discountLimitExceeded === true) { | ||
| throw new ReactionError("error-occurred", "Code is expired"); | ||
| } | ||
|
|
||
| if (!cart.billing) { | ||
| cart.billing = []; | ||
| } | ||
|
|
||
| cart.billing.push({ | ||
| _id: Random.id(), | ||
| amount: discount.discount, | ||
| createdAt: new Date(), | ||
| currencyCode: objectToApplyDiscount.currencyCode, | ||
| data: { | ||
| discountId: discount._id, | ||
| code: discount.code | ||
| }, | ||
| displayName: `Discount Code: ${discount.code}`, | ||
| method: discount.calculation.method, | ||
| mode: "discount", | ||
| name: "discount_code", | ||
| paymentPluginName: "discount-codes", | ||
| processor: discount.discountMethod, | ||
| shopId: objectToApplyDiscount.shopId, | ||
| status: "created", | ||
| transactionId: Random.id() | ||
| }); | ||
|
|
||
| // Instead of directly updating cart, we add the discount billing | ||
| // object from the existing cart, then pass to `saveCart` | ||
| // to re-run cart through all transforms and validations. | ||
| const savedCart = await context.mutations.saveCart(context, cart); | ||
|
|
||
| return savedCart; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import applyDiscountCodeToCart from "./applyDiscountCodeToCart.js"; | ||
| import removeDiscountCodeFromCart from "./removeDiscountCodeFromCart.js"; | ||
|
|
||
| export default { | ||
| applyDiscountCodeToCart, | ||
| removeDiscountCodeFromCart | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import SimpleSchema from "simpl-schema"; | ||
| import ReactionError from "@reactioncommerce/reaction-error"; | ||
| import getCart from "../util/getCart.js"; | ||
|
|
||
| const inputSchema = new SimpleSchema({ | ||
| cartId: String, | ||
| discountId: String, | ||
| shopId: String, | ||
| token: { | ||
| type: String, | ||
| optional: true | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * @method removeDiscountCodeFromCart | ||
| * @summary Applies a discount code to a cart | ||
| * @param {Object} context - an object containing the per-request state | ||
| * @param {Object} input - an object of all mutation arguments that were sent by the client | ||
| * @param {Object} input.cartId - Cart to remove discount from | ||
| * @param {Object} input.discountId - Discount code to remove from cart | ||
| * @param {String} input.shopId - Shop cart belongs to | ||
| * @param {String} [input.token] - Cart token, if anonymous | ||
| * @returns {Promise<Object>} An object with the updated cart with the removed discount | ||
| */ | ||
| export default async function removeDiscountCodeFromCart(context, input) { | ||
| inputSchema.validate(input); | ||
|
|
||
| const { cartId, discountId, shopId, token } = input; | ||
| const { collections, userHasPermission } = context; | ||
| const { Cart } = collections; | ||
|
|
||
| let cart = await getCart(context, shopId, cartId, { cartToken: token, throwIfNotFound: false }); | ||
|
|
||
| // If we didn't find a cart, it means it belongs to another user, | ||
| // not the currently logged in user. | ||
| // Check to make sure current user has admin permission. | ||
| if (!cart) { | ||
| if (!userHasPermission(["owner", "admin", "discounts/apply"], shopId)) { | ||
| throw new ReactionError("access-denied", "Access Denied"); | ||
| } | ||
|
|
||
| cart = await Cart.findOne({ _id: cartId, shopId }); | ||
| if (!cart) { | ||
| throw new ReactionError("not-found", "Cart not found"); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you already have |
||
| } | ||
|
|
||
| // Instead of directly updating cart, we remove the discount billing | ||
| // object from the existing cart, then pass to `saveCart` | ||
| // to re-run cart through all transforms and validations. | ||
| const updatedCartBilling = cart.billing.filter((doc) => doc._id !== discountId); | ||
| if (cart.billing.length === updatedCartBilling.length) { | ||
| throw new ReactionError("not-found", "No applied discount found with that ID"); | ||
| } | ||
| cart.billing = updatedCartBilling; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could add a check for whether |
||
|
|
||
| const savedCart = await context.mutations.saveCart(context, cart); | ||
|
|
||
| return savedCart; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import { decodeCartOpaqueId } from "@reactioncommerce/reaction-graphql-xforms/cart"; | ||
| import { decodeShopOpaqueId } from "@reactioncommerce/reaction-graphql-xforms/shop"; | ||
|
|
||
| /** | ||
| * @name Mutation/applyDiscountCodeToCart | ||
| * @method | ||
| * @memberof Fulfillment/GraphQL | ||
| * @summary resolver for the applyDiscountCodeToCart GraphQL mutation | ||
| * @param {Object} parentResult - unused | ||
| * @param {Object} args.input - an object of all mutation arguments that were sent by the client | ||
| * @param {Object} args.input.cartId - Cart to add discount to | ||
| * @param {Object} args.input.discountCode - Discount code to add to cart | ||
| * @param {String} args.input.shopId - Shop cart belongs to | ||
| * @param {String} [args.input.token] - Cart token, if anonymous | ||
| * @param {String} [args.input.clientMutationId] - An optional string identifying the mutation call | ||
| * @param {Object} context - an object containing the per-request state | ||
| * @returns {Promise<Object>} applyDiscountCodeToCartPayload | ||
| */ | ||
| export default async function applyDiscountCodeToCart(parentResult, { input }, context) { | ||
| const { | ||
| clientMutationId = null, | ||
| cartId, | ||
| discountCode, | ||
| shopId, | ||
| token | ||
| } = input; | ||
|
|
||
| const updatedCartWithAppliedDiscountCode = await context.mutations.applyDiscountCodeToCart(context, { | ||
| cartId: decodeCartOpaqueId(cartId), | ||
| discountCode, | ||
| shopId: decodeShopOpaqueId(shopId), | ||
| token | ||
| }); | ||
|
|
||
| return { | ||
| clientMutationId, | ||
| cart: updatedCartWithAppliedDiscountCode | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import applyDiscountCodeToCart from "./applyDiscountCodeToCart.js"; | ||
| import removeDiscountCodeFromCart from "./removeDiscountCodeFromCart.js"; | ||
|
|
||
| export default { | ||
| applyDiscountCodeToCart, | ||
| removeDiscountCodeFromCart | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { decodeCartOpaqueId } from "@reactioncommerce/reaction-graphql-xforms/cart"; | ||
| import { decodeDiscountOpaqueId } from "@reactioncommerce/reaction-graphql-xforms/discount"; | ||
| import { decodeShopOpaqueId } from "@reactioncommerce/reaction-graphql-xforms/shop"; | ||
|
|
||
| /** | ||
| * @name Mutation/removeDiscountCodeFromCart | ||
| * @method | ||
| * @memberof Fulfillment/GraphQL | ||
| * @summary resolver for the removeDiscountCodeFromCart GraphQL mutation | ||
| * @param {Object} parentResult - unused | ||
| * @param {Object} args.input - an object of all mutation arguments that were sent by the client | ||
| * @param {Object} args.input.cartId - Cart to remove discount from | ||
| * @param {Object} args.input.discountId - Discount code Id to remove from cart | ||
| * @param {String} args.input.shopId - Shop cart belongs to | ||
| * @param {String} [args.input.token] - Cart token, if anonymous | ||
| * @param {String} [args.input.clientMutationId] - An optional string identifying the mutation call | ||
| * @param {Object} context - an object containing the per-request state | ||
| * @returns {Promise<Object>} removeDiscountCodeFromCartPayload | ||
| */ | ||
| export default async function removeDiscountCodeFromCart(parentResult, { input }, context) { | ||
| const { | ||
| clientMutationId = null, | ||
| cartId, | ||
| discountId, | ||
| shopId, | ||
| token | ||
| } = input; | ||
|
|
||
| const updatedCartWithRemovedDiscountCode = await context.mutations.removeDiscountCodeFromCart(context, { | ||
| cartId: decodeCartOpaqueId(cartId), | ||
| discountId: decodeDiscountOpaqueId(discountId), | ||
| shopId: decodeShopOpaqueId(shopId), | ||
| token | ||
| }); | ||
|
|
||
| return { | ||
| clientMutationId, | ||
| cart: updatedCartWithRemovedDiscountCode | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import Mutation from "./Mutation/index.js"; | ||
|
|
||
| export default { | ||
| Mutation | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import schema from "./schema.graphql"; | ||
|
|
||
| export default [schema]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| extend type Mutation { | ||
| "Apply a discount code to a cart" | ||
| applyDiscountCodeToCart( | ||
| "Mutation input" | ||
| input: ApplyDiscountCodeToCartInput! | ||
| ): ApplyDiscountCodeToCartPayload! | ||
|
|
||
| "Remove a discount code from a cart" | ||
| removeDiscountCodeFromCart( | ||
| "Mutation input" | ||
| input: RemoveDiscountCodeFromCartInput! | ||
| ): RemoveDiscountCodeFromCartPayload! | ||
| } | ||
|
|
||
| "Input for an `ApplyDiscountCodeToCartInput`" | ||
| input ApplyDiscountCodeToCartInput { | ||
| "Cart to add discount to" | ||
| cartId: ID! | ||
|
|
||
| "Discount code to add to cart" | ||
| discountCode: String! | ||
|
|
||
| "Shop cart belongs to" | ||
| shopId: ID! | ||
|
|
||
| "Cart token, if anonymous" | ||
| token: String | ||
| } | ||
|
|
||
| "Input for an `RemoveDiscountCodeFromCartInput`" | ||
| input RemoveDiscountCodeFromCartInput { | ||
| "Cart to add discount to" | ||
| cartId: ID! | ||
|
|
||
| "ID of the discount you want to remove from the cart" | ||
| discountId: ID! | ||
|
|
||
| "Shop cart belongs to" | ||
| shopId: ID! | ||
|
|
||
| "Cart token, if anonymous" | ||
| token: String | ||
| } | ||
|
|
||
| "Response from the `applyDiscountCodeToCart` mutation" | ||
| type ApplyDiscountCodeToCartPayload { | ||
| "The updated cart with discount code applied" | ||
| cart: Cart! | ||
|
|
||
| "The same string you sent with the mutation params, for matching mutation calls with their responses" | ||
| clientMutationId: String | ||
| } | ||
|
|
||
| "Response from the `removeDiscountCodeFromCart` mutation" | ||
| type RemoveDiscountCodeFromCartPayload { | ||
| "The updated cart with discount code removed" | ||
| cart: Cart! | ||
|
|
||
| "The same string you sent with the mutation params, for matching mutation calls with their responses" | ||
| clientMutationId: String | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
discountsis more for defining/editing discounts, I'd create a new rolediscounts/applyfor here.