How to add 2 conditions in 'new nlobjSearchFilter'? - netsuite

My code is like that:
var filters = new Array();
filters[0] = new nlobjSearchFilter("isperson", "customer", "is", "F")
filters[1] = new nlobjSearchFilter([["minimumquantity", "equalto", "0"], "OR", ["minimumquantity", "isempty", ""]]);
if (customerId) filters.push(new nlobjSearchFilter("customer", null, "anyof", customerId));
if (currency) filters.push(new nlobjSearchFilter("currency", null, "anyof", currency));
My question is how do I make filters[1] works with the 'OR' operator?

You were on the right track with the 'or' condition.
I can't tell which record you're trying to query, but the easiest way to control multiple and/or conditions when building a search is to use search "filter expressions" rather than manually building with nlobjSearchFilter().
If you want to continue using nlobjSearchFilter(), look up how to use the .setLeftParens()/.setRightParens() and .setOr() functions (example). They're not documented in the NetSuite help).
var filters = [
// this is how joins are referenced in filter expressions
// this is equivalent to nlobjSearchFilter('isperson', 'customer', 'is', 'F')
['customer.isperson', 'is', 'F'],
'and', [
['minimumquantity', 'equalto', 0], 'or', ['minimumquantity', 'isempty', null]
],
];
if (customerId) filters.push('and', ['customer', 'anyof', customerId]);
if (currencyId) filters.push('and', ['currency', 'anyof', currency]);

Related

Suitescript N/Search Filter by custom sublist line field

I am trying to add a search filter for a custom line item field in a suitelet and it is returning no results.
function getExpenseSearch(soNum){
log.debug('getExpenseSearch entered')
log.debug('soNum: ' + soNum)
var billSearch = search.create({
type: 'transaction',
filters: [
[ 'type', search.Operator.ANYOF , ['VendBill']], 'and',
['mainline', search.Operator.IS,['F']], 'and',
['custcol_connected_so', search.Operator.ANYOF, [soNum]] ///<=== this is the problem why is it not registering?
],
columns: ['trandate',
'tranid',
'amount'
]
}).run().getRange({start: 0, end: 100})
log.debug('return billSearch[0].tranid: ' + billSearch[0].tranid) //<== always undefined
return billSearch
}
I have isolated the problem to the sublist field
custcol_connected_so is a List field (of sales orders)
soNum is the netsuite internal id of the record
I have already tried the following:
changed .IS to to .ANYOF
used TEXT value instead of recID
hardcoded the correct recID
used 'expense.custcol_connected_so (and other variations, shot in the dark)
input different syntax for create filter
In the records browser there is no join table for the vendorBill so I would think just the custcol_connected_so filter should work fine.
Taking another look there are a couple of issues.
Your syntax for getting the tranid is incorrect (or at least not supported) and you would not be able to get the mainline amount with a single query because you are only going to be able to return the line level amount. In the example below you could use ref.id to load the sales order or to do a lookup Fields call:
This works in my account:
require(['N/search'], search=>{
search.create({
type:'creditmemo',
filters:[
['mainline', 'is', 'F'], 'AND',
['custcol_linked_transaction', 'anyof', [2403605]]
],
columns:['tranid', 'custcol_linked_transaction']
}).run().each(ref=>{
console.log(ref.id, ref.getValue({name:'tranid'}), ref.getValue({name:'custcol_linked_transaction'}));
return false;
});
});
If soNum is the visible sales order number you'd need to get the SO's internal id in order to run that search. Consider:
function getExpenseSearch(soNum) {
log.debug('getExpenseSearch entered')
log.debug('soNum: ' + soNum)
var soInternalId = null;
search.create({
type: 'salesorder',
filters: ['tranid', 'is', soNum]
}).run().each(function(ref) {
soInternalId = ref.id;
return false;
});
var billSearch = search.create({
type: 'vendorbill',
filters: [
['mainline', 'is', 'F'], 'and',
['custcol_connected_so', 'is', soInternalId] ///<=== this is the problem why is it not registering?
],
columns: ['trandate',
'tranid',
'amount'
]
}).run().getRange({
start: 0,
end: 100
})
log.debug('return billSearch[0].tranid: ' + billSearch[0].tranid) //<== always undefined
return billSearch
}

Add dynamic filter expression OR with script 2.0 in Netsuite

