'use strict';
/**
* @namespace Cart
*/
var server = require('server');
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');
var consentTracking = require('*/cartridge/scripts/middleware/consentTracking');
/**
* Cart-MiniCart : The Cart-MiniCart endpoint is responsible for displaying the cart icon in the header with the number of items in the current basket
* @name Base/Cart-MiniCart
* @function
* @memberof Cart
* @param {middleware} - server.middleware.include
* @param {category} - sensitive
* @param {renders} - isml
* @param {serverfunction} - get
*/
server.get('MiniCart', server.middleware.include, function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var currentBasket = BasketMgr.getCurrentBasket();
var quantityTotal;
if (currentBasket) {
quantityTotal = currentBasket.productQuantityTotal;
} else {
quantityTotal = 0;
}
res.render('/components/header/miniCart', { quantityTotal: quantityTotal });
next();
});
/**
* Cart-AddProduct : The Cart-MiniCart endpoint is responsible for displaying the cart icon in the header with the number of items in the current basket
* @name Base/Cart-AddProduct
* @function
* @memberof Cart
* @param {httpparameter} - pid - product ID
* @param {httpparameter} - quantity - quantity of product
* @param {httpparameter} - options - list of product options
* @param {category} - sensitive
* @param {returns} -json
* @param {serverfunction} - post
*/
server.post('AddProduct', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var URLUtils = require('dw/web/URLUtils');
var Transaction = require('dw/system/Transaction');
var CartModel = require('*/cartridge/models/cart');
var ProductLineItemsModel = require('*/cartridge/models/productLineItems');
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentOrNewBasket();
var previousBonusDiscountLineItems = currentBasket.getBonusDiscountLineItems();
var productId = req.form.pid;
var childProducts = Object.hasOwnProperty.call(req.form, 'childProducts')
? JSON.parse(req.form.childProducts)
: [];
var options = req.form.options ? JSON.parse(req.form.options) : [];
var quantity;
var result;
var pidsObj;
if (currentBasket) {
Transaction.wrap(function () {
if (!req.form.pidsObj) {
quantity = parseInt(req.form.quantity, 10);
result = cartHelper.addProductToCart(
currentBasket,
productId,
quantity,
childProducts,
options
);
} else {
// product set
pidsObj = JSON.parse(req.form.pidsObj);
result = {
error: false,
message: Resource.msg('text.alert.addedtobasket', 'product', null)
};
pidsObj.forEach(function (PIDObj) {
quantity = parseInt(PIDObj.qty, 10);
var pidOptions = PIDObj.options ? JSON.parse(PIDObj.options) : {};
var PIDObjResult = cartHelper.addProductToCart(
currentBasket,
PIDObj.pid,
quantity,
childProducts,
pidOptions
);
if (PIDObjResult.error) {
result.error = PIDObjResult.error;
result.message = PIDObjResult.message;
}
});
}
if (!result.error) {
cartHelper.ensureAllShipmentsHaveMethods(currentBasket);
basketCalculationHelpers.calculateTotals(currentBasket);
}
});
}
var quantityTotal = ProductLineItemsModel.getTotalQuantity(currentBasket.productLineItems);
var cartModel = new CartModel(currentBasket);
var urlObject = {
url: URLUtils.url('Cart-ChooseBonusProducts').toString(),
configureProductstUrl: URLUtils.url('Product-ShowBonusProducts').toString(),
addToCartUrl: URLUtils.url('Cart-AddBonusProducts').toString()
};
var newBonusDiscountLineItem =
cartHelper.getNewBonusDiscountLineItem(
currentBasket,
previousBonusDiscountLineItems,
urlObject,
result.uuid
);
if (newBonusDiscountLineItem) {
var allLineItems = currentBasket.allProductLineItems;
var collections = require('*/cartridge/scripts/util/collections');
collections.forEach(allLineItems, function (pli) {
if (pli.UUID === result.uuid) {
Transaction.wrap(function () {
pli.custom.bonusProductLineItemUUID = 'bonus'; // eslint-disable-line no-param-reassign
pli.custom.preOrderUUID = pli.UUID; // eslint-disable-line no-param-reassign
});
}
});
}
var reportingURL = cartHelper.getReportingUrlAddToCart(currentBasket, result.error);
res.json({
reportingURL: reportingURL,
quantityTotal: quantityTotal,
message: result.message,
cart: cartModel,
newBonusDiscountLineItem: newBonusDiscountLineItem || {},
error: result.error,
pliUUID: result.uuid,
minicartCountOfItems: Resource.msgf('minicart.count', 'common', null, quantityTotal)
});
next();
});
/**
* Cart-Show : The Cart-Show endpoint renders the cart page with the current basket
* @name Base/Cart-Show
* @function
* @memberof Cart
* @param {middleware} - server.middleware.https
* @param {middleware} - consentTracking.consent
* @param {middleware} - csrfProtection.generateToken
* @param {category} - sensitive
* @param {renders} - isml
* @param {serverfunction} - get
*/
server.get(
'Show',
server.middleware.https,
consentTracking.consent,
csrfProtection.generateToken,
function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Transaction = require('dw/system/Transaction');
var CartModel = require('*/cartridge/models/cart');
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var reportingUrlsHelper = require('*/cartridge/scripts/reportingUrls');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
var reportingURLs;
if (currentBasket) {
Transaction.wrap(function () {
if (currentBasket.currencyCode !== req.session.currency.currencyCode) {
currentBasket.updateCurrency();
}
cartHelper.ensureAllShipmentsHaveMethods(currentBasket);
basketCalculationHelpers.calculateTotals(currentBasket);
});
}
if (currentBasket && currentBasket.allLineItems.length) {
reportingURLs = reportingUrlsHelper.getBasketOpenReportingURLs(currentBasket);
}
res.setViewData({ reportingURLs: reportingURLs });
var basketModel = new CartModel(currentBasket);
res.render('cart/cart', basketModel);
next();
}
);
/**
* Cart-Get : The Cart-Get endpoints is responsible for returning the current basket in JSON format
* @name Base/Cart-Get
* @function
* @memberof Cart
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get('Get', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Transaction = require('dw/system/Transaction');
var CartModel = require('*/cartridge/models/cart');
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (currentBasket) {
Transaction.wrap(function () {
cartHelper.ensureAllShipmentsHaveMethods(currentBasket);
basketCalculationHelpers.calculateTotals(currentBasket);
});
}
var basketModel = new CartModel(currentBasket);
res.json(basketModel);
next();
});
/**
* Cart-RemoveProductLineItem : The Cart-RemoveProductLineItem endpoint removes a product line item from the basket
* @name Base/Cart-RemoveProductLineItem
* @function
* @memberof Cart
* @param {querystringparameter} - pid - the product id
* @param {querystringparameter} - uuid - the universally unique identifier of the product object
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get('RemoveProductLineItem', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var Transaction = require('dw/system/Transaction');
var URLUtils = require('dw/web/URLUtils');
var CartModel = require('*/cartridge/models/cart');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.setStatusCode(500);
res.json({
error: true,
redirectUrl: URLUtils.url('Cart-Show').toString()
});
return next();
}
var isProductLineItemFound = false;
var bonusProductsUUIDs = [];
Transaction.wrap(function () {
if (req.querystring.pid && req.querystring.uuid) {
var productLineItems = currentBasket.getAllProductLineItems(req.querystring.pid);
var bonusProductLineItems = currentBasket.bonusLineItems;
var mainProdItem;
for (var i = 0; i < productLineItems.length; i++) {
var item = productLineItems[i];
if ((item.UUID === req.querystring.uuid)) {
if (bonusProductLineItems && bonusProductLineItems.length > 0) {
for (var j = 0; j < bonusProductLineItems.length; j++) {
var bonusItem = bonusProductLineItems[j];
mainProdItem = bonusItem.getQualifyingProductLineItemForBonusProduct();
if (mainProdItem !== null
&& (mainProdItem.productID === item.productID)) {
bonusProductsUUIDs.push(bonusItem.UUID);
}
}
}
var shipmentToRemove = item.shipment;
currentBasket.removeProductLineItem(item);
if (shipmentToRemove.productLineItems.empty && !shipmentToRemove.default) {
currentBasket.removeShipment(shipmentToRemove);
}
isProductLineItemFound = true;
break;
}
}
}
basketCalculationHelpers.calculateTotals(currentBasket);
});
if (isProductLineItemFound) {
var basketModel = new CartModel(currentBasket);
var basketModelPlus = {
basket: basketModel,
toBeDeletedUUIDs: bonusProductsUUIDs
};
res.json(basketModelPlus);
} else {
res.setStatusCode(500);
res.json({ errorMessage: Resource.msg('error.cannot.remove.product', 'cart', null) });
}
return next();
});
/**
* Cart-UpdateQuantity : The Cart-UpdateQuantity endpoint handles updating the quantity of a product line item in the basket
* @name Base/Cart-UpdateQuantity
* @function
* @memberof Cart
* @param {querystringparameter} - pid - the product id
* @param {querystringparameter} - quantity - the quantity to be updated for the line item
* @param {querystringparameter} - uuid - the universally unique identifier of the product object
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get('UpdateQuantity', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var Transaction = require('dw/system/Transaction');
var URLUtils = require('dw/web/URLUtils');
var CartModel = require('*/cartridge/models/cart');
var collections = require('*/cartridge/scripts/util/collections');
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.setStatusCode(500);
res.json({
error: true,
redirectUrl: URLUtils.url('Cart-Show').toString()
});
return next();
}
var productId = req.querystring.pid;
var updateQuantity = parseInt(req.querystring.quantity, 10);
var uuid = req.querystring.uuid;
var productLineItems = currentBasket.productLineItems;
var matchingLineItem = collections.find(productLineItems, function (item) {
return item.productID === productId && item.UUID === uuid;
});
var availableToSell = 0;
var totalQtyRequested = 0;
var qtyAlreadyInCart = 0;
var minOrderQuantity = 0;
var perpetual = false;
var canBeUpdated = false;
var bundleItems;
var bonusDiscountLineItemCount = currentBasket.bonusDiscountLineItems.length;
if (matchingLineItem) {
if (matchingLineItem.product.bundle) {
bundleItems = matchingLineItem.bundledProductLineItems;
canBeUpdated = collections.every(bundleItems, function (item) {
var quantityToUpdate = updateQuantity *
matchingLineItem.product.getBundledProductQuantity(item.product).value;
qtyAlreadyInCart = cartHelper.getQtyAlreadyInCart(
item.productID,
productLineItems,
item.UUID
);
totalQtyRequested = quantityToUpdate + qtyAlreadyInCart;
availableToSell = item.product.availabilityModel.inventoryRecord.ATS.value;
perpetual = item.product.availabilityModel.inventoryRecord.perpetual;
minOrderQuantity = item.product.minOrderQuantity.value;
return (totalQtyRequested <= availableToSell || perpetual) &&
(quantityToUpdate >= minOrderQuantity);
});
} else {
availableToSell = matchingLineItem.product.availabilityModel.inventoryRecord.ATS.value;
perpetual = matchingLineItem.product.availabilityModel.inventoryRecord.perpetual;
qtyAlreadyInCart = cartHelper.getQtyAlreadyInCart(
productId,
productLineItems,
matchingLineItem.UUID
);
totalQtyRequested = updateQuantity + qtyAlreadyInCart;
minOrderQuantity = matchingLineItem.product.minOrderQuantity.value;
canBeUpdated = (totalQtyRequested <= availableToSell || perpetual) &&
(updateQuantity >= minOrderQuantity);
}
}
if (canBeUpdated) {
Transaction.wrap(function () {
matchingLineItem.setQuantityValue(updateQuantity);
var previousBounsDiscountLineItems = collections.map(currentBasket.bonusDiscountLineItems, function (bonusDiscountLineItem) {
return bonusDiscountLineItem.UUID;
});
basketCalculationHelpers.calculateTotals(currentBasket);
if (currentBasket.bonusDiscountLineItems.length > bonusDiscountLineItemCount) {
var prevItems = JSON.stringify(previousBounsDiscountLineItems);
collections.forEach(currentBasket.bonusDiscountLineItems, function (bonusDiscountLineItem) {
if (prevItems.indexOf(bonusDiscountLineItem.UUID) < 0) {
bonusDiscountLineItem.custom.bonusProductLineItemUUID = matchingLineItem.UUID; // eslint-disable-line no-param-reassign
matchingLineItem.custom.bonusProductLineItemUUID = 'bonus';
matchingLineItem.custom.preOrderUUID = matchingLineItem.UUID;
}
});
}
});
}
if (matchingLineItem && canBeUpdated) {
var basketModel = new CartModel(currentBasket);
res.json(basketModel);
} else {
res.setStatusCode(500);
res.json({
errorMessage: Resource.msg('error.cannot.update.product.quantity', 'cart', null)
});
}
return next();
});
/**
* Cart-SelectShippingMethod : The Cart-SelectShippingMethod endpoint is responsible for assigning a shipping method to the shipment in basket
* @name Base/Cart-SelectShippingMethod
* @function
* @memberof Cart
* @param {middleware} - server.middleware.https
* @param {querystringparameter} - methodID - ID of the selected shipping method
* @param {querystringparameter} - shipmentUUID - UUID of the shipment object
* @param {httpparameter} - methodID - ID of the selected shipping method
* @param {httpparameter} - shipmentUUID - UUID of the shipment object
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - post
*/
server.post('SelectShippingMethod', server.middleware.https, function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var Transaction = require('dw/system/Transaction');
var URLUtils = require('dw/web/URLUtils');
var CartModel = require('*/cartridge/models/cart');
var shippingHelper = require('*/cartridge/scripts/checkout/shippingHelpers');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.json({
error: true,
redirectUrl: URLUtils.url('Cart-Show').toString()
});
return next();
}
var error = false;
var shipUUID = req.querystring.shipmentUUID || req.form.shipmentUUID;
var methodID = req.querystring.methodID || req.form.methodID;
var shipment;
if (shipUUID) {
shipment = shippingHelper.getShipmentByUUID(currentBasket, shipUUID);
} else {
shipment = currentBasket.defaultShipment;
}
Transaction.wrap(function () {
shippingHelper.selectShippingMethod(shipment, methodID);
if (currentBasket && !shipment.shippingMethod) {
error = true;
return;
}
basketCalculationHelpers.calculateTotals(currentBasket);
});
if (!error) {
var basketModel = new CartModel(currentBasket);
res.json(basketModel);
} else {
res.setStatusCode(500);
res.json({
errorMessage: Resource.msg('error.cannot.select.shipping.method', 'cart', null)
});
}
return next();
});
/**
* Cart-MiniCartShow : The Cart-MiniCartShow is responsible for getting the basket and showing the contents when you hover over minicart in header
* @name Base/Cart-MiniCartShow
* @function
* @memberof Cart
* @param {category} - sensitive
* @param {renders} - isml
* @param {serverfunction} - get
*/
server.get('MiniCartShow', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Transaction = require('dw/system/Transaction');
var CartModel = require('*/cartridge/models/cart');
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var reportingUrlsHelper = require('*/cartridge/scripts/reportingUrls');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
var reportingURLs;
if (currentBasket) {
Transaction.wrap(function () {
if (currentBasket.currencyCode !== req.session.currency.currencyCode) {
currentBasket.updateCurrency();
}
cartHelper.ensureAllShipmentsHaveMethods(currentBasket);
basketCalculationHelpers.calculateTotals(currentBasket);
});
}
if (currentBasket && currentBasket.allLineItems.length) {
reportingURLs = reportingUrlsHelper.getBasketOpenReportingURLs(currentBasket);
}
res.setViewData({ reportingURLs: reportingURLs });
var basketModel = new CartModel(currentBasket);
res.render('checkout/cart/miniCart', basketModel);
next();
});
/**
* Cart-AddCoupon : The Cart-AddCoupon endpoint is responsible for adding a coupon to a basket
* @name Base/Cart-AddCoupon
* @function
* @memberof Cart
* @param {middleware} - server.middleware.https
* @param {middleware} - csrfProtection.validateAjaxRequest
* @param {querystringparameter} - couponCode - the coupon code to be applied
* @param {querystringparameter} - csrf_token - hidden input field csrf token
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get(
'AddCoupon',
server.middleware.https,
csrfProtection.validateAjaxRequest,
function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var Transaction = require('dw/system/Transaction');
var URLUtils = require('dw/web/URLUtils');
var CartModel = require('*/cartridge/models/cart');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.setStatusCode(500);
res.json({
error: true,
redirectUrl: URLUtils.url('Cart-Show').toString()
});
return next();
}
if (!currentBasket) {
res.setStatusCode(500);
res.json({ errorMessage: Resource.msg('error.add.coupon', 'cart', null) });
return next();
}
var error = false;
var errorMessage;
try {
Transaction.wrap(function () {
return currentBasket.createCouponLineItem(req.querystring.couponCode, true);
});
} catch (e) {
error = true;
var errorCodes = {
COUPON_CODE_ALREADY_IN_BASKET: 'error.coupon.already.in.cart',
COUPON_ALREADY_IN_BASKET: 'error.coupon.cannot.be.combined',
COUPON_CODE_ALREADY_REDEEMED: 'error.coupon.already.redeemed',
COUPON_CODE_UNKNOWN: 'error.unable.to.add.coupon',
COUPON_DISABLED: 'error.unable.to.add.coupon',
REDEMPTION_LIMIT_EXCEEDED: 'error.unable.to.add.coupon',
TIMEFRAME_REDEMPTION_LIMIT_EXCEEDED: 'error.unable.to.add.coupon',
NO_ACTIVE_PROMOTION: 'error.unable.to.add.coupon',
default: 'error.unable.to.add.coupon'
};
var errorMessageKey = errorCodes[e.errorCode] || errorCodes.default;
errorMessage = Resource.msg(errorMessageKey, 'cart', null);
}
if (error) {
res.json({
error: error,
errorMessage: errorMessage
});
return next();
}
Transaction.wrap(function () {
basketCalculationHelpers.calculateTotals(currentBasket);
});
var basketModel = new CartModel(currentBasket);
res.json(basketModel);
return next();
}
);
/**
* Cart-RemoveCouponLineItem : The Cart-RemoveCouponLineItem endpoint is responsible for removing a coupon from a basket
* @name Base/Cart-RemoveCouponLineItem
* @function
* @memberof Cart
* @param {querystringparameter} - code - the coupon code
* @param {querystringparameter} - uuid - the UUID of the coupon line item object
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get('RemoveCouponLineItem', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var Transaction = require('dw/system/Transaction');
var URLUtils = require('dw/web/URLUtils');
var CartModel = require('*/cartridge/models/cart');
var collections = require('*/cartridge/scripts/util/collections');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.setStatusCode(500);
res.json({
error: true,
redirectUrl: URLUtils.url('Cart-Show').toString()
});
return next();
}
var couponLineItem;
if (currentBasket && req.querystring.uuid) {
couponLineItem = collections.find(currentBasket.couponLineItems, function (item) {
return item.UUID === req.querystring.uuid;
});
if (couponLineItem) {
Transaction.wrap(function () {
currentBasket.removeCouponLineItem(couponLineItem);
basketCalculationHelpers.calculateTotals(currentBasket);
});
var basketModel = new CartModel(currentBasket);
res.json(basketModel);
return next();
}
}
res.setStatusCode(500);
res.json({ errorMessage: Resource.msg('error.cannot.remove.coupon', 'cart', null) });
return next();
});
/**
* Cart-AddBonusProducts : The Cart-AddBonusProducts endpoint handles adding bonus products to basket
* @name Base/Cart-AddBonusProducts
* @function
* @memberof Cart
* @param {querystringparameter} - pids - an object containing: 1. totalQty (total quantity of total bonus products) 2. a list of bonus products with each index being an object containing pid (product id of the bonus product), qty (quantity of the bonus product), a list of options of the bonus product
* @param {querystringparameter} - uuid - UUID of the mian product
* @param {querystringparameter} - pliuud - UUID of the bonus product line item
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - post
*/
server.post('AddBonusProducts', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var ProductMgr = require('dw/catalog/ProductMgr');
var productHelper = require('*/cartridge/scripts/helpers/productHelpers');
var Transaction = require('dw/system/Transaction');
var collections = require('*/cartridge/scripts/util/collections');
var Resource = require('dw/web/Resource');
var currentBasket = BasketMgr.getCurrentOrNewBasket();
var data = JSON.parse(req.querystring.pids);
var pliUUID = req.querystring.pliuuid;
var newBonusDiscountLineItems = currentBasket.getBonusDiscountLineItems();
var qtyAllowed = data.totalQty;
var totalQty = 0;
for (var i = 0; i < data.bonusProducts.length; i++) {
totalQty += data.bonusProducts[i].qty;
}
if (totalQty === 0) {
res.json({
errorMessage: Resource.msg(
'error.alert.choiceofbonus.no.product.selected',
'product',
null),
error: true,
success: false
});
} else if (totalQty > qtyAllowed) {
res.json({
errorMessage: Resource.msgf(
'error.alert.choiceofbonus.max.quantity',
'product',
null,
qtyAllowed,
totalQty),
error: true,
success: false
});
} else {
var bonusDiscountLineItem = collections.find(newBonusDiscountLineItems, function (item) {
return item.UUID === req.querystring.uuid;
});
if (currentBasket) {
Transaction.wrap(function () {
collections.forEach(bonusDiscountLineItem.getBonusProductLineItems(), function (dli) {
if (dli.product) {
currentBasket.removeProductLineItem(dli);
}
});
var pli;
data.bonusProducts.forEach(function (bonusProduct) {
var product = ProductMgr.getProduct(bonusProduct.pid);
var selectedOptions = bonusProduct.options;
var optionModel = productHelper.getCurrentOptionModel(
product.optionModel,
selectedOptions
);
pli = currentBasket.createBonusProductLineItem(
bonusDiscountLineItem,
product,
optionModel,
null
);
pli.setQuantityValue(bonusProduct.qty);
pli.custom.bonusProductLineItemUUID = pliUUID;
});
collections.forEach(currentBasket.getAllProductLineItems(), function (productLineItem) {
if (productLineItem.UUID === pliUUID) {
productLineItem.custom.bonusProductLineItemUUID = 'bonus';// eslint-disable-line no-param-reassign
productLineItem.custom.preOrderUUID = productLineItem.UUID;// eslint-disable-line no-param-reassign
}
});
});
}
res.json({
totalQty: currentBasket.productQuantityTotal,
msgSuccess: Resource.msg('text.alert.choiceofbonus.addedtobasket', 'product', null),
success: true,
error: false
});
}
next();
});
/**
* Cart-EditBonusProduct : The Cart-EditBonusProduct endpoint is responsible for editing the bonus products in a basket
* @name Base/Cart-EditBonusProduct
* @function
* @memberof Cart
* @param {querystringparameter} - duuid - discount line item UUID
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get('EditBonusProduct', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var collections = require('*/cartridge/scripts/util/collections');
var Resource = require('dw/web/Resource');
var URLUtils = require('dw/web/URLUtils');
var currentBasket = BasketMgr.getCurrentOrNewBasket();
var duuid = req.querystring.duuid;
var bonusDiscountLineItem = collections.find(currentBasket.getBonusDiscountLineItems(), function (item) {
return item.UUID === duuid;
});
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var selectedBonusProducts = collections.map(bonusDiscountLineItem.bonusProductLineItems, function (bonusProductLineItem) {
return {
pid: bonusProductLineItem.productID,
name: bonusProductLineItem.productName,
submittedQty: bonusProductLineItem.quantityValue
};
});
var pids = collections.pluck(bonusDiscountLineItem.bonusProducts, 'ID').join();
res.json({
selectedBonusProducts: selectedBonusProducts,
addToCartUrl: URLUtils.url('Cart-AddBonusProducts').relative().toString(),
showProductsUrl: URLUtils.url('Product-ShowBonusProducts').toString(),
maxBonusItems: bonusDiscountLineItem.maxBonusItems,
pageSize: cartHelper.BONUS_PRODUCTS_PAGE_SIZE,
pliUUID: bonusDiscountLineItem.custom.bonusProductLineItemUUID,
uuid: bonusDiscountLineItem.UUID,
bonusChoiceRuleBased: bonusDiscountLineItem.bonusChoiceRuleBased,
selectprods: [],
labels: {
selectprods: Resource.msg('modal.header.selectproducts', 'product', null),
close: Resource.msg('link.choiceofbonus.close', 'product', null)
},
showProductsUrlRuleBased: URLUtils.url('Product-ShowBonusProducts', 'DUUID', bonusDiscountLineItem.UUID, 'pagesize', cartHelper.BONUS_PRODUCTS_PAGE_SIZE, 'pagestart', 0, 'maxpids', bonusDiscountLineItem.maxBonusItems).toString(),
showProductsUrlListBased: URLUtils.url('Product-ShowBonusProducts', 'DUUID', bonusDiscountLineItem.UUID, 'pids', pids, 'maxpids', bonusDiscountLineItem.maxBonusItems).toString()
});
next();
});
/**
* Cart-GetProduct : The Cart-GetProduct endpoint handles showing the product details in a modal/quickview for editing a product in basket on cart page
* @name Base/Cart-GetProduct
* @function
* @memberof Cart
* @param {querystringparameter} - uuid - UUID of the product line item (to edit)
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - get
*/
server.get('GetProduct', function (req, res, next) {
var BasketMgr = require('dw/order/BasketMgr');
var Resource = require('dw/web/Resource');
var URLUtils = require('dw/web/URLUtils');
var collections = require('*/cartridge/scripts/util/collections');
var ProductFactory = require('*/cartridge/scripts/factories/product');
var renderTemplateHelper = require('*/cartridge/scripts/renderTemplateHelper');
var requestUuid = req.querystring.uuid;
var requestPLI = collections.find(BasketMgr.getCurrentBasket().allProductLineItems, function (item) {
return item.UUID === requestUuid;
});
var requestQuantity = requestPLI.quantityValue.toString();
// If the product has options
var optionProductLineItems = requestPLI.getOptionProductLineItems();
var selectedOptions = null;
var selectedOptionValueId = null;
if (optionProductLineItems && optionProductLineItems.length) {
var optionProductLineItem = optionProductLineItems.iterator().next();
selectedOptionValueId = optionProductLineItem.optionValueID;
selectedOptions = [{ optionId: optionProductLineItem.optionID, selectedValueId: optionProductLineItem.optionValueID, productId: requestPLI.productID }];
}
var pliProduct = {
pid: requestPLI.productID,
quantity: requestQuantity,
options: selectedOptions
};
var context = {
product: ProductFactory.get(pliProduct),
selectedQuantity: requestQuantity,
selectedOptionValueId: selectedOptionValueId,
uuid: requestUuid,
updateCartUrl: URLUtils.url('Cart-EditProductLineItem'),
closeButtonText: Resource.msg('link.editProduct.close', 'cart', null),
enterDialogMessage: Resource.msg('msg.enter.edit.product', 'cart', null),
template: 'product/quickView.isml'
};
res.setViewData(context);
this.on('route:BeforeComplete', function (req, res) { // eslint-disable-line no-shadow
var viewData = res.getViewData();
res.json({
renderedTemplate: renderTemplateHelper.getRenderedHtml(viewData, viewData.template)
});
});
next();
});
/**
* Cart-EditProductLineItem : The Cart-EditProductLineItem endpoint edits a product line item in the basket on cart page
* @name Base/Cart-EditProductLineItem
* @function
* @memberof Cart
* @param {httpparameter} - uuid - UUID of product line item being edited
* @param {httpparameter} - pid - Product ID
* @param {httpparameter} - quantity - Quantity
* @param {httpparameter} - selectedOptionValueId - ID of selected option
* @param {category} - sensitive
* @param {returns} - json
* @param {serverfunction} - post
*/
server.post('EditProductLineItem', function (req, res, next) {
var renderTemplateHelper = require('*/cartridge/scripts/renderTemplateHelper');
var arrayHelper = require('*/cartridge/scripts/util/array');
var BasketMgr = require('dw/order/BasketMgr');
var ProductMgr = require('dw/catalog/ProductMgr');
var Resource = require('dw/web/Resource');
var URLUtils = require('dw/web/URLUtils');
var Transaction = require('dw/system/Transaction');
var CartModel = require('*/cartridge/models/cart');
var collections = require('*/cartridge/scripts/util/collections');
var cartHelper = require('*/cartridge/scripts/cart/cartHelpers');
var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers');
var currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.setStatusCode(500);
res.json({
error: true,
redirectUrl: URLUtils.url('Cart-Show').toString()
});
return next();
}
var uuid = req.form.uuid;
var productId = req.form.pid;
var selectedOptionValueId = req.form.selectedOptionValueId;
var updateQuantity = parseInt(req.form.quantity, 10);
var productLineItems = currentBasket.allProductLineItems;
var requestLineItem = collections.find(productLineItems, function (item) {
return item.UUID === uuid;
});
var uuidToBeDeleted = null;
var pliToBeDeleted;
var newPidAlreadyExist = collections.find(productLineItems, function (item) {
if (item.productID === productId && item.UUID !== uuid) {
uuidToBeDeleted = item.UUID;
pliToBeDeleted = item;
updateQuantity += parseInt(item.quantity, 10);
return true;
}
return false;
});
var availableToSell = 0;
var totalQtyRequested = 0;
var qtyAlreadyInCart = 0;
var minOrderQuantity = 0;
var canBeUpdated = false;
var perpetual = false;
var bundleItems;
if (requestLineItem) {
if (requestLineItem.product.bundle) {
bundleItems = requestLineItem.bundledProductLineItems;
canBeUpdated = collections.every(bundleItems, function (item) {
var quantityToUpdate = updateQuantity *
requestLineItem.product.getBundledProductQuantity(item.product).value;
qtyAlreadyInCart = cartHelper.getQtyAlreadyInCart(
item.productID,
productLineItems,
item.UUID
);
totalQtyRequested = quantityToUpdate + qtyAlreadyInCart;
availableToSell = item.product.availabilityModel.inventoryRecord.ATS.value;
perpetual = item.product.availabilityModel.inventoryRecord.perpetual;
minOrderQuantity = item.product.minOrderQuantity.value;
return (totalQtyRequested <= availableToSell || perpetual) &&
(quantityToUpdate >= minOrderQuantity);
});
} else {
availableToSell = requestLineItem.product.availabilityModel.inventoryRecord.ATS.value;
perpetual = requestLineItem.product.availabilityModel.inventoryRecord.perpetual;
qtyAlreadyInCart = cartHelper.getQtyAlreadyInCart(
productId,
productLineItems,
requestLineItem.UUID
);
totalQtyRequested = updateQuantity + qtyAlreadyInCart;
minOrderQuantity = requestLineItem.product.minOrderQuantity.value;
canBeUpdated = (totalQtyRequested <= availableToSell || perpetual) &&
(updateQuantity >= minOrderQuantity);
}
}
var error = false;
if (canBeUpdated) {
var product = ProductMgr.getProduct(productId);
try {
Transaction.wrap(function () {
if (newPidAlreadyExist) {
var shipmentToRemove = pliToBeDeleted.shipment;
currentBasket.removeProductLineItem(pliToBeDeleted);
if (shipmentToRemove.productLineItems.empty && !shipmentToRemove.default) {
currentBasket.removeShipment(shipmentToRemove);
}
}
if (!requestLineItem.product.bundle) {
requestLineItem.replaceProduct(product);
}
// If the product has options
var optionModel = product.getOptionModel();
if (optionModel && optionModel.options && optionModel.options.length) {
var productOption = optionModel.options.iterator().next();
var productOptionValue = optionModel.getOptionValue(productOption, selectedOptionValueId);
var optionProductLineItems = requestLineItem.getOptionProductLineItems();
var optionProductLineItem = optionProductLineItems.iterator().next();
optionProductLineItem.updateOptionValue(productOptionValue);
}
requestLineItem.setQuantityValue(updateQuantity);
basketCalculationHelpers.calculateTotals(currentBasket);
});
} catch (e) {
error = true;
}
}
if (!error && requestLineItem && canBeUpdated) {
var cartModel = new CartModel(currentBasket);
var responseObject = {
cartModel: cartModel,
newProductId: productId
};
if (uuidToBeDeleted) {
responseObject.uuidToBeDeleted = uuidToBeDeleted;
}
var cartItem = arrayHelper.find(cartModel.items, function (item) {
return item.UUID === uuid;
});
var productCardContext = { lineItem: cartItem, actionUrls: cartModel.actionUrls };
var productCardTemplate = 'cart/productCard/cartProductCardServer.isml';
responseObject.renderedTemplate = renderTemplateHelper.getRenderedHtml(
productCardContext,
productCardTemplate
);
res.json(responseObject);
} else {
res.setStatusCode(500);
res.json({
errorMessage: Resource.msg('error.cannot.update.product', 'cart', null)
});
}
return next();
});
module.exports = server.exports();