Get Saved Search values for multiple "formula" columns - netsuite

Morning Gurus,
I have a saved search within Netsuite with multiple "formula" columns.
For example, there are several formulapercent' named columns, although thelabel' for each is unique.
However when using nlobjSearchResult.getValue('formulapercent') naturally I only get the first formulapercent column value.
How do I specify in getValue which of the formula columns I want to return the value for?
I really don't want to use a column number, in case I need to insert a new column to the saved search within Netsuite later.
Hoping for something along the lines of nlobjSearchResult.getValue('formulapercent','<label>')
I have tried the multi parameter option, but it does not work.
Simple fix?
Cheers
Steve

What I generally do is add a label to the saved search formula columns. Then:
var f1Val, f2Val, etc;
results.forEach(function(res){
var cols = res.getAllColumns();
cols.forEach(function(col){
switch(col.getLabel()){
case 'formula1' : f1Val = res.getValue(col); break;
case 'formula2' : f2Val = res.getValue(col); break;
...
}
});
});

Thought I'd add an answer I have since learned.
Instead of generically numbering the columns. For example:
var column = []
column[0] = new nlobjSearchColumn('formulanumeric').setFormula('myformula1');
column[1] = new nlobjSearchColumn('formulanumeric').setFormula('myformula2');
searchresults = nlapiSearchRecord(.......);
Instead of this, I found the easiest way to retrieve the formula column values was to uniquely define the columns:
var colformula1 = new nlobjSearchColumn('formulanumeric').setFormula('myformula1');
var colformula2 = new nlobjSearchColumn('formulanumeric').setFormula('myformula2');
var searchresults = nlapiSearchRecord('item',null,filters,[colformula1,colformula2]);
To then grab the formula results:
var formulares1 = searchresults[i].getValue(colformula1');
var formulares2 = searchresults[i].getValue(colformula2');
Removes the issue if column orders change.
Thought this might help somebody.

There is a method in the nlobjSearchResult object called getAllColumns(). Then I use the index of the formula columns to get the value.
I dont't know of any other way to get the values of the formula columns. Do note that if you use this method, if you change the order of the columns in the saved search it will break your script.

This works for me using SuiteScript 2.0. Place this into a function and pass in the needed variables
if(join){
if(summary){
if(String(name).startsWith("formula")){
return result.getValue(result.columns[column])
}else{
var searchResult = result.getValue({
name: name,
join: join,
summary:summary
});
return searchResult
}
}else{
if(String(name).startsWith("formula")){
return result.getValue(result.columns[column])
}else{
var searchResult = result.getValue({
name: name,
join: join
});
return searchResult
}
}
}else{
if(summary){
if(String(name).startsWith("formula")){
return result.getValue(result.columns[column])
}else{
var searchResult = result.getValue({
name: name,
summary: summary,
});
if((column==7 || column ==8 || column==10 || column==12) && type=='cases'){
return dropDown_Obj[column].getKeyByValue(searchResult)
}
return searchResult
}
}else{
if(String(name).startsWith("formula")){
return result.getValue(result.columns[column])
}else{
var searchResult = result.getValue({
name: name
});
return searchResult
}
}
}

Related

Mongoose, NodeJS & Express: Sorting by column given by api call

I'm currently writing a small API for a cooking app. I have a Recipe model and would like to implement sorting by columns based on the req Parameter given.
I'd like to sort by whatever is passed in the api call. the select parameter works perfectly fine, I can select the columns to be displayed but when I try to sort anything (let's say by rating) the return does sort but I'm not sure what it does sort by.
The code i'm using:
query = Recipe.find(JSON.parse(queryStr));
if(req.query.select){
const fields = req.query.select.split(',').join(' ');
query = query.select(fields);
}
if(req.query.sort){
const sortBy = req.query.sort.split(',').join(' ');
query = query.sort({ sortBy: 1 });
} else {
query = query.sort({ _id: -1 });
}
The result, when no sorting is set: https://pastebin.com/rPLv8n5s
vs. the result when I pass &sort=rating: https://pastebin.com/7eYwAvQf
also, when sorting my name the result is also mixed up.
You are not using the value of sortBy but the string "sortBy". You will need to create an object that has the rating as an object key.
You need the sorting object to look like this.
{
rating: 1
}
You can use something like this so it will be dynamic.
if(req.query.sort){
const sortByKey = req.query.sort.split(',').join(' ');
const sortByObj = {};
sortByObj[sortByKey] = 1; // <-- using sortBy as the key
query = query.sort(sortByObj);
} else {
query = query.sort({ _id: -1 });
}

SQL Server : lower camelcase for each result

I am creating an API with SQL Server as the database. My tables and columns are using Pascal case (CountryId, IsDeleted, etc) that cannot be changed.
So when I do this:
const mssql = require('mssql');
var sqlstr =
'select * from Country where CountryId = #countryId';
var db = await koaApp.getDb();
let result = await db.request()
.input('countryId', mssql.Int, countryId)
.query(sqlstr);
My resulting object is
{
CountryId: 1,
CountryName: "Germany"
}
But I want it to be
{
countryId: 1,
countryName: "Germany"
}
I know there is a "row" event, but I wanted something more performant (since I may be returning several rows from the query, above is just an example).
Any suggestions?
PS: I want to avoid the FOR JSON syntax
Posting this as an actual answer, as it proved helpful to the OP:
if it's viable, you may try simply specifying the columns in the query as such:
select
CountryID countryId,
CountryName countryName
from
Country
where
CountryId = #countryId
Typically it's not best practice to use select * within queries anyways because of performance.
A simple explanation, putting a space and a new name (or perhaps better practice, within square brackets after each column name, such as CountryName [countryName] - this allows for characters such as spaces to be included within the new names) is aliasing the name with a new name of your choosing when returned from SQL.
I'd suggest using the lodash utility library to convert the column names, there is a _.camelCase function for this:
CamelCase documentation
_.camelCase('Foo Bar');
// => 'fooBar'
_.camelCase('--foo-bar--');
// => 'fooBar'
_.camelCase('__FOO_BAR__');
// => 'fooBar'
You can enumerate the result keys using Object.entries then do a reduce, e.g.
let result = {
CountryId: 1,
CountryName: "Germany"
};
let resultCamelCase = Object.entries(result).reduce((obj,[key,value]) => {
obj[_.camelCase(key)] = value;
return obj;
}, {});
console.log(resultCamelCase);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Netsuite: Sort categories by what's in stock?

In Netsuite, on a category page, is there a way to sort by what's in stock? So those things in stock show up at the top of a category?
Yes. There are 3 ways I know of to achieve this.
use a saved search based category instead of a static category. Make sure the layout uses Sort by Sequence. Remember NS caches these for 6 hours so updates are not immediate.
can run a scheduled script that targets certain categories; have the script remove out-of-stock items from the category and then add them back in. This has the effect of moving them to the end of the category list
similar but run the script on stock affecting transactions (SO commitments; Item Receipts; each out-of-stock item would remove itself and re-add itself to all categories. I would actually post the affected item ids to a queue (custom record) and work through that every 15 minutes.
in either of the scheduled script cases you'd probably want to take advantage of {disabletriggers:true,enablesourcing:false} to minimize unnecessary user events firing.
var itemRec = nlapiLoadRecord(ki.getRecordType(), ki.getId());
itemRec.insertLineItem('sitecategory', 1); // at the start
itemRec.setLineItemValue('sitecategory', 'category', 1, targetCat);
nlapiSubmitRecord(itemRec,{disabletriggers:true,enablesourcing:false});
This is what we use to sort items by quantity and then by item name. You'd have to tweak the tags, ids, etc. to match your own info where needed, but this is basically it.
function ReadXMLData(selectLayout) {
var itemName = document.getElementsByTagName('itemdisplayname');
var storeDesc = document.getElementsByTagName('storediscription');
var desc = document.getElementsByTagName('discription');
var itemQuantity = document.getElementsByTagName('itemquantity');
var itemPrice = document.getElementsByTagName('itemprice');
var itemImgUrl = document.getElementsByTagName('itemimgurl');
var itemUrl = document.getElementsByTagName('itemurl');
var displayName2 = document.getElementsByTagName('itemdisplayname2');
var itemSKU = document.getElementsByTagName('itemid');
var internalId = document.getElementsByTagName('iteminternalid');
var itemList = [];
for (var i = 0; i < itemName.length; i++) {
itemList.push({
Name: itemName[i].innerHTML,
Description: storeDesc[i].innerHTML,
Desc: desc[i].innerHTML,
Quantity: parseInt(itemQuantity[i].innerHTML),
Price: itemPrice[i].innerHTML,
ImageURL: itemImgUrl[i].innerHTML,
StoreURL: itemUrl[i].innerHTML,
DisplayName2: displayName2[i].innerHTML,
InternalId: internalId[i].innerHTML,
ItemSKU: itemSKU[i].innerHTML
});
}
//Sort the array by quantity descending order and then by name ascending order
var sortedList = Enumerable.From(itemList)
.OrderByDescending(function(x) {
return x.Quantity
})
.ThenBy(function(x) {
return x.Name
})
.ToArray();
if (document.getElementById('itemDisplayArea')) {
document.getElementById('itemDisplayArea')
.innerHTML = '<br/>' + GetLayoutHTML(selectLayout, sortedList);
}
if (selectLayout == "imgList") {
DisplayDescription(sortedList);
} else {
DisplayStarGrid(sortedList);
}
}

$.unique(array) is not working for array elements having multiple words

var availableNames=['Hello India', 'Hello India', 'Test', 'Test']
$.unique(availableNames);
$("#corpName").autocomplete({
source : availableNames,
minLength : 4
});
availableNames is my array source for auto-complete. I want to show unique values in the list so called jquery unique function.
The unique function is working fine for single words like 'Hello' but not for two word strings like 'Hello India'. Its showing two 'Hello India' in dropdown and one 'Hello'.
Please Suggest me how to display only unique values in the drop-down list.
Thank You.
you have to write your own function. There are two ways to do that:
use filter:
// returns a new array with unique entries
Array.prototype.unique = function() {
return this.filter(function(el, index, oThis) {
return index === oThis.indexOf(el);
});
}
EDIT here is a real prototype version, that changes the original array
Array.prototype.unique2 = function() {
var c=this.length;
while(c--)
c===this.indexOf(this[c])||this.splice(c,1);
};
you can test both versions in this fiddle: http://jsfiddle.net/6mpqaxhk/

NodeJS Module Pattern

I'm about to begin writing a new module for a system I'm developing. We use a MySQL database (so I'm using node-mysql) which contains a customers table.
What I want to achieve is:
Outside of the module I'm looking to do var C = new Customer(1) where 1 is the customer ID.
Now when I want to get something from this customer, I can do C.email or C.first_name which will simply return a value.
I also need to be able to set values back on this customer, C.email = 'example#example.com' or perhaps:
C.set('email', 'example#example.com')
What would be the best pattern to create such a model?
I already have something like this... Not exactly what you demanded but very close to that
I have generalized the core part and here is the code..Hope this will help....
var mysql = require('mysql');
var con = mysql.createConnection({
host:"yourHostName",
user:"yourUserName",
password:"yourPassword"
});
con.query("use databaseName");
function getCustomerDetails(custId){
con.query("select * from customer where custId = "+custId,function(err,result,fields){
if(!err)
return result;
else
console.log(err);
});
}
function updateCustomerDetails(custId,fieldName,fieldValue){
con.query("update customer set "+fieldName+" = "+fieldValue+" where custId = "+custId,function(err,result,fields){
if(!err)
return true;
else
console.log(err);
return false;
});
}
exports.getCustomerDetails = getCustomerDetails;
exports.updateCustomerDetails = updateCustomerDetails;
And then suppose you saved the module as dbAccessModule.js Then you can use the functions like this
var C = require('./dbAccessModule');
result = C.getCustomerDetails(1);
console.log(result.fieldName);
var success = C.updateCustomerDetails(1,'name','sumit');
if(success)
console.log('Table Updated successfully....');
else
// take necessary action according to your application
One thing you need to take care of is that if you are updating any field with string value
then please don't forget to surround the value of fieldValue with single quotes.
If this is not what you asked for then please ignore it....
I recently created two database modules you might be interested in checking out to see if they fit your needs - an ORM: http://bookshelfjs.org and Query Builder: http://knexjs.org
The ORM is based off of the design patterns of Backbone.js
So, you'd be able to do something like this:
// Create the base customer object
var Customer = Bookshelf.Model.extend({
tableName: 'customers'
});
// Create a new customer instance with an id of 1, fetch it, and then
// act on the result model 'customer'.
new Customer({id: 1}).fetch().then(function(customer) {
console.log(customer.get('name'))
customer.set('email', 'email#example.com')
return customer.save();
});
You could also extend the base Customer class to enable a shortened syntax, similar to what you're looking for:
// Create the base customer object, with a static findOne method.
var Customer = Bookshelf.Model.extend({
tableName: 'customers'
}, {
find: function(id) {
return new this({id: id}).fetch();
}
});
Customer.find(1).then(function(C) {
console.log(C.get('name'))
C.set('email', 'email#example.com')
});

Resources