Credit Limit Customization

This customization is to restrict approval of SO according to the customer’s credit limit

User Event script

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 * 
 * 
 * * VKC Nuts India NS
 * VKCN-447: Credit Limit Customization
 * ***************************************************************
 * 
 * Author: Jobin and Jismi IT Services
 * Date Created: 18/7/2023
 * Description: Script used to restrict approval of the Sales orders if the customer does noy have enough credit limit
 * 
 * REVISION HISTORY
 * @version 1.0: VKCN-447: Credit Limit Customization Initial build by JJ0131
 */
define(['N/record', 'N/search', 'N/ui/serverWidget'],

    (record, search, serverWidget) => {

        /**
         * Defines the function definition that is executed before record is loaded.
         * @param {Object} scriptContext
         * @param {Record} scriptContext.newRecord - New record
         * @param {string} scriptContext.type - Trigger type; use values from the context.UserEventType enum
         * @param {Form} scriptContext.form - Current form
        */
        const PENDING_APPROVAL = 'A';
        const beforeLoad = (scriptContext) => {

            if (scriptContext.type === scriptContext.UserEventType.DELETE) return;
            try {
                let soForm = scriptContext.form;
                let soRecord = scriptContext.newRecord;
                let status = soRecord.getValue({
                    fieldId: 'orderstatus'
                });
                let soCus = soRecord.getValue({
                    fieldId: 'entity'
                });
                let total = soRecord.getValue({
                    fieldId: 'total'
                });
                let statusFld = soForm.getField({
                    id: 'orderstatus'
                });
                let alert = soForm.addField({
                    id: 'custpage_alert',
                    type: serverWidget.FieldType.INLINEHTML,
                    label: 'Alert'
                });
                //Alert Box template
                const fadingAlertHTML = '<!DOCTYPE html>' +
                    '<html>' +
                    '<head>' +
                    '<title>Fading Floating Alert</title>' +
                    '<style>' +
                    '.floating-alert {' +
                    'position: fixed;' +
                    'bottom: 20px;' +
                    'right: 20px;' +
                    'background-color: #E4287C;' +
                    'border: 1px solid #ddd;' +
                    'padding: 20px;' +
                    'border-radius: 8px;' +
                    'box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);' +
                    'font-size: 18px;' +
                    'color: #FFF;' +
                    'display: flex;' +
                    'align-items: center;' +
                    'animation: fadeInUp 0.5s ease;' +
                    'transition: opacity 0.5s ease;' +
                    '}' +
                    '@keyframes fadeInUp {' +
                    'from {' +
                    'opacity: 0;' +
                    'transform: translateY(10px);' +
                    '}' +
                    'to {' +
                    'opacity: 1;' +
                    'transform: translateY(0);' +
                    '}' +
                    '}' +
                    '.floating-alert svg {' +
                    'width: 32px;' +
                    'height: 32px;' +
                    'margin-right: 10px;' +
                    'fill: #FFF;' +
                    '}' +
                    '.floating-alert span {' +
                    'font-weight: bold;' +
                    '}' +
                    '</style>' +
                    '</head>' +
                    '<body>' +
                    '<!-- Your other HTML content goes here -->' +
                    '<script>' +
                    'function showFadingFloatingAlert() {' +
                    'const value = \'<div class="floating-alert">\' +' +
                    '\'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">\'+ ' +
                    '\'<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm0 22c-5.523 0-10-4.477-10-10S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-17.172c-.45 0-.828.308-.936.726L11 8.524V16h2V8.524l-.064-.97c-.056-.85-.737-1.51-1.54-1.512zM11 18h2v2h-2v-2z" />\' + ' +
                    '\'</svg>\' +' +
                    '\'<span>Insufficient Customer Credit Limit</span>\' +' +
                    '\'</div>\';' +
                    'const alertElement = document.createElement(\'div\');' +
                    'alertElement.innerHTML = value;' +
                    'document.body.appendChild(alertElement);' +
                    'setTimeout(() => {' +
                    'alertElement.style.opacity = \'0\';' +
                    'setTimeout(() => {' +
                    'alertElement.remove();' +
                    '}, 500);' +
                    '}, 7000);' +
                    '}' +
                    'showFadingFloatingAlert();' +
                    '</script>' +
                    '</body>' +
                    '</html>';

                statusFld.updateDisplayType({
                    displayType: serverWidget.FieldDisplayType.DISABLED
                });
                let hasCreditLimit = creditLimitValidation(total, soCus)
                if ((status == PENDING_APPROVAL) && (hasCreditLimit == false)) {
                    alert.defaultValue = fadingAlertHTML;
                }
            } catch (e) {
                log.error("Error@load", e.message)
            }
        }

        /**
         * Defines the function definition that is executed before record is submitted.
         * @param {Object} scriptContext
         */
        const afterSubmit = (scriptContext) => {
            try {

                let soRec = scriptContext.newRecord;
                let soRecId = soRec.id;
                let soCus = soRec.getValue({
                    fieldId: 'entity'
                });
                let soTotal = soRec.getValue({
                    fieldId: 'total'
                });

                if (scriptContext.type === scriptContext.UserEventType.APPROVE) {
                    let hasCredLimit = creditLimitValidation(soTotal, soCus)
                    if (!hasCredLimit) {

                        record.submitFields({
                            type: 'salesorder',
                            id: soRecId,
                            values: {
                                'orderstatus': PENDING_APPROVAL
                            }
                        });
                    }
                }
            } catch (e) {
                log.error("Error@afterSubmit", e.message)
            }
        }

        /**
         * function to get the total of return authorizations
         * @param {string} soCus 
         */
        function returnAuthSrch(soCus) {
            let returnauthorizationSearchObj = search.create({
                type: "returnauthorization",
                filters:
                    [
                        ["type", "anyof", "RtnAuth"],
                        "AND",
                        ["name", "anyof", soCus],
                        "AND",
                        ["mainline", "is", "T"],
                        "AND",
                        ["status", "anyof", "RtnAuth:A", "RtnAuth:D", "RtnAuth:B", "RtnAuth:F"],
                        
                    ],
                columns:
                    [
                        search.createColumn({ name: "amount", label: "Amount" })
                    ]
            });
            let total = 0;;
            returnauthorizationSearchObj.run().each(function (result) {
                total += Number(result.getValue({
                    name: "amount",
                    label: "Amount"
                }))
                return true;
            });
            return total;
        }

        /**
        * Defines the function for validating the credit limit of the customer
        * @param {string} soTotal -  SO total
        * @param {string} soCus - customer ID
        */
        function creditLimitValidation(soTotal, soCus) {

            let hasCreditLimit = true;
            let cusSrch = search.lookupFields({
                type: 'customer',
                id: soCus,
                columns: ['balance', 'unbilledorders', 'creditlimit']
            });
            let bal = parseFloat(cusSrch.balance);
            let unbilledOrders = parseFloat(cusSrch.unbilledorders);
            let credLimit = cusSrch.creditlimit;
            let returnTotal = returnAuthSrch(soCus);
            log.debug("Return Total", returnTotal)
            
            unbilledOrders = (returnTotal * -1) + unbilledOrders
            let currentCredLimit = 0;
            if (credLimit == "" || credLimit == "0" || credLimit == "0.0" || credLimit == "undefined" || credLimit == null) {
                credLimit = 0;
            }
            currentCredLimit = parseFloat(credLimit) - (bal + unbilledOrders);
            log.debug("Credit Limit", currentCredLimit)
            log.debug("Total", soTotal)
            if (currentCredLimit < 0) {
                hasCreditLimit = false;
            }
            return hasCreditLimit;
        }
        return { beforeLoad, afterSubmit }

    });

Leave a comment

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