Restlet to create Credit Memo

/**
 * @NApiVersion 2.1
 * @NScriptType RestLet
 * @NModuleScope SameAccount
 */

define(['N/record', 'N/search', 'N/runtime', './moment.js', 'N/format', 'N/email', 'N/error'],

    function (record, search, runtime, moment, format, email, error) {
        const DOCUMENT_DATE = "custbody_document_date"
        const DOCUMENT_PDF_LINK = "custbody_ota_documentpdflink"
        const SALESFORCE_RECORD_ID = "custbody_ota_salesforcerecordid"
        const SALESFORCE_UPDATED_DATE = "custbody_ota_salesforceupdateddate"
        const SALESFORCEURL = "custbody_ota_salesforceurl"
        const SALESFORCE_SYNCHED_DATE = "custbody_ota_sfsyncheddate"
        const SALESFORCE_TRANSACTION_EMAIL_SENT_DATETIME = "custbody_ota_transactionemailsentdate"
        const OTA_SERVICE_PERIOD_START_DATE = "custcol_ota_serviceperiodstartdate"
        const OTA_SERVICE_PERIOD_END_DATE = "custcol_ota_serviceperiodenddate"

        const STATUS_REC_TYPE_PARAM = '211';
        const STATUS_REC_TYPE = "customrecord_grw_003_rec_intgrn_status"
        const STATUS_FLD_TRAN_TYPE = "custrecord_grw_003_tran_type"
        const STATUS_FLD_ERROR_MSSG = "custrecord_grw_003_json_response"
        const STATUS_FLD_RESQUEST_JSON = "custrecord_grw_003_req_json"
        const STATUS_STAT_CODE = "custrecord_grw_003_statuscode"

        /**
         * Post action data handling and triggers credit memo creation
         * @param {*} context - json object request from api call
         * @returns 
         */
        function doPost(context) {
            let responseObj = {};
            try {
                let requestBody = context
                log.debug('requestBody', requestBody);

                if (!isEmpty(requestBody)) {
                    let cmObjJson = requestBody //requestBody.CreditMemo
                    log.debug('cmObjJson', cmObjJson);

                    let user = runtime.getCurrentUser();
                    let datePref = user.getPreference({
                        name: 'DATEFORMAT'
                    });
                    log.debug("datePref", datePref)

                    if (!isEmpty(cmObjJson)) {
                        // Get Currency
                        let cmCurrency = cmObjJson.currency
                        log.debug("cmCurrency", cmCurrency);

                        // Get Document Date
                        let cmDocDate = cmObjJson.custbody_document_date
                        if (!isEmpty(cmDocDate)) {
                            cmDocDate = moment(cmDocDate).format(datePref)
                        }
                        log.debug("New cmDocDate", cmDocDate)

                        // Get Transaction Date
                        let cmTranDate = cmObjJson.tranDate
                        if (!isEmpty(cmTranDate)) {
                            cmTranDate = moment(cmTranDate).format(datePref)
                        }
                        log.debug("New cmTranDate", cmTranDate);

                        // Get Due Date
                        let cmDueDate = cmObjJson.dueDate
                        if (!isEmpty(cmDueDate)) {
                            cmDueDate = moment(cmDueDate).format(datePref)
                        }
                        log.debug("cmDueDate", cmDueDate);

                        let cmDocPdfLink = cmObjJson.custbody_ota_documentpdflink
                        log.debug("cmDocPdfLink", cmDocPdfLink);

                        let cmSfRecId = cmObjJson.custbody_ota_salesforcerecordid
                        log.debug("cmSfRecId", cmSfRecId);

                        // Get value for Salesforce Updated Date
                        let cmSfUpdateDate = cmObjJson.custbody_ota_salesforceupdateddate
                        if (!isEmpty(cmSfUpdateDate)) {
                            cmSfUpdateDate = format.format({ value: new Date(cmSfUpdateDate), type: format.Type.DATETIME })
                        }
                        log.debug("New cmSfUpdateDate", cmSfUpdateDate)

                        let cmSfUrl = cmObjJson.custbody_ota_salesforceurl
                        log.debug("cmSfUrl", cmSfUrl);

                        // Get value for Salesforce Synched Date field
                        let cmSfSyncDate = cmObjJson.custbody_ota_sfsyncheddate
                        if (!isEmpty(cmSfSyncDate)) {
                            cmSfSyncDate = format.format({ value: new Date(cmSfSyncDate), type: format.Type.DATETIME })
                        }
                        log.debug("New cmSfSyncDate", cmSfSyncDate)

                        // Get Data for Salesforce Transaction Email Sent DateTime field
                        let cmEmailSentDate = cmObjJson.custbody_ota_transactionemailsentdate
                        if (!isEmpty(cmEmailSentDate)) {
                            cmEmailSentDate = format.format({ value: new Date(cmEmailSentDate), type: format.Type.DATETIME })
                            log.debug("New cmEmailSentDate", cmEmailSentDate)
                        }

                        //Set customer
                        let cmEntity = cmObjJson.entity
                        log.debug("cmEntity", cmEntity);

                        //Set External ID (unique identifier for records)
                        let cmExternalId = cmObjJson.externalId
                        log.debug("cmExternalId", cmExternalId);

                        //Get item object
                        let cmItem = cmObjJson.item
                        log.debug("cmItem", cmItem);

                        //Get Memo
                        let cmMemo = cmObjJson.memo
                        log.debug("cmMemo", cmMemo);

                        let cmSubsidiary = cmObjJson.subsidiary
                        log.debug("cmSubsidiary", cmSubsidiary);

                        //Get Document number
                        let cmTranId = cmObjJson.tranId
                        log.debug("cmTranId", cmTranId);

                        // Get Location value (Mandatory Field in CM record, so if it null system will throw error)
                        let cmLocation = cmObjJson.location
                        log.debug("cmLocation", cmLocation);

                        let cmCostCenter = cmObjJson.department
                        log.debug("cmCostCenter", cmCostCenter)

                        if (!isEmpty(cmExternalId)) {
                            // For duplicate detection using External Id
                            let extId = cmAlreadyExits(cmExternalId)
                            log.debug("extId", extId)

                            if (!extId) {
                                let cmId = createNSCreditMemo(cmCurrency, cmDocDate, cmDocPdfLink, cmSfRecId, cmSfUpdateDate, cmSfUrl, cmSfSyncDate, cmEmailSentDate, cmDueDate, cmEntity, cmExternalId, cmItem, cmMemo, cmSubsidiary, cmTranDate, datePref, cmTranId, cmLocation, cmCostCenter)
                                log.debug("cmId", cmId)

                                if (Number.isInteger(cmId)) {
                                    responseObj.statusCode = "SUCCESS";
                                    responseObj.recordId = cmId;
                                    log.debug("log1", "log1")
                                    return JSON.stringify(responseObj);
                                }
                                else {
                                    responseObj.statusCode = "FAILURE";
                                    responseObj.error = cmId;
                                    log.debug("log2", "log2")
                                    let statusRecId = createStatusRecord(responseObj, requestBody)
                                }
                            }
                            else {
                                responseObj.statusCode = "FAILURE";
                                responseObj.error = "This record already exists";
                                log.debug("log3", "log3")
                                let statusRecId = createStatusRecord(responseObj, requestBody)
                            }
                        }
                        else {
                            responseObj.statusCode = "FAILURE";
                            responseObj.error = "External Id is missing";
                            log.debug("log4", "log4")
                            let statusRecId = createStatusRecord(responseObj, requestBody)
                        }
                    }
                }
            } catch (e) {
                log.error('e', e);
                log.debug("log4", "log4")
                responseObj.statusCode = "FAILURE";
                responseObj.error = e.message;
                return JSON.stringify({ responseObj })
            }
        }

        /**
         * Creation of Credit Memo
         */
        function createNSCreditMemo(cmCurrency, cmDocDate, cmDocPdfLink, cmSfRecId, cmSfUpdateDate, cmSfUrl, cmSfSyncDate, cmEmailSentDate, cmDueDate, cmEntity, cmExternalId, cmItem, cmMemo, cmSubsidiary, cmTranDate, datePref, cmTranId, cmLocation, cmCostCenter) {
            let cmResponse;
            try {
                let cmRecord = record.create({
                    type: record.Type.CREDIT_MEMO,
                    isDynamic: true
                });

                cmRecord.setValue({
                    fieldId: 'entity',
                    value: cmEntity
                });

                if (!isEmpty(cmSubsidiary)) {
                    cmRecord.setValue({
                        fieldId: 'subsidiary',
                        value: cmSubsidiary
                    });
                }

                if (!isEmpty(cmCurrency)) {
                    cmRecord.setValue({
                        fieldId: 'currency',
                        value: cmCurrency
                    });
                }

                cmRecord.setValue({
                    fieldId: 'externalid',
                    value: cmExternalId
                })

                if (!isEmpty(cmTranDate)) {
                    cmRecord.setText({
                        fieldId: 'trandate',
                        text: cmTranDate
                    })
                }
                else {
                    cmRecord.setValue({
                        fieldId: 'trandate',
                        value: new Date()
                    })
                }

                if (!isEmpty(cmTranId)) {
                    cmRecord.setValue({
                        fieldId: 'tranid',
                        value: cmTranId
                    });
                }

                cmRecord.setValue({
                    fieldId: 'location',
                    value: cmLocation
                });

                if (!isEmpty(cmCostCenter)) {
                    cmRecord.setValue({
                        fieldId: 'department',
                        value: cmCostCenter
                    });
                }

                try {
                    if (!isEmpty(cmDocDate)) {
                        cmRecord.setText({
                            fieldId: DOCUMENT_DATE,
                            text: cmDocDate
                        });
                    }

                    if (!isEmpty(cmDocPdfLink)) {
                        cmRecord.setValue({
                            fieldId: DOCUMENT_PDF_LINK,
                            value: cmDocPdfLink
                        });
                    }

                    if (!isEmpty(cmSfRecId)) {
                        cmRecord.setValue({
                            fieldId: SALESFORCE_RECORD_ID,
                            value: cmSfRecId
                        });
                    }

                    if (!isEmpty(cmSfUpdateDate)) {
                        cmRecord.setText({
                            fieldId: SALESFORCE_UPDATED_DATE,
                            text: cmSfUpdateDate
                        });
                    }

                    if (!isEmpty(cmSfUrl)) {
                        cmRecord.setValue({
                            fieldId: SALESFORCEURL,
                            value: cmSfUrl
                        });
                    }

                    if (!isEmpty(cmSfSyncDate)) {
                        cmRecord.setText({
                            fieldId: SALESFORCE_SYNCHED_DATE,
                            text: cmSfSyncDate
                        });
                    }

                    if (!isEmpty(cmEmailSentDate)) {
                        cmRecord.setText({
                            fieldId: SALESFORCE_TRANSACTION_EMAIL_SENT_DATETIME,
                            text: cmEmailSentDate
                        });
                    }

                    if (!isEmpty(cmDueDate)) {
                        cmRecord.setText({
                            fieldId: 'duedate',
                            text: cmDueDate
                        })
                    }

                    if (!isEmpty(cmMemo)) {
                        cmRecord.setValue({
                            fieldId: 'memo',
                            value: cmMemo
                        })
                    }
                } catch (e) {
                    log.error("Err@skipcustomFields", e)
                }

                if (!isEmpty(cmItem)) {
                    let cmItems = cmItem.items
                    log.debug("cmItems", cmItems);

                    if (!isEmpty(cmItems)) {
                        let itemLineCount = cmItems.length
                        log.debug("itemLineCount", itemLineCount);

                        for (let index = 0; index < itemLineCount; index++) {
                            let lineItem = cmItems[index].item

                            if (!isEmpty(lineItem)) {
                                cmRecord.selectNewLine({
                                    sublistId: 'item'
                                });
                                cmRecord.setCurrentSublistValue({
                                    sublistId: 'item',
                                    fieldId: 'item',
                                    value: lineItem,
                                    ignoreFieldChange: false,
                                    forceSyncSourcing: true
                                });

                                cmRecord.setCurrentSublistValue({
                                    sublistId: 'item',
                                    fieldId: 'quantity',
                                    value: cmItems[index].quantity
                                });

                                cmRecord.setCurrentSublistValue({
                                    sublistId: 'item',
                                    fieldId: 'rate',
                                    value: cmItems[index].rate
                                });

                                cmRecord.setCurrentSublistValue({
                                    sublistId: 'item',
                                    fieldId: 'tax1amt',
                                    value: cmItems[index].taxamount
                                });

                                try {
                                    let servicePeriodStartdate = cmItems[index].custcol_ota_serviceperiodstartdate
                                    if (!isEmpty(servicePeriodStartdate)) {
                                        servicePeriodStartdate = moment(servicePeriodStartdate).format(datePref)
                                        log.debug("servicePeriodStartdate", servicePeriodStartdate)
                                        cmRecord.setCurrentSublistText({
                                            sublistId: 'item',
                                            fieldId: OTA_SERVICE_PERIOD_START_DATE,
                                            text: servicePeriodStartdate
                                        });
                                    }

                                    let servicePeriodEnddate = cmItems[index].custcol_ota_serviceperiodenddate
                                    if (!isEmpty(servicePeriodEnddate)) {
                                        servicePeriodEnddate = moment(servicePeriodEnddate).format(datePref)
                                        log.debug("servicePeriodEnddate", servicePeriodEnddate)
                                        cmRecord.setCurrentSublistText({
                                            sublistId: 'item',
                                            fieldId: OTA_SERVICE_PERIOD_END_DATE,
                                            text: servicePeriodEnddate
                                        });
                                    }

                                    if (!isEmpty(cmItems[index].department)) {
                                        cmRecord.setCurrentSublistValue({
                                            sublistId: 'item',
                                            fieldId: 'department',
                                            value: cmItems[index].department
                                        });
                                    }

                                } catch (Err) {
                                    log.error("Errskipcustomlinefields", Err)
                                }

                                cmRecord.commitLine({
                                    sublistId: 'item'
                                });
                            }
                        }
                    }
                }

                let recordID = cmRecord.save({
                    enableSourcing: true,
                    ignoreMandatoryFields: true
                });
                log.debug("recordID", recordID);

                cmResponse = recordID

            }
            catch (Err) {
                cmResponse = Err.message;

                log.error("Err@Sales Order Creation", Err)
            }

            return cmResponse;
        }


        /**
         * Duplicate validation of transaction using external id
         * @param {*} cmExtId 
         * @returns 
         */
        function cmAlreadyExits(cmExtId) {
            let resultval;
            try {
                let creditmemoSearchObj = search.create({
                    type: "creditmemo",
                    filters:
                        [
                            ["type", "anyof", "CustCred"],
                            "AND",
                            ["externalid", "anyof", cmExtId]
                        ],
                    columns:
                        [
                            search.createColumn({
                                name: "internalid",
                                summary: "GROUP",
                                label: "Internal ID"
                            })

                        ]
                });
                let searchResultCount = creditmemoSearchObj.runPaged().count;
                log.debug("creditmemoSearchObj result count", searchResultCount);
                creditmemoSearchObj.run().each(function (result) {
                    resultval = result.getValue({
                        name: "internalid",
                        summary: "GROUP",
                        label: "Internal ID"
                    });
                    log.debug("resultval", resultval)

                    return false;
                });
            } catch (e) {
                log.error("Err@cmAlreadyExits", e)
            }

            return resultval ? resultval : false;
        }

        /**
         * Custom record creation for error handling
         * @param {*} reponseJson 
         * @param {*} requestBody 
         * @returns 
         */
        function createStatusRecord(reponseJson, requestBody) {
            try {
                let statusRecObj = record.create({
                    type: STATUS_REC_TYPE,
                    isDynamic: true
                });
                statusRecObj.setValue({
                    fieldId: STATUS_FLD_TRAN_TYPE,
                    value: "Credit Memo Generation API"
                });
                statusRecObj.setValue({
                    fieldId: STATUS_FLD_ERROR_MSSG,
                    value: reponseJson.error
                });
                statusRecObj.setValue({
                    fieldId: STATUS_STAT_CODE,
                    value: reponseJson.statusCode
                });
                statusRecObj.setValue({
                    fieldId: STATUS_FLD_RESQUEST_JSON,
                    value: requestBody
                });

                let statusRecId = statusRecObj.save({
                    enableSourcing: true,
                    ignoreMandatoryFields: true
                });
                log.debug("statusRecId", statusRecId);

                sendEmailNotification(statusRecId)

                var missingIdError = error.create({
                    name: reponseJson.statusCode,
                    message: reponseJson.error,
                    notifyOff: true
                });

                missingIdError.toString = function () { return missingIdError.message };

                throw missingIdError;

            } catch (Err) {
                log.error("Err@createStatusRecord", Err)
            }
        }


        /**
         * Send Email if errors blocks transaction creation
         * @param {*} statusRecId 
         */
        function sendEmailNotification(statusRecId) {
            try {
                let senderId = runtime.getCurrentUser().id;
                let recipientId = 242 //113; // For now we set the receipient Employee JJ Consultant 3, will be updated as -5 later;

                let accId = runtime.accountId;
                log.debug('Account ID', accId);

                let nsBaseUrl = 'https://' + accId + '.app.netsuite.com/app/common/custom/custrecordentry.nl?rectype=';

                let recLink = '<a href="' + nsBaseUrl + STATUS_REC_TYPE_PARAM + '&id=' + statusRecId + '"> View Record </a>';
                log.debug("recLink", recLink)

                let emailSubject = "Alert: Credit Memo Creation API Failure"

                let emailBody = "<BR />Hi, <BR/> <BR/>This email is to notify you that a Credit Memo Generation triggered from SalesForce is failed exceution. <BR/> Please find the failure reason from the below record" + " " + recLink + "."

                email.send({
                    author: senderId,
                    recipients: recipientId,
                    subject: emailSubject,
                    body: emailBody,
                    relatedRecords: {
                        entityId: recipientId
                    }
                });
            } catch (e) {
                log.error("Err@sendEmailNotification", e)
            }
        }


        /**
         * validating variable values has value or not
         * @param {*} value 
         * @returns 
         */
        function isEmpty(value) {
            let isEmptyObject = function (a) {
                if (typeof a.length === 'undefined') { // it's an Object, not an Array
                    let hasNonempty = Object.keys(a).some(function nonEmpty(element) {
                        return !isEmpty(a[element]);
                    });
                    return hasNonempty ? false : isEmptyObject(Object.keys(a));
                }
                return !a.some(function nonEmpty(element) { // check if array is really not empty as JS thinks
                    return !isEmpty(element); // at least one element should be non-empty
                });
            };
            return (
                value == false
                || typeof value === 'undefined'
                || value == null
                || (typeof value === 'object' && isEmptyObject(value))
            );
        }

        return {
            'post': doPost
        }
    });

Leave a comment

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