Shipping cost calculation in SCA

Shipping costs will be calculated for credit card-based(role-based) customers. For any shipment whose total value of the product is $150 or higher, the shopping cost will be 0. Any shipment value less than $150 will be charged shipping cost.

Steps:
  • Enabled SCRIPTABLE CART AND CHECKOUT in the website setup.
  • A client script will be added for our shipping cost calculation and deployed to sales order.
  • The shipping cost will be calculated once an item is added to cart. 
  • If the total value of the product in cart  is $150 or higher, the shopping cost will be 0. If the total value of the product in cart is  less than $150 will be charged shipping cost. 
  • The summary table will be updated with the total shipping cost.
  • In the cart page and checkout page, the total shipping cost will be updated.

Client Script

/**
 * Script Description
 * This script will update the shippng cost based on item line 
 */
/*******************************************************************************
 * Good Earth
 * **************************************************************************
 * 
 * Date: 29-10-2021
 * 
 * Author: Jobin & Jismi IT Services LLP
 * 
 * 
 * REVISION HISTORY 
 * 
 *****************************************************************************
 **/
var jjContext, entity, accessRole, ItemId, responseData, Role = 1054;

function ClientPageInit(type) {
    var requestURL = null;

    jjContext = nlapiGetContext().getExecutionContext();
    accessRole = nlapiGetRole();
    try {
        nlapiLogExecution('DEBUG', 'type', type);
        //Checking condition for the role Customer Center - Card Payment.
        if (accessRole == Role && jjContext == 'webstore') {
            entity = nlapiGetFieldValue('entity')
            var lineItemCount = nlapiGetLineItemCount('item');
            var subtotal = nlapiGetFieldValue('subtotal')
            if (lineItemCount > 0 && subtotal < 150)
                individualShippingCost(lineItemCount)
            else {
                nlapiSetFieldValue('shippingcost', 0.00, true, true)
            }

        } else {
            nlapiSetFieldValue('shippingcost', 0.00, true, true)
        }
    } catch (error) {
        nlapiLogExecution('DEBUG', 'entity', error);
    }
}

function getSuiteletValues(entity, ItemId) {
    try {
        var scriptId = 'customscript_jj_sl_gd45_companyinformati',
            deploymentId = 'customdeploy_jj_sl_gd45_companyinformati';
        requestURL = nlapiResolveURL('SUITELET', scriptId, deploymentId, 'external');
        requestURL = requestURL + "&entity=" + entity + "&ItemId=" + ItemId;
        var responseData = nlapiRequestURL(requestURL);
        responseData = JSON.parse(responseData.getBody())

        if (responseData) {

            if (responseData.response == "SUCCESS") {
                nlapiLogExecution('DEBUG', 'responseData', JSON.stringify(responseData.message));
                var shippingcost = Number((responseData.message))
                nlapiLogExecution('DEBUG', 'shippingcost', shippingcost);
                nlapiSetFieldValue('shippingcost', shippingcost, true, true)
            }
        }
        return (responseData);
    } catch (error) {
        nlapiLogExecution('DEBUG', 'getSuiteletValues', error);
    }
}


/**
 * Set correct price; apply column mapping
 * runs on each line validation (on checkout - on back-end)
 */
function shippingCostRecalc(type, action) {
    //
    try {


        if (type == 'item' && jjContext == 'webstore' && accessRole == Role) {
            var ItemId = nlapiGetCurrentLineItemValue('item', 'item');
            var itemType = nlapiGetCurrentLineItemValue('item', 'itemtype');
            var itemQuantity = nlapiGetCurrentLineItemValue('item', 'quantity');
            var lineItemCount = nlapiGetLineItemCount('item');

            // if (ItemId && (itemType == 'NonInvtPart' || itemType == 'InvtPart')) {
            var subtotal = nlapiGetFieldValue('subtotal')
            if (lineItemCount > 0 && subtotal < 150)
                individualShippingCost(lineItemCount)
            else {
                nlapiSetFieldValue('shippingcost', 0.00, true, true)
            }
            //}
        }
    } catch (error) {
        nlapiLogExecution('DEBUG', 'shippingCostRecalc', error);
    }

}