I want to add filters with OR condition dynamically to the search object in script 2.0.
You can use filter expressions to add and/or operators.
As per NetSuite
Use filter expressions as a shortcut to create filters (search.Filter).
eg. search filter like
search.createFilter({
name: 'transactionnumber',
operator: 'is',
values: 'ABC'
});
can be replaced with
[['transactionnumber', 'is', 'ABC'], 'or', ['transactionnumber', 'is', 'XYZ']]
In essence, Search Filters are array or array joined together with operators.
Had the same issue. This is what worked for me:
var soLines = salesOrder.lineItems;
var filteredIDs = [];
for (var i = 0; i < soLines.length; i++) {
filteredIDs.push(['customid', 'is', soLines[i].customID])
filteredIDs.push('OR');
}
filteredIDs.pop();
var mySearch = search.create({
type: search.Type.SALES_ORDER
join: 'item',
columns: [
"internalid",
"item.itemid",
"customid"
],
filters: [filteredIDs]
});
The trick is to create the filter before the search is created. Then you can assign the filtered list as your filters

SuiteScript 2.0 search.create returning empty results

I am trying to get all the sales orders which are pending fulfilment at the point of create a new sales order. This is to alert the user that a sales order is already in progress. The code I am using is as such;
function saleOrderInPendingFulfillmentAlreadyExists(scriptContext)
{
//Check if the customer already has an order which is pending fulfillment
debugger;
var idCustomer = scriptContext.currentRecord.getValue('entity');
var recCustomer;
if(idCustomer)
{
var filters = [
["mainline", "is", "T"], "and",
["type", "anyOf", search.Type.SALES_ORDER], "and",
["entity", "anyOf", idCustomer],
];
var columns = [ "tranid" ];
var searchQuery = search.create({
"type": search.Type.TRANSACTION,
"filters": filters,
"columns": columns
});
var salesorders = searchQuery.run().getRange({"start": 0, "end": 1000}) || [];
}
}
When debugging the code, the variable salesorders is an empty array yet I know the customer file has at least 8 Sales Orders on it. What am I doing wrong?
Your problem is that type search filter expects the record in a different format to the search.Type enum ('SalesOrd' instead of 'salesorder'). Welcome to NetSuite!
You can change the filters to
var filters = [
["mainline", "is", "T"], "and",
["type", "anyOf", 'SalesOrd'], "and",
["entity", "anyOf", idCustomer],
];
or, even better
var searchQuery = search.create({
"type": search.Type.SALES_ORDER,
"filters": filters,
"columns": columns
});
BTW, you should definitely look into the NetSuite Search Export Chrome Extension, which lets you build a search in the UI and converts it automatically to SuiteScript.

Searching an array of items in NetSuite using SuiteScript 2

