From d7b40d04eeab75e91120b01907644b165c85daa9 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 07:51:20 +0800 Subject: [PATCH 01/44] When creating shipping records, create one for each shop --- server/methods/core/shipping.js | 97 +++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/server/methods/core/shipping.js b/server/methods/core/shipping.js index d8352454e39..bdfe8f4f7c3 100644 --- a/server/methods/core/shipping.js +++ b/server/methods/core/shipping.js @@ -4,6 +4,71 @@ import { Cart } from "/lib/collections"; import { Logger, Hooks } from "/server/api"; import { Cart as CartSchema } from "/lib/collections/schemas"; +function createShippingRecordByShop(cart, rates) { + const cartId = cart._id; + const itemsByShop = cart.getItemsByShop(); + const shops = Object.keys(itemsByShop); + const selector = { _id: cartId }; + shops.map((shopId) => { + const update = { + $push: { + shipping: { + shipmentQuotes: rates, + shopId: shopId + } + } + }; + return Cart.update(selector, update, (error) => { + if (error) { + Logger.warn(`Error adding rates to cart ${cartId}`, error); + return; + } + Logger.debug(`Success adding rates to cart ${cartId}`, rates); + }); + }); +} + +function updateShippingRecordByShop(cart, rates) { + const cartId = cart._id; + const itemsByShop = cart.getItemsByShop(); + const shops = Object.keys(itemsByShop); + let update; + let selector; + shops.map((shopId) => { + selector = { + "_id": cartId, + "shipping.shopId": shopId + }; + const shippingRecord = Cart.findOne(selector); + // we may have added a new shop since the last time we did this, if so we need to add a new record + + if (shippingRecord) { + update = { + $set: { + "shipping.$.shipmentQuotes": rates + } + }; + } else { + selector = { _id: cartId }; + update = { + $push: { + shipping: { + shipmentQuotes: rates, + shopId: shopId + } + } + }; + } + Cart.update(selector, update, function (error) { + if (error) { + Logger.warn(`Error updating rates for cart ${cartId}`, error); + return; + } + Logger.debug(`Success updating rates for cart ${cartId}`, rates); + }); + }); + +} /* * Reaction Shipping Methods * methods typically used for checkout (shipping, taxes, etc) @@ -27,39 +92,11 @@ export const methods = { if (cart) { const rates = Meteor.call("shipping/getShippingRates", cart); - let selector; - let update; - // temp hack until we build out multiple shipment handlers if we have an existing item update it, otherwise add to set. if (cart.shipping) { - selector = { - "_id": cartId, - "shipping._id": cart.shipping[0]._id - }; - update = { - $set: { - "shipping.$.shipmentQuotes": rates - } - }; + updateShippingRecordByShop(cart, rates) } else { - selector = { - _id: cartId - }; - update = { - $push: { - shipping: { - shipmentQuotes: rates - } - } - }; + createShippingRecordByShop(cart, rates); } - // add quotes to the cart - Cart.update(selector, update, function (error) { - if (error) { - Logger.warn(`Error adding rates to cart ${cartId}`, error); - return; - } - Logger.debug(`Success adding rates to cart ${cartId}`, rates); - }); } }, From 864e52d511359c68847dc42ac05252e23ad771ed Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 08:36:40 +0800 Subject: [PATCH 02/44] Return an empty object if cart has no items --- lib/collections/transform/cartOrder.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/collections/transform/cartOrder.js b/lib/collections/transform/cartOrder.js index c4e3b2b2011..2674be47d64 100644 --- a/lib/collections/transform/cartOrder.js +++ b/lib/collections/transform/cartOrder.js @@ -158,13 +158,17 @@ export const cartOrderTransform = { * @return {Object} Dict of shopIds with an array of items from that shop that are present in the cart/order */ getItemsByShop() { - return this.items.reduce((itemsByShop, item) => { - if (!itemsByShop[item.shopId]) { - itemsByShop[item.shopId] = [item]; - } else { - itemsByShop[item.shopId].push(item); - } - return itemsByShop; - }, {}); + if (this.items) { + return this.items.reduce((itemsByShop, item) => { + if (!itemsByShop[item.shopId]) { + itemsByShop[item.shopId] = [item]; + } else { + itemsByShop[item.shopId].push(item); + } + return itemsByShop; + }, {}); + } + return {}; + } }; From dc3f5ee4766144351ac7bbaacdac4e99085dc184 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 08:39:11 +0800 Subject: [PATCH 03/44] Fix grammatical errors in test description --- server/methods/accounts/accounts.app-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/methods/accounts/accounts.app-test.js b/server/methods/accounts/accounts.app-test.js index c484fd4a895..ba82a142553 100644 --- a/server/methods/accounts/accounts.app-test.js +++ b/server/methods/accounts/accounts.app-test.js @@ -161,8 +161,8 @@ describe("Account Meteor method ", function () { return done(); }); - it("should disabled isShipping/BillingDefault properties inside sibling" + - " address if we enable their while adding", + it("should disable isShipping/BillingDefault properties inside sibling" + + " address if we enable themwhile adding", function (done) { const account = Factory.create("account"); sandbox.stub(Meteor, "userId", function () { From e0dc83e2cdee969c1766552630ec7edb61cd2178 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 09:53:47 +0800 Subject: [PATCH 04/44] Update copyToCart to work with by shop shipping records --- server/methods/core/cart.js | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/server/methods/core/cart.js b/server/methods/core/cart.js index 148a7d29d6a..1870121835f 100644 --- a/server/methods/core/cart.js +++ b/server/methods/core/cart.js @@ -612,15 +612,22 @@ Meteor.methods({ delete order.getTotal; delete order._id; - // TODO: update this to handle multiple shipments instead of hardcoding to - // first element in `order.shipping` array + + // Create a shipping record for each shop on the order if (Array.isArray(order.shipping)) { if (order.shipping.length > 0) { - order.shipping[0].paymentId = order.billing[0]._id; - - if (!Array.isArray(order.shipping[0].items)) { - order.shipping[0].items = []; - } + const shippingRecords = []; + order.shipping.map((shippingRecord) => { + const billingRecord = order.billing.find(billing => billing.shopId === shippingRecord.shopId); + shippingRecord.paymentId = billingRecord._id; + shippingRecord.items = []; + shippingRecord.items.packed = false; + shippingRecord.items.shipped = false; + shippingRecord.items.delivered = false; + shippingRecord.workflow = { status: "new", workflow: ["coreOrderWorkflow/notStarted"] }; + shippingRecords.push(shippingRecord); + }); + order.shipping = shippingRecords; } } else { // if not - create it order.shipping = []; @@ -686,18 +693,6 @@ Meteor.methods({ } }); - // TODO: Set all shipping statuses to false. Consider eliminating in favor - // of order item workflow status. - // Set shipping statuses to false - order.shipping[0].items.packed = false; - order.shipping[0].items.shipped = false; - order.shipping[0].items.delivered = false; - - // begin a new shipping workflow for the order - order.shipping[0].workflow = { - status: "new", - workflow: ["coreOrderWorkflow/notStarted"] - }; order.billing[0].currency.exchangeRate = exchangeRate; order.workflow.status = "new"; order.workflow.workflow = ["coreOrderWorkflow/created"]; From e23ed7c20bc176c84f35bd87d691b74fbd05dd45 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 10:14:07 +0800 Subject: [PATCH 05/44] Add billing/shipping shopIds to fix stripe test --- server/imports/fixtures/cart.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/imports/fixtures/cart.js b/server/imports/fixtures/cart.js index 9251b74e774..3f963390968 100755 --- a/server/imports/fixtures/cart.js +++ b/server/imports/fixtures/cart.js @@ -155,12 +155,14 @@ export default function () { shipping: [ { _id: Random.id(), + shopId: getShop()._id, address: addressForOrder } ], billing: [ { _id: Random.id(), + shopId: getShop()._id, address: addressForOrder } ], From aa772eec4968bb01b96da87da1f4e95c1c59e1fa Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 10:31:44 +0800 Subject: [PATCH 06/44] Break copyCartToOrder to it's own file --- server/methods/core/cart.js | 202 --------------------------- server/methods/core/cartToOrder.js | 211 +++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 202 deletions(-) create mode 100644 server/methods/core/cartToOrder.js diff --git a/server/methods/core/cart.js b/server/methods/core/cart.js index 1870121835f..f3cc9f4e394 100644 --- a/server/methods/core/cart.js +++ b/server/methods/core/cart.js @@ -536,208 +536,6 @@ Meteor.methods({ return result; }); }, - - /** - * cart/copyCartToOrder - * @summary transform cart to order when a payment is processed we want to - * copy the cart over to an order object, and give the user a new empty - * cart. reusing the cart schema makes sense, but integrity of the order, we - * don't want to just make another cart item - * @todo: Partial order processing, shopId processing - * @todo: Review Security on this method - * @param {String} cartId - cartId to transform to order - * @return {String} returns orderId - */ - "cart/copyCartToOrder": function (cartId) { - check(cartId, String); - const cart = Collections.Cart.findOne(cartId); - - // security check - method can only be called on own cart - if (cart.userId !== Meteor.userId()) { - throw new Meteor.Error(403, "Access Denied"); - } - - // Init new order object from existing cart - const order = Object.assign({}, cart); - - // get sessionId from cart while cart is fresh - const sessionId = cart.sessionId; - - // If there are no order items, throw an error. We won't create an empty order - if (!order.items || order.items.length === 0) { - const msg = "An error occurred saving the order. Missing cart items."; - Logger.error(msg); - throw new Meteor.Error("no-cart-items", msg); - } - - // Debug only message to identify the current cartId - Logger.debug("cart/copyCartToOrder", cartId); - - // Set our new order's cartId to existing cart._id - // We'll get a new _id for our order - order.cartId = cart._id; - - // This block assigns an existing user's email associated with their account to this order - // We copied order from cart, so this userId and email are coming from the existing cart - if (order.userId && !order.email) { - // If we have a userId, but do _not_ have an email associated with this order - // we need to go find the account associated with this userId - const account = Collections.Accounts.findOne(order.userId); - - // Check to make sure that the account exists and has an emails field - if (typeof account === "object" && account.emails) { - for (const email of account.emails) { - // If a user has specified an alternate "order" email address, use that - if (email.provides === "orders") { - order.email = email.address; - // Otherwise, check to see if the user has a "default" email address - } else if (email.provides === "default") { - order.email = email.address; - } - // If we can't find any relevant email addresses for the user, we'll - // let them assign an email address to this order after the checkout - } - } - } - - // The schema will provide default values for these fields in our new order - // so we'll delete the values copied from the cart - delete order.createdAt; // autovalues from cart - delete order.updatedAt; - delete order.getCount; - delete order.getShippingTotal; - delete order.getSubTotal; - delete order.getTaxTotal; - delete order.getDiscounts; - delete order.getTotal; - delete order._id; - - - // Create a shipping record for each shop on the order - if (Array.isArray(order.shipping)) { - if (order.shipping.length > 0) { - const shippingRecords = []; - order.shipping.map((shippingRecord) => { - const billingRecord = order.billing.find(billing => billing.shopId === shippingRecord.shopId); - shippingRecord.paymentId = billingRecord._id; - shippingRecord.items = []; - shippingRecord.items.packed = false; - shippingRecord.items.shipped = false; - shippingRecord.items.delivered = false; - shippingRecord.workflow = { status: "new", workflow: ["coreOrderWorkflow/notStarted"] }; - shippingRecords.push(shippingRecord); - }); - order.shipping = shippingRecords; - } - } else { // if not - create it - order.shipping = []; - } - - // Add current exchange rate into order.billing.currency - // If user currency === shop currency, exchange rate = 1.0 - const currentUser = Meteor.user(); - let userCurrency = Reaction.getShopCurrency(); - let exchangeRate = "1.00"; - - if (currentUser && currentUser.profile && currentUser.profile.currency) { - userCurrency = Meteor.user().profile.currency; - } - - if (userCurrency !== Reaction.getShopCurrency()) { - const userExchangeRate = Meteor.call("shop/getCurrencyRates", userCurrency); - - if (typeof userExchangeRate === "number") { - exchangeRate = userExchangeRate; - } else { - Logger.warn("Failed to get currency exchange rates. Setting exchange rate to null."); - exchangeRate = null; - } - } - - if (!order.billing[0].currency) { - order.billing[0].currency = { - // userCurrency is shopCurrency unless user has selected a different currency than the shop - userCurrency: userCurrency - }; - } - - order.items = order.items.map(item => { - item.shippingMethod = order.shipping[order.shipping.length - 1]; - item.workflow = { - status: "new", - workflow: ["coreOrderWorkflow/created"] - }; - - return item; - }); - - // TODO: update this to assign each item to the correct shipment based on - // which fulfillment provider is serving that item. - _.each(order.items, (item) => { - // TODO: Loop through items based on fulfillment provider / payment / shopID - // TODO: Set each order item workflow to new - // TODO: Set each order item workflow workflow to "created" - // TODO: Assign correct shipment to order item - // TODO: Assign correct payment to order item (perhaps in a different part of code) - - // If the shipment exists - if (order.shipping[0].items) { - // Assign each item in the order to the correct shipment - // TODO: We should also be assigning the correct shipment to each order item here - order.shipping[0].items.push({ - _id: item._id, - productId: item.productId, - shopId: item.shopId, - variantId: item.variants._id - }); - } - }); - - order.billing[0].currency.exchangeRate = exchangeRate; - order.workflow.status = "new"; - order.workflow.workflow = ["coreOrderWorkflow/created"]; - - // insert new reaction order - const orderId = Collections.Orders.insert(order); - - if (orderId) { - Collections.Cart.remove({ - _id: order.cartId - }); - // create a new cart for the user - // even though this should be caught by - // subscription handler, it's not always working - const newCartExists = Collections.Cart.find({ userId: order.userId }); - if (newCartExists.count() === 0) { - Meteor.call("cart/createCart", this.userId, sessionId); - // after recreate new cart we need to make it looks like previous by - // updating `cart/workflow/status` to "coreCheckoutShipping" - // by calling `workflow/pushCartWorkflow` three times. This is the only - // way to do that without refactoring of `workflow/pushCartWorkflow` - Meteor.call("workflow/pushCartWorkflow", "coreCartWorkflow", "checkoutLogin"); - Meteor.call("workflow/pushCartWorkflow", "coreCartWorkflow", "checkoutAddressBook"); - Meteor.call("workflow/pushCartWorkflow", "coreCartWorkflow", "coreCheckoutShipping"); - } - - Logger.info("Transitioned cart " + cartId + " to order " + orderId); - // catch send notification, we don't want - // to block because of notification errors - - if (order.email) { - Meteor.call("orders/sendNotification", Collections.Orders.findOne(orderId), (err) => { - if (err) { - Logger.error(err, `Error in orders/sendNotification for order ${orderId}`); - } - }); - } - - // order success - return orderId; - } - // we should not have made it here, throw error - throw new Meteor.Error(400, "cart/copyCartToOrder: Invalid request"); - }, - /** * cart/setShipmentMethod * @summary saves method as order default diff --git a/server/methods/core/cartToOrder.js b/server/methods/core/cartToOrder.js new file mode 100644 index 00000000000..d2d5fbf8562 --- /dev/null +++ b/server/methods/core/cartToOrder.js @@ -0,0 +1,211 @@ +import _ from "lodash"; +import { Meteor } from "meteor/meteor"; +import { check } from "meteor/check"; +import * as Collections from "/lib/collections"; +import { Logger, Reaction } from "/server/api"; + + +/** + * cart/copyCartToOrder + * @summary transform cart to order when a payment is processed we want to + * copy the cart over to an order object, and give the user a new empty + * cart. reusing the cart schema makes sense, but integrity of the order, we + * don't want to just make another cart item + * @todo: Partial order processing, shopId processing + * @todo: Review Security on this method + * @param {String} cartId - cartId to transform to order + * @return {String} returns orderId + */ +export function copyCartToOrder(cartId) { + check(cartId, String); + const cart = Collections.Cart.findOne(cartId); + + // security check - method can only be called on own cart + if (cart.userId !== Meteor.userId()) { + throw new Meteor.Error(403, "Access Denied"); + } + + // Init new order object from existing cart + const order = Object.assign({}, cart); + + // get sessionId from cart while cart is fresh + const sessionId = cart.sessionId; + + // If there are no order items, throw an error. We won't create an empty order + if (!order.items || order.items.length === 0) { + const msg = "An error occurred saving the order. Missing cart items."; + Logger.error(msg); + throw new Meteor.Error("no-cart-items", msg); + } + + // Debug only message to identify the current cartId + Logger.debug("cart/copyCartToOrder", cartId); + + // Set our new order's cartId to existing cart._id + // We'll get a new _id for our order + order.cartId = cart._id; + + // This block assigns an existing user's email associated with their account to this order + // We copied order from cart, so this userId and email are coming from the existing cart + if (order.userId && !order.email) { + // If we have a userId, but do _not_ have an email associated with this order + // we need to go find the account associated with this userId + const account = Collections.Accounts.findOne(order.userId); + + // Check to make sure that the account exists and has an emails field + if (typeof account === "object" && account.emails) { + for (const email of account.emails) { + // If a user has specified an alternate "order" email address, use that + if (email.provides === "orders") { + order.email = email.address; + // Otherwise, check to see if the user has a "default" email address + } else if (email.provides === "default") { + order.email = email.address; + } + // If we can't find any relevant email addresses for the user, we'll + // let them assign an email address to this order after the checkout + } + } + } + + // The schema will provide default values for these fields in our new order + // so we'll delete the values copied from the cart + delete order.createdAt; // autovalues from cart + delete order.updatedAt; + delete order.getCount; + delete order.getShippingTotal; + delete order.getSubTotal; + delete order.getTaxTotal; + delete order.getDiscounts; + delete order.getTotal; + delete order._id; + + + // Create a shipping record for each shop on the order + if (Array.isArray(order.shipping)) { + if (order.shipping.length > 0) { + const shippingRecords = []; + order.shipping.map((shippingRecord) => { + const billingRecord = order.billing.find(billing => billing.shopId === shippingRecord.shopId); + shippingRecord.paymentId = billingRecord._id; + shippingRecord.items = []; + shippingRecord.items.packed = false; + shippingRecord.items.shipped = false; + shippingRecord.items.delivered = false; + shippingRecord.workflow = { status: "new", workflow: ["coreOrderWorkflow/notStarted"] }; + shippingRecords.push(shippingRecord); + }); + order.shipping = shippingRecords; + } + } else { // if not - create it + order.shipping = []; + } + + // Add current exchange rate into order.billing.currency + // If user currency === shop currency, exchange rate = 1.0 + const currentUser = Meteor.user(); + let userCurrency = Reaction.getShopCurrency(); + let exchangeRate = "1.00"; + + if (currentUser && currentUser.profile && currentUser.profile.currency) { + userCurrency = Meteor.user().profile.currency; + } + + if (userCurrency !== Reaction.getShopCurrency()) { + const userExchangeRate = Meteor.call("shop/getCurrencyRates", userCurrency); + + if (typeof userExchangeRate === "number") { + exchangeRate = userExchangeRate; + } else { + Logger.warn("Failed to get currency exchange rates. Setting exchange rate to null."); + exchangeRate = null; + } + } + + if (!order.billing[0].currency) { + order.billing[0].currency = { + // userCurrency is shopCurrency unless user has selected a different currency than the shop + userCurrency: userCurrency + }; + } + + order.items = order.items.map(item => { + item.shippingMethod = order.shipping[order.shipping.length - 1]; + item.workflow = { + status: "new", + workflow: ["coreOrderWorkflow/created"] + }; + + return item; + }); + + // TODO: update this to assign each item to the correct shipment based on + // which fulfillment provider is serving that item. + _.each(order.items, (item) => { + // TODO: Loop through items based on fulfillment provider / payment / shopID + // TODO: Set each order item workflow to new + // TODO: Set each order item workflow workflow to "created" + // TODO: Assign correct shipment to order item + // TODO: Assign correct payment to order item (perhaps in a different part of code) + + // If the shipment exists + if (order.shipping[0].items) { + // Assign each item in the order to the correct shipment + // TODO: We should also be assigning the correct shipment to each order item here + order.shipping[0].items.push({ + _id: item._id, + productId: item.productId, + shopId: item.shopId, + variantId: item.variants._id + }); + } + }); + + order.billing[0].currency.exchangeRate = exchangeRate; + order.workflow.status = "new"; + order.workflow.workflow = ["coreOrderWorkflow/created"]; + + // insert new reaction order + const orderId = Collections.Orders.insert(order); + + if (orderId) { + Collections.Cart.remove({ + _id: order.cartId + }); + // create a new cart for the user + // even though this should be caught by + // subscription handler, it's not always working + const newCartExists = Collections.Cart.find({ userId: order.userId }); + if (newCartExists.count() === 0) { + Meteor.call("cart/createCart", this.userId, sessionId); + // after recreate new cart we need to make it looks like previous by + // updating `cart/workflow/status` to "coreCheckoutShipping" + // by calling `workflow/pushCartWorkflow` three times. This is the only + // way to do that without refactoring of `workflow/pushCartWorkflow` + Meteor.call("workflow/pushCartWorkflow", "coreCartWorkflow", "checkoutLogin"); + Meteor.call("workflow/pushCartWorkflow", "coreCartWorkflow", "checkoutAddressBook"); + Meteor.call("workflow/pushCartWorkflow", "coreCartWorkflow", "coreCheckoutShipping"); + } + + Logger.info("Transitioned cart " + cartId + " to order " + orderId); + // catch send notification, we don't want + // to block because of notification errors + + if (order.email) { + Meteor.call("orders/sendNotification", Collections.Orders.findOne(orderId), (err) => { + if (err) { + Logger.error(err, `Error in orders/sendNotification for order ${orderId}`); + } + }); + } + + // order success + return orderId; + } + // we should not have made it here, throw error + throw new Meteor.Error(400, "cart/copyCartToOrder: Invalid request"); +} + +Meteor.methods({ + "cart/copyCartToOrder": copyCartToOrder +}); From fa45c4f312b4d09e809ba7c440404f2623ebea7c Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 11:35:36 +0800 Subject: [PATCH 07/44] Add shopId to schema --- lib/collections/schemas/shipping.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/collections/schemas/shipping.js b/lib/collections/schemas/shipping.js index 1875a113f4b..bf3478fe303 100644 --- a/lib/collections/schemas/shipping.js +++ b/lib/collections/schemas/shipping.js @@ -236,6 +236,9 @@ export const Shipment = new SimpleSchema({ label: "Shipment Id", autoValue: schemaIdAutoValue }, + shopId: { + type: String + }, paymentId: { type: String, label: "Payment Id", From bf9e50dbd779e82f00aaaa6440a0334cd77fba7a Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 13:12:35 +0800 Subject: [PATCH 08/44] Set selected method on all shipping records --- server/methods/core/cart.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/server/methods/core/cart.js b/server/methods/core/cart.js index f3cc9f4e394..8f56891f937 100644 --- a/server/methods/core/cart.js +++ b/server/methods/core/cart.js @@ -557,19 +557,24 @@ Meteor.methods({ "Cart not found for user with such id"); } - // temp hack until we build out multiple shipping handlers + // Sets all shipping methods to the one selected + // TODO: Accept an object of shopId to method map to ship via different methods per shop let selector; let update; - // temp hack until we build out multiple shipment handlers // if we have an existing item update it, otherwise add to set. if (cart.shipping) { + const updatedShipping = []; + cart.shipping.map((shipRecord) => { + shipRecord.shipmentMethod = method; + updatedShipping.push(shipRecord); + }); + selector = { - "_id": cartId, - "shipping._id": cart.shipping[0]._id + _id: cartId }; update = { $set: { - "shipping.$.shipmentMethod": method + shipping: updatedShipping } }; } else { @@ -579,7 +584,8 @@ Meteor.methods({ update = { $addToSet: { shipping: { - shipmentMethod: method + shipmentMethod: method, + shopId: cart.shopId } } }; From 42d63411800a892bf02728fc848ff3615d6e3ab5 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 14:31:04 +0800 Subject: [PATCH 09/44] Only show shipping methods associate with the primary shop --- .../core/shipping/client/templates/checkout/shipping.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imports/plugins/core/shipping/client/templates/checkout/shipping.js b/imports/plugins/core/shipping/client/templates/checkout/shipping.js index 0609e60cee4..5ad094637ba 100644 --- a/imports/plugins/core/shipping/client/templates/checkout/shipping.js +++ b/imports/plugins/core/shipping/client/templates/checkout/shipping.js @@ -29,16 +29,17 @@ function cartShippingQuotes(currentCart) { function cartShipmentMethods(currentCart) { const cart = currentCart || Cart.findOne(); const shipmentMethods = []; - + const primaryShopId = Reaction.getPrimaryShopId(); if (cart) { if (cart.shipping) { for (const shipping of cart.shipping) { - if (shipping.shipmentMethod) { + if (shipping.shipmentMethod && shipping.shopId === primaryShopId) { shipmentMethods.push(shipping.shipmentMethod); } } } } + console.log("shipmentMethod", shipmentMethods); return shipmentMethods; } From a9433c46ee792f022cf734e18e8189652b4513d5 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 14:31:28 +0800 Subject: [PATCH 10/44] Check rates against schema --- server/methods/core/shipping.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/methods/core/shipping.js b/server/methods/core/shipping.js index bdfe8f4f7c3..f6f90aa08ca 100644 --- a/server/methods/core/shipping.js +++ b/server/methods/core/shipping.js @@ -2,9 +2,10 @@ import { Meteor } from "meteor/meteor"; import { check } from "meteor/check"; import { Cart } from "/lib/collections"; import { Logger, Hooks } from "/server/api"; -import { Cart as CartSchema } from "/lib/collections/schemas"; +import { Cart as CartSchema, ShippingMethod as ShippingMethodSchema } from "/lib/collections/schemas"; function createShippingRecordByShop(cart, rates) { + check(rates, ShippingMethodSchema); const cartId = cart._id; const itemsByShop = cart.getItemsByShop(); const shops = Object.keys(itemsByShop); @@ -20,7 +21,7 @@ function createShippingRecordByShop(cart, rates) { }; return Cart.update(selector, update, (error) => { if (error) { - Logger.warn(`Error adding rates to cart ${cartId}`, error); + Logger.warn(`Error adding rates to cart from createShippingRecordByShop ${cartId}`); return; } Logger.debug(`Success adding rates to cart ${cartId}`, rates); @@ -29,6 +30,7 @@ function createShippingRecordByShop(cart, rates) { } function updateShippingRecordByShop(cart, rates) { + check(rates, ShippingMethodSchema); const cartId = cart._id; const itemsByShop = cart.getItemsByShop(); const shops = Object.keys(itemsByShop); From cd701b1327a8f2f22f2aa08c3a5fd8ae9ec97c7d Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 14:31:56 +0800 Subject: [PATCH 11/44] Remove blackbox from Cart.shipping so it will actually validate --- lib/collections/schemas/cart.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/collections/schemas/cart.js b/lib/collections/schemas/cart.js index dcb08a080fb..22d3036f0a9 100644 --- a/lib/collections/schemas/cart.js +++ b/lib/collections/schemas/cart.js @@ -135,8 +135,7 @@ export const Cart = new SimpleSchema({ }, shipping: { type: [Shipment], - optional: true, - blackbox: true + optional: true }, billing: { type: [Payment], From 5ba6521c94f07e076e372a05aaeef8fc278527e6 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Fri, 1 Sep 2017 14:34:05 +0800 Subject: [PATCH 12/44] Validate shipping methods --- server/methods/core/cart.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/methods/core/cart.js b/server/methods/core/cart.js index 8f56891f937..3cc2734de0f 100644 --- a/server/methods/core/cart.js +++ b/server/methods/core/cart.js @@ -4,6 +4,7 @@ import { check, Match } from "meteor/check"; import { Roles } from "meteor/alanning:roles"; import { Random } from "meteor/random"; import * as Collections from "/lib/collections"; +import { ShippingMethod } from "/lib/collections/schemas"; import { Logger, Reaction } from "/server/api"; /** @@ -545,7 +546,7 @@ Meteor.methods({ */ "cart/setShipmentMethod": function (cartId, method) { check(cartId, String); - check(method, Object); + check(method, ShippingMethod); // get current cart const cart = Collections.Cart.findOne({ _id: cartId, From 37f6a7ce3b3110cde16b579c901e34f7fbddf085 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Tue, 5 Sep 2017 10:49:05 +0800 Subject: [PATCH 13/44] Put blackbox back --- lib/collections/schemas/cart.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/collections/schemas/cart.js b/lib/collections/schemas/cart.js index 22d3036f0a9..dcb08a080fb 100644 --- a/lib/collections/schemas/cart.js +++ b/lib/collections/schemas/cart.js @@ -135,7 +135,8 @@ export const Cart = new SimpleSchema({ }, shipping: { type: [Shipment], - optional: true + optional: true, + blackbox: true }, billing: { type: [Payment], From baab68c93ff0d750446e4ca0e3c0abebf0e53806 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Tue, 5 Sep 2017 12:59:58 +0800 Subject: [PATCH 14/44] simple-schema not working, remove --- .../core/shipping/client/templates/checkout/shipping.js | 1 - server/methods/core/shipping.js | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/imports/plugins/core/shipping/client/templates/checkout/shipping.js b/imports/plugins/core/shipping/client/templates/checkout/shipping.js index 5ad094637ba..6ee6c053829 100644 --- a/imports/plugins/core/shipping/client/templates/checkout/shipping.js +++ b/imports/plugins/core/shipping/client/templates/checkout/shipping.js @@ -39,7 +39,6 @@ function cartShipmentMethods(currentCart) { } } } - console.log("shipmentMethod", shipmentMethods); return shipmentMethods; } diff --git a/server/methods/core/shipping.js b/server/methods/core/shipping.js index f6f90aa08ca..d709d6e425b 100644 --- a/server/methods/core/shipping.js +++ b/server/methods/core/shipping.js @@ -2,10 +2,9 @@ import { Meteor } from "meteor/meteor"; import { check } from "meteor/check"; import { Cart } from "/lib/collections"; import { Logger, Hooks } from "/server/api"; -import { Cart as CartSchema, ShippingMethod as ShippingMethodSchema } from "/lib/collections/schemas"; +import { Cart as CartSchema } from "/lib/collections/schemas"; function createShippingRecordByShop(cart, rates) { - check(rates, ShippingMethodSchema); const cartId = cart._id; const itemsByShop = cart.getItemsByShop(); const shops = Object.keys(itemsByShop); @@ -21,7 +20,7 @@ function createShippingRecordByShop(cart, rates) { }; return Cart.update(selector, update, (error) => { if (error) { - Logger.warn(`Error adding rates to cart from createShippingRecordByShop ${cartId}`); + Logger.error(`Error adding rates to cart from createShippingRecordByShop ${cartId}`, error); return; } Logger.debug(`Success adding rates to cart ${cartId}`, rates); @@ -30,7 +29,6 @@ function createShippingRecordByShop(cart, rates) { } function updateShippingRecordByShop(cart, rates) { - check(rates, ShippingMethodSchema); const cartId = cart._id; const itemsByShop = cart.getItemsByShop(); const shops = Object.keys(itemsByShop); @@ -95,7 +93,7 @@ export const methods = { if (cart) { const rates = Meteor.call("shipping/getShippingRates", cart); if (cart.shipping) { - updateShippingRecordByShop(cart, rates) + updateShippingRecordByShop(cart, rates); } else { createShippingRecordByShop(cart, rates); } From 8916529bdf817764d4b7e9903826e29002818e75 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Tue, 5 Sep 2017 13:20:27 +0800 Subject: [PATCH 15/44] only show shipping methods from primaryShopId --- .../core/shipping/client/templates/checkout/shipping.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imports/plugins/core/shipping/client/templates/checkout/shipping.js b/imports/plugins/core/shipping/client/templates/checkout/shipping.js index 6ee6c053829..b0187bee130 100644 --- a/imports/plugins/core/shipping/client/templates/checkout/shipping.js +++ b/imports/plugins/core/shipping/client/templates/checkout/shipping.js @@ -9,13 +9,15 @@ import { Cart } from "/lib/collections"; function cartShippingQuotes(currentCart) { const cart = currentCart || Cart.findOne(); const shipmentQuotes = []; - + const primaryShopId = Reaction.getPrimaryShopId(); if (cart) { if (cart.shipping) { for (const shipping of cart.shipping) { if (shipping.shipmentQuotes) { for (const quote of shipping.shipmentQuotes) { - shipmentQuotes.push(quote); + if (shipping.shopId === primaryShopId) { + shipmentQuotes.push(quote); + } } } } From d3d1da98a9182a29f7c7d1496e31e0abf42c1bdc Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Tue, 5 Sep 2017 13:24:48 +0800 Subject: [PATCH 16/44] Lint fixes --- imports/plugins/core/ui/client/components/menu/dropDownMenu.js | 1 + lib/collections/transform/cartOrder.js | 1 - server/methods/accounts/accounts.app-test.js | 2 +- server/methods/core/shipping.js | 1 - 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/imports/plugins/core/ui/client/components/menu/dropDownMenu.js b/imports/plugins/core/ui/client/components/menu/dropDownMenu.js index 0c56a6abcd5..04c8ea81d0a 100644 --- a/imports/plugins/core/ui/client/components/menu/dropDownMenu.js +++ b/imports/plugins/core/ui/client/components/menu/dropDownMenu.js @@ -118,6 +118,7 @@ DropDownMenu.propTypes = { closeOnClick: PropTypes.bool, isEnabled: PropTypes.bool, isOpen: PropTypes.bool, + menuClassName: PropTypes.string, menuStyle: PropTypes.object, onChange: PropTypes.func, onPublishClick: PropTypes.func, diff --git a/lib/collections/transform/cartOrder.js b/lib/collections/transform/cartOrder.js index 2674be47d64..cdd2c61fe0a 100644 --- a/lib/collections/transform/cartOrder.js +++ b/lib/collections/transform/cartOrder.js @@ -169,6 +169,5 @@ export const cartOrderTransform = { }, {}); } return {}; - } }; diff --git a/server/methods/accounts/accounts.app-test.js b/server/methods/accounts/accounts.app-test.js index ba82a142553..8de46d2905b 100644 --- a/server/methods/accounts/accounts.app-test.js +++ b/server/methods/accounts/accounts.app-test.js @@ -162,7 +162,7 @@ describe("Account Meteor method ", function () { }); it("should disable isShipping/BillingDefault properties inside sibling" + - " address if we enable themwhile adding", + " address if we enable them while adding", function (done) { const account = Factory.create("account"); sandbox.stub(Meteor, "userId", function () { diff --git a/server/methods/core/shipping.js b/server/methods/core/shipping.js index d709d6e425b..db73ce01140 100644 --- a/server/methods/core/shipping.js +++ b/server/methods/core/shipping.js @@ -67,7 +67,6 @@ function updateShippingRecordByShop(cart, rates) { Logger.debug(`Success updating rates for cart ${cartId}`, rates); }); }); - } /* * Reaction Shipping Methods From b24c32a5a64579535547f7ffc1e5af3139420563 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Thu, 7 Sep 2017 13:31:18 +0800 Subject: [PATCH 17/44] Assign items to shipping records based on shopId --- server/methods/core/cartToOrder.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/server/methods/core/cartToOrder.js b/server/methods/core/cartToOrder.js index d2d5fbf8562..23f81287ea0 100644 --- a/server/methods/core/cartToOrder.js +++ b/server/methods/core/cartToOrder.js @@ -139,25 +139,26 @@ export function copyCartToOrder(cartId) { return item; }); - // TODO: update this to assign each item to the correct shipment based on - // which fulfillment provider is serving that item. + // Assign items to each shipping record based on the shopId of the item _.each(order.items, (item) => { - // TODO: Loop through items based on fulfillment provider / payment / shopID - // TODO: Set each order item workflow to new - // TODO: Set each order item workflow workflow to "created" - // TODO: Assign correct shipment to order item - // TODO: Assign correct payment to order item (perhaps in a different part of code) - + const shippingRecord = order.shipping.find((sRecord) => sRecord.shopId === item.shopId); // If the shipment exists - if (order.shipping[0].items) { - // Assign each item in the order to the correct shipment - // TODO: We should also be assigning the correct shipment to each order item here - order.shipping[0].items.push({ + if (shippingRecord.items) { + shippingRecord.items.push({ _id: item._id, productId: item.productId, shopId: item.shopId, variantId: item.variants._id }); + } else { + shippingRecord.items = [ + { + _id: item._id, + productId: item.productId, + shopId: item.shopId, + variantId: item.variants._id + } + ]; } }); From 278ee70af5365e2c159bac10f0722064dfaf9ad4 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Thu, 7 Sep 2017 14:23:34 +0800 Subject: [PATCH 18/44] Assign shopIds when adding shipping address --- server/methods/core/cart.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/methods/core/cart.js b/server/methods/core/cart.js index 3cc2734de0f..57d68bf8646 100644 --- a/server/methods/core/cart.js +++ b/server/methods/core/cart.js @@ -711,6 +711,7 @@ Meteor.methods({ let selector; let update; + const primaryShopId = Reaction.getPrimaryShopId(); // temp hack until we build out multiple shipment handlers // if we have an existing item update it, otherwise add to set. if (Array.isArray(cart.shipping) && cart.shipping.length > 0) { @@ -720,7 +721,8 @@ Meteor.methods({ }; update = { $set: { - "shipping.$.address": address + "shipping.$.address": address, + "shopId": primaryShopId } }; } else { @@ -730,7 +732,8 @@ Meteor.methods({ update = { $addToSet: { shipping: { - address: address + address: address, + shopId: primaryShopId } } }; From b245a4ded301df2d37073f0cd3192487fe4d83d7 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Thu, 7 Sep 2017 14:38:51 +0800 Subject: [PATCH 19/44] Only show the address when it has data --- .../client/components/completedOrder.js | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/imports/plugins/core/checkout/client/components/completedOrder.js b/imports/plugins/core/checkout/client/components/completedOrder.js index 5578ed93976..e5f587f1099 100644 --- a/imports/plugins/core/checkout/client/components/completedOrder.js +++ b/imports/plugins/core/checkout/client/components/completedOrder.js @@ -63,15 +63,18 @@ const CompletedOrder = ({ order, orderId, shops, orderSummary, paymentMethods, h {orderSummary.shipping.map((shipment) => { - return
-
-

- {shipment.address.fullName}
- {shipment.address.address1}
- {shipment.address.city}, {shipment.address.region} {shipment.address.postal} {shipment.address.country} -

-
-
; + if (shipment.address.fullName || shipment.address.address1) { + return
+
+

+ {shipment.address.fullName}
+ {shipment.address.address1}
+ {shipment.address.city}, {shipment.address.region} {shipment.address.postal} {shipment.address.country} +

+
+
; + } + })}
From 48b81fe2f0ebe477da906bbcc8157670c5911463 Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Thu, 7 Sep 2017 14:44:28 +0800 Subject: [PATCH 20/44] Lint fix --- .../plugins/core/checkout/client/components/completedOrder.js | 1 - 1 file changed, 1 deletion(-) diff --git a/imports/plugins/core/checkout/client/components/completedOrder.js b/imports/plugins/core/checkout/client/components/completedOrder.js index e5f587f1099..421f45c10ad 100644 --- a/imports/plugins/core/checkout/client/components/completedOrder.js +++ b/imports/plugins/core/checkout/client/components/completedOrder.js @@ -74,7 +74,6 @@ const CompletedOrder = ({ order, orderId, shops, orderSummary, paymentMethods, h
; } - })}
From 553d893c7800f9f3590ba71df961fe3dc50d67dd Mon Sep 17 00:00:00 2001 From: Brent Hoover Date: Thu, 7 Sep 2017 15:14:46 +0800 Subject: [PATCH 21/44] FIx tests --- server/imports/fixtures/cart.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/imports/fixtures/cart.js b/server/imports/fixtures/cart.js index 3f963390968..d5fd6f59163 100755 --- a/server/imports/fixtures/cart.js +++ b/server/imports/fixtures/cart.js @@ -68,12 +68,14 @@ export function createCart(productId, variantId) { shipping: [ { _id: Random.id(), + shopId: getShop()._id, address: getAddress() } ], billing: [ { _id: Random.id(), + shopId: getShop()._id, address: getAddress() } ], From f33da7d4cebbb67a80fb70792fd6d14e1a1c99cc Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Fri, 8 Sep 2017 02:34:20 +0300 Subject: [PATCH 22/44] Remove hardcoded shipping object --- .../containers/orderDashboardContainer.js | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index 7562e89b643..6d6cac29ead 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -272,6 +272,17 @@ class OrderDashboardContainer extends Component { return false; } + /** + * getShipppingObject + * + * @summary get proper shipping obect as per current active shop + * @param {Object} order - order object to check against + * @return {Object} shipping object to use + */ + getShipppingObject = (order) => { + return order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + } + /** * shippingStatusUpdateCall * @@ -304,7 +315,9 @@ class OrderDashboardContainer extends Component { // TODO: rethink this type of flow for updating shipping statuses selectedOrders.forEach((order) => { - Meteor.call(`orders/shipment${capitalizeStatus}`, order, order.shipping[0], (err) => { + const shippingRecord = this.getShipppingObject(order); + + Meteor.call(`orders/shipment${capitalizeStatus}`, order, shippingRecord, (err) => { if (err) { Alerts.toast(`An error occured while setting the status: ${err}`, "error"); } else { @@ -445,11 +458,11 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - // TODO: remove these hard-coded zero indexes to enable multiple shipments in marketplace - const orderWorkflow = order.shipping[0].workflow; + const orderWorkflow = this.getShipppingObject(order).workflow; // check if the order(s) are in this state already or in the previous state - // TODO: model this with the assumption that there may be different workflows depending on the type of shop or product that a shop is selling. + // TODO: model this with the assumption that there may be different workflows + // depending on the type of shop or product that a shop is selling. if (orderWorkflow.status === "new") { isNotPicked++; } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { @@ -496,11 +509,12 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - // TODO: remove these hard-coded zero indexes to enable multiple shipments in marketplace - const orderWorkflow = order.shipping[0].workflow; + const orderWorkflow = this.getShipppingObject(order).workflow; + // check if the order(s) are in this state already or in one of the previous states - // TODO: model this with the assumption that there may be different workflows depending on the type of shop or product that a shop is selling. + // TODO: model this with the assumption that there may be different workflows + // depending on the type of shop or product that a shop is selling. if (orderWorkflow.status === "new") { isNotPicked++; } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { @@ -555,11 +569,11 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - // TODO: remove these hard-coded zero indexes to enable multiple shipments in marketplace - const orderWorkflow = order.shipping[0].workflow; + const orderWorkflow = this.getShipppingObject(order).workflow; // check if the order(s) are in this state already or in one of the previous states - // TODO: model this with the assumption that there may be different workflows depending on the type of shop or product that a shop is selling. + // TODO: model this with the assumption that there may be different workflows + // depending on the type of shop or product that a shop is selling. if (orderWorkflow.status === "new") { isNotPacked++; whichFalseState = shippingStates.picked; @@ -615,11 +629,11 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - // TODO: remove these hard-coded zero indexes to enable multiple shipments in marketplace - const orderWorkflow = order.shipping[0].workflow.status; + const orderWorkflow = this.getShipppingObject(order).workflow.status; // check if the order(s) are in this state already or in one of the previous states - // TODO: model this with the assumption that there may be different workflows depending on the type of shop or product that a shop is selling. + // TODO: model this with the assumption that there may be different workflows + // depending on the type of shop or product that a shop is selling. if (orderWorkflow === "new") { isNotLabeled++; whichFalseState = shippingStates.picked; From 4fd58e1b55adbd4180366457176a14ad006f4b3f Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Fri, 8 Sep 2017 03:28:30 +0300 Subject: [PATCH 23/44] Remove more instances of shipping[0] and billing[0] --- .../templates/workflow/shippingTracking.js | 18 ++++++---- server/methods/core/orders.js | 36 ++++++++++++------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js index a2d76809f5a..b594a93da45 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js @@ -44,7 +44,8 @@ Template.coreOrderShippingTracking.events({ }, "click [data-event-action=shipmentShipped]": function () { const template = Template.instance(); - Meteor.call("orders/shipmentShipped", template.order, template.order.shipping[0], (err) => { + const shipment = template.order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + Meteor.call("orders/shipmentShipped", template.order, shipment, (err) => { if (err) { Alerts.toast(i18next.t("mail.alerts.cantSendEmail"), "error"); } else { @@ -76,8 +77,9 @@ Template.coreOrderShippingTracking.events({ "click [data-event-action=shipmentPacked]": () => { const template = Template.instance(); + const shipment = template.order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); - Meteor.call("orders/shipmentPacked", template.order, template.order.shipping[0]); + Meteor.call("orders/shipmentPacked", template.order, shipment); }, "submit form[name=addTrackingForm]": (event, template) => { @@ -104,7 +106,9 @@ Template.coreOrderShippingTracking.events({ Template.coreOrderShippingTracking.helpers({ printableLabels() { - const { shippingLabelUrl, customsLabelUrl } = Template.instance().order.shipping[0]; + const order = Template.instance().order; + const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const { shippingLabelUrl, customsLabelUrl } = shipment; if (shippingLabelUrl || customsLabelUrl) { return { shippingLabelUrl, customsLabelUrl }; } @@ -170,7 +174,8 @@ Template.coreOrderShippingTracking.helpers({ // TODO: future proof by not using flatRates, but rather look for editable:true if (settings && settings.flatRates.enabled === true) { const template = Template.instance(); - const shipment = template.order.shipping[0]; + const order = template.order; + const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); const editing = template.showTrackingEditForm.get(); let view = false; if (editing === true || !shipment.tracking && editing === false) { @@ -187,11 +192,12 @@ Template.coreOrderShippingTracking.helpers({ return Template.instance().order; }, shipment() { - return Template.instance().order.shipping[0]; + const order = Template.instance().order; + return order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); }, shipmentReady() { const order = Template.instance().order; - const shipment = order.shipping[0]; + const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); return _.includes(shipment.workflow.workflow, "coreOrderWorkflow/packed") && shipment.tracking || _.includes(shipment.workflow.workflow, "coreOrderWorkflow/packed"); diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index 486acb97b3b..7cf0329ad0f 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -13,14 +13,16 @@ import { Logger, Hooks, Reaction } from "/server/api"; // helper to return the order credit object -// the first credit paymentMethod on the order +// credit paymentMethod on the order as per current active shop // returns entire payment method export function orderCreditMethod(order) { - return order.billing.filter(value => value.paymentMethod.method === "credit")[0]; + const creditBillingRecords = order.billing.filter(value => value.paymentMethod.method === "credit"); + return creditBillingRecords.billing.find((billing) => { return billing.shopId === Reaction.getShopId(); }); } // helper to return the order debit object export function orderDebitMethod(order) { - return order.billing.filter(value => value.paymentMethod.method === "debit")[0]; + const debitBillingRecords = order.billing.filter(value => value.paymentMethod.method === "debit"); + return debitBillingRecords.billing.find((billing) => { return billing.shopId === Reaction.getShopId(); }); } // REVIEW: This jsdoc doesn't seem to be accurate @@ -215,6 +217,7 @@ export const methods = { return Orders.update({ "_id": order._id, + "billing.shopId": Reaction.getShopId, "billing.paymentMethod.method": "credit" }, { $set: { @@ -256,6 +259,7 @@ export const methods = { return Orders.update({ "_id": order._id, + "billing.shopId": Reaction.getShopId, "billing.paymentMethod.method": "credit" }, { $set: { @@ -290,10 +294,13 @@ export const methods = { ordersInventoryAdjust(order._id); } + const billingRecord = order.billing.find((billing) => { return billing.shopId === Reaction.getShopId(); }); + const shippingRecord = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + let paymentMethod = orderCreditMethod(order).paymentMethod; paymentMethod = Object.assign(paymentMethod, { amount: Number(paymentMethod.amount) }); - const invoiceTotal = order.billing[0].invoice.total; - const shipment = order.shipping[0]; + const invoiceTotal = billingRecord.invoice.total; + const shipment = shippingRecord; const itemIds = shipment.items.map((item) => { return item._id; }); @@ -314,6 +321,7 @@ export const methods = { return Orders.update({ "_id": order._id, + "billing.shopId": Reaction.getShopId, "billing.paymentMethod.method": "credit" }, { $set: { @@ -348,8 +356,9 @@ export const methods = { if (result) { Meteor.call("workflow/pushOrderWorkflow", "coreOrderWorkflow", "coreProcessPayment", order._id); + const shippingRecord = order.shipping.find((shipping) => {return shipping.shopId === Reaction.getShopId();}); // Set the status of the items as shipped - const itemIds = order.shipping[0].items.map((item) => { + const itemIds = shippingRecord.items.map((item) => { return item._id; }); @@ -524,6 +533,7 @@ export const methods = { } const billing = orderCreditMethod(order); + const shippingRecord = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); // TODO: Update */refunds/list for marketplace const refundResult = Meteor.call("orders/refunds/list", order); const refundTotal = refundResult.reduce((acc, refund) => acc + refund.amount, 0); @@ -651,13 +661,13 @@ export const methods = { orderDate: moment(order.createdAt).format("MM/DD/YYYY"), orderUrl: getSlug(shop.name) + "/cart/completed?_id=" + order.cartId, shipping: { - tracking: order.shipping[0].tracking, - carrier: order.shipping[0].shipmentMethod.carrier, + tracking: shippingRecord.tracking, + carrier: shippingRecord.shipmentMethod.carrier, address: { - address: order.shipping[0].address.address1, - city: order.shipping[0].address.city, - region: order.shipping[0].address.region, - postal: order.shipping[0].address.postal + address: shippingRecord.address.address1, + city: shippingRecord.address.city, + region: shippingRecord.address.region, + postal: shippingRecord.address.postal } } }; @@ -990,6 +1000,7 @@ export const methods = { Orders.update({ "_id": orderId, + "billing.shopId": Reaction.getShopId(), "billing.paymentMethod.transactionId": transactionId }, { $set: { @@ -1050,6 +1061,7 @@ export const methods = { Orders.update({ "_id": orderId, + "billing.shopId": Reaction.getShopId(), "billing.paymentMethod.transactionId": transactionId }, { $set: { From a3c4c4c0f888a0a1c334e2159cef34e3543b2854 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Fri, 8 Sep 2017 19:05:19 +0300 Subject: [PATCH 24/44] Fix react proptype error --- imports/plugins/core/accounts/client/components/updateEmail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imports/plugins/core/accounts/client/components/updateEmail.js b/imports/plugins/core/accounts/client/components/updateEmail.js index c4d2cbef75d..4f3f05af2ca 100644 --- a/imports/plugins/core/accounts/client/components/updateEmail.js +++ b/imports/plugins/core/accounts/client/components/updateEmail.js @@ -50,7 +50,7 @@ class UpdateEmail extends Component { /> Date: Fri, 8 Sep 2017 19:05:56 +0300 Subject: [PATCH 25/44] Fix billingRecord error --- server/methods/core/orders.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index 7cf0329ad0f..4475e2b3da8 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -17,12 +17,12 @@ import { Logger, Hooks, Reaction } from "/server/api"; // returns entire payment method export function orderCreditMethod(order) { const creditBillingRecords = order.billing.filter(value => value.paymentMethod.method === "credit"); - return creditBillingRecords.billing.find((billing) => { return billing.shopId === Reaction.getShopId(); }); + return creditBillingRecords.find((billing) => { return billing.shopId === Reaction.getShopId(); }); } // helper to return the order debit object export function orderDebitMethod(order) { const debitBillingRecords = order.billing.filter(value => value.paymentMethod.method === "debit"); - return debitBillingRecords.billing.find((billing) => { return billing.shopId === Reaction.getShopId(); }); + return debitBillingRecords.find((billing) => { return billing.shopId === Reaction.getShopId(); }); } // REVIEW: This jsdoc doesn't seem to be accurate From 7e624ac310c1c512fe5b7a1ae3eb70f7f52ebbb7 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Fri, 8 Sep 2017 19:06:52 +0300 Subject: [PATCH 26/44] export getShipppingObject function outside of component --- .../containers/orderDashboardContainer.js | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index 6d6cac29ead..9a4fbcd2fa0 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -70,6 +70,17 @@ const OrderHelper = { } }; +/** + * getShipppingObject + * + * @summary get proper shipping obect as per current active shop + * @param {Object} order - order object to check against + * @return {Object} shipping object to use + */ +function getShipppingObject(order) { + return order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); +} + class OrderDashboardContainer extends Component { static propTypes = { handleMenuClick: PropTypes.func, @@ -272,17 +283,6 @@ class OrderDashboardContainer extends Component { return false; } - /** - * getShipppingObject - * - * @summary get proper shipping obect as per current active shop - * @param {Object} order - order object to check against - * @return {Object} shipping object to use - */ - getShipppingObject = (order) => { - return order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); - } - /** * shippingStatusUpdateCall * @@ -315,7 +315,7 @@ class OrderDashboardContainer extends Component { // TODO: rethink this type of flow for updating shipping statuses selectedOrders.forEach((order) => { - const shippingRecord = this.getShipppingObject(order); + const shippingRecord = getShipppingObject(order); Meteor.call(`orders/shipment${capitalizeStatus}`, order, shippingRecord, (err) => { if (err) { @@ -458,7 +458,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = this.getShipppingObject(order).workflow; + const orderWorkflow = getShipppingObject(order).workflow; // check if the order(s) are in this state already or in the previous state // TODO: model this with the assumption that there may be different workflows @@ -509,7 +509,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = this.getShipppingObject(order).workflow; + const orderWorkflow = getShipppingObject(order).workflow; // check if the order(s) are in this state already or in one of the previous states @@ -569,7 +569,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = this.getShipppingObject(order).workflow; + const orderWorkflow = getShipppingObject(order).workflow; // check if the order(s) are in this state already or in one of the previous states // TODO: model this with the assumption that there may be different workflows @@ -629,7 +629,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = this.getShipppingObject(order).workflow.status; + const orderWorkflow = getShipppingObject(order).workflow.status; // check if the order(s) are in this state already or in one of the previous states // TODO: model this with the assumption that there may be different workflows From 5297781d337665bfcfe4c4e3dd32f6e61a26d4e8 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Fri, 8 Sep 2017 22:27:29 +0300 Subject: [PATCH 27/44] More removal of hardcoded shipping object --- .../orders/client/components/orderSummary.js | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index 6eee3a77b50..43585559561 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -1,6 +1,7 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; import moment from "moment"; +import { Reaction } from "/client/api"; import { Badge, ClickToCopy } from "@reactioncommerce/reaction-ui"; class OrderSummary extends Component { @@ -41,6 +42,20 @@ class OrderSummary extends Component { return shortId; } + // helper function to get appropriate billing info + getBillingInfo(order) { + return order.billing.find( + billing => billing.shopId === Reaction.getShopId() + ) || {}; + } + + // helper function to get appropriate shipping info + getShippingInfo(order) { + return order.shipping.find( + shipping => shipping.shopId === Reaction.getShopId() + ) || {}; + } + render() { const { dateFormat, tracking, order, profileShippingAddress, printableLabels } = this.props; @@ -86,28 +101,28 @@ class OrderSummary extends Component {
Processor
- {order.billing[0].paymentMethod.processor} + {this.getBillingInfo(order).paymentMethod.processor}
Payment
- {order.billing[0].paymentMethod.storedCard} ({order.billing[0].invoice.total}) + {this.getBillingInfo(order).paymentMethod.storedCard} ({this.getBillingInfo(order).invoice.total})
Transaction
- {order.billing[0].paymentMethod.transactionId} + {this.getBillingInfo(order).paymentMethod.transactionId}
Carrier
- {order.shipping[0].shipmentMethod.carrier} - {order.shipping[0].shipmentMethod.label} + {this.getBillingInfo(order).shipmentMethod.carrier} - {this.getBillingInfo(order).shipmentMethod.label}
From 09e17ad43686884b3e4ab5f313cf4a788fb46730 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Fri, 8 Sep 2017 23:49:07 +0300 Subject: [PATCH 28/44] More removal of hardcoded shipping and billing object --- .../orders/client/components/orderSummary.js | 2 +- .../orders/client/components/orderTable.js | 62 ++++++++++++++----- .../client/components/orderTableColumn.js | 6 +- .../containers/orderDashboardContainer.js | 2 +- .../containers/orderSummaryContainer.js | 20 ++++-- server/methods/core/orders.js | 4 +- 6 files changed, 69 insertions(+), 27 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index 43585559561..deca04deff6 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -122,7 +122,7 @@ class OrderSummary extends Component {
Carrier
- {this.getBillingInfo(order).shipmentMethod.carrier} - {this.getBillingInfo(order).shipmentMethod.label} + {this.getShippingInfo(order).shipmentMethod.carrier} - {this.getShippingInfo(order).shipmentMethod.label}
diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index f12ae263137..71e04cc36ce 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -60,6 +60,13 @@ class OrderTable extends Component { ) || {}; } + // helper function to get appropriate shipping info + getShippingInfo(order) { + return order.shipping.find( + shipping => shipping.shopId === Reaction.getShopId() + ) || {}; + } + /** * Fullfilment Badge * @param {Object} order object containing info for order and coreOrderWorkflow @@ -143,24 +150,26 @@ class OrderTable extends Component { } renderShipmentInfo(order) { - const emailAddress = order.email || ; + const emailAddress = order.email || + ; + return (
- {order.shipping[0].address.fullName} | {emailAddress} + {this.getShippingInfo(order).address.fullName} | {emailAddress}
this.getShippingInfo(row).address.fullName, + id: "shippingfullName" + }, + "Email": { + accessor: "email", + id: "email" + }, + "Date": { + accessor: "createdAt", + id: "createdAt" + }, + "ID": { + accessor: "_id", + id: "_id" + }, + "Total": { + accessor: row => this.getBillingInfo(row).invoice.total, + id: "billingTotal" + }, + "Shipping": { + accessor: row => this.getShippingInfo(row).workflow.status, + id: "shippingStatus" + }, + "Status": { + accessor: "workflow.status", + id: "workflow.status" + }, + "": { + accessor: "", + id: "" + } }; const columnNames = Object.keys(filteredFields); @@ -262,7 +295,8 @@ class OrderTable extends Component { } const columnMeta = { - accessor: filteredFields[columnName], + accessor: filteredFields[columnName].accessor, + id: filteredFields[columnName].id, Header: colHeader ? colHeader : columnName, headerClassName: classNames.headerClassNames[columnName], className: classNames.colClassNames[columnName], diff --git a/imports/plugins/core/orders/client/components/orderTableColumn.js b/imports/plugins/core/orders/client/components/orderTableColumn.js index a1317be8bf3..a67f8f88b6a 100644 --- a/imports/plugins/core/orders/client/components/orderTableColumn.js +++ b/imports/plugins/core/orders/client/components/orderTableColumn.js @@ -49,7 +49,7 @@ class OrderTableColumn extends Component { render() { const columnAccessor = this.props.row.column.id; - if (columnAccessor === "shipping[0].address.fullName") { + if (columnAccessor === "shippingfullName") { return (
{this.renderCheckboxOnSelect(this.props.row)} @@ -82,14 +82,14 @@ class OrderTableColumn extends Component {
); } - if (columnAccessor === "billing[0].invoice.total") { + if (columnAccessor === "billingTotal") { return (
{formatPriceString(this.props.row.original.billing[0].invoice.total)}
); } - if (columnAccessor === "shipping[0].workflow.status") { + if (columnAccessor === "shippingStatus") { return ( { return shipping.shopId === Reaction.getShopId(); }); + return order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); } class OrderDashboardContainer extends Component { diff --git a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js index 9faf381ff3f..be196c9e32c 100644 --- a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js +++ b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js @@ -6,9 +6,16 @@ import { Meteor } from "meteor/meteor"; import { composeWithTracker } from "@reactioncommerce/reaction-components"; import { Orders } from "/lib/collections"; import { Card, CardHeader, CardBody, CardGroup } from "/imports/plugins/core/ui/client/components"; -import { i18next } from "/client/api"; +import { Reaction, i18next } from "/client/api"; import OrderSummary from "../components/orderSummary"; +// helper function to get appropriate shipping info +function getShippingInfo(order) { + return order.shipping.find( + shipping => shipping.shopId === Reaction.getShopId() + ) || {}; +} + class OrderSummaryContainer extends Component { static propTypes = { order: PropTypes.object @@ -27,15 +34,16 @@ class OrderSummaryContainer extends Component { } tracking = () => { - if (this.props.order.shipping[0].tracking) { - return this.props.order.shipping[0].tracking; + const shipping = getShippingInfo(this.props.order); + if (shipping.tracking) { + return shipping.tracking; } return i18next.t("orderShipping.noTracking"); } shipmentStatus = () => { const order = this.props.order; - const shipment = order.shipping[0]; + const shipment = getShippingInfo(this.props.order); if (shipment.delivered) { return { @@ -95,7 +103,7 @@ class OrderSummaryContainer extends Component { } printableLabels = () => { - const { shippingLabelUrl, customsLabelUrl } = this.props.order.shipping[0]; + const { shippingLabelUrl, customsLabelUrl } = getShippingInfo(this.props.order); if (shippingLabelUrl || customsLabelUrl) { return { shippingLabelUrl, customsLabelUrl }; } @@ -139,7 +147,7 @@ const composer = (props, onData) => { "shipping._id": props.fulfillment._id }); - const profileShippingAddress = order.shipping[0].address; + const profileShippingAddress = getShippingInfo(order).address; if (order.workflow) { if (order.workflow.status === "coreOrderCreated") { diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index 4475e2b3da8..aad18600cae 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -17,12 +17,12 @@ import { Logger, Hooks, Reaction } from "/server/api"; // returns entire payment method export function orderCreditMethod(order) { const creditBillingRecords = order.billing.filter(value => value.paymentMethod.method === "credit"); - return creditBillingRecords.find((billing) => { return billing.shopId === Reaction.getShopId(); }); + return creditBillingRecords.find(billing => billing.shopId === Reaction.getShopId()); } // helper to return the order debit object export function orderDebitMethod(order) { const debitBillingRecords = order.billing.filter(value => value.paymentMethod.method === "debit"); - return debitBillingRecords.find((billing) => { return billing.shopId === Reaction.getShopId(); }); + return debitBillingRecords.find(billing => billing.shopId === Reaction.getShopId()); } // REVIEW: This jsdoc doesn't seem to be accurate From e8709c3b9299b4e3b345d374504a951c6bb8b8fd Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Sat, 9 Sep 2017 02:55:26 +0300 Subject: [PATCH 29/44] Fix failing tests --- server/imports/fixtures/orders.js | 2 ++ server/methods/core/orders.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/server/imports/fixtures/orders.js b/server/imports/fixtures/orders.js index c6cda497776..d0fb8a706e1 100755 --- a/server/imports/fixtures/orders.js +++ b/server/imports/fixtures/orders.js @@ -129,6 +129,7 @@ export default function () { }, requiresShipping: true, shipping: [{ + shopId: getShopId(), items: [ { _id: itemIdOne, @@ -148,6 +149,7 @@ export default function () { }], // Shipping Schema billing: [{ _id: Random.id(), + shopId: getShopId(), address: getAddress({ isBillingDefault: true }), paymentMethod: paymentMethod({ method: "credit", diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index aad18600cae..224f6805c35 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -454,7 +454,7 @@ export const methods = { this.unblock(); - const shipment = order.shipping[0]; + const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); if (order.email) { Meteor.call("orders/sendNotification", order, (err) => { From eed0d3d41b20dee9e795dcb1f3eae2a7eda419fc Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Mon, 11 Sep 2017 20:22:03 +0300 Subject: [PATCH 30/44] Remove hardcoded shipping object --- .../plugins/core/orders/client/templates/list/ordersList.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imports/plugins/core/orders/client/templates/list/ordersList.js b/imports/plugins/core/orders/client/templates/list/ordersList.js index 108ac46300d..1798a81a65a 100644 --- a/imports/plugins/core/orders/client/templates/list/ordersList.js +++ b/imports/plugins/core/orders/client/templates/list/ordersList.js @@ -1,6 +1,7 @@ import moment from "moment"; import { Template } from "meteor/templating"; import { Orders, Shops } from "/lib/collections"; +import { Reaction } from "/client/api"; /** * dashboardOrdersList helpers @@ -27,7 +28,7 @@ Template.dashboardOrdersList.helpers({ return moment(this.createdAt).fromNow(); }, shipmentTracking() { - return this.shipping[0].shipmentMethod.tracking; + return this.shipping.find(shipping => shipping.shopId === Reaction.getShopId()).shipmentMethod.tracking; }, shopName() { const shop = Shops.findOne(this.shopId); From 847805f6b70bf2e7ea50920d8d32781ebc97a9fe Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 12 Sep 2017 21:39:20 +0300 Subject: [PATCH 31/44] Rewrite test suits to remove hardcoded shipping and billing objects --- server/imports/fixtures/orders.js | 1 + server/methods/core/orders.app-test.js | 101 +++++++++++++++---------- 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/server/imports/fixtures/orders.js b/server/imports/fixtures/orders.js index d0fb8a706e1..7d9982b7576 100755 --- a/server/imports/fixtures/orders.js +++ b/server/imports/fixtures/orders.js @@ -182,6 +182,7 @@ export default function () { Factory.extend("order", { billing: [{ _id: Random.id(), + shopId: getShopId(), address: getAddress({ isBillingDefault: true }), paymentMethod: paymentMethod({ processor: "Paypal", diff --git a/server/methods/core/orders.app-test.js b/server/methods/core/orders.app-test.js index 655f383ee99..32415385fac 100644 --- a/server/methods/core/orders.app-test.js +++ b/server/methods/core/orders.app-test.js @@ -6,6 +6,7 @@ import { expect } from "meteor/practicalmeteor:chai"; import { sinon } from "meteor/practicalmeteor:sinon"; import Fixtures from "/server/imports/fixtures"; import { Reaction } from "/server/api"; +import { getShop } from "/server/imports/fixtures/shops"; import { Orders, Media, Notifications, Products, Shops } from "/lib/collections"; @@ -13,11 +14,12 @@ Fixtures(); // examplePaymentMethod(); describe("orders test", function () { + const shop = getShop(); + const shopId = shop._id; let methods; let sandbox; let order; let example; - let shop; before(function (done) { methods = { @@ -56,10 +58,9 @@ describe("orders test", function () { check(arguments, [Match.Any]); }); - shop = Factory.create("shop"); order = Factory.create("order"); sandbox.stub(Reaction, "getShopId", () => order.shopId); - const paymentMethod = order.billing[0].paymentMethod; + const paymentMethod = billingObjectMethod(order).paymentMethod; sandbox.stub(paymentMethod, "paymentPackageId", example._id); return done(); }); @@ -78,8 +79,17 @@ describe("orders test", function () { }); } + function billingObjectMethod(orderObject) { + return orderObject.billing.find(billing => billing.shopId === shopId); + } + + function shippingObjectMethod(orderObject) { + return orderObject.shipping.find(shipping => shipping.shopId === shopId); + } + function orderCreditMethod(orderData) { - return orderData.billing.filter(value => value.paymentMethod.method === "credit")[0]; + const billingRecord = orderData.billing.filter(value => value.paymentMethod.method === "credit"); + return billingRecord.find(billing => billing.shopId === shopId); } describe("orders/cancelOrder", function () { @@ -135,8 +145,8 @@ describe("orders test", function () { const returnToStock = false; spyOnMethod("cancelOrder", order.userId); Meteor.call("orders/cancelOrder", order, returnToStock); - const Order = Orders.findOne({ _id: order._id }); - expect(Order.billing[0].paymentMethod.mode).to.equal("cancel"); + const orderObject = Orders.findOne({ _id: order._id }); + expect(billingObjectMethod(orderObject).paymentMethod.mode).to.equal("cancel"); }); it("should change the workflow status of the item to coreOrderItemWorkflow/canceled", function () { @@ -152,7 +162,7 @@ describe("orders test", function () { describe("orders/shipmentPicked", function () { it("should throw an error if user is not admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentPicked", order, shipment); function shipmentPicked() { @@ -163,7 +173,7 @@ describe("orders test", function () { it("should update the order item workflow status to coreOrderItemWorkflow/picked", function () { sandbox.stub(Reaction, "hasPermission", () => true); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentPicked", order.userId); Meteor.call("orders/shipmentPicked", order, shipment); const orderItem = Orders.findOne({ _id: order._id }).items[0]; @@ -172,10 +182,10 @@ describe("orders test", function () { it("should update the shipment workflow status to coreOrderWorkflow/picked", function () { sandbox.stub(Reaction, "hasPermission", () => true); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentPicked", order.userId); Meteor.call("orders/shipmentPicked", order, shipment); - const orderShipment = Orders.findOne({ _id: order._id }).shipping[0]; + const orderShipment = shippingObjectMethod(Orders.findOne({ _id: order._id })); expect(orderShipment.workflow.status).to.equal("coreOrderWorkflow/picked"); }); }); @@ -183,7 +193,7 @@ describe("orders test", function () { describe("orders/shipmentPacked", function () { it("should throw an error if user is not admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentPacked", order, shipment); function shipmentPacked() { @@ -194,7 +204,7 @@ describe("orders test", function () { it("should update the order item workflow status to coreOrderItemWorkflow/packed", function () { sandbox.stub(Reaction, "hasPermission", () => true); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentPacked", order.userId); Meteor.call("orders/shipmentPacked", order, shipment); const orderItem = Orders.findOne({ _id: order._id }).items[0]; @@ -203,10 +213,10 @@ describe("orders test", function () { it("should update the shipment workflow status to coreOrderWorkflow/packed", function () { sandbox.stub(Reaction, "hasPermission", () => true); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentPacked", order.userId); Meteor.call("orders/shipmentPacked", order, shipment); - const orderShipment = Orders.findOne({ _id: order._id }).shipping[0]; + const orderShipment = shippingObjectMethod(Orders.findOne({ _id: order._id })); expect(orderShipment.workflow.status).to.equal("coreOrderWorkflow/packed"); }); }); @@ -214,7 +224,7 @@ describe("orders test", function () { describe("orders/shipmentLabeled", function () { it("should throw an error if user is not admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentLabeled", order, shipment); function shipmentLabeled() { @@ -225,7 +235,7 @@ describe("orders test", function () { it("should update the order item workflow status to coreOrderItemWorkflow/labeled", function () { sandbox.stub(Reaction, "hasPermission", () => true); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentLabeled", order.userId); Meteor.call("orders/shipmentLabeled", order, shipment); const orderItem = Orders.findOne({ _id: order._id }).items[0]; @@ -234,10 +244,10 @@ describe("orders test", function () { it("should update the shipment workflow status to coreOrderWorkflow/labeled", function () { sandbox.stub(Reaction, "hasPermission", () => true); - const shipment = order.shipping[0]; + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentLabeled", order.userId); Meteor.call("orders/shipmentLabeled", order, shipment); - const orderShipment = Orders.findOne({ _id: order._id }).shipping[0]; + const orderShipment = shippingObjectMethod(Orders.findOne({ _id: order._id })); expect(orderShipment.workflow.status).to.equal("coreOrderWorkflow/labeled"); }); }); @@ -257,7 +267,7 @@ describe("orders test", function () { sandbox.stub(Reaction, "hasPermission", () => true); spyOnMethod("makeAdjustmentsToInvoice", order.userId); Meteor.call("orders/makeAdjustmentsToInvoice", order); - const orderPaymentMethodStatus = Orders.findOne({ _id: order._id }).billing[0].paymentMethod.status; + const orderPaymentMethodStatus = billingObjectMethod(Orders.findOne({ _id: order._id })).paymentMethod.status; expect(orderPaymentMethodStatus).equal("adjustments"); }); }); @@ -283,7 +293,7 @@ describe("orders test", function () { const discountTotal = Math.max(0, subTotal - discount); // ensure no discounting below 0. const total = accounting.toFixed(discountTotal + shipping + taxes, 2); Meteor.call("orders/approvePayment", order); - const orderBilling = Orders.findOne({ _id: order._id }).billing[0]; + const orderBilling = billingObjectMethod(Orders.findOne({ _id: order._id })); expect(orderBilling.paymentMethod.status).to.equal("approved"); expect(orderBilling.paymentMethod.mode).to.equal("capture"); expect(orderBilling.invoice.discounts).to.equal(discount); @@ -294,43 +304,47 @@ describe("orders test", function () { describe("orders/shipmentShipped", function () { it("should throw an error if user does not have permission", function () { sandbox.stub(Reaction, "hasPermission", () => false); + const shipment = shippingObjectMethod(order); spyOnMethod("shipmentShipped", order.userId); function shipmentShipped() { - return Meteor.call("orders/shipmentShipped", order, order.shipping[0]); + return Meteor.call("orders/shipmentShipped", order, shipment); } expect(shipmentShipped).to.throw(Meteor.Error, /Access Denied/); }); it("should update the order item workflow status to coreOrderItemWorkflow/completed", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const shipment = shippingObjectMethod(order); sandbox.stub(Meteor.server.method_handlers, "orders/sendNotification", function () { check(arguments, [Match.Any]); }); spyOnMethod("shipmentShipped", order.userId); - Meteor.call("orders/shipmentShipped", order, order.shipping[0]); + Meteor.call("orders/shipmentShipped", order, shipment); const orderItem = Orders.findOne({ _id: order._id }).items[0]; expect(orderItem.workflow.status).to.equal("coreOrderItemWorkflow/completed"); }); it("should update the order workflow status to completed", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const shipment = shippingObjectMethod(order); sandbox.stub(Meteor.server.method_handlers, "orders/sendNotification", function () { check(arguments, [Match.Any]); }); spyOnMethod("shipmentShipped", order.userId); - Meteor.call("orders/shipmentShipped", order, order.shipping[0]); + Meteor.call("orders/shipmentShipped", order, shipment); const orderStatus = Orders.findOne({ _id: order._id }).workflow.status; expect(orderStatus).to.equal("coreOrderWorkflow/completed"); }); it("should update the order shipping workflow status to coreOrderWorkflow/shipped", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const shipment = shippingObjectMethod(order); sandbox.stub(Meteor.server.method_handlers, "orders/sendNotification", function () { check(arguments, [Match.Any]); }); spyOnMethod("shipmentShipped", order.userId); - Meteor.call("orders/shipmentShipped", order, order.shipping[0]); - const orderShipped = Orders.findOne({ _id: order._id }).shipping[0]; + Meteor.call("orders/shipmentShipped", order, shipment); + const orderShipped = shippingObjectMethod(Orders.findOne({ _id: order._id })); expect(orderShipped.workflow.status).to.equal("coreOrderWorkflow/shipped"); }); }); @@ -363,7 +377,7 @@ describe("orders test", function () { sandbox.stub(Reaction, "hasPermission", () => true); spyOnMethod("shipmentDelivered", order.userId); Meteor.call("orders/shipmentDelivered", order); - const orderShipping = Orders.findOne({ _id: order._id }).shipping[0]; + const orderShipping = shippingObjectMethod(Orders.findOne({ _id: order._id })); expect(orderShipping.workflow.status).to.equal("coreOrderWorkflow/delivered"); }); @@ -403,21 +417,23 @@ describe("orders test", function () { describe("orders/updateShipmentTracking", function () { it("should return an error if user does not have permission", function () { sandbox.stub(Reaction, "hasPermission", () => false); + const shipment = shippingObjectMethod(order); spyOnMethod("updateShipmentTracking", order.userId); function updateShipmentTracking() { const trackingValue = "2340FLKD104309"; - return Meteor.call("orders/updateShipmentTracking", order, order.shipping[0], trackingValue); + return Meteor.call("orders/updateShipmentTracking", order, shipment, trackingValue); } expect(updateShipmentTracking).to.throw(Meteor.error, /Access Denied/); }); it("should update the order tracking value", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const shipment = shippingObjectMethod(order); spyOnMethod("updateShipmentTracking", order.userId); const trackingValue = "2340FLKD104309"; - Meteor.call("orders/updateShipmentTracking", order, order.shipping[0], trackingValue); + Meteor.call("orders/updateShipmentTracking", order, shipment, trackingValue); const orders = Orders.findOne({ _id: order._id }); - expect(orders.shipping[0].tracking).to.equal(trackingValue); + expect(shippingObjectMethod(orders).tracking).to.equal(trackingValue); }); }); @@ -468,7 +484,7 @@ describe("orders test", function () { beforeEach(function (done) { Orders.update({ "_id": order._id, - "billing.paymentMethod.transactionId": order.billing[0].paymentMethod.transactionId + "billing.paymentMethod.transactionId": billingObjectMethod(order).paymentMethod.transactionId }, { $set: { "billing.$.paymentMethod.mode": "capture", @@ -499,7 +515,7 @@ describe("orders test", function () { sandbox.stub(Reaction, "hasPermission", () => true); spyOnMethod("capturePayments", order.userId); Meteor.call("orders/capturePayments", order._id, () => { - const orderPaymentMethod = Orders.findOne({ _id: order._id }).billing[0].paymentMethod; + const orderPaymentMethod = billingObjectMethod(Orders.findOne({ _id: order._id })).paymentMethod; expect(orderPaymentMethod.mode).to.equal("capture"); expect(orderPaymentMethod.status).to.equal("completed"); }); @@ -517,7 +533,7 @@ describe("orders test", function () { }; }); Meteor.call("orders/capturePayments", order._id, () => { - const orderPaymentMethod = Orders.findOne({ _id: order._id }).billing[0].paymentMethod; + const orderPaymentMethod = billingObjectMethod(Orders.findOne({ _id: order._id })).paymentMethod; expect(orderPaymentMethod.mode).to.equal("capture"); expect(orderPaymentMethod.status).to.equal("error"); }); @@ -545,21 +561,23 @@ describe("orders test", function () { it("should return error if user is does not have admin permissions", function () { sandbox.stub(Reaction, "hasPermission", () => false); + const billing = billingObjectMethod(order); spyOnMethod("refunds/create", order.userId); function refundsCreate() { const amount = 5.20; - return Meteor.call("orders/refunds/create", order._id, order.billing[0].paymentMethod, amount); + return Meteor.call("orders/refunds/create", order._id, billing.paymentMethod, amount); } expect(refundsCreate).to.throw(Meteor.error, /Access Denied/); }); it("should update the order as refunded", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const billing = billingObjectMethod(order); spyOnMethod("refunds/create", order.userId); const amount = 5.20; - Meteor.call("orders/refunds/create", order._id, order.billing[0].paymentMethod, amount); + Meteor.call("orders/refunds/create", order._id, billing.paymentMethod, amount); const updateOrder = Orders.findOne({ _id: order._id }); - expect(updateOrder.billing[0].paymentMethod.status).to.equal("refunded"); + expect(billingObjectMethod(updateOrder).paymentMethod.status).to.equal("refunded"); }); }); @@ -572,6 +590,7 @@ describe("orders test", function () { it("should return error if user does not have admin permissions", function () { sandbox.stub(Reaction, "hasPermission", () => false); + const billing = billingObjectMethod(order); spyOnMethod("refunds/refundItems", order.userId); function refundItems() { const refundItemsInfo = { @@ -579,13 +598,14 @@ describe("orders test", function () { quantity: 2, items: [{}, {}] }; - return Meteor.call("orders/refunds/refundItems", order._id, order.billing[0].paymentMethod, refundItemsInfo); + return Meteor.call("orders/refunds/refundItems", order._id, billing.paymentMethod, refundItemsInfo); } expect(refundItems).to.throw(Meteor.error, /Access Denied/); }); it("should update the order as partially refunded if not all of items in the order are refunded", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const billing = billingObjectMethod(order); spyOnMethod("refunds/refundItems", order.userId); const originalQuantity = order.items.reduce((acc, item) => acc + item.quantity, 0); const quantity = originalQuantity - 1; @@ -594,13 +614,14 @@ describe("orders test", function () { quantity: quantity, items: [{}, {}] }; - Meteor.call("orders/refunds/refundItems", order._id, order.billing[0].paymentMethod, refundItemsInfo); + Meteor.call("orders/refunds/refundItems", order._id, billing.paymentMethod, refundItemsInfo); const updateOrder = Orders.findOne({ _id: order._id }); - expect(updateOrder.billing[0].paymentMethod.status).to.equal("partialRefund"); + expect(billingObjectMethod(updateOrder).paymentMethod.status).to.equal("partialRefund"); }); it("should update the order as refunded if all items in the order are refunded", function () { sandbox.stub(Reaction, "hasPermission", () => true); + const billing = billingObjectMethod(order); spyOnMethod("refunds/refundItems", order.userId); const originalQuantity = order.items.reduce((acc, item) => acc + item.quantity, 0); const refundItemsInfo = { @@ -608,9 +629,9 @@ describe("orders test", function () { quantity: originalQuantity, items: [{}, {}] }; - Meteor.call("orders/refunds/refundItems", order._id, order.billing[0].paymentMethod, refundItemsInfo); + Meteor.call("orders/refunds/refundItems", order._id, billing.paymentMethod, refundItemsInfo); const updateOrder = Orders.findOne({ _id: order._id }); - expect(updateOrder.billing[0].paymentMethod.status).to.equal("refunded"); + expect(billingObjectMethod(updateOrder).paymentMethod.status).to.equal("refunded"); }); }); }); From 3e04d1d49fc1b0bb38e8700d704b9a2488960444 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 12 Sep 2017 22:44:28 +0300 Subject: [PATCH 32/44] Export helper functions out of components, add JSDOCs for them --- .../orders/client/components/orderSummary.js | 48 ++++++++++------ .../orders/client/components/orderTable.js | 56 +++++++++++-------- .../containers/orderDashboardContainer.js | 6 +- .../containers/orderSummaryContainer.js | 8 ++- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index deca04deff6..92b9278c08b 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -4,6 +4,32 @@ import moment from "moment"; import { Reaction } from "/client/api"; import { Badge, ClickToCopy } from "@reactioncommerce/reaction-ui"; +/** + * getBillingInfo + * + * @summary get proper billing object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper billing object to use + */ +function getBillingInfo(order) { + return order.billing.find( + billing => billing.shopId === Reaction.getShopId() + ) || {}; +} + +/** + * getShippingInfo + * + * @summary get proper shipping object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper shipping object to use + */ +function getShippingInfo(order) { + return order.shipping.find( + shipping => shipping.shopId === Reaction.getShopId() + ) || {}; +} + class OrderSummary extends Component { static propTypes = { dateFormat: PropTypes.func, @@ -42,20 +68,6 @@ class OrderSummary extends Component { return shortId; } - // helper function to get appropriate billing info - getBillingInfo(order) { - return order.billing.find( - billing => billing.shopId === Reaction.getShopId() - ) || {}; - } - - // helper function to get appropriate shipping info - getShippingInfo(order) { - return order.shipping.find( - shipping => shipping.shopId === Reaction.getShopId() - ) || {}; - } - render() { const { dateFormat, tracking, order, profileShippingAddress, printableLabels } = this.props; @@ -101,28 +113,28 @@ class OrderSummary extends Component {
Processor
- {this.getBillingInfo(order).paymentMethod.processor} + {getBillingInfo(order).paymentMethod.processor}
Payment
- {this.getBillingInfo(order).paymentMethod.storedCard} ({this.getBillingInfo(order).invoice.total}) + {getBillingInfo(order).paymentMethod.storedCard} ({getBillingInfo(order).invoice.total})
Transaction
- {this.getBillingInfo(order).paymentMethod.transactionId} + {getBillingInfo(order).paymentMethod.transactionId}
Carrier
- {this.getShippingInfo(order).shipmentMethod.carrier} - {this.getShippingInfo(order).shipmentMethod.label} + {getShippingInfo(order).shipmentMethod.carrier} - {getShippingInfo(order).shipmentMethod.label}
diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 34b5b56f29f..15d57e03c78 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -34,6 +34,32 @@ const classNames = { } }; +/** + * getBillingInfo + * + * @summary get proper billing object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper billing object to use + */ +function getBillingInfo(order) { + return order.billing.find( + billing => billing.shopId === Reaction.getShopId() + ) || {}; +} + +/** + * getShippingInfo + * + * @summary get proper shipping object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper shipping object to use + */ +function getShippingInfo(order) { + return order.shipping.find( + shipping => shipping.shopId === Reaction.getShopId() + ) || {}; +} + class OrderTable extends Component { static propTypes = { displayMedia: PropTypes.func, @@ -53,20 +79,6 @@ class OrderTable extends Component { toggleShippingFlowList: PropTypes.func } - // helper function to get appropriate billing info - getBillingInfo(order) { - return order.billing.find( - billing => billing.shopId === Reaction.getShopId() - ) || {}; - } - - // helper function to get appropriate shipping info - getShippingInfo(order) { - return order.shipping.find( - shipping => shipping.shopId === Reaction.getShopId() - ) || {}; - } - /** * Fullfilment Badge * @param {Object} order object containing info for order and coreOrderWorkflow @@ -125,7 +137,7 @@ class OrderTable extends Component { - Total: {formatPriceString(this.getBillingInfo(order).invoice.total)} + Total: {formatPriceString(getBillingInfo(order).invoice.total)}
@@ -159,17 +171,17 @@ class OrderTable extends Component { - {this.getShippingInfo(order).address.fullName} | {emailAddress} + {getShippingInfo(order).address.fullName} | {emailAddress}
this.getShippingInfo(row).address.fullName, + accessor: row => getShippingInfo(row).address.fullName, id: "shippingfullName" }, "Email": { @@ -231,11 +243,11 @@ class OrderTable extends Component { id: "_id" }, "Total": { - accessor: row => this.getBillingInfo(row).invoice.total, + accessor: row => getBillingInfo(row).invoice.total, id: "billingTotal" }, "Shipping": { - accessor: row => this.getShippingInfo(row).workflow.status, + accessor: row => getShippingInfo(row).workflow.status, id: "shippingStatus" }, "Status": { diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index c5f827c0397..1e08b37024a 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -73,9 +73,9 @@ const OrderHelper = { /** * getShipppingObject * - * @summary get proper shipping obect as per current active shop + * @summary get proper shipping object as per current active shop * @param {Object} order - order object to check against - * @return {Object} shipping object to use + * @return {Object} proper shipping object to use */ function getShipppingObject(order) { return order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); @@ -243,7 +243,7 @@ class OrderDashboardContainer extends Component { Reaction.setUserPreferences(PACKAGE_NAME, ORDER_LIST_FILTERS_PREFERENCE_NAME, "processing"); } - /* TODO: + /* TODO: a) What other routes have a query parameter of _id=XXXXXXX ? b) What exactly are we using the order dashboard for? If it's search, well, clicking a search result doesn't CURRENTLY do anything. What's diff --git a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js index be196c9e32c..2f06cf8b585 100644 --- a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js +++ b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js @@ -9,7 +9,13 @@ import { Card, CardHeader, CardBody, CardGroup } from "/imports/plugins/core/ui/ import { Reaction, i18next } from "/client/api"; import OrderSummary from "../components/orderSummary"; -// helper function to get appropriate shipping info +/** + * getShippingInfo + * + * @summary get proper shipping object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper shipping object to use + */ function getShippingInfo(order) { return order.shipping.find( shipping => shipping.shopId === Reaction.getShopId() From 70592a7594ece0faf5f887644df71f78560e4bd8 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Mon, 18 Sep 2017 22:58:03 +0300 Subject: [PATCH 33/44] Move getBillingInfo and getShippingInfo to helper file; refactor find method --- .../orders/client/components/orderSummary.js | 28 +----------------- .../orders/client/components/orderTable.js | 28 +----------------- .../containers/orderDashboardContainer.js | 22 ++++---------- .../containers/orderSummaryContainer.js | 16 ++-------- .../client/templates/list/ordersList.js | 6 +++- .../templates/workflow/shippingTracking.js | 13 +++++---- .../core/orders/lib/helpers/orderHelpers.js | 29 +++++++++++++++++++ server/methods/core/orders.app-test.js | 15 ++++++++-- server/methods/core/orders.js | 10 +++++-- 9 files changed, 71 insertions(+), 96 deletions(-) create mode 100644 imports/plugins/core/orders/lib/helpers/orderHelpers.js diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index 92b9278c08b..3b25ef594b4 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -1,34 +1,8 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; import moment from "moment"; -import { Reaction } from "/client/api"; import { Badge, ClickToCopy } from "@reactioncommerce/reaction-ui"; - -/** - * getBillingInfo - * - * @summary get proper billing object as per current active shop - * @param {Object} order - order object to check against - * @return {Object} proper billing object to use - */ -function getBillingInfo(order) { - return order.billing.find( - billing => billing.shopId === Reaction.getShopId() - ) || {}; -} - -/** - * getShippingInfo - * - * @summary get proper shipping object as per current active shop - * @param {Object} order - order object to check against - * @return {Object} proper shipping object to use - */ -function getShippingInfo(order) { - return order.shipping.find( - shipping => shipping.shopId === Reaction.getShopId() - ) || {}; -} +import { getBillingInfo, getShippingInfo } from "../../lib/helpers/orderHelpers"; class OrderSummary extends Component { static propTypes = { diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 15d57e03c78..77c21b9c988 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -3,13 +3,13 @@ import PropTypes from "prop-types"; import Avatar from "react-avatar"; import moment from "moment"; import classnames from "classnames/dedupe"; -import { Reaction } from "/client/api"; import { Orders } from "/lib/collections"; import { Badge, ClickToCopy, Icon, Translation, Checkbox, Loading, SortableTable } from "@reactioncommerce/reaction-ui"; import OrderTableColumn from "./orderTableColumn"; import OrderBulkActionsBar from "./orderBulkActionsBar"; import { formatPriceString } from "/client/api"; import ProductImage from "./productImage"; +import { getBillingInfo, getShippingInfo } from "../../lib/helpers/orderHelpers"; const classNames = { colClassNames: { @@ -34,32 +34,6 @@ const classNames = { } }; -/** - * getBillingInfo - * - * @summary get proper billing object as per current active shop - * @param {Object} order - order object to check against - * @return {Object} proper billing object to use - */ -function getBillingInfo(order) { - return order.billing.find( - billing => billing.shopId === Reaction.getShopId() - ) || {}; -} - -/** - * getShippingInfo - * - * @summary get proper shipping object as per current active shop - * @param {Object} order - order object to check against - * @return {Object} proper shipping object to use - */ -function getShippingInfo(order) { - return order.shipping.find( - shipping => shipping.shopId === Reaction.getShopId() - ) || {}; -} - class OrderTable extends Component { static propTypes = { displayMedia: PropTypes.func, diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index 9fcb35dc85c..95877bc4688 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -12,6 +12,7 @@ import { ORDER_LIST_SELECTED_ORDER_PREFERENCE_NAME, shippingStates } from "../../lib/constants"; +import { getShippingInfo } from "../../lib/helpers/orderHelpers"; const shippingStrings = ["picked", "packed", "labeled", "shipped"]; @@ -70,17 +71,6 @@ const OrderHelper = { } }; -/** - * getShipppingObject - * - * @summary get proper shipping object as per current active shop - * @param {Object} order - order object to check against - * @return {Object} proper shipping object to use - */ -function getShipppingObject(order) { - return order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); -} - class OrderDashboardContainer extends Component { static propTypes = { handleMenuClick: PropTypes.func, @@ -370,7 +360,7 @@ class OrderDashboardContainer extends Component { // TODO: rethink this type of flow for updating shipping statuses selectedOrders.forEach((order) => { - const shippingRecord = getShipppingObject(order); + const shippingRecord = getShippingInfo(order); Meteor.call(`orders/shipment${capitalizeStatus}`, order, shippingRecord, (err) => { if (err) { @@ -513,7 +503,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = getShipppingObject(order).workflow; + const orderWorkflow = getShippingInfo(order).workflow; // check if the order(s) are in this state already or in the previous state // TODO: model this with the assumption that there may be different workflows @@ -564,7 +554,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = getShipppingObject(order).workflow; + const orderWorkflow = getShippingInfo(order).workflow; // check if the order(s) are in this state already or in one of the previous states @@ -624,7 +614,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = getShipppingObject(order).workflow; + const orderWorkflow = getShippingInfo(order).workflow; // check if the order(s) are in this state already or in one of the previous states // TODO: model this with the assumption that there may be different workflows @@ -684,7 +674,7 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = getShipppingObject(order).workflow.status; + const orderWorkflow = getShippingInfo(order).workflow.status; // check if the order(s) are in this state already or in one of the previous states // TODO: model this with the assumption that there may be different workflows diff --git a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js index 2f06cf8b585..ed78ea1aadd 100644 --- a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js +++ b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js @@ -6,21 +6,9 @@ import { Meteor } from "meteor/meteor"; import { composeWithTracker } from "@reactioncommerce/reaction-components"; import { Orders } from "/lib/collections"; import { Card, CardHeader, CardBody, CardGroup } from "/imports/plugins/core/ui/client/components"; -import { Reaction, i18next } from "/client/api"; +import { i18next } from "/client/api"; import OrderSummary from "../components/orderSummary"; - -/** - * getShippingInfo - * - * @summary get proper shipping object as per current active shop - * @param {Object} order - order object to check against - * @return {Object} proper shipping object to use - */ -function getShippingInfo(order) { - return order.shipping.find( - shipping => shipping.shopId === Reaction.getShopId() - ) || {}; -} +import { getShippingInfo } from "../../lib/helpers/orderHelpers"; class OrderSummaryContainer extends Component { static propTypes = { diff --git a/imports/plugins/core/orders/client/templates/list/ordersList.js b/imports/plugins/core/orders/client/templates/list/ordersList.js index 1798a81a65a..17b283113af 100644 --- a/imports/plugins/core/orders/client/templates/list/ordersList.js +++ b/imports/plugins/core/orders/client/templates/list/ordersList.js @@ -3,6 +3,7 @@ import { Template } from "meteor/templating"; import { Orders, Shops } from "/lib/collections"; import { Reaction } from "/client/api"; + /** * dashboardOrdersList helpers * @@ -28,7 +29,10 @@ Template.dashboardOrdersList.helpers({ return moment(this.createdAt).fromNow(); }, shipmentTracking() { - return this.shipping.find(shipping => shipping.shopId === Reaction.getShopId()).shipmentMethod.tracking; + const shippingObject = this.shipping.find((shipping) => { + return shipping.shopId === Reaction.getShopId(); + }); + return shippingObject.shipmentMethod.tracking; }, shopName() { const shop = Shops.findOne(this.shopId); diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js index b594a93da45..a0afd59b093 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js @@ -5,6 +5,7 @@ import { ReactiveVar } from "meteor/reactive-var"; import { Template } from "meteor/templating"; import { i18next, Reaction } from "/client/api"; import { Orders } from "/lib/collections"; +import { getShippingInfo } from "../../../lib/helpers/orderHelpers"; Template.coreOrderShippingTracking.onCreated(() => { const template = Template.instance(); @@ -44,7 +45,7 @@ Template.coreOrderShippingTracking.events({ }, "click [data-event-action=shipmentShipped]": function () { const template = Template.instance(); - const shipment = template.order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shipment = getShippingInfo(template.order); Meteor.call("orders/shipmentShipped", template.order, shipment, (err) => { if (err) { Alerts.toast(i18next.t("mail.alerts.cantSendEmail"), "error"); @@ -77,7 +78,7 @@ Template.coreOrderShippingTracking.events({ "click [data-event-action=shipmentPacked]": () => { const template = Template.instance(); - const shipment = template.order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shipment = getShippingInfo(template.order); Meteor.call("orders/shipmentPacked", template.order, shipment); }, @@ -107,7 +108,7 @@ Template.coreOrderShippingTracking.events({ Template.coreOrderShippingTracking.helpers({ printableLabels() { const order = Template.instance().order; - const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shipment = getShippingInfo(order); const { shippingLabelUrl, customsLabelUrl } = shipment; if (shippingLabelUrl || customsLabelUrl) { return { shippingLabelUrl, customsLabelUrl }; @@ -175,7 +176,7 @@ Template.coreOrderShippingTracking.helpers({ if (settings && settings.flatRates.enabled === true) { const template = Template.instance(); const order = template.order; - const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shipment = getShippingInfo(order); const editing = template.showTrackingEditForm.get(); let view = false; if (editing === true || !shipment.tracking && editing === false) { @@ -193,11 +194,11 @@ Template.coreOrderShippingTracking.helpers({ }, shipment() { const order = Template.instance().order; - return order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + return getShippingInfo(order); }, shipmentReady() { const order = Template.instance().order; - const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shipment = getShippingInfo(order); return _.includes(shipment.workflow.workflow, "coreOrderWorkflow/packed") && shipment.tracking || _.includes(shipment.workflow.workflow, "coreOrderWorkflow/packed"); diff --git a/imports/plugins/core/orders/lib/helpers/orderHelpers.js b/imports/plugins/core/orders/lib/helpers/orderHelpers.js new file mode 100644 index 00000000000..8cebbd10395 --- /dev/null +++ b/imports/plugins/core/orders/lib/helpers/orderHelpers.js @@ -0,0 +1,29 @@ +import { Reaction } from "/client/api"; + +/** + * getBillingInfo + * + * @summary get proper billing object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper billing object to use + */ +export function getBillingInfo(order) { + const billingInfo = order.billing.find((billing) => { + return billing.shopId === Reaction.getShopId(); + }); + return billingInfo || {}; +} + +/** + * getShippingInfo + * + * @summary get proper shipping object as per current active shop + * @param {Object} order - order object to check against + * @return {Object} proper shipping object to use + */ +export function getShippingInfo(order) { + const shippingInfo = order.shipping.find((shipping) => { + return shipping.shopId === Reaction.getShopId(); + }); + return shippingInfo || {}; +} diff --git a/server/methods/core/orders.app-test.js b/server/methods/core/orders.app-test.js index 32415385fac..8f954d9f63c 100644 --- a/server/methods/core/orders.app-test.js +++ b/server/methods/core/orders.app-test.js @@ -80,16 +80,25 @@ describe("orders test", function () { } function billingObjectMethod(orderObject) { - return orderObject.billing.find(billing => billing.shopId === shopId); + const billingObject = orderObject.billing.find((billing) => { + return billing.shopId === shopId; + }); + return billingObject; } function shippingObjectMethod(orderObject) { - return orderObject.shipping.find(shipping => shipping.shopId === shopId); + const shippingObject = orderObject.shipping.find((shipping) => { + return shipping.shopId === shopId; + }); + return shippingObject; } function orderCreditMethod(orderData) { const billingRecord = orderData.billing.filter(value => value.paymentMethod.method === "credit"); - return billingRecord.find(billing => billing.shopId === shopId); + const billingObject = billingRecord.find((billing) => { + return billing.shopId === shopId; + }); + return billingObject; } describe("orders/cancelOrder", function () { diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index 224f6805c35..c8ae909003e 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -17,12 +17,18 @@ import { Logger, Hooks, Reaction } from "/server/api"; // returns entire payment method export function orderCreditMethod(order) { const creditBillingRecords = order.billing.filter(value => value.paymentMethod.method === "credit"); - return creditBillingRecords.find(billing => billing.shopId === Reaction.getShopId()); + const billingRecord = creditBillingRecords.find((billing) => { + return billing.shopId === Reaction.getShopId(); + }); + return billingRecord; } // helper to return the order debit object export function orderDebitMethod(order) { const debitBillingRecords = order.billing.filter(value => value.paymentMethod.method === "debit"); - return debitBillingRecords.find(billing => billing.shopId === Reaction.getShopId()); + const billingRecord = debitBillingRecords.find((billing) => { + return billing.shopId === Reaction.getShopId(); + }); + return billingRecord; } // REVIEW: This jsdoc doesn't seem to be accurate From 2db1e560b7be4d70c10581485b6c7ac76b79008b Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 19 Sep 2017 21:52:43 +0300 Subject: [PATCH 34/44] Replace empty string object key with non-empty string; create headerless column using colHeader --- .../orders/client/components/orderTable.js | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 77c21b9c988..d08bf2d1186 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -13,24 +13,24 @@ import { getBillingInfo, getShippingInfo } from "../../lib/helpers/orderHelpers" const classNames = { colClassNames: { - "Name": "order-table-column-name", - "Email": "order-table-column-email", - "Date": "order-table-column-date hidden-xs hidden-sm", - "ID": "order-table-column-id hidden-xs hidden-sm", - "Total": "order-table-column-total", - "Shipping": "order-table-column-shipping hidden-xs hidden-sm", - "Status": "order-table-column-status", - "": "order-table-column-control" + Name: "order-table-column-name", + Email: "order-table-column-email", + Date: "order-table-column-date hidden-xs hidden-sm", + ID: "order-table-column-id hidden-xs hidden-sm", + Total: "order-table-column-total", + Shipping: "order-table-column-shipping hidden-xs hidden-sm", + Status: "order-table-column-status", + Control: "order-table-column-control" }, headerClassNames: { - "Name": "order-table-header-name", - "Email": "order-table-header-email", - "Date": "order-table-header-date hidden-xs hidden-sm", - "ID": "order-table-header-id hidden-xs hidden-sm", - "Total": "order-table-header-total", - "Shipping": "order-table-header-shipping hidden-xs hidden-sm", - "Status": "order-table-header-status", - "": "order-table-header-control" + Name: "order-table-header-name", + Email: "order-table-header-email", + Date: "order-table-header-date hidden-xs hidden-sm", + ID: "order-table-header-id hidden-xs hidden-sm", + Total: "order-table-header-total", + Shipping: "order-table-header-shipping hidden-xs hidden-sm", + Status: "order-table-header-status", + Control: "order-table-header-control" } }; @@ -200,35 +200,35 @@ class OrderTable extends Component { if (this.props.isOpen) { // Render order list column/row data const filteredFields = { - "Name": { + Name: { accessor: row => getShippingInfo(row).address.fullName, id: "shippingfullName" }, - "Email": { + Email: { accessor: "email", id: "email" }, - "Date": { + Date: { accessor: "createdAt", id: "createdAt" }, - "ID": { + ID: { accessor: "_id", id: "_id" }, - "Total": { + Total: { accessor: row => getBillingInfo(row).invoice.total, id: "billingTotal" }, - "Shipping": { + Shipping: { accessor: row => getShippingInfo(row).workflow.status, id: "shippingStatus" }, - "Status": { + Status: { accessor: "workflow.status", id: "workflow.status" }, - "": { + Control: { accessor: "", id: "" } @@ -275,11 +275,13 @@ class OrderTable extends Component { ); } - if (columnName === "") { + if (columnName === "Control") { + colHeader = " "; resizable = false; sortable = false; } + const columnMeta = { accessor: filteredFields[columnName].accessor, id: filteredFields[columnName].id, From c566890cc3b29d9ae304b000350c86be5f20557b Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 19 Sep 2017 22:02:48 +0300 Subject: [PATCH 35/44] Fix typo; prefer 'error' over 'err' --- .../orders/client/components/orderTable.js | 2 +- .../containers/orderDashboardContainer.js | 18 +++++++++--------- .../templates/workflow/shippingTracking.js | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index d08bf2d1186..2b7cc999c47 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -137,7 +137,7 @@ class OrderTable extends Component { renderShipmentInfo(order) { const emailAddress = order.email || - ; + ; return (
diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index 95877bc4688..2daf17c2033 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -362,9 +362,9 @@ class OrderDashboardContainer extends Component { selectedOrders.forEach((order) => { const shippingRecord = getShippingInfo(order); - Meteor.call(`orders/shipment${capitalizeStatus}`, order, shippingRecord, (err) => { - if (err) { - Alerts.toast(`An error occured while setting the status: ${err}`, "error"); + Meteor.call(`orders/shipment${capitalizeStatus}`, order, shippingRecord, (error) => { + if (error) { + Alerts.toast(`An error occured while setting the status: ${error}`, "error"); } else { Meteor.call("orders/updateHistory", order._id, "Shipping state set by bulk operation", status); } @@ -753,25 +753,25 @@ class OrderDashboardContainer extends Component { // TODO: send these orders in batch as an array. This would entail re-writing the // "orders/approvePayment" method to receive an array of orders as a param. selectedOrders.forEach((order) => { - Meteor.call("orders/approvePayment", order, (err) => { - if (err) { + Meteor.call("orders/approvePayment", order, (error) => { + if (error) { this.setState({ isLoading: { capturePayment: false } }); - Alerts.toast(`An error occured while approving the payment: ${err}`, "error"); + Alerts.toast(`An error occured while approving the payment: ${error}`, "error"); } else { // TODO: send these orders in batch as an array. This would entail re-writing the // "orders/capturePayments" method to receive an array of orders as a param. - Meteor.call("orders/capturePayments", order._id, (error) => { - if (error) { + Meteor.call("orders/capturePayments", order._id, (err) => { + if (err) { this.setState({ isLoading: { capturePayment: false } }); - Alerts.toast(`An error occured while capturing the payment: ${error}`, "error"); + Alerts.toast(`An error occured while capturing the payment: ${err}`, "error"); } orderCount++; diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js index a0afd59b093..b86beec1d14 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js @@ -39,15 +39,15 @@ Template.coreOrderShippingTracking.events({ Meteor.call("shipping/status/refresh", orderId, (result) => { if (result && result.error) { instance.$("#btn-processing").addClass("hidden"); - Alerts.toast(i18next.t("orderShipping.labelError", { err: result.error }), "error", { timeout: 7000 }); + Alerts.toast(i18next.t("orderShipping.labelError", { error: result.error }), "error", { timeout: 7000 }); } }); }, "click [data-event-action=shipmentShipped]": function () { const template = Template.instance(); const shipment = getShippingInfo(template.order); - Meteor.call("orders/shipmentShipped", template.order, shipment, (err) => { - if (err) { + Meteor.call("orders/shipmentShipped", template.order, shipment, (error) => { + if (error) { Alerts.toast(i18next.t("mail.alerts.cantSendEmail"), "error"); } else { Alerts.toast(i18next.t("mail.alerts.emailSent"), "success"); @@ -67,8 +67,8 @@ Template.coreOrderShippingTracking.events({ "click [data-event-action=resendNotification]": function () { const template = Template.instance(); - Meteor.call("orders/sendNotification", template.order, "shipped", (err) => { - if (err) { + Meteor.call("orders/sendNotification", template.order, "shipped", (error) => { + if (error) { Alerts.toast(i18next.t("mail.alerts.cantSendEmail"), "error"); } else { Alerts.toast(i18next.t("mail.alerts.emailSent"), "success"); From 50c4f2b67b191b341ba6d4b2d0d08398520c52b9 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 19 Sep 2017 22:19:01 +0300 Subject: [PATCH 36/44] Revert spinner fix --- imports/plugins/core/accounts/client/components/updateEmail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imports/plugins/core/accounts/client/components/updateEmail.js b/imports/plugins/core/accounts/client/components/updateEmail.js index 4f3f05af2ca..c4d2cbef75d 100644 --- a/imports/plugins/core/accounts/client/components/updateEmail.js +++ b/imports/plugins/core/accounts/client/components/updateEmail.js @@ -50,7 +50,7 @@ class UpdateEmail extends Component { /> Date: Thu, 21 Sep 2017 03:02:56 +0300 Subject: [PATCH 37/44] Scope nested callback errors based on Meteor call action --- .../client/containers/orderDashboardContainer.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index be746063a88..b06d619cdb4 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -796,25 +796,25 @@ class OrderDashboardContainer extends Component { // TODO: send these orders in batch as an array. This would entail re-writing the // "orders/approvePayment" method to receive an array of orders as a param. selectedOrders.forEach((order) => { - Meteor.call("orders/approvePayment", order, (error) => { - if (error) { + Meteor.call("orders/approvePayment", order, (approvePaymentError) => { + if (approvePaymentError) { this.setState({ isLoading: { capturePayment: false } }); - Alerts.toast(`An error occured while approving the payment: ${error}`, "error"); + Alerts.toast(`An error occured while approving the payment: ${approvePaymentError}`, "error"); } else { // TODO: send these orders in batch as an array. This would entail re-writing the // "orders/capturePayments" method to receive an array of orders as a param. - Meteor.call("orders/capturePayments", order._id, (err) => { - if (err) { + Meteor.call("orders/capturePayments", order._id, (capturePaymentError) => { + if (capturePaymentError) { this.setState({ isLoading: { capturePayment: false } }); - Alerts.toast(`An error occured while capturing the payment: ${err}`, "error"); + Alerts.toast(`An error occured while capturing the payment: ${capturePaymentError}`, "error"); } orderCount++; From 2a179402037f607a8da522902eae179601ff46c9 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Thu, 21 Sep 2017 06:00:56 +0300 Subject: [PATCH 38/44] Handle errors if getBillingInfo method returns empty object --- .../orders/client/components/orderSummary.js | 8 ++- .../orders/client/components/orderTable.js | 5 +- .../client/components/orderTableColumn.js | 4 +- .../client/containers/invoiceContainer.js | 67 ++++++++----------- .../templates/workflow/shippingInvoice.js | 23 ++++--- .../core/orders/lib/helpers/orderHelpers.js | 4 +- 6 files changed, 56 insertions(+), 55 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index 3b25ef594b4..61aae04c698 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -44,6 +44,8 @@ class OrderSummary extends Component { render() { const { dateFormat, tracking, order, profileShippingAddress, printableLabels } = this.props; + const paymentMethod = getBillingInfo(order).paymentMethod; + const invoice = getBillingInfo(order).invoice; return (
@@ -87,21 +89,21 @@ class OrderSummary extends Component {
Processor
- {getBillingInfo(order).paymentMethod.processor} + {paymentMethod && paymentMethod.processor}
Payment
- {getBillingInfo(order).paymentMethod.storedCard} ({getBillingInfo(order).invoice.total}) + {paymentMethod && paymentMethod.storedCard} ({invoice && invoice.total})
Transaction
- {getBillingInfo(order).paymentMethod.transactionId} + {paymentMethod && paymentMethod.transactionId}
diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 2b7cc999c47..512fb64342d 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -91,6 +91,7 @@ class OrderTable extends Component { renderOrderInfo(order) { const { displayMedia } = this.props; + const invoice = getBillingInfo(order).invoice; return (
@@ -111,7 +112,7 @@ class OrderTable extends Component { - Total: {formatPriceString(getBillingInfo(order).invoice.total)} + Total: {formatPriceString(invoice && invoice.total)}
@@ -217,7 +218,7 @@ class OrderTable extends Component { id: "_id" }, Total: { - accessor: row => getBillingInfo(row).invoice.total, + accessor: row => getBillingInfo(row).invoice && getBillingInfo(row).invoice.total, id: "billingTotal" }, Shipping: { diff --git a/imports/plugins/core/orders/client/components/orderTableColumn.js b/imports/plugins/core/orders/client/components/orderTableColumn.js index a67f8f88b6a..d990de7f7e0 100644 --- a/imports/plugins/core/orders/client/components/orderTableColumn.js +++ b/imports/plugins/core/orders/client/components/orderTableColumn.js @@ -5,6 +5,7 @@ import moment from "moment"; import { formatPriceString } from "/client/api"; import Avatar from "react-avatar"; import { Badge, ClickToCopy, Icon, RolloverCheckbox, Checkbox } from "@reactioncommerce/reaction-ui"; +import { getBillingInfo } from "../../lib/helpers/orderHelpers"; class OrderTableColumn extends Component { static propTypes = { @@ -48,6 +49,7 @@ class OrderTableColumn extends Component { render() { const columnAccessor = this.props.row.column.id; + const invoice = getBillingInfo(this.props.row.original).invoice; if (columnAccessor === "shippingfullName") { return ( @@ -85,7 +87,7 @@ class OrderTableColumn extends Component { if (columnAccessor === "billingTotal") { return (
- {formatPriceString(this.props.row.original.billing[0].invoice.total)} + {formatPriceString(invoice && invoice.total)}
); } diff --git a/imports/plugins/core/orders/client/containers/invoiceContainer.js b/imports/plugins/core/orders/client/containers/invoiceContainer.js index fe27871388f..07b24633c5e 100644 --- a/imports/plugins/core/orders/client/containers/invoiceContainer.js +++ b/imports/plugins/core/orders/client/containers/invoiceContainer.js @@ -7,6 +7,7 @@ import { i18next, Logger, Reaction, formatPriceString } from "/client/api"; import { Media, Packages } from "/lib/collections"; import { composeWithTracker, registerComponent } from "@reactioncommerce/reaction-components"; import Invoice from "../components/invoice.js"; +import { getBillingInfo } from "../../lib/helpers/orderHelpers"; class InvoiceContainer extends Component { static propTypes = { @@ -219,10 +220,10 @@ class InvoiceContainer extends Component { hasRefundingEnabled() { const order = this.state.order; const orderBillingInfo = getBillingInfo(order); - const paymentMethodId = orderBillingInfo.paymentMethod.paymentPackageId; - const paymentMethodName = orderBillingInfo.paymentMethod.paymentSettingsKey; + const paymentMethodId = orderBillingInfo.paymentMethod && orderBillingInfo.paymentMethod.paymentPackageId; + const paymentMethodName = orderBillingInfo.paymentMethod && orderBillingInfo.paymentMethod.paymentSettingsKey; const paymentMethod = Packages.findOne({ _id: paymentMethodId }); - const isRefundable = paymentMethod.settings[paymentMethodName].support.includes("Refund"); + const isRefundable = paymentMethod && paymentMethod.settings[paymentMethodName].support.includes("Refund"); return isRefundable; } @@ -248,20 +249,20 @@ class InvoiceContainer extends Component { handleCancelPayment = (event) => { event.preventDefault(); const order = this.state.order; - const invoiceTotal = getBillingInfo(order).invoice.total; + const invoiceTotal = getBillingInfo(order).invoice && getBillingInfo(order).invoice.total; const currencySymbol = this.state.currency.symbol; Meteor.subscribe("Packages", Reaction.getShopId()); - const packageId = getBillingInfo(order).paymentMethod.paymentPackageId; - const settingsKey = getBillingInfo(order).paymentMethod.paymentSettingsKey; + const packageId = getBillingInfo(order).paymentMethod && getBillingInfo(order).paymentMethod.paymentPackageId; + const settingsKey = getBillingInfo(order).paymentMethod && getBillingInfo(order).paymentMethod.paymentSettingsKey; // check if payment provider supports de-authorize const checkSupportedMethods = Packages.findOne({ _id: packageId, shopId: Reaction.getShopId() }).settings[settingsKey].support; - const orderStatus = getBillingInfo(order).paymentMethod.status; - const orderMode = getBillingInfo(order).paymentMethod.mode; + const orderStatus = getBillingInfo(order).paymentMethod && getBillingInfo(order).paymentMethod.status; + const orderMode = getBillingInfo(order).paymentMethod && getBillingInfo(order).paymentMethod.mode; let alertText; if (_.includes(checkSupportedMethods, "de-authorize") || @@ -297,18 +298,18 @@ class InvoiceContainer extends Component { const currencySymbol = this.state.currency.symbol; const order = this.state.order; - const paymentMethod = orderCreditMethod(order).paymentMethod; - const orderTotal = paymentMethod.amount; - const discounts = paymentMethod.discounts; + const paymentMethod = orderCreditMethod(order) && orderCreditMethod(order).paymentMethod; + const orderTotal = paymentMethod && paymentMethod.amount; + const discounts = paymentMethod && paymentMethod.discounts; const refund = value; const refunds = this.state.refunds; - const refundTotal = refunds.reduce((acc, item) => acc + parseFloat(item.amount), 0); + const refundTotal = refunds && refunds.reduce((acc, item) => acc + parseFloat(item.amount), 0); let adjustedTotal; // TODO extract Stripe specific fullfilment payment handling out of core. // Stripe counts discounts as refunds, so we need to re-add the discount to not "double discount" in the adjustedTotal - if (paymentMethod.processor === "Stripe") { + if (paymentMethod && paymentMethod.processor === "Stripe") { adjustedTotal = accounting.toFixed(orderTotal + discounts - refundTotal, 2); } else { adjustedTotal = accounting.toFixed(orderTotal - refundTotal, 2); @@ -347,8 +348,8 @@ class InvoiceContainer extends Component { } handleRefundItems = () => { - const paymentMethod = orderCreditMethod(this.state.order).paymentMethod; - const orderMode = paymentMethod.mode; + const paymentMethod = orderCreditMethod(this.state.order) && orderCreditMethod(this.state.order).paymentMethod; + const orderMode = paymentMethod && paymentMethod.mode; const order = this.state.order; // Check if payment is yet to be captured approve and capture first before return @@ -358,7 +359,7 @@ class InvoiceContainer extends Component { type: "warning", text: i18next.t("order.refundItemsApproveAlert", { refundItemsQuantity: this.getRefundedItemsInfo().quantity, - totalAmount: formatPriceString(getBillingInfo(order).invoice.total) + totalAmount: formatPriceString(getBillingInfo(order).invoice && getBillingInfo(order).invoice.total) }), showCancelButton: true, confirmButtonText: i18next.t("order.approveInvoice") @@ -378,7 +379,7 @@ class InvoiceContainer extends Component { title: i18next.t("order.refundItemsTitle"), text: i18next.t("order.refundItemsCaptureAlert", { refundItemsQuantity: this.getRefundedItemsInfo().quantity, - totalAmount: formatPriceString(getBillingInfo(order).invoice.total) + totalAmount: formatPriceString(getBillingInfo(order).invoice && getBillingInfo(order).invoice.total) }), type: "warning", showCancelButton: true, @@ -392,8 +393,8 @@ class InvoiceContainer extends Component { } alertToRefund = (order) => { - const paymentMethod = orderCreditMethod(order).paymentMethod; - const orderMode = paymentMethod.mode; + const paymentMethod = orderCreditMethod(order) && orderCreditMethod(order).paymentMethod; + const orderMode = paymentMethod && paymentMethod.mode; const refundInfo = this.getRefundedItemsInfo(); Alerts.alert({ @@ -484,19 +485,6 @@ class InvoiceContainer extends Component { } } -/** - * @method getBillingInfo - * @summary helper method to get appropriate billing info - * @param {Object} order - object representing an order - * @return {Object} object representing the order billing info - */ -function getBillingInfo(order) { - return order.billing.find( - billing => billing.shopId === Reaction.getShopId() - ) || {}; -} - - /** * @method orderCreditMethod * @summary helper method to return the order payment object @@ -506,7 +494,7 @@ function getBillingInfo(order) { function orderCreditMethod(order) { const billingInfo = getBillingInfo(order); - if (billingInfo.paymentMethod.method === "credit") { + if (billingInfo.paymentMethod && billingInfo.paymentMethod.method === "credit") { return billingInfo; } } @@ -587,10 +575,11 @@ const composer = (props, onData) => { const refunds = props.refunds; const shopBilling = getBillingInfo(order); + const creditMethod = orderCreditMethod(order); - const paymentMethod = orderCreditMethod(order).paymentMethod; - const orderStatus = orderCreditMethod(order).paymentMethod.status; - const orderDiscounts = orderCreditMethod(order).invoice.discounts; + const paymentMethod = creditMethod && creditMethod.paymentMethod; + const orderStatus = creditMethod && creditMethod.paymentMethod && creditMethod.paymentMethod.status; + const orderDiscounts = creditMethod && creditMethod.invoice.discounts; const paymentApproved = orderStatus === "approved"; const showAfterPaymentCaptured = orderStatus === "completed"; @@ -602,12 +591,12 @@ const composer = (props, onData) => { // get adjusted Total let adjustedTotal; - const refundTotal = refunds.reduce((acc, item) => acc + parseFloat(item.amount), 0); + const refundTotal = refunds && refunds.reduce((acc, item) => acc + parseFloat(item.amount), 0); - if (paymentMethod.processor === "Stripe") { + if (paymentMethod && paymentMethod.processor === "Stripe") { adjustedTotal = Math.abs(paymentMethod.amount + orderDiscounts - refundTotal); } - adjustedTotal = Math.abs(paymentMethod.amount - refundTotal); + adjustedTotal = Math.abs(paymentMethod && paymentMethod.amount - refundTotal); // get invoice const invoice = Object.assign({}, shopBilling.invoice, { diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js b/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js index 9546762f42b..be57d29b5c4 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js @@ -8,13 +8,19 @@ import { ReactiveDict } from "meteor/reactive-dict"; import { i18next, Logger, Reaction } from "/client/api"; import { Orders, Shops, Packages } from "/lib/collections"; import InvoiceContainer from "../../containers/invoiceContainer.js"; - +import { getBillingInfo } from "../../../lib/helpers/orderHelpers"; // helper to return the order payment object // the first credit paymentMethod on the order // returns entire payment method function orderCreditMethod(order) { - return order.billing.filter(value => value.paymentMethod.method === "credit")[0]; + const creditMethods = order.billing && order.billing.filter((value) => { + return value && value.paymentMethod && value.paymentMethod.method === "credit"; + }); + const creditMethod = creditMethods && creditMethods.find((billing) => { + billing && billing.shopId === Reaction.getShopId(); + }); + return creditMethod || {}; } // @@ -115,20 +121,21 @@ Template.coreOrderShippingInvoice.events({ "click [data-event-action=cancelOrder]": (event, instance) => { event.preventDefault(); const order = instance.state.get("order"); - const invoiceTotal = order.billing[0].invoice.total; + const invoiceTotal = getBillingInfo(order).invoice && getBillingInfo(order).invoice.total; const currencySymbol = instance.state.get("currency").symbol; + const paymentMethod = getBillingInfo(order).paymentMethod; Meteor.subscribe("Packages", Reaction.getShopId()); - const packageId = order.billing[0].paymentMethod.paymentPackageId; - const settingsKey = order.billing[0].paymentMethod.paymentSettingsKey; + const packageId = paymentMethod && paymentMethod.paymentPackageId; + const settingsKey = paymentMethod && paymentMethod.paymentSettingsKey; // check if payment provider supports de-authorize const checkSupportedMethods = Packages.findOne({ _id: packageId, shopId: Reaction.getShopId() }).settings[settingsKey].support; - const orderStatus = order.billing[0].paymentMethod.status; - const orderMode = order.billing[0].paymentMethod.mode; + const orderStatus = paymentMethod && paymentMethod.status; + const orderMode = paymentMethod && paymentMethod.mode; let alertText; if (_.includes(checkSupportedMethods, "de-authorize") || @@ -189,7 +196,7 @@ Template.coreOrderShippingInvoice.helpers({ disabled() { const instance = Template.instance(); const order = instance.state.get("order"); - const status = orderCreditMethod(order).paymentMethod.status; + const status = orderCreditMethod(order).paymentMethod && orderCreditMethod(order).paymentMethod.status; if (status === "approved" || status === "completed") { return "disabled"; diff --git a/imports/plugins/core/orders/lib/helpers/orderHelpers.js b/imports/plugins/core/orders/lib/helpers/orderHelpers.js index 8cebbd10395..eb7e1b5da3d 100644 --- a/imports/plugins/core/orders/lib/helpers/orderHelpers.js +++ b/imports/plugins/core/orders/lib/helpers/orderHelpers.js @@ -8,8 +8,8 @@ import { Reaction } from "/client/api"; * @return {Object} proper billing object to use */ export function getBillingInfo(order) { - const billingInfo = order.billing.find((billing) => { - return billing.shopId === Reaction.getShopId(); + const billingInfo = order.billing && order.billing.find((billing) => { + return billing && (billing.shopId === Reaction.getShopId()); }); return billingInfo || {}; } From 6e59986d68bcc862902476014e889fc1a9268efa Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Thu, 21 Sep 2017 20:49:44 +0300 Subject: [PATCH 39/44] Handle errors if getBillingInfo method returns empty object --- .../orders/client/components/orderSummary.js | 36 +++-- .../orders/client/components/orderTable.js | 13 +- .../client/containers/invoiceContainer.js | 4 +- .../containers/orderDashboardContainer.js | 128 ++++++++++-------- .../containers/orderSummaryContainer.js | 29 ++-- .../templates/workflow/shippingTracking.js | 22 +-- .../core/orders/lib/helpers/orderHelpers.js | 6 +- .../server/methods/searchcollections.js | 18 +-- 8 files changed, 147 insertions(+), 109 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index 61aae04c698..508afcb3f8b 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -15,7 +15,8 @@ class OrderSummary extends Component { } badgeStatus() { - const orderStatus = this.props.order.workflow.status; + const order = this.props.order; + const orderStatus = order && order.workflow && order.workflow.status; if (orderStatus === "new") { return "info"; @@ -46,11 +47,15 @@ class OrderSummary extends Component { const { dateFormat, tracking, order, profileShippingAddress, printableLabels } = this.props; const paymentMethod = getBillingInfo(order).paymentMethod; const invoice = getBillingInfo(order).invoice; + const shipmentMethod = getShippingInfo(order).shipmentMethod; return (
-
- {profileShippingAddress.fullName} +
+ {profileShippingAddress && profileShippingAddress.fullName}
{order.email}
@@ -61,8 +66,8 @@ class OrderSummary extends Component {
@@ -110,7 +115,7 @@ class OrderSummary extends Component {
Carrier
- {getShippingInfo(order).shipmentMethod.carrier} - {getShippingInfo(order).shipmentMethod.label} + { shipmentMethod && shipmentMethod.carrier} - {shipmentMethod && shipmentMethod.label}
@@ -141,15 +146,24 @@ class OrderSummary extends Component {
Ship to
- Phone: {profileShippingAddress.phone} + Phone: {profileShippingAddress && profileShippingAddress.phone}
- {profileShippingAddress.fullName} -
{profileShippingAddress.address1} - {profileShippingAddress.address2 &&
{profileShippingAddress.address2}
} -
{profileShippingAddress.city}, {profileShippingAddress.region}, {profileShippingAddress.country} {profileShippingAddress.postal} + {profileShippingAddress && profileShippingAddress.fullName} +
+ {profileShippingAddress && profileShippingAddress.address1} + {profileShippingAddress && profileShippingAddress.address2 && +
{profileShippingAddress.address2}
+ } +
+ + {profileShippingAddress && profileShippingAddress.city},  + {profileShippingAddress && profileShippingAddress.region},  + {profileShippingAddress && profileShippingAddress.country}  + {profileShippingAddress && profileShippingAddress.postal} +
); diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 512fb64342d..7447bc51f98 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -139,6 +139,7 @@ class OrderTable extends Component { renderShipmentInfo(order) { const emailAddress = order.email || ; + const shipping = getShippingInfo(order); return (
@@ -146,17 +147,17 @@ class OrderTable extends Component { - {getShippingInfo(order).address.fullName} | {emailAddress} + {shipping.address && shipping.address.fullName} | {emailAddress}
getShippingInfo(row).address.fullName, + accessor: row => getShippingInfo(row).address && getShippingInfo(row).address.fullName, id: "shippingfullName" }, Email: { @@ -222,7 +223,7 @@ class OrderTable extends Component { id: "billingTotal" }, Shipping: { - accessor: row => getShippingInfo(row).workflow.status, + accessor: row => getShippingInfo(row).workflow && getShippingInfo(row).workflow.status, id: "shippingStatus" }, Status: { diff --git a/imports/plugins/core/orders/client/containers/invoiceContainer.js b/imports/plugins/core/orders/client/containers/invoiceContainer.js index 07b24633c5e..1e3c7bf3c09 100644 --- a/imports/plugins/core/orders/client/containers/invoiceContainer.js +++ b/imports/plugins/core/orders/client/containers/invoiceContainer.js @@ -626,7 +626,7 @@ const composer = (props, onData) => { // returns order items with shipping detail const returnItems = order.items.map((item) => { - const shipping = shipment.shipmentMethod; + const shipping = shipment && shipment.shipmentMethod; item.shipping = shipping; return item; }); @@ -653,7 +653,7 @@ const composer = (props, onData) => { const printOrder = Reaction.Router.pathFor("dashboard/pdf/orders", { hash: { id: props.order._id, - shipment: props.currentData.fulfillment._id + shipment: props.currentData.fulfillment && props.currentData.fulfillment._id } }); diff --git a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js index b06d619cdb4..a1e59bd4d2d 100644 --- a/imports/plugins/core/orders/client/containers/orderDashboardContainer.js +++ b/imports/plugins/core/orders/client/containers/orderDashboardContainer.js @@ -380,6 +380,9 @@ class OrderDashboardContainer extends Component { * @return {null} no return value */ shippingStatusUpdateCall = (selectedOrders, status) => { + const filteredSelectedOrders = selectedOrders.filter((order) => { + return order.shipping && Object.keys(getShippingInfo(order)).length; + }); this.setState({ isLoading: { [status]: true @@ -387,7 +390,7 @@ class OrderDashboardContainer extends Component { }); let orderText = "order"; - if (selectedOrders.length > 1) { + if (filteredSelectedOrders.length > 1) { orderText = "orders"; } @@ -402,7 +405,7 @@ class OrderDashboardContainer extends Component { // different shipping statuses to receive an array of objects(orders) as a param // TODO: rethink this type of flow for updating shipping statuses - selectedOrders.forEach((order) => { + filteredSelectedOrders.forEach((order) => { const shippingRecord = getShippingInfo(order); Meteor.call(`orders/shipment${capitalizeStatus}`, order, shippingRecord, (error) => { @@ -412,7 +415,7 @@ class OrderDashboardContainer extends Component { Meteor.call("orders/updateHistory", order._id, "Shipping state set by bulk operation", status); } orderCount++; - if (orderCount === selectedOrders.length) { + if (orderCount === filteredSelectedOrders.length) { this.setState({ shipping: { [status]: true @@ -423,7 +426,7 @@ class OrderDashboardContainer extends Component { }); Alerts.alert({ text: i18next.t("order.orderSetToState", { - orderNumber: selectedOrders.length, + orderNumber: filteredSelectedOrders.length, orderText: orderText, status: status }), @@ -551,19 +554,21 @@ class OrderDashboardContainer extends Component { // TODO: model this with the assumption that there may be different workflows // depending on the type of shop or product that a shop is selling. - if (orderWorkflow.status === "new") { - isNotPicked++; - } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { - isPicked++; - } else { - // check if the selected order(s) are being regressed back to this state - if (orderWorkflow.workflow.includes("coreOrderWorkflow/picked")) { - ordersToRegress++; - } else if (!orderWorkflow.workflow.includes("coreOrderWorkflow/picked") && - (orderWorkflow.status === "coreOrderWorkflow/packed" || - orderWorkflow.status === "coreOrderWorkflow/labeled" || - orderWorkflow.status === "coreOrderWorkflow/shipped")) { - ordersToRegress++; + if (orderWorkflow) { + if (orderWorkflow.status === "new") { + isNotPicked++; + } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { + isPicked++; + } else { + // check if the selected order(s) are being regressed back to this state + if (orderWorkflow.workflow.includes("coreOrderWorkflow/picked")) { + ordersToRegress++; + } else if (!orderWorkflow.workflow.includes("coreOrderWorkflow/picked") && + (orderWorkflow.status === "coreOrderWorkflow/packed" || + orderWorkflow.status === "coreOrderWorkflow/labeled" || + orderWorkflow.status === "coreOrderWorkflow/shipped")) { + ordersToRegress++; + } } } }); @@ -603,20 +608,22 @@ class OrderDashboardContainer extends Component { // TODO: model this with the assumption that there may be different workflows // depending on the type of shop or product that a shop is selling. - if (orderWorkflow.status === "new") { - isNotPicked++; - } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { - isNotPacked++; - } else if (orderWorkflow.status === "coreOrderWorkflow/packed") { - isPacked++; - } else { - // check if the selected order(s) are being regressed back to this state - if (orderWorkflow.workflow.includes("coreOrderWorkflow/packed")) { - ordersToRegress++; - } else if (!orderWorkflow.workflow.includes("coreOrderWorkflow/packed") && + if (orderWorkflow) { + if (orderWorkflow.status === "new") { + isNotPicked++; + } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { + isNotPacked++; + } else if (orderWorkflow.status === "coreOrderWorkflow/packed") { + isPacked++; + } else { + // check if the selected order(s) are being regressed back to this state + if (orderWorkflow.workflow.includes("coreOrderWorkflow/packed")) { + ordersToRegress++; + } else if (!orderWorkflow.workflow.includes("coreOrderWorkflow/packed") && (orderWorkflow.status === "coreOrderWorkflow/labeled" || orderWorkflow.status === "coreOrderWorkflow/shipped")) { - ordersToRegress++; + ordersToRegress++; + } } } }); @@ -662,21 +669,23 @@ class OrderDashboardContainer extends Component { // TODO: model this with the assumption that there may be different workflows // depending on the type of shop or product that a shop is selling. - if (orderWorkflow.status === "new") { - isNotPacked++; - whichFalseState = shippingStates.picked; - } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { - isNotPacked++; - whichFalseState = shippingStates.packed; - } else if (orderWorkflow.status === "coreOrderWorkflow/packed") { - isNotLabeled++; - } else if (orderWorkflow.status === "coreOrderWorkflow/labeled") { - isLabeled++; - } else { - // check if the selected order(s) are being regressed back to this state - if (orderWorkflow.workflow.includes("coreOrderWorkflow/labeled") || - orderWorkflow.status === "coreOrderWorkflow/shipped") { - ordersToRegress++; + if (orderWorkflow) { + if (orderWorkflow.status === "new") { + isNotPacked++; + whichFalseState = shippingStates.picked; + } else if (orderWorkflow.status === "coreOrderWorkflow/picked") { + isNotPacked++; + whichFalseState = shippingStates.packed; + } else if (orderWorkflow.status === "coreOrderWorkflow/packed") { + isNotLabeled++; + } else if (orderWorkflow.status === "coreOrderWorkflow/labeled") { + isLabeled++; + } else { + // check if the selected order(s) are being regressed back to this state + if (orderWorkflow.workflow.includes("coreOrderWorkflow/labeled") || + orderWorkflow.status === "coreOrderWorkflow/shipped") { + ordersToRegress++; + } } } }); @@ -717,24 +726,27 @@ class OrderDashboardContainer extends Component { // status of each order in regard to the other statuses // TODO: optimise this process to avoid having this similar repetitive block of code across 4 methods selectedOrders.forEach((order) => { - const orderWorkflow = getShippingInfo(order).workflow.status; + const orderWorkflow = getShippingInfo(order).workflow; // check if the order(s) are in this state already or in one of the previous states // TODO: model this with the assumption that there may be different workflows // depending on the type of shop or product that a shop is selling. - if (orderWorkflow === "new") { - isNotLabeled++; - whichFalseState = shippingStates.picked; - } else if (orderWorkflow === "coreOrderWorkflow/picked") { - isNotLabeled++; - whichFalseState = shippingStates.packed; - } else if (orderWorkflow === "coreOrderWorkflow/packed") { - isNotLabeled++; - whichFalseState = shippingStates.labeled; - } else if (orderWorkflow === "coreOrderWorkflow/labeled") { - isNotShipped++; - } else if (orderWorkflow === "coreOrderWorkflow/shipped") { - isShipped++; + if (orderWorkflow) { + const orderWorkflowStatus = orderWorkflow.status; + if (orderWorkflowStatus === "new") { + isNotLabeled++; + whichFalseState = shippingStates.picked; + } else if (orderWorkflowStatus === "coreOrderWorkflow/picked") { + isNotLabeled++; + whichFalseState = shippingStates.packed; + } else if (orderWorkflowStatus === "coreOrderWorkflow/packed") { + isNotLabeled++; + whichFalseState = shippingStates.labeled; + } else if (orderWorkflowStatus === "coreOrderWorkflow/labeled") { + isNotShipped++; + } else if (orderWorkflowStatus === "coreOrderWorkflow/shipped") { + isShipped++; + } } }); diff --git a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js index ed78ea1aadd..2dfca78d7da 100644 --- a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js +++ b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js @@ -138,22 +138,29 @@ const composer = (props, onData) => { // Find current order const order = Orders.findOne({ "_id": props.orderId, - "shipping._id": props.fulfillment._id + "shipping._id": props.fulfillment && props.fulfillment._id }); - const profileShippingAddress = getShippingInfo(order).address; + if (order) { + const profileShippingAddress = getShippingInfo(order).address; - if (order.workflow) { - if (order.workflow.status === "coreOrderCreated") { - order.workflow.status = "coreOrderCreated"; - Meteor.call("workflow/pushOrderWorkflow", "coreOrderWorkflow", "coreOrderCreated", order); + if (order.workflow) { + if (order.workflow.status === "coreOrderCreated") { + order.workflow.status = "coreOrderCreated"; + Meteor.call("workflow/pushOrderWorkflow", "coreOrderWorkflow", "coreOrderCreated", order); + } } - } - onData(null, { - order: order, - profileShippingAddress: profileShippingAddress - }); + onData(null, { + order: order, + profileShippingAddress: profileShippingAddress + }); + } else { + onData(null, { + order: {}, + profileShippingAddress: {} + }); + } } }; diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js index b86beec1d14..6470eb2c2e8 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js @@ -23,7 +23,7 @@ Template.coreOrderShippingTracking.onCreated(() => { } Tracker.autorun(() => { - template.order = getOrder(currentData.orderId, currentData.fulfillment._id); + template.order = getOrder(currentData.orderId, currentData.fulfillment && currentData.fulfillment._id); }); }); @@ -109,9 +109,12 @@ Template.coreOrderShippingTracking.helpers({ printableLabels() { const order = Template.instance().order; const shipment = getShippingInfo(order); - const { shippingLabelUrl, customsLabelUrl } = shipment; - if (shippingLabelUrl || customsLabelUrl) { - return { shippingLabelUrl, customsLabelUrl }; + + if (shipment) { + const { shippingLabelUrl, customsLabelUrl } = shipment; + if (shippingLabelUrl || customsLabelUrl) { + return { shippingLabelUrl, customsLabelUrl }; + } } return false; @@ -120,7 +123,7 @@ Template.coreOrderShippingTracking.helpers({ const currentData = Template.currentData(); const order = Template.instance().order; - const shippedItems = _.every(currentData.fulfillment.items, (shipmentItem) => { + const shippedItems = _.every(currentData.fulfillment && currentData.fulfillment.items, (shipmentItem) => { const fullItem = _.find(order.items, (orderItem) => { if (orderItem._id === shipmentItem._id) { return true; @@ -137,7 +140,7 @@ Template.coreOrderShippingTracking.helpers({ const currentData = Template.currentData(); const order = Template.instance().order; - const canceledItems = _.every(currentData.fulfillment.items, (shipmentItem) => { + const canceledItems = _.every(currentData.fulfillment && currentData.fulfillment.items, (shipmentItem) => { const fullItem = _.find(order.items, (orderItem) => { if (orderItem._id === shipmentItem._id) { return true; @@ -154,7 +157,7 @@ Template.coreOrderShippingTracking.helpers({ const currentData = Template.currentData(); const order = Template.instance().order; - const completedItems = _.every(currentData.fulfillment.items, (shipmentItem) => { + const completedItems = _.every(currentData.fulfillment && currentData.fulfillment.items, (shipmentItem) => { const fullItem = _.find(order.items, (orderItem) => { if (orderItem._id === shipmentItem._id) { return true; @@ -199,8 +202,9 @@ Template.coreOrderShippingTracking.helpers({ shipmentReady() { const order = Template.instance().order; const shipment = getShippingInfo(order); + const shipmentWorkflow = shipment.workflow; - return _.includes(shipment.workflow.workflow, "coreOrderWorkflow/packed") && shipment.tracking || - _.includes(shipment.workflow.workflow, "coreOrderWorkflow/packed"); + return _.includes(shipmentWorkflow && shipmentWorkflow.workflow, "coreOrderWorkflow/packed") && shipment.tracking + || _.includes(shipmentWorkflow && shipmentWorkflow.workflow, "coreOrderWorkflow/packed"); } }); diff --git a/imports/plugins/core/orders/lib/helpers/orderHelpers.js b/imports/plugins/core/orders/lib/helpers/orderHelpers.js index eb7e1b5da3d..418ece82cfd 100644 --- a/imports/plugins/core/orders/lib/helpers/orderHelpers.js +++ b/imports/plugins/core/orders/lib/helpers/orderHelpers.js @@ -8,7 +8,7 @@ import { Reaction } from "/client/api"; * @return {Object} proper billing object to use */ export function getBillingInfo(order) { - const billingInfo = order.billing && order.billing.find((billing) => { + const billingInfo = order && order.billing && order.billing.find((billing) => { return billing && (billing.shopId === Reaction.getShopId()); }); return billingInfo || {}; @@ -22,8 +22,8 @@ export function getBillingInfo(order) { * @return {Object} proper shipping object to use */ export function getShippingInfo(order) { - const shippingInfo = order.shipping.find((shipping) => { - return shipping.shopId === Reaction.getShopId(); + const shippingInfo = order && order.shipping && order.shipping.find((shipping) => { + return shipping && shipping.shopId === Reaction.getShopId(); }); return shippingInfo || {}; } diff --git a/imports/plugins/included/search-mongo/server/methods/searchcollections.js b/imports/plugins/included/search-mongo/server/methods/searchcollections.js index 1d0a7a53310..fc61c8c6632 100644 --- a/imports/plugins/included/search-mongo/server/methods/searchcollections.js +++ b/imports/plugins/included/search-mongo/server/methods/searchcollections.js @@ -174,8 +174,8 @@ export function buildOrderSearchRecord(orderId) { } } // get the billing object for the current shop on the order (and not hardcoded [0]) - const shopBilling = order.billing.find( - billing => billing.shopId === Reaction.getShopId() + const shopBilling = order.billing && order.billing.find( + billing => billing && billing.shopId === Reaction.getShopId() ) || {}; // get the shipping object for the current shop on the order (and not hardcoded [0]) @@ -185,8 +185,8 @@ export function buildOrderSearchRecord(orderId) { orderSearch.billingName = shopBilling.address && shopBilling.address.fullName; orderSearch.billingPhone = _.replace(shopBilling.address && shopBilling.address.phone, /\D/g, ""); - orderSearch.shippingName = shopShipping.address.fullName; - orderSearch.shippingPhone = _.replace(shopShipping.address.phone, /\D/g, ""); + orderSearch.shippingName = shopShipping.address && shopShipping.address.fullName; + orderSearch.shippingPhone = _.replace(shopShipping.address && shopShipping.address.phone, /\D/g, ""); orderSearch.billingAddress = { address: shopBilling.address && shopBilling.address.address1, postal: shopBilling.address && shopBilling.address.postal, @@ -195,11 +195,11 @@ export function buildOrderSearchRecord(orderId) { country: shopBilling.address && shopBilling.address.country }; orderSearch.shippingAddress = { - address: shopShipping.address.address1, - postal: shopShipping.address.postal, - city: shopShipping.address.city, - region: shopShipping.address.region, - country: shopShipping.address.country + address: shopShipping.address && shopShipping.address.address1, + postal: shopShipping.address && shopShipping.address.postal, + city: shopShipping.address && shopShipping.address.city, + region: shopShipping.address && shopShipping.address.region, + country: shopShipping.address && shopShipping.address.country }; orderSearch.userEmails = userEmails; orderSearch.orderTotal = shopBilling.invoice && shopBilling.invoice.total; From 529a531fe90aa44a0775991044bfbbe6d49cfa66 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 26 Sep 2017 20:39:39 +0300 Subject: [PATCH 40/44] Pass empty object to 'getBillingInfo' and 'getShippingInfo' calls if undefined --- .../orders/client/components/orderSummary.js | 27 ++++++++----------- .../orders/client/components/orderTable.js | 4 +-- .../client/components/orderTableColumn.js | 4 +-- .../containers/orderSummaryContainer.js | 2 +- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderSummary.js b/imports/plugins/core/orders/client/components/orderSummary.js index 002c810b666..09ee96a5645 100644 --- a/imports/plugins/core/orders/client/components/orderSummary.js +++ b/imports/plugins/core/orders/client/components/orderSummary.js @@ -45,9 +45,9 @@ class OrderSummary extends Component { render() { const { dateFormat, tracking, order, profileShippingAddress, printableLabels } = this.props; - const paymentMethod = getBillingInfo(order).paymentMethod; - const invoice = getBillingInfo(order).invoice; - const shipmentMethod = getShippingInfo(order).shipmentMethod; + const paymentMethod = getBillingInfo(order).paymentMethod || {}; + const invoice = getBillingInfo(order).invoice || {}; + const shipmentMethod = getShippingInfo(order).shipmentMethod || {}; const orderRisk = getOrderRiskStatus(order); return ( @@ -111,21 +111,21 @@ class OrderSummary extends Component {
Payment
- {paymentMethod && paymentMethod.storedCard} ({invoice && invoice.total}) + {paymentMethod.storedCard} ({invoice.total})
Transaction
- {paymentMethod && paymentMethod.transactionId} + {paymentMethod.transactionId}
Carrier
- { shipmentMethod && shipmentMethod.carrier} - {shipmentMethod && shipmentMethod.label} + {shipmentMethod.carrier} - {shipmentMethod.label}
@@ -156,23 +156,18 @@ class OrderSummary extends Component {
Ship to
- Phone: {profileShippingAddress && profileShippingAddress.phone} + Phone: {profileShippingAddress.phone}
- {profileShippingAddress && profileShippingAddress.fullName} + {profileShippingAddress.fullName}
- {profileShippingAddress && profileShippingAddress.address1} - {profileShippingAddress && profileShippingAddress.address2 && -
{profileShippingAddress.address2}
- } + {profileShippingAddress.address1} + {profileShippingAddress.address2 &&
{profileShippingAddress.address2}
}
- {profileShippingAddress && profileShippingAddress.city},  - {profileShippingAddress && profileShippingAddress.region},  - {profileShippingAddress && profileShippingAddress.country}  - {profileShippingAddress && profileShippingAddress.postal} + {profileShippingAddress.city}, {profileShippingAddress.region}, {profileShippingAddress.country} {profileShippingAddress.postal}
diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 62c339e841b..68fb25f911f 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -93,7 +93,7 @@ class OrderTable extends Component { renderOrderInfo(order) { const { displayMedia } = this.props; - const invoice = getBillingInfo(order).invoice; + const invoice = getBillingInfo(order).invoice || {}; return (
@@ -114,7 +114,7 @@ class OrderTable extends Component { - Total: {formatPriceString(invoice && invoice.total)} + Total: {formatPriceString(invoice.total)}
diff --git a/imports/plugins/core/orders/client/components/orderTableColumn.js b/imports/plugins/core/orders/client/components/orderTableColumn.js index aaa2b31ffd3..e5886ff8b66 100644 --- a/imports/plugins/core/orders/client/components/orderTableColumn.js +++ b/imports/plugins/core/orders/client/components/orderTableColumn.js @@ -49,7 +49,7 @@ class OrderTableColumn extends Component { render() { const columnAccessor = this.props.row.column.id; - const invoice = getBillingInfo(this.props.row.original).invoice; + const invoice = getBillingInfo(this.props.row.original).invoice || {}; const orderRisk = getOrderRiskStatus(this.props.row.original); if (columnAccessor === "shippingfullName") { @@ -97,7 +97,7 @@ class OrderTableColumn extends Component { if (columnAccessor === "billingTotal") { return (
- {formatPriceString(invoice && invoice.total)} + {formatPriceString(invoice.total)}
); } diff --git a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js index dde29c912be..5e2795ab176 100644 --- a/imports/plugins/core/orders/client/containers/orderSummaryContainer.js +++ b/imports/plugins/core/orders/client/containers/orderSummaryContainer.js @@ -142,7 +142,7 @@ const composer = (props, onData) => { }); if (order) { - const profileShippingAddress = getShippingInfo(order).address; + const profileShippingAddress = getShippingInfo(order).address || {}; if (order.workflow) { if (order.workflow.status === "coreOrderCreated") { From 16a7be46c3e3ac520f04e980c24fa9d7c31697bf Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 26 Sep 2017 21:09:44 +0300 Subject: [PATCH 41/44] Remove lodash references --- .../templates/workflow/shippingTracking.js | 21 +++++++++---------- .../server/methods/searchcollections.js | 13 ++++++------ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js index 2e9fc379c3c..8473f110bdc 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js @@ -1,4 +1,3 @@ -import _ from "lodash"; import { Meteor } from "meteor/meteor"; import { Tracker } from "meteor/tracker"; import { ReactiveVar } from "meteor/reactive-var"; @@ -123,14 +122,14 @@ Template.coreOrderShippingTracking.helpers({ const currentData = Template.currentData(); const order = Template.instance().order; - const shippedItems = _.every(currentData.fulfillment && currentData.fulfillment.items, (shipmentItem) => { - const fullItem = _.find(order.items, (orderItem) => { + const shippedItems = currentData.fulfillment && currentData.fulfillment.items.every((shipmentItem) => { + const fullItem = order.items.find((orderItem) => { if (orderItem._id === shipmentItem._id) { return true; } }); - return !_.includes(fullItem.workflow.workflow, "coreOrderItemWorkflow/shipped"); + return !fullItem.workflow.workflow.includes("coreOrderItemWorkflow/shipped"); }); return shippedItems; @@ -140,8 +139,8 @@ Template.coreOrderShippingTracking.helpers({ const currentData = Template.currentData(); const order = Template.instance().order; - const canceledItems = _.every(currentData.fulfillment && currentData.fulfillment.items, (shipmentItem) => { - const fullItem = _.find(order.items, (orderItem) => { + const canceledItems = currentData.fulfillment && currentData.fulfillment.items.every((shipmentItem) => { + const fullItem = order.items.find((orderItem) => { if (orderItem._id === shipmentItem._id) { return true; } @@ -157,14 +156,14 @@ Template.coreOrderShippingTracking.helpers({ const currentData = Template.currentData(); const order = Template.instance().order; - const completedItems = _.every(currentData.fulfillment && currentData.fulfillment.items, (shipmentItem) => { - const fullItem = _.find(order.items, (orderItem) => { + const completedItems = currentData.fulfillment && currentData.fulfillment.items.every((shipmentItem) => { + const fullItem = order.items.find((orderItem) => { if (orderItem._id === shipmentItem._id) { return true; } }); - return _.includes(fullItem.workflow.workflow, "coreOrderItemWorkflow/completed"); + return fullItem.workflow.workflow.includes("coreOrderItemWorkflow/completed"); }); return completedItems; @@ -204,7 +203,7 @@ Template.coreOrderShippingTracking.helpers({ const shipment = getShippingInfo(order); const shipmentWorkflow = shipment.workflow; - return _.includes(shipmentWorkflow && shipmentWorkflow.workflow, "coreOrderWorkflow/packed") && shipment.tracking - || _.includes(shipmentWorkflow && shipmentWorkflow.workflow, "coreOrderWorkflow/packed"); + return shipmentWorkflow && shipmentWorkflow.workflow.includes("coreOrderWorkflow/packed") && shipment.tracking + || shipmentWorkflow && shipmentWorkflow.workflow.includes("coreOrderWorkflow/packed"); } }); diff --git a/imports/plugins/included/search-mongo/server/methods/searchcollections.js b/imports/plugins/included/search-mongo/server/methods/searchcollections.js index fc61c8c6632..507e3f4d429 100644 --- a/imports/plugins/included/search-mongo/server/methods/searchcollections.js +++ b/imports/plugins/included/search-mongo/server/methods/searchcollections.js @@ -1,6 +1,5 @@ /* eslint camelcase: 0 */ import moment from "moment"; -import _ from "lodash"; import { Meteor } from "meteor/meteor"; import { check, Match } from "meteor/check"; import { Reaction, Logger } from "/server/api"; @@ -26,7 +25,7 @@ const supportedLanguages = ["da", "nl", "en", "fi", "fr", "de", "hu", "it", "nb" function filterFields(customFields) { const fieldNames = []; - const fieldKeys = _.keys(customFields); + const fieldKeys = Object.keys(customFields); for (const fieldKey of fieldKeys) { if (customFields[fieldKey]) { fieldNames.push(fieldKey); @@ -38,8 +37,8 @@ function filterFields(customFields) { // get the weights for all enabled fields function getScores(customFields, settings, collection = "products") { const weightObject = {}; - for (const weight of _.keys(settings[collection].weights)) { - if (_.includes(customFields, weight)) { + for (const weight of Object.keys(settings[collection].weights)) { + if (customFields.includes(weight)) { weightObject[weight] = settings[collection].weights[weight]; } } @@ -49,7 +48,7 @@ function getScores(customFields, settings, collection = "products") { function getSearchLanguage() { const shopId = Reaction.getShopId(); const shopLanguage = Shops.findOne(shopId).language; - if (_.includes(supportedLanguages, shopLanguage)) { + if (supportedLanguages.includes(shopLanguage)) { return { default_language: shopLanguage }; } return { default_language: "en" }; @@ -184,9 +183,9 @@ export function buildOrderSearchRecord(orderId) { ) || {}; orderSearch.billingName = shopBilling.address && shopBilling.address.fullName; - orderSearch.billingPhone = _.replace(shopBilling.address && shopBilling.address.phone, /\D/g, ""); + orderSearch.billingPhone = shopBilling.address && shopBilling.address.phone.replace(/\D/g, ""); orderSearch.shippingName = shopShipping.address && shopShipping.address.fullName; - orderSearch.shippingPhone = _.replace(shopShipping.address && shopShipping.address.phone, /\D/g, ""); + orderSearch.shippingPhone = shopShipping.address && shopShipping.address.phone.replace(/\D/g, ""); orderSearch.billingAddress = { address: shopBilling.address && shopBilling.address.address1, postal: shopBilling.address && shopBilling.address.postal, From 608b0860e4bd6ac03aa7496eeaf35ff1941d195b Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 26 Sep 2017 21:29:48 +0300 Subject: [PATCH 42/44] Remove more lodash references; use shorthand function patters for one-liners --- server/methods/core/orders.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index c8ae909003e..8aaf5e00785 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -300,8 +300,8 @@ export const methods = { ordersInventoryAdjust(order._id); } - const billingRecord = order.billing.find((billing) => { return billing.shopId === Reaction.getShopId(); }); - const shippingRecord = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const billingRecord = order.billing.find(billing => billing.shopId === Reaction.getShopId()); + const shippingRecord = order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); let paymentMethod = orderCreditMethod(order).paymentMethod; paymentMethod = Object.assign(paymentMethod, { amount: Number(paymentMethod.amount) }); @@ -362,7 +362,7 @@ export const methods = { if (result) { Meteor.call("workflow/pushOrderWorkflow", "coreOrderWorkflow", "coreProcessPayment", order._id); - const shippingRecord = order.shipping.find((shipping) => {return shipping.shopId === Reaction.getShopId();}); + const shippingRecord = order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); // Set the status of the items as shipped const itemIds = shippingRecord.items.map((item) => { return item._id; @@ -460,7 +460,7 @@ export const methods = { this.unblock(); - const shipment = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shipment = order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); if (order.email) { Meteor.call("orders/sendNotification", order, (err) => { @@ -479,8 +479,8 @@ export const methods = { Meteor.call("workflow/pushItemWorkflow", "coreOrderItemWorkflow/delivered", order, itemIds); Meteor.call("workflow/pushItemWorkflow", "coreOrderItemWorkflow/completed", order, itemIds); - const isCompleted = _.every(order.items, (item) => { - return _.includes(item.workflow.workflow, "coreOrderItemWorkflow/completed"); + const isCompleted = order.items.every((item) => { + return item.workflow.workflow.includes("coreOrderItemWorkflow/completed"); }); Orders.update({ @@ -531,7 +531,7 @@ export const methods = { // Get shop logo, if available let emailLogo; if (Array.isArray(shop.brandAssets)) { - const brandAsset = _.find(shop.brandAssets, (asset) => asset.type === "navbarBrandImage"); + const brandAsset = shop.brandAssets.find((asset) => asset.type === "navbarBrandImage"); const mediaId = Media.findOne(brandAsset.mediaId); emailLogo = path.join(Meteor.absoluteUrl(), mediaId.url()); } else { @@ -539,7 +539,7 @@ export const methods = { } const billing = orderCreditMethod(order); - const shippingRecord = order.shipping.find((shipping) => { return shipping.shopId === Reaction.getShopId(); }); + const shippingRecord = order.shipping.find(shipping => shipping.shopId === Reaction.getShopId()); // TODO: Update */refunds/list for marketplace const refundResult = Meteor.call("orders/refunds/list", order); const refundTotal = refundResult.reduce((acc, refund) => acc + refund.amount, 0); @@ -847,7 +847,7 @@ export const methods = { } // process order..payment.paymentMethod - _.each(order.billing, function (billing) { + order.billing.forEach((billing) => { const paymentMethod = billing.paymentMethod; const transactionId = paymentMethod.transactionId; @@ -972,7 +972,7 @@ export const methods = { let result; let query = {}; - if (_.includes(checkSupportedMethods, "De-authorize")) { + if (checkSupportedMethods.includes("De-authorize")) { result = Meteor.call(`${processor}/payment/deAuthorize`, paymentMethod, amount); query = { $push: { From e6368d7179d45810ad8c21ff15ab9af2da2ef707 Mon Sep 17 00:00:00 2001 From: Njeri Kieha Date: Tue, 26 Sep 2017 22:29:38 +0300 Subject: [PATCH 43/44] Fix failing tests --- server/methods/core/orders.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index 8aaf5e00785..ff5695a2234 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -480,7 +480,7 @@ export const methods = { Meteor.call("workflow/pushItemWorkflow", "coreOrderItemWorkflow/completed", order, itemIds); const isCompleted = order.items.every((item) => { - return item.workflow.workflow.includes("coreOrderItemWorkflow/completed"); + return item.workflow.workflow && item.workflow.workflow.includes("coreOrderItemWorkflow/completed"); }); Orders.update({ From 0fe9e6a27dac1330ba3eeb3e957913898439eb0d Mon Sep 17 00:00:00 2001 From: Spencer Norman Date: Tue, 26 Sep 2017 14:28:38 -0600 Subject: [PATCH 44/44] Fix case issue in orderTable --- imports/plugins/core/orders/client/components/orderTable.js | 2 +- .../plugins/core/orders/client/components/orderTableColumn.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imports/plugins/core/orders/client/components/orderTable.js b/imports/plugins/core/orders/client/components/orderTable.js index 68fb25f911f..ead147c5d28 100644 --- a/imports/plugins/core/orders/client/components/orderTable.js +++ b/imports/plugins/core/orders/client/components/orderTable.js @@ -214,7 +214,7 @@ class OrderTable extends Component { const filteredFields = { name: { accessor: row => getShippingInfo(row).address && getShippingInfo(row).address.fullName, - id: "shippingfullName" + id: "shippingFullName" }, email: { accessor: "email", diff --git a/imports/plugins/core/orders/client/components/orderTableColumn.js b/imports/plugins/core/orders/client/components/orderTableColumn.js index e5886ff8b66..2699fb34828 100644 --- a/imports/plugins/core/orders/client/components/orderTableColumn.js +++ b/imports/plugins/core/orders/client/components/orderTableColumn.js @@ -52,7 +52,7 @@ class OrderTableColumn extends Component { const invoice = getBillingInfo(this.props.row.original).invoice || {}; const orderRisk = getOrderRiskStatus(this.props.row.original); - if (columnAccessor === "shippingfullName") { + if (columnAccessor === "shippingFullName") { return (
{this.renderCheckboxOnSelect(this.props.row)}