function individualShippingCost(lineItemCount) {
    try {

        nlapiLogExecution('DEBUG', 'individuallineItemCount', lineItemCount);

        var caseItemTotalValue = 0;

        var itemObj = {}
        if (lineItemCount > 0) {

            for (i = 1; i <= lineItemCount; i++) {
                var itemId = nlapiGetLineItemValue('item', 'item', i);
                var itemQuantity = nlapiGetLineItemValue('item', 'quantity', i);
                var itemtype = nlapiGetLineItemValue('item', 'itemtype', i);

                if (itemObj[itemId]) {
                    itemObj[itemId].qty += itemQuantity
                } else {

                    itemObj[itemId] = {
                        type: itemtype,
                        qty: itemQuantity
                    }
                }

            }

            nlapiLogExecution('DEBUG', 'individualShippingCostitemObj', (JSON.stringify(itemObj)));
            var suiteletResult = getSuiteletValues(entity, (JSON.stringify(itemObj)))
        }

        //return unitaryShippingCost;
    } catch (error) {
        nlapiLogExecution('DEBUG', 'individualShippingCost', error);
    }
}

Suitelet

/*******************************************************************************
 * * Jobin & Jismi IT Services | Good Earth | This script will update the shippng cost based on item line *
 * **************************************************************************
 *
 * Author: Jobin & Jismi IT Services LLP
 *
 * Date Created : 
 *
 * Created By : Jobin & Jismi IT Services LLP
 *
 * SCRIPT ID: 
 *
 * DEPLOYMENT ID: 
 *
 * REVISION HISTORY 1.0 AB
 *                  1.1 MD
 *
 *
 ******************************************************************************/
var entityData = {}

