/**
* @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
}
});