I am attempting to write a suitescript search that allows me to pass an array of identifiers to a particular field in Netsuite and return the results. I have tried 'ANYOF', 'ALLOF' and "WITHIN' but I keep getting errors
Here is my code so far:
if(params.type=='sku'){
var filter_name = 'itemid';
}else{
var filter_name = 'upccode';
}
var filters = [
search.createFilter({
name: filter_name,
operator: search.Operator.ANYOF,
values: ['HERHR5201','HERHR5202','HERHR5203']
}),
];
var s = search.create({
'type': record.Type.INVENTORY_ITEM,
'filters':filters,
}).run();
s = s.getRange(0,100);
return JSON.stringify(s);
Does anyone know the right sequence to create a multiple search of itemid's? Also, for a bonus, is there a way to have the resultset return the columns I need verses just the ideas? Do I need to createColumn?
You cannot use ANYOF, ALLOF, etc. when filtering a search on a text field. You'll need to create a filter expression with ORs to search on multiple values.
I would do this:
if(params.type=='sku'){
var filter_name = 'itemid';
}else{
var filter_name = 'upccode';
}
var filters = [
[filter_name, 'is', 'HERHR5201'], 'OR',
[filter_name, 'is', 'HERHR5202'], 'OR',
[filter_name, 'is', 'HERHR5203']
];
var s = search.create({
'type': record.Type.INVENTORY_ITEM,
'filters':filters
}).run();
As far as returning specific columns from your search, you'll need to use search.createColumn(), as you point out. So it'd be something like:
//Previous code...
var s = search.create({
'type': record.Type.INVENTORY_ITEM,
'filters':filters,
'columns': [search.createColumn({name: 'internalid'}),
search.createColumn({name: 'upccode'}),
search.createColumn({name: 'itemid'})
/*Other columns as needed*/]
}).run();
The provided answer is correct, however based on your example code provided I am assuming that the search needs to be created somewhat dynamically. Meaning the 'array of identifiers' you mention will not always be the same, nor will they always be the same length. In order to create a search that is completely dynamic based on incoming 'array of identifiers' you would need to get pretty creative. In the below solution I am assuming the function parameter 'params' is an object with a 'type' property, and an arrIn (array of strings) property. The search below uses the formula function 'DECODE', a description of which can be found here.
function execute(params) {
var filter_name;
var itemSearchObj;
var stringArr = '';
var arrIn = params.arrIn;
var i;
var count;
// create search filter type
filter_name = params.type === 'sku' ? 'itemid' : 'upccode';
// create stringArr using incoming arrIn
for (i = 0; arrIn && arrIn.length > i; i += 1) {
stringArr += i > 0 ? ", '" + arrIn[i] + "', 'true'" : "'" + arrIn[i] + "', 'true'";
}
if (arrIn.length > 0) {
itemSearchObj = nsSearch.create({
type: 'item',
filters: [
["formulatext: DECODE({" + filter_name + "}," + stringArr + ")", "is", 'true']
],
columns: [
'itemid', // dont need to get fancy here, just put the internal id of whichever fields you want in the columns
'description'
]
});
count = itemSearchObj.runPaged().count;
itemSearchObj.run().each(function (result) {
// Do things for each result
});
}
}
I found this quite a bit of a curveball as I was overthinking it. The search requires an array:
results = search.create({
type: search.Type.CUSTOMER,
filters: [],
columns: [ search.createColumn({ name: "internalid", sort: search.Sort.ASC }) ]
})
This filter array consists of a search term array and logical operators (AND, OR).
['fieldid', 'is', yourValue], // search term array
'AND' // logical operator
So you can create your own filter array, by pushing in the search terms and logical operators as required.
For example if you want to return the internal id for customer emails in an array:
let email = ['abc#test.com', 'def#test.com'];
let myFilter = createFilter(email);
function createFilter(email){
let filter = [];
email.forEach((result, index) => {
if(index > 0)
filter.push('OR'); // Logical Operator
filter.push(['email', 'is', result]);
});
return filter;
}
Variable myFilter will now equal:
[ ['email', 'is', 'abc#test.com'], 'OR', ['email', 'is', 'def#test.com'] ]
And can be directly referenced as the filter in the search.
let results = search.create({
type: search.Type.CUSTOMER,
filters: myFilter,
columns: [ search.createColumn({ name: "internalid", sort: search.Sort.ASC }) ]
})

Search filter in Netsuite for specified months

In netsuite we have months (Not in serial order).
months values are say :
list_month = [182,183,186,187,188,190,191,192,194,195,196,199,200,201];
I want to apply search filter to get records within certain months say from 183 to 194.
var period = 183;
var period1 = 194;
I used the "between" and "within" but it did not work'
Here is my filter:
filters.push(new nlobjSearchFilter("postingperiod","transaction","within",period,period1));
this returns only the values of 183. I want all of them : 183,186,187,188,190,191,192,194.
*Note this are not dates but months (starting from 1 to last date of that month)
How can i get this.
Thanks
You would need to specify each period as a separate filter and use .setParens(1) and .setOr(true) to build out the logic of your search like this:
var results = nlapiSearchRecord('invoice', null, [
new nlobjSearchFilter('mainline', null, 'is', 'T'),
new nlobjSearchFilter('postingperiod', null, 'within', 122).setLeftParens(1).setOr(true),
new nlobjSearchFilter('postingperiod', null, 'within', 123).setRightParens(1)
], [
new nlobjSearchColumn('internalid', null, 'count')
]);
If you don't always know which periods you'll need, you can generate these filters dynamically with a function like this:
function buildPeriodFilters(periodIds) {
// Return empty array if nothing is passed in so our search doesn't break
if (!periodIds) {
return [];
}
// convert to array if only a single period id is passed in.
periodIds = [].concat(periodIds);
return periodIds.map(function(periodId, index, periodIds) {
var filter = new nlobjSearchFilter('postingperiod', null, 'within', periodId);
// if this is the first periodid, add a left parenthesis
if (index === 0) {
filter = filter.setLeftParens(1);
}
// if this is the last period id, add a right parenthesis, otherwise add an 'or' condition
if (index !== periodIds.length - 1) {
filter = filter.setOr(true);
} else {
filter = filter.setRightParens(1);
}
return filter;
});
}
var dynamicPeriodFilter = buildPeriodFilters([122,123,124]);
var results = nlapiSearchRecord('invoice', null, [
new nlobjSearchFilter('mainline', null, 'is', 'T'),
].concat(dynamicPeriodFilter), [
new nlobjSearchColumn('internalid', null, 'count')
]);

Resources