How to prevent error being displayed in NetSuite? - javascript

I am writing a script to take a value from one field and place it into a list field in NetSuite. I believe the issue is because upon saving the record a value is trying to be set in a list that does not contain that value.
I want this to fail silently when set within the context of my script, how can I prevent the error message from showing up and allow the record to be created but without that field being populated?
Scenario - Value is placed into this field, the script tries to map that value to a list value (IT DOES NOT EXIST), the record should still save, but without that data being set - NO ERRORS.
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
*/
define(['N/record', 'N/log'],
/**
* #param {record} record
*/
function(record) {
function customer_beforeLoad(scriptContext) {
}
function customer_beforeSubmit(scriptContext) {
//Segment
setNonIntegrationFieldValue(scriptContext, 'custentity_cus_segmentintegration', 'custentity_cus_segment');
//Currency
setNonIntegrationFieldValue(scriptContext, 'custentity_cus_primarycurrencyintegratio', 'currency');
//Billing Cycle
setNonIntegrationFieldValue(scriptContext, 'custentity_cus_billingcycleintegration', 'custentity_cus_billingcycle');
//Type
setNonIntegrationFieldValue(scriptContext, 'custentity_cus_typeintegration', 'custentity_cus_type');
//Industry
setNonIntegrationFieldValue(scriptContext, 'custentity_cus_industryintegration', 'custentity_esc_industry');
//Sales Rep
setNonIntegrationFieldValue(scriptContext, 'custentity_cus_salesrepintegration', 'salesrep');
}
function customer_afterSubmit(scriptContext) {
}
function setNonIntegrationFieldValue(scriptContext, integrationFieldName, actualFieldName){
try {
var integrationFieldValue = scriptContext.newRecord.getValue(integrationFieldName);
if(integrationFieldValue == '' || integrationFieldValue == null){
scriptContext.newRecord.setValue({
fieldId: actualFieldName,
value: ''
});
} else {
scriptContext.newRecord.setText({
fieldId: actualFieldName,
text: integrationFieldValue
});
}
} catch(e){
log.error({
title: "setNonIntegrationFieldValue() has encountered an error.",
details: e.message
});
//nlapiLogExecution('ERROR','setNonIntegrationFieldValue() has encountered an error.', errText(e));
}
}
return {
//beforeLoad: customer_beforeLoad,
beforeSubmit: customer_beforeSubmit,
//afterSubmit: customer_afterSubmit
};
});

I think the solution should not be preventing a message from showing up, instead, it should be preventing setting of the value when it's not a valid value. You can try firstly get the array of all valid options in that list, secondly check if the value you want to use is contained in the array, if yes then set the value.
To be specific:
var actualField = scriptContext.form.getField(actualFieldName);
var options = actualField.getSelectOptions();
var integrationFieldValue = scriptContext.newRecord.getValue(integrationFieldName);
if (options.indexOf(integrationFieldValue) > -1) {
scriptContext.newRecord.setText({
fieldId: actualFieldName,
text: integrationFieldValue
});
}
For more details for the function getSelectOptions, please refer to Netsuite Help center (search Field.getSelectOptions)

Just wrap ANY AND ALL netsuite logic with a try catch. We have over 614,00 LOC in netsuite and this works 100%:
try {
// your code here
} catch (e) {
// this ternary operator will catch all the ns errors. you can fail silently here
var error = e.details || e.message || e.toString();
throw error;
}

Related

0 Results Returned from NetSuite Search

