Restlet to create Sales Order

/**
 * @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 OTA_INV_BATCH_CUSTOMER_NO = "custbody_ota_invoicebatchcustomer"
        const SO_AUTO_INVOICE = "custbody_grw_005_need_auto_invoicing"
        const SO_AUTO_PAYMENT = "custbody_grw_005_need_auto_payment"
        const OTA_SF_SYNC_STATUS = "custbody_ota_salesforcesynchstatus"
        const SF_SYNC_STATUS_VAL = "1"

        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"

        const ENTITY_INVOICE_BATCH = "custentity_ota_invoicebatch"
        const ENTITY_PAYMENTMETHOD = "custentity_ota_paymentmethod"
        const ENTITY_TERMS = "terms"

        const CUST_INV_BATCH_MAP_REC = "customrecord_grw_005_inv_batch_mapping"
        const CUST_TO_BE_AUTOINV = "custrecord_grw_005_cust_auto_inv"
        const CUST_TO_BE_AUTOPAID = "custrecord_grw_005_cust_auto_pay"

        const SCRIPT_PARAM = "custscript_grw_003_adyn_id"


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

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

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

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

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

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

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

                    let soDocPdfLink = soObjJson.custbody_ota_documentpdflink
                    log.debug("soDocPdfLink", soDocPdfLink);

                    let soSfRecId = soObjJson.custbody_ota_salesforcerecordid
                    log.debug("soSfRecId", soSfRecId);

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

                    let soSfUrl = soObjJson.custbody_ota_salesforceurl
                    log.debug("soSfUrl", soSfUrl);

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

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

                    let soEntity = soObjJson.entity
                    log.debug("soEntity", soEntity);

                    let soExternalId
                    //log.debug("soExternalId", soExternalId);

                    let soItem = soObjJson.item
                    log.debug("soItem", soItem);

                    let soMemo = soObjJson.memo
                    log.debug("soMemo", soMemo);

                    let soSubsidiary = soObjJson.subsidiary
                    log.debug("soSubsidiary", soSubsidiary);

                    let soTranId = soObjJson.tranId
                    log.debug("soTranId", soTranId);

                    let soCostCenter = soObjJson.department
                    log.debug("soCostCenter", soCostCenter);

                    if (!isEmpty(soSfRecId)) {
                        soExternalId = "SO" + soSfRecId
                        log.debug("soExternalId", soExternalId);

                        //For duplicate detection using External Id
                        let extId = soAlreadyExits(soExternalId)
                        log.debug("extId", extId)

                        if (!extId) {

                            let soId = createNSSalesOrder(soCurrency, soDocDate, soDocPdfLink, soSfRecId, soSfUpdateDate, soSfUrl, soSfSyncDate, soEmailSentDate, soDueDate, soEntity, soExternalId, soItem, soMemo, soSubsidiary, soTranDate, datePref, soTranId, soCostCenter)
                            log.debug("soId", soId)

                            if (Number.isInteger(soId)) {
                                responseObj.statusCode = "SUCCESS";
                                responseObj.recordId = soId;
                                log.debug("log1", "log1")
                                return JSON.stringify(responseObj);
                            }
                            else {
                                responseObj.statusCode = "FAILURE";
                                responseObj.error = soId;
                                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)
                    }
                }
            }
        }

        /**
         * creation of sales order
         */
        function createNSSalesOrder(soCurrency, soDocDate, soDocPdfLink, soSfRecId, soSfUpdateDate, soSfUrl, soSfSyncDate, soEmailSentDate, soDueDate, soEntity, soExternalId, soItem, soMemo, soSubsidiary, soTranDate, datePref, soTranId, soCostCenter) {
            let soResponse;
            try {
                let soRecord = record.create({
                    type: record.Type.SALES_ORDER,
                    isDynamic: true
                });
                soRecord.setValue({
                    fieldId: 'entity',
                    value: soEntity
                });

                if (!isEmpty(soEntity)) {

                    let customerfieldLookUp = getCustomerInfo(soEntity)
                    log.debug("customerfieldLookUp", customerfieldLookUp)

                    if (!isEmpty(customerfieldLookUp)) {

                        let soTerms = customerfieldLookUp[0].entityTerms
                        log.debug("soTerms", soTerms)

                        let sobatch = customerfieldLookUp[0].entityBatch
                        log.debug("sobatch", sobatch)

                        let soPayMethod = customerfieldLookUp[0].entityPaymentMethod
                        log.debug("soPayMethod", soPayMethod)


                        if (!isEmpty(sobatch)) {
                            soRecord.setValue({
                                fieldId: OTA_INV_BATCH_CUSTOMER_NO,
                                value: sobatch
                            });

                            let InvMapfieldLookUp = getInvoiceMapInfo(sobatch)

                            if (!isEmpty(InvMapfieldLookUp)) {
                                let isAutoInvChecked = InvMapfieldLookUp[0].isAutoInv
                                log.debug("isAutoInvChecked", isAutoInvChecked)

                                if (isAutoInvChecked) {
                                    soRecord.setValue({
                                        fieldId: SO_AUTO_INVOICE,
                                        value: isAutoInvChecked
                                    });
                                }

                                let isAutoPayChecked = InvMapfieldLookUp[0].isAutoPay
                                log.debug("isAutoPayChecked", isAutoPayChecked)

                                if (isAutoPayChecked) {
                                    soRecord.setValue({
                                        fieldId: SO_AUTO_PAYMENT,
                                        value: isAutoPayChecked
                                    });
                                }
                            }
                          
                        }
                    }
                }

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

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

                if (!isEmpty(soExternalId)) {
                    soRecord.setValue({
                        fieldId: 'externalid',
                        value: soExternalId
                    })
                }

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

                log.debug("soTranId", soTranId)
                if (!isEmpty(soTranId)) {
                    soRecord.setValue({
                        fieldId: 'tranid',
                        value: soTranId
                    });
                }

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


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

                    if (!isEmpty(soDocPdfLink)) {
                        soRecord.setValue({
                            fieldId: DOCUMENT_PDF_LINK,
                            value: soDocPdfLink
                        });
                    }

                    if (!isEmpty(soSfRecId)) {
                        soRecord.setValue({
                            fieldId: SALESFORCE_RECORD_ID,
                            value: soSfRecId
                        });
                    }

                    if (!isEmpty(soSfUpdateDate)) {
                        soRecord.setText({
                            fieldId: SALESFORCE_UPDATED_DATE,
                            text: soSfUpdateDate
                        });
                    }

                    if (!isEmpty(soSfUrl)) {
                        soRecord.setValue({
                            fieldId: SALESFORCEURL,
                            value: soSfUrl
                        });
                    }

                    if (!isEmpty(soSfSyncDate)) {
                        soRecord.setText({
                            fieldId: SALESFORCE_SYNCHED_DATE,
                            text: soSfSyncDate
                        });
                    }

                    if (!isEmpty(soEmailSentDate)) {
                        soRecord.setText({
                            fieldId: SALESFORCE_TRANSACTION_EMAIL_SENT_DATETIME,
                            text: soEmailSentDate
                        });
                    }

                    if (!isEmpty(soDueDate)) {
                        soRecord.setText({
                            fieldId: 'duedate',
                            text: soDueDate
                        })
                    }

                    if (!isEmpty(soMemo)) {
                        soRecord.setValue({
                            fieldId: 'memo',
                            value: soMemo
                        })
                    }

                    // soRecord.setValue({
                    //     fieldId: OTA_SF_SYNC_STATUS,
                    //     value: SF_SYNC_STATUS_VAL
                    // })

                } catch (e) {
                    log.debug("Err@skipcustomFields", e)
                }

                if (!isEmpty(soItem)) {
                    let soItems = soItem.items
                    log.debug("soItems", soItems);

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

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

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

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

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

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

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

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

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

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

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

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

                if (recordID) {
                    let payId = runtime.getCurrentScript().getParameter({ name: SCRIPT_PARAM });
                    log.debug("payId", payId);

                    var id = record.submitFields({
                        type: record.Type.SALES_ORDER,
                        id: recordID,
                        values: {
                            orderstatus: 'F',
                            paymentoption: payId,
                            paymentoperation: "AUTHORIZATION",
                            handlingmode: "PROCESS"
                        },
                        options: {
                            enableSourcing: false,
                            ignoreMandatoryFields: true
                        }
                    });
                }

                soResponse = recordID

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

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

            }

            return soResponse;
        }


        /**
         * Duplicate validation of transaction using external id
         * @param {*} soExtId 
         * @returns 
         */
        function soAlreadyExits(soExtId) {
            let resultval;

            let salesorderSearchObj = search.create({
                type: "salesorder",
                filters:
                    [
                        ["type", "anyof", "SalesOrd"],
                        "AND",
                        ["externalid", "anyof", soExtId]
                    ],
                columns:
                    [
                        search.createColumn({
                            name: "internalid",
                            summary: "GROUP",
                            label: "Internal ID"
                        })

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

                return false;
            });

            return resultval ? resultval : false;
        }

        /**
         * Custom record creation for error handling
         * @param {*} reponseJson 
         * @param {*} requestBody 
         * @returns 
         */
        function createStatusRecord(reponseJson, requestBody) {
            let statusRecObj = record.create({
                type: STATUS_REC_TYPE,
                isDynamic: true
            });
            statusRecObj.setValue({
                fieldId: STATUS_FLD_TRAN_TYPE,
                value: "Sales Order 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)

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

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

            throw missingIdError;
        }


        /**
         * Send Email if errors blocks transaction creation
         * @param {integer} statusRecId 
         */
        function sendEmailNotification(statusRecId) {
            let senderId = runtime.getCurrentUser().id;
            let recipientId = -5; //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>';

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

            let emailSubject = "Alert: Sales Order Creation API Failure"

            let emailBody = "<BR />Hi, <BR/> <BR/>This email is to notify you that a Sales Order 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
                }
            });
        }

        /**
         * Information required from Customer record
         * @param {integer} soEntity 
         * @returns 
         */
        function getCustomerInfo(soEntity) {
            try {
                let customerSearchObj = search.create({
                    type: "customer",
                    filters:
                        [
                            ["internalidnumber", "equalto", soEntity]
                        ],
                    columns:
                        [
                            search.createColumn({ name: ENTITY_INVOICE_BATCH }),
                            search.createColumn({ name: ENTITY_PAYMENTMETHOD }),
                            search.createColumn({ name: ENTITY_TERMS })
                        ]
                });
                let searchResultCount = customerSearchObj.runPaged().count;
                log.debug("customerSearchObj result count", searchResultCount);

                let customerLookup = [];
                let entityBatch, entityPaymentMethod, entityTerms;

                customerSearchObj.run().each(function (result) {
                    entityBatch = result.getValue(ENTITY_INVOICE_BATCH);
                    entityPaymentMethod = result.getValue(ENTITY_PAYMENTMETHOD);
                    entityTerms = result.getValue(ENTITY_TERMS);

                    customerLookup.push({ entityBatch, entityPaymentMethod, entityTerms });
                    return true;
                });

                log.debug("customerLookup", customerLookup)

                return customerLookup;

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

        function getInvoiceMapInfo(sobatch) {
            try {
                let mappingRecSearchObj = search.create({
                    type: CUST_INV_BATCH_MAP_REC,
                    filters:
                        [
                            ["internalidnumber", "equalto", sobatch]
                        ],
                    columns:
                        [
                            search.createColumn({ name: CUST_TO_BE_AUTOINV }),
                            search.createColumn({ name: CUST_TO_BE_AUTOPAID })
                        ]
                });
                let searchResultCount = mappingRecSearchObj.runPaged().count;
                log.debug("mappingRecSearchObj result count", searchResultCount);

                let mappingRecLookup = [];
                let isAutoInv, isAutoPay;

                mappingRecSearchObj.run().each(function (result) {
                    isAutoInv = result.getValue(CUST_TO_BE_AUTOINV);
                    isAutoPay = result.getValue(CUST_TO_BE_AUTOPAID);

                    mappingRecLookup.push({ isAutoInv, isAutoPay });
                    return true;
                });

                log.debug("mappingRecLookup", mappingRecLookup)

                return mappingRecLookup;

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

        /**
         * 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': createSalesOrder
        }
    });

Leave a comment

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