function companyInformation(request, response) {
    try {
        var entity = 0,
            weightUnits = 0,
            volumeUnits = 0;
        if (request.getMethod() == 'GET') {
            //load Netsuite configuration page
            var companyInfo = nlapiLoadConfiguration('companyinformation');
            //get field values
            var minimumCharge = companyInfo.getFieldValue('minimumCharge');
            var intercept = companyInfo.getFieldValue('intercept');
            var zoneCoef = companyInfo.getFieldValue('zoneCoef');
            var weightCoef = companyInfo.getFieldValue('weightCoef');
            var curveCoef = companyInfo.getFieldValue('curveCoef');
            var ShipAddr1 = companyInfo.getFieldValue('shippingaddress1');
            //set field values
            var fuelSurcharge = companyInfo.getFieldValue('fuelSurcharge');
            var weightThreshold = companyInfo.getFieldValue('weightThreshold');

            //save changes to the configuration page
            // nlapiSubmitConfiguration(companyInfo);
            var entity = request.getParameter('entity');
            var customerMarkup;
            if (entity) {
                customerMarkup = nlapiLookupField('customer', entity, 'custentity_frt_markup');
                nlapiLogExecution('DEBUG', 'customerMarkup', customerMarkup);
            }


            /*var entityData = {
                minimumCharge: minimumCharge,
                intercept: intercept,
                zoneCoef: zoneCoef,
                weightCoef: weightCoef,
                curveCoef: curveCoef,
                fuelSurcharge: fuelSurcharge,
                weightThreshold: weightThreshold,
                ShipAddr1: ShipAddr1,
                customerMarkup: customerMarkup
            }*/

            entityData = {
                minimumCharge: 8.23,
                intercept: 4.00,
                zoneCoef: 3.00,
                weightCoef: 0.10,
                curveCoef: 50.00,
                fuelSurcharge: 12,
                weightThreshold: 25.00,
                customerMarkup: customerMarkup ? Number(customerMarkup) : 0.00
            };
            nlapiLogExecution('DEBUG', 'entityData', JSON.stringify(entityData));


            var ItemId = JSON.parse(request.getParameter('ItemId'));
            var itemIDs = [],
                itemDetails = [],
                itemIDsArr = [],
                itemDetailsArr = []


            for (var key in ItemId) {

                itemIDs.push(key.toString())
                itemDetails.push(ItemId[key])
            }

            var itemResultObj = itemSearch(itemIDs);

            for (var key1 in itemResultObj) {
                itemIDsArr.push(key1.toString())
                itemDetailsArr.push(itemResultObj[key1])
            }

            var CaseItemList = getitemTypeList(itemDetailsArr, 'Case');
            var nonCaseItemList = getitemTypeList(itemDetailsArr, 'NonCase');

            nlapiLogExecution('DEBUG', 'CaseItemList', JSON.stringify(CaseItemList));

            var indShipCost = 0;

            CaseItemList.forEach(function(each) {
                var individualShipCost = individualShippingCost(each.itemtype, each.weight, each.volume)
                nlapiLogExecution('DEBUG', 'individualShipCost case item', individualShipCost);
                indShipCost += (individualShipCost * Number(ItemId[each.internalid].qty))
            })

            var nonCaseitemInvt = {
                itemtype: 'InvtPart',
                weight: 0,
                volume: 0,
                qty: 0
            }

            var nonCaseitemNonInvt = {
                itemtype: 'NonInvtPart',
                weight: 0,
                volume: 0,
                qty: 0
            }

            var nonCaseitemNonInvtExist = false
            var nonCaseitemInvtExist = false

            nlapiLogExecution('DEBUG', 'nonCaseItemList', JSON.stringify(nonCaseItemList));

            nonCaseItemList.forEach(function(each) {
                if (each.itemtype == 'NonInvtPart') {

                    nonCaseitemNonInvt.weight += (Number(each.weight) * Number(ItemId[each.internalid].qty))
                    nonCaseitemNonInvt.volume += (Number(each.volume) * Number(ItemId[each.internalid].qty))
                    nonCaseitemNonInvt.qty += Number(ItemId[each.internalid].qty)
                    nonCaseitemNonInvtExist = true
                }
                if (each.itemtype == 'InvtPart') {

                    nonCaseitemInvt.weight += (Number(each.weight) * Number(ItemId[each.internalid].qty))
                    nonCaseitemInvt.volume += (Number(each.volume) * Number(ItemId[each.internalid].qty))
                    nonCaseitemInvt.qty += Number(ItemId[each.internalid].qty)
                    nonCaseitemInvtExist = true
                }
            })




            nlapiLogExecution('DEBUG', 'nonCaseitemInvt', JSON.stringify(nonCaseitemInvt));
            nlapiLogExecution('DEBUG', 'nonCaseitemNonInvt', JSON.stringify(nonCaseitemNonInvt));

            // var nonCaseitemInvtDimensionalWeight = Number(nonCaseitemInvt.volume) / 166;
            // var nonCaseitemNonInvtDimensionalWeight = Number(nonCaseitemNonInvt.volume) / 166;

            var nonCaseitemInvtConsolidatedShippingWeight = ShippingWeightCalculation(nonCaseitemInvt.weight, nonCaseitemInvt.volume);
            var nonCaseitemNonInvtConsolidatedShippingWeight = ShippingWeightCalculation(nonCaseitemNonInvt.weight, nonCaseitemNonInvt.volume);

            nlapiLogExecution('DEBUG', 'indShipCost', JSON.stringify(indShipCost));

            if (nonCaseitemInvtExist) {
                var nonCaseitemInvtCarton = shippingCartons(nonCaseitemInvtConsolidatedShippingWeight)
                var nonCaseitemInvtindividualShipCost = individualShippingCost(nonCaseitemInvt.itemtype, (nonCaseitemInvtConsolidatedShippingWeight/nonCaseitemInvtCarton), nonCaseitemInvt.volume)

                indShipCost += (Number(nonCaseitemInvtindividualShipCost) * Number(nonCaseitemInvtCarton))

                nlapiLogExecution('DEBUG', 'indShipCostnonCaseitemNonInvtExist', JSON.stringify(indShipCost));

            }

            if (nonCaseitemNonInvtExist) {
                var nonCaseitemNonInvtCarton = shippingCartons(nonCaseitemNonInvtConsolidatedShippingWeight)
                var nonCaseitemNonInvtindividualShipCost = individualShippingCost(nonCaseitemNonInvt.itemtype, (nonCaseitemNonInvtConsolidatedShippingWeight/nonCaseitemNonInvtCarton), nonCaseitemNonInvt.volume)
  
                indShipCost += (Number(nonCaseitemNonInvtindividualShipCost) * Number(nonCaseitemNonInvtCarton))
                nlapiLogExecution('DEBUG', 'indShipCostnonCaseitemInvtExist', JSON.stringify(indShipCost));
            }


            nlapiLogExecution('DEBUG', 'resultindShipCost', JSON.stringify(indShipCost));


            /*var resultJSON = JSON.stringify({
                minimumCharge: minimumCharge,
                intercept: intercept,
                zoneCoef: zoneCoef,
                weightCoef: weightCoef,
                curveCoef: curveCoef,
                fuelSurcharge: fuelSurcharge,
                weightThreshold: weightThreshold,
                ShipAddr1: ShipAddr1,
                customerMarkup: customerMarkup,
                saleunit: saleunit,
                weightUnits: weightUnits,
                volumeUnits: volumeUnits

            })*/

            var resultJSON = formatResponse("SUCCESS", ((indShipCost).toFixed(2)), null);

            response.write(resultJSON);
        }
    } catch (error) {
        nlapiLogExecution('DEBUG', 'companyInformation', error);
        var resultJSON = formatResponse("FAILURE", "ERROR WHILE shippingCost calculation", "@main.updateQuote", error.message);
        response.write(resultJSON);
    }
}