I am attempting to stop a record from being created based on a search result. I can't seem to return any data through my SuiteScript search though, even though I know for a fact the data exists.
I created a Custom Saved Search with the exact filter being used below and return the results I am looking for.
Does anything stand out on why I may not be retrieving any results?
NOTE: The sfdcAccountId Variable does have a value, so I am searching on a valid value.
// 2.0
define(["N/error", "N/log", "N/search"], function (err, log, search) {
/**
* User Event 2.0 example showing usage of the Submit events
*
* #NApiVersion 2.x
* #NModuleScope SameAccount
* #NScriptType UserEventScript
* #appliedtorecord customer
*/
var exports = {};
function beforeSubmit(scriptContext) {
log.debug({
"title": "Before Submit",
"details": "action=" + scriptContext.type
});
if (doesCustomerExist(scriptContext)) {
throw err.create({
"name": "DUPLICATE_SFDC_ACCOUNT_ID",
"message": "Customer Already Contains SFDC Account Id",
"notifyOff": true
});
}
}
function doesCustomerExist(scriptContext) {
var sfdcAccountId = scriptContext.newRecord.getValue('custentitysfdc_account_id');
log.debug({
"title": "Before Submit",
"details": "sfdcAccountId=" + sfdcAccountId
});
if(sfdcAccountId == null || sfdcAccountId == '') return false;
var searchResult = search.create({
type: search.Type.CUSTOMER,
filters: ['custentitysfdc_account_id', search.Operator.IS, sfdcAccountId]
}).run();
return (searchResult != null && searchResult.length > 0);
}
exports.beforeSubmit = beforeSubmit;
return exports;
});
When you call .run() on a search, it returns a search.ResultSet object. If you call getRange() on that object, you'll get the array of results that you're looking for. Here's an updated version of your search that returns search.Result[] on which you can check the length or iterate through as necessary.
var searchResult = search.create({
type: search.Type.CUSTOMER,
filters: ['custentitysfdc_account_id', search.Operator.IS, sfdcAccountId]
}).run().getRange({start: 0, end: 1000});

Verifying sendKeys result in a Page Object file results in undefined error (Protractor)

So, I have a page object file that provides a number of methods for the elements on a page. The page is a login page with some text, a username and password input elements, and a login button. I've created a generic object called "InputLabel.js" which ties the label and input element together for testing purposes.
The problem I'm having is that after I clear the input, send the data, and then verify the data, I'm getting a Failed: Cannot read property 'verifyValue' of undefined error.
Here is the relevant code:
// InputLabel.js
function InputLabel(container) {
this.Container = container;
}
InputLabel.prototype = {
constructor: InputLabel,
// ...
/**
* Return the element for the input of the input/label combination of elements.
*
* #returns {ElementFinder}
*/
getInput: function () {
return this.Container.$('input');
},
/**
* Return the text shown in the input of the input/label combination of elements.
*
* #returns {Promise}
*/
getValue: function () {
return this.getInput().getAttribute('value');
},
/**
* Verify the text shown in the input of the input/label combination of elements.
*
* #param expected The expected text in the input element.
*/
verifyValue: function (expected) {
console.log('Asserting input value [' + expected + ']');
expect(this.getValue()).toEqual(expected);
},
// ...
/**
* Clears the input element then puts the text from data into the input element.
*
* #param data The text to be entered into the input element.
*/
sendKeys: function (data) {
var el = this.getInput();
el.clear().then(function () {
el.sendKeys(data).then(function () {
console.log("Verifying [" + data + "] was sent to the input.")
this.verifyValue(data);
});
});
}
};
After requiring the file, I can call any of these methods without issue except the sendKeys. If I disabled the this.verifyValue(data); method, sendKeys works fine.
// LoginPage.js
var InputLabel = require('InputLabel.js');
function LoginPage() {
}
var username = new InputLabel($('#username'));
var password = new InputLabel($('#password'));
function.prototype = {
// ...
username: username,
password: password,
loginButton: {
get: function() { return $('#Login'); },
click: function() { return this.get().click(); }
},
// ...
login: function(user, pw) {
this.username.sendKeys(user);
this.password.sendKeys(pw);
this.loginButton.click()
}
}
Am I losing something in scope? Again, the error is that it fails because it cannot read property 'verifyValue' of undefined after sending the keys.
You have a scoping issue with "this" keyword on the line containing "this.verifyValue(data);". In this case "this" keyword doesn't refer to the InputLabel class. Also it is considered a good practice to keep page objects assertion-free. See http://martinfowler.com/bliki/PageObject.html

ComboBox typeAhead works but valueField is null under certain behavioral conditions

