diff --git a/imports/plugins/core/discounts/server/no-meteor/startup.js b/imports/plugins/core/discounts/server/no-meteor/startup.js index 60708d5b944..f5a834c9bc6 100644 --- a/imports/plugins/core/discounts/server/no-meteor/startup.js +++ b/imports/plugins/core/discounts/server/no-meteor/startup.js @@ -1,3 +1,4 @@ +import Logger from "@reactioncommerce/logger"; import appEvents from "/imports/node-app/core/util/appEvents"; import getDiscountsTotalForCart from "/imports/plugins/core/discounts/server/no-meteor/util/getDiscountsTotalForCart"; @@ -14,6 +15,7 @@ export default function startup(context) { if (!cart) { throw new Error("afterCartUpdate hook run with no cart argument"); } + Logger.debug("Handling afterCartUpdate: discounts"); const cartId = cart._id; const { total: discount } = await getDiscountsTotalForCart(context, cartId); diff --git a/imports/plugins/core/shipping/server/no-meteor/startup.js b/imports/plugins/core/shipping/server/no-meteor/startup.js index f1fb967d581..1e895b9a39a 100644 --- a/imports/plugins/core/shipping/server/no-meteor/startup.js +++ b/imports/plugins/core/shipping/server/no-meteor/startup.js @@ -1,3 +1,4 @@ +import Logger from "@reactioncommerce/logger"; import Random from "@reactioncommerce/random"; import ReactionError from "@reactioncommerce/reaction-error"; @@ -28,6 +29,7 @@ export default function startup({ appEvents, collections }) { if (!updatedCart) { throw new Error("afterCartUpdate hook run with no cart argument"); } + Logger.debug("Handling afterCartUpdate: shipping"); // Every time the cart is updated, create any missing fulfillment groups as necessary. // We need one group per type per shop, containing only the items from that shop. diff --git a/imports/plugins/core/taxes/server/no-meteor/startup.js b/imports/plugins/core/taxes/server/no-meteor/startup.js index 32fa13c5fb0..badeac20d5f 100644 --- a/imports/plugins/core/taxes/server/no-meteor/startup.js +++ b/imports/plugins/core/taxes/server/no-meteor/startup.js @@ -1,4 +1,5 @@ import { isEqual } from "lodash"; +import Logger from "@reactioncommerce/logger"; import getUpdatedCartItems from "./util/getUpdatedCartItems"; const EMITTED_BY_NAME = "TAXES_CORE_PLUGIN"; @@ -18,6 +19,7 @@ export default function startup(context) { // have changed. appEvents.on("afterCartUpdate", async ({ cart }, { emittedBy } = {}) => { if (emittedBy === EMITTED_BY_NAME) return; // short circuit infinite loops + Logger.debug("Handling afterCartUpdate: taxes"); const { cartItems, taxSummary } = await getUpdatedCartItems(context, cart); diff --git a/imports/plugins/included/surcharges/server/no-meteor/startup.js b/imports/plugins/included/surcharges/server/no-meteor/startup.js index 36fb9fd1253..8271c75a4f6 100644 --- a/imports/plugins/included/surcharges/server/no-meteor/startup.js +++ b/imports/plugins/included/surcharges/server/no-meteor/startup.js @@ -1,3 +1,5 @@ +import { isEqual } from "lodash"; +import Logger from "@reactioncommerce/logger"; import xformCartGroupToCommonOrder from "/imports/plugins/core/cart/server/no-meteor/util/xformCartGroupToCommonOrder"; import collectionIndex from "/imports/utils/collectionIndex"; import getSurcharges from "./getSurcharges"; @@ -20,8 +22,9 @@ export default function startup(context) { // Update the cart to include surcharges, if applicable appEvents.on("afterCartUpdate", async ({ cart }, { emittedBy } = {}) => { if (emittedBy === EMITTED_BY_NAME) return; // short circuit infinite loops + Logger.debug("Handling afterCartUpdate: surcharges"); - const { shipping } = cart; + const { surcharges, shipping } = cart; const cartSurcharges = []; // Merge surcharges from each shipping group @@ -35,6 +38,13 @@ export default function startup(context) { }); } + // To avoid infinite looping among various `afterCartUpdate` handlers that also + // update cart and emit a subsequent `afterCartUpdate`, we need to be sure we + // do not do the update or emit the event unless we truly need to update something. + const previousSurcharges = (surcharges || []).map((appliedSurcharge) => ({ ...appliedSurcharge, _id: null })); + const nextSurcharges = cartSurcharges.map((appliedSurcharge) => ({ ...appliedSurcharge, _id: null })); + if (isEqual(previousSurcharges, nextSurcharges)) return; + const { value: updatedCart } = await Cart.findOneAndUpdate({ _id: cart._id }, { $set: { surcharges: cartSurcharges @@ -44,6 +54,6 @@ export default function startup(context) { returnOriginal: false }); - appEvents.emit("afterCartUpdate", { cart: updatedCart }, { emittedBy: EMITTED_BY_NAME }); + appEvents.emit("afterCartUpdate", { cart: updatedCart, updatedBy: null }, { emittedBy: EMITTED_BY_NAME }); }); }