function itemSearch(itemArray) {
    var itemObj = {}


    var itemSearchObj = nlapiSearchRecord(
        'item',
        null,
        getFilters(itemArray),
        getColumns()
    ) || {};


    if (itemSearchObj && itemSearchObj.length > 0) {

        itemSearchObj.forEach(function(result) {

            itemObj[(result.getValue('internalid'))] = {
                weight: (result.getValue('weight')) || 0, //If field is empty value is set as 0
                weightunit: (result.getValue('weightunit')),
                baseuomtype: (result.getValue('custitem_3plbaseuomtype')),
                volume: (result.getValue('custitem_baseuom_vol')) || 0, //If field is empty value is set as 0
                saleunit: (result.getText('saleunit') || result.getValue('saleunit')),
                internalid: (result.getValue('internalid')),
                itemtype: (result.getValue('type'))
            };
            return true;
        });
    }
    return itemObj
}

function getColumns() {
    return [
        new nlobjSearchColumn("weight"),
        new nlobjSearchColumn("weightunit"),
        new nlobjSearchColumn("custitem_3plbaseuomtype"),
        new nlobjSearchColumn("custitem_baseuom_vol"),
        new nlobjSearchColumn("saleunit"),
        new nlobjSearchColumn("internalid"),
        new nlobjSearchColumn("type")
    ];
}

function getFilters(itemArray) {

    var filter = [
        ['isinactive', 'is', 'F'],
        'AND',
        (['internalid', 'anyof'].concat(itemArray))
    ]
    nlapiLogExecution('DEBUG', 'idFilter', JSON.stringify(filter));

    return filter
}


function ShippingWeightCalculation(actualWeight, volume) {

    try {
        var dimensionalWeight = volume / 166;
        var shippingWeight = volume < 5184 ? (parseFloat(Math.ceil(actualWeight))) : (Math.ceil((Math.max(actualWeight, dimensionalWeight))))
        return shippingWeight
    } catch (error) {
        nlapiLogExecution('DEBUG', 'ShippingWeightCalculation', error);
    }
}

function shippingCartons(consolidatedShippingWeight) {
    try {
        // body...

        var shippingCartons = (consolidatedShippingWeight > (Number(entityData.weightThreshold) * 1.5)) ? Math.ceil((consolidatedShippingWeight / Number(entityData.weightThreshold))) : 1
        return shippingCartons
    } catch (error) {
        console.log('shippingCartonserror', error)
        nlapiLogExecution('DEBUG', 'shippingCartons', error);
    }
}

function shippingZoneCalculation(itemType) {
    try {

        var shippingZoneValue = (itemType == 'NonInvtPart') ? 4 : 6;

        return shippingZoneValue;

    } catch (error) {
        nlapiLogExecution('DEBUG', 'shippingZone', error);
    }
}

function individualShippingCost(itemType, weight, volume) {

    try {
        var shippingZone = shippingZoneCalculation(itemType);
        nlapiLogExecution('DEBUG', 'shippingZone case', shippingZone);

        var shippingWeight = ShippingWeightCalculation(weight, volume);
        nlapiLogExecution('DEBUG', 'shippingWeight case', shippingWeight);

        var calculatedCharge = (Number(entityData.intercept)) + (Number(shippingZone) * Number(entityData.zoneCoef)) * (Number(shippingWeight) / Number(entityData.curveCoef)) +
            (Number(weight) * Number(entityData.weightCoef)) * ((Number(entityData.curveCoef) - Number(weight)) / Number(entityData.curveCoef))

            nlapiLogExecution('DEBUG', 'calculatedCharge case', calculatedCharge);
        
        var unitaryShippingCost = (Math.max(Number(calculatedCharge), Number(entityData.minimumCharge))) + (Math.max(Number(calculatedCharge), Number(entityData.minimumCharge))) *
            ((Number(entityData.fuelSurcharge) + Number(entityData.customerMarkup)) / 100);

        return unitaryShippingCost;

    } catch (error) {
        nlapiLogExecution('DEBUG', 'individualShippingCost', error);
    }
}


function getitemTypeList(itemArray, saleunit) {
    function itemTypeList(each) {

        if (saleunit == 'Case')
            return each.saleunit == 'Case';
        if (saleunit == 'NonCase')
            return each.saleunit != 'Case';

    }
    return itemArray.filter(itemTypeList)
}

function formatResponse(SHORT_RESPONSE, LONG_RESPONSE, FAULT_POSITION, MORE_INFO) {
    var responseObj = {};
    responseObj.response = (SHORT_RESPONSE) ? SHORT_RESPONSE : "FAILURE";
    responseObj.message = (LONG_RESPONSE) ? LONG_RESPONSE : null;
    responseObj.position = (FAULT_POSITION) ? FAULT_POSITION : null;
    responseObj.information = (MORE_INFO) ? MORE_INFO : null;
    return JSON.stringify(responseObj);
}

Leave a comment

Your email address will not be published. Required fields are marked *