Requesting a sanity check here please...
ExtJS 4.2 comboBox Typeahead works but having issues retrieving the valueField under the following conditions:-
1) If a user types a value and then instead of hitting enter or clicking on the select combo list, they click elsewhere then the valueField is empty but the selected value is present.
2) Assuming that the combobox item was selected correctly, If I enter an additional character and then backspace that character, the combo box can no longer find the valueField..its almost like it has reset itself.
Fiddle example
https://fiddle.sencha.com/#fiddle/je1
How to reproduce
If you enter Maggie in the combo box, you will see the valueField ID in the console window, if you append a character and then backspace the character, the ID in the console window is null
(You will need to open the console window to see the output)
forceSelection does not resolve this issue as I have a template and it will not accept an entry in the combobox that is not part of the store, and I need to use sumID for my valueField as I need to retrieve and pass that value to the server.
Thank you everyone, awesome to have such a great community!!
I was able to get around this by using forceSelection and overriding the setValue thus allowing template items not in the store but in the combo to be selected via forceSelection. From playing around with the combobox, IMO, for a good look and feel, forceSelection is the way to go.
Here is my override, refer to statement //start of override
This was a quick fix, I will refine statement when I am back in the office, below I am pasting the solution from memory, you get the idea.
setValue: function(value, doSelect) {
var me = this,
valueNotFoundText = me.valueNotFoundText,
inputEl = me.inputEl,
i, len, record,
dataObj,
matchedRecords = [],
displayTplData = [],
processedValue = [];
if (me.store.loading) {
// Called while the Store is loading. Ensure it is processed by the onLoad method.
me.value = value;
me.setHiddenValue(me.value);
return me;
}
// This method processes multi-values, so ensure value is an array.
value = Ext.Array.from(value);
// Loop through values, matching each from the Store, and collecting matched records
for (i = 0, len = value.length; i < len; i++) {
record = value[i];
if (!record || !record.isModel) {
record = me.findRecordByValue(record);
}
// record found, select it.
if (record) {
matchedRecords.push(record);
displayTplData.push(record.data);
processedValue.push(record.get(me.valueField));
}
// record was not found, this could happen because
// store is not loaded or they set a value not in the store
else {
//start of override
// 'Select All Names' is the template item that was added // to the combo box, it looks like an entry from the store
// but it is not in the store
if (me.forceSelection && me.getDisplayValue() === 'Select All Names'){
processedValue.push(value[i]);
dataObj = {};
dataObj[me.displayField] = value[i];
displayTplData.push(dataObj);
}
//end of override
if (!me.forceSelection) {
processedValue.push(value[i]);
dataObj = {};
dataObj[me.displayField] = value[i];
displayTplData.push(dataObj);
// TODO: Add config to create new records on selection of a value that has no match in the Store
}
// Else, if valueNotFoundText is defined, display it, otherwise display nothing for this value
else if (Ext.isDefined(valueNotFoundText)) {
displayTplData.push(valueNotFoundText);
}
}
}
// Set the value of this field. If we are multiselecting, then that is an array.
me.setHiddenValue(processedValue);
me.value = me.multiSelect ? processedValue : processedValue[0];
if (!Ext.isDefined(me.value)) {
me.value = null;
}
me.displayTplData = displayTplData; //store for getDisplayValue method
me.lastSelection = me.valueModels = matchedRecords;
if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
inputEl.removeCls(me.emptyCls);
}
// Calculate raw value from the collection of Model data
me.setRawValue(me.getDisplayValue());
me.checkChange();
if (doSelect !== false) {
me.syncSelection();
}
me.applyEmptyText();
return me;
},
Look at the sources of Combobox and try override this method as follows
doLocalQuery: function(queryPlan) {
var me = this,
queryString = queryPlan.query;
if (!me.queryFilter) {
me.queryFilter = new Ext.util.Filter({
id: me.id + '-query-filter',
anyMatch: me.anyMatch,
caseSensitive: me.caseSensitive,
root: 'data',
property: me.displayField
});
me.store.addFilter(me.queryFilter, false);
}
if (queryString || !queryPlan.forceAll) {
me.queryFilter.disabled = false;
me.queryFilter.setValue(me.enableRegEx ? new RegExp(queryString) : queryString);
}
else {
me.queryFilter.disabled = true;
}
me.store.filter();
if (me.store.getCount()) {
if (me.rawValue === me.lastSelection[0].get(me.displayField)){
me.setValue(me.lastSelection);
} else {
if(me.store.getCount() === 1){
me.setValue(me.store.first());
}
me.expand();
}
} else {
me.collapse();
}
me.afterQuery(queryPlan);
},

YDN-DB How to verify if a record exists?

I'm trying to verify if a specific record exist inside a table by a given ID. For example:
var id = 23;
db.count('products',id).done(function(count) {
if(count>0){
db.get('products',id).done(function(r) {
//Do something
});
}else{
alert('No product found');
}
});
When I try this, I get the following error: uncaught exception: null
I'd really appreciate your help Thanks!.
Your solution is almost correct.
In IndexedDB API, there is no exists method, probably because it can be emulated using count method. But count method accepts only key range, so existence test should be:
var id = 23;
db.count('products', ydn.db.KeyRange.only(id)).done(function(cnt) {
if (cnt) { // exist
} else { // no exist
}
});
Another reason, exists method don't exist in the IndexedDB api is that, get don't give error for non-existing key. So you can safely, and recommended, to do:
var id = 23;
db.get('products', id).done(function(product) {
if (product) { // exist
} else { // no exist
}
});
I would like to point out that, in these two ways to detect existence, the first method is more efficient because it avoid deserialization. So if you just need to test for existence, use first method. For retrieving a record, which may or may not exist, use second method.
EDIT:
To query a record by primary key, id, or unique secondary key, sku
/**
* #param {string} id id or sku
* #param {Function} cb callback to invoke resulting record value. If not exists in the
* database, null or undefined is returned.
*/
var getByIdOrSku = function(id, cb) {
var req = db.get('items', id);
req.done(function(item) {
if (item) {
cb(item)
} else {
db.values('items', 'SKU', ydn.db.KeyRange.only(id), 1).done(function(items) {
cb(items[0]); // may not have result
});
}
});
};
If you prefer promise way:
db.get('items', id).then(function(item) {
if (item) {
return item;
} else {
return db.values('items', 'SKU', ydn.db.KeyRange.only(id), 1).done(function(items) {
return items[0];
});
}
}).done(function(item) {
// result query as as id or SKU
console.log(item);
});

How to save my model using Parse cloud js?

I had a read of the meme example but it doesn't seem to update, just create new objects! What I want is to
a. find some given db table
b. update some fields in the db table
c. save the db table back to the database
Given this code, what is the missing piece so that I can actually update an object?
query.find(
function(results){
if (results.length > 0){
return results[0];
} else {
//no object found, so i want to make an object... do i do that here?
return null;
}
},
function(error){
response.error("ServerDown");
console.error("ServerDown - getModuleIfAny URGENT. Failed to retrieve from the ModuleResults table" + +error.code+ " " +error.message);
}
).then(
function(obj){
var module;
if (obj != null){
console.log("old");
module = obj;
module.moduleId = 10; //let's just say this is where i update the field
//is this how i'd update some column in the database?
} else {
console.log("new");
var theModuleClass = Parse.Object.extend("ModuleResults");
module= new theModuleClass();
}
module.save().then(
function(){
response.success("YAY");
},
function(error) {
response.error('Failed saving: '+error.code);
}
);
},
function(error){
console.log("sod");
}
);
I thought the above code would work - but it does not. When it finds an object, it instead refuses to save, stupidly telling me that my object has no "save" method.
First I would double check the version of the javascript sdk you're using in your cloud code. Make sure it's up to date e.g. 1.2.8. The version is set in the config/global.json file under your cloud code directory.
Assuming you're up to date I would try modifying your code by chaining the promises using multiple then's like so:
query.find().then(function(results){
if (results.length > 0){
return results[0];
} else {
//no object found, so i want to make an object... do i do that here?
return null;
}
},
function(error){
response.error("ServerDown");
console.error("ServerDown - getModuleIfAny URGENT. Failed to retrieve from the ModuleResults table" + +error.code+ " " +error.message);
}).then(function(obj){
var module;
if (obj != null){
console.log("old");
module = obj;
module.moduleId = 10; //let's just say this is where i update the field
//is this how i'd update some column in the database?
} else {
console.log("new");
var theModuleClass = Parse.Object.extend("ModuleResults");
module= new theModuleClass();
}
module.save();
}).then(function(result) {
// the object was saved.
},
function(error) {
// there was some error.
});
I think this should work. Fingers crossed. Cheers!

Categories

Resources