I’ve written a function to retrieve either locationquantityavailable or locationquantityonhand from another subsidiary.
The assumption is the user has visibility of both subsidiaries, in a scenario where a sales order is being entered under Subsidiary A, and a SO item custom field is to show the items stock on hand in Subsidiary B.
At the moment I’m getting a null result from the saved search below. I’m sure I’m missing something very basic.
The logger line is correctly giving results: Get Stock Sub:36 Loc:16 Item:4448
I know there IS both onhand and available stock in the source sub/loc/item combination.
function getStock(sub, loc, itemid, available ) {
try {
var subsidiary = isNum(sub),
location = isNum(loc),
item = isNum(itemid);
if (subsidiary == 0 || location == 0 || item == 0) {return 0}
var filters = [ new nlobjSearchFilter('subsidiary', null, 'anyof', sub ),
new nlobjSearchFilter('location', null, 'anyof', loc ),
new nlobjSearchFilter('internalid', null, 'is', itemid )];
var columns = [ new nlobjSearchColumn('subsidiary' ),
new nlobjSearchColumn('location' ),
new nlobjSearchColumn('internalid' ),
new nlobjSearchColumn('locationquantityonhand' ),
new nlobjSearchColumn('locationquantityavailable' )];
logger('Get Stock Sub:'+subsidiary+' Loc:'+location+' Item:'+item);
logger(filters);
logger(columns);
var res = nlapiSearchRecord('item',null,filters,columns);
logger('Get Stock Search:');logger(res);
if (res == null ) {
return 0;
}
if (available) {
return res[0].getValue('locationquantityavailable');
}
else {
return res[0].getValue('locationquantityonhand');
}
} catch (err) { logger(err) }
}
Disregard... doh!! inventory versus inventorylocation in the search. not enough coffee
Related
I have created a search in Netsuite using Suitescript 1.0 for searching a particular "Account" using its account number. When I save the following script file, an error is being displayed in "filters[0]" line in the code below, where it says "acctnumber is not a valid internal id.". I am new to Netsuite and would want to know why the error is being displayed, and the solution for the same. Below is the following piece of code written in which the error is being occured.
function COGSAcnt() {
var cOGSAcntNumber = '50001';
var acntNo;
var filters = new Array();
filters[0] = new nlobjSearchFilter('acctnumber', null, 'startswith', cOGSAcntNumber);
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
var acntSearch = nlapiSearchRecord('account', null, filters, columns);
if (acntSearch != null) {
for (x=0; x<acntSearch.length; x++) {
acntNo = ITMSearch[x].getValue('internalid');
}
}
nlapiLogExecution('debug', 'acntNo', acntNo);
return acntNo;
}
NOTE: I want the filter to be acctnumber (Account Number), and using that would want to retrieve the internalid of the account in Netsuite.
This is where NS can be a little confusing. If you look at the NS Record browser (http://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2016_2/script/record/account.html) look under the Filters section. Account Number (acctnumber) isn't there. However Number (number) is the filter.
Try rewriting the code to use number instead
function COGSAcnt() {
var cOGSAcntNumber = '50001';
var acntNo = [];
var filters = new nlobjSearchFilter('number', null, 'startswith', cOGSAcntNumber);
var acntSearch = nlapiSearchRecord('account', null, filters, columns);
if (acntSearch != null) {
for (x=0; x<acntSearch.length; x++) {
acntNo.push(ITMSearch[x].getId();
}
}
return acntNo;
}
I was searching for a value from contract record in Purchase record but i am unable to get the field where the value is. Below is the code for that. I am applying this code for the contract record and the function is for before submit.
I think I am applying the search in wrong way.
function srchfield()
{
var recordid = nlapiGetRecordId() //retunrs the contract id
nlapiLogExecution('DEBUG', 'recordid ', recordid );
var recordtype = nlapiGetRecordType(); //retunrs the contract recordtype = jobs
nlapiLogExecution('DEBUG', 'RecordType', recordtype);
var loadrecord = nlapiLoadRecord(recordtype, recordid); //loads the record
nlapiLogExecution('DEBUG', 'Load Record', loadrecord );
var contractname = nlapiGetFieldValue('entityid'); //returs the value of the field contractname whose fieldid is = entityid
nlapiLogExecution('DEBUG', 'ContractName ', contractname );
var filters = new Array();
new nlobjSearchFilter('entityid', null, 'anyof', contractname ); // entityid is field id in contract Record and contractname is defined above for contract record
// nlapiLogExecution('DEBUG', 'SearchFilter', filters );
var columns = new Array();
new nlobjSearchColumn('custbodycontract'); // custbodycontractis field id in PO Record
var searchresults = nlapiSearchRecord('purchaseorder', null, filters, columns);
for ( var i = 0; searchresults != null && i < searchresults.length; i++ )
{
var searchresult = searchresults[ i ];
var record = searchresult.getId( );
var rectype = searchresult.getRecordType( );
var cntrct_name= searchresult.getValue( 'custbodycontract' );
}
}
Thanks in advance
****Update: I have completed my answer based on the comments provided. Please see at the last section. I hope it helps. Thanks!***
**I might provide you the snippet if you will explain this further. Please advise
If I understand correctly your code, these are what you are doing and you want to do:
Your contract record is the native entity record - project/job. It had just been renamed to contract by your functional consultant.
You have an user event script (SuiteScript 1.0) before submit and deployed to the contract (project/job) record.
Using the information from the contract record (in this case using the contract name (entityid), you wanted to search for POs to get 'custbodycontract' at the header.
Then you are filtering the search on POs using "entityid" but PO doesnt have that native field on the header. It only has it on the expense line and item line but the id is 'customer'.
Can you explain how is the contract record related to PO. Which field (native/custom) is available on PO that can be used as a join on contract record?
Then, please take note this best practice as freebie.
To optimize your script. You don't need to use nlapiLoadRecord on beforesubmit. Please see below the best practice.:
- With beforesubmit and if you are only getting or setting values on the script deployed record, use nlapiGet** and nlapiSet** API.
- On beforesubmit, only use nlapiLoadRecord if you are getting and setting the value on the sublist of a different record. But utilize first nlapiSearchRecord if you are only getting value at the line level (different record). If it will not give what you need, use nlapiLoadRecord.
- On aftersubmit, only use nlapiLoadRecord if you are setting and getting value at the line level of the deployed record and different record. If you are only getting value at the level, same practice with beforesubmit.
- On aftersubmit, use nlapiLookUp for getting value from the header, and nlapiSubmitField if you are setting. Only use nlapiLoadRecord if it doesnt give you what you need.
****This might what you need...
function srchfield()
{
var stRecordid = nlapiGetRecordId(); /*retunrs the contract id*/
nlapiLogExecution('DEBUG', 'recordid ', stRecordid);
var stRecordtype = nlapiGetRecordType(); /*retunrs the contract recordtype = jobs*/
nlapiLogExecution('DEBUG', 'RecordType', stRecordtype);
var stContractname = nlapiGetFieldValue('entityid'); /*returs the value of the field contractname whose fieldid is = entityid*/
nlapiLogExecution('DEBUG', 'ContractName ', stContractname);
var arrFilters = new Array();
arrFilters.push(new nlobjSearchFilter('type', null, 'anyof',
[
'PurchOrd'
])); /*As best practice, instead of directly searching on POs, add filter for transaction type since you might use this later in other transaction.*/
arrFilters.push(new nlobjSearchFilter('mainline', null, 'is', 'T')); /*This is to exclude line level results*/
arrFilters.push(new nlobjSearchFilter('custbodycontract', null, 'is', stContractname));
var arrColumns = new Array();
arrColumns.push(new nlobjSearchColumn('trandate')); /*I just wanted to include this column on the result. :)*/
arrColumns.push(new nlobjSearchColumn('type')); /*I just wanted to include this column on the result. :)*/
arrColumns.push(new nlobjSearchColumn('tranid')); /*I just wanted to include this column on the result. :)*/
arrColumns.push(new nlobjSearchColumn('custbodycontract')); /*This is what you need.*/
var arrSearchresults = nlapiSearchRecord('transaction', null, arrFilters, arrColumns);
for (var i = 0; arrSearchresults != null && i < arrSearchresults.length; i++)
{
var objResult = arrSearchresults[i];
var stRecId = objResult.getId();
var stRecType = objResult.getRecordType();
var stCntrctName = objResult.getValue('custbodycontract');
}
The problem I notice on your code is the creation of the filter.
You instantiated nlobjSearchFilter but you didn't push it in an array. So basically, you are searching without filter.
And I believe your search criteria were complete.
Try below codes. By the way make sure that the field type of custbodycontract is a freeform text to properly compare it with the entityid of the contract record.
function srchfield()
{
var stRecordid = nlapiGetRecordId(); /*retunrs the contract id*/
nlapiLogExecution('DEBUG', 'recordid ', stRecordid);
var stRecordtype = nlapiGetRecordType(); /*retunrs the contract recordtype = jobs*/
nlapiLogExecution('DEBUG', 'RecordType', stRecordtype);
var stContractname = nlapiGetFieldValue('entityid'); /*returs the value of the field contractname whose fieldid is = entityid*/
nlapiLogExecution('DEBUG', 'ContractName ', stContractname);
var arrFilters = new Array();
arrFilters.push(new nlobjSearchFilter('type', null, 'anyof',
[
'PurchOrd'
])); /*As best practice, instead of directly searching on POs, add filter for transaction type since you might use this later in other transaction.*/
arrFilters.push(new nlobjSearchFilter('mainline', null, 'is', 'T')); /*This is to exclude line level results*/
arrFilters.push(new nlobjSearchFilter('custbodycontract', null, 'is', stContractname));
var arrColumns = new Array();
arrColumns.push(new nlobjSearchColumn('trandate')); /*I just wanted to include this column on the result. :)*/
arrColumns.push(new nlobjSearchColumn('type')); /*I just wanted to include this column on the result. :)*/
arrColumns.push(new nlobjSearchColumn('tranid')); /*I just wanted to include this column on the result. :)*/
arrColumns.push(new nlobjSearchColumn('custbodycontract')); /*This is what you need.*/
var arrSearchresults = nlapiSearchRecord('transaction', null, arrFilters, arrColumns);
for (var i = 0; arrSearchresults != null && i < arrSearchresults.length; i++)
{
var objResult = arrSearchresults[i];
var stRecId = objResult.getId();
var stRecType = objResult.getRecordType();
var stCntrctName = objResult.getValue('custbodycontract');
}
}
i want to get all the records in particular record type , but i got 1000 only.
This is the code I used.
function getRecords() {
return nlapiSearchRecord('contact', null, null, null);
}
I need two codes.
1) Get whole records at a single time
2) Get the records page wise by passing pageindex as an argument to the getRecords [1st =>0-1000 , 2nd =>1000 - 2000 , ...........]
function getRecords(pageIndex) {
.........
}
Thanks in advance
you can't get whole records at a time. However, you can sort results by internalid, and remember the last internalId of 1st search result and use an additional filter in your next search result.
var totalResults = [];
var res = nlapiSearchRecord('contact', null, null, new nlobjSearchColumn('internalid').setSort()) || [];
lastId = res[res.length - 1].getId();
copyAndPushToArray(totalResult, res);
while(res.length < 1000)
{
res = nlapiSearchRecord('contact', null, ['internalidnumber', 'greaterthan', lastId], new nlobjSearchColumn('internalid').setSort());
copyAndPushToArray(totalResult, res);
lastId = res[res.length - 1].getId();
}
Beware, if the number of records are high you may overuse governance limit in terms of time and usage points.
If you remember the lastId you can write a logic in RESTlet to take id as param and then use that as additional filter to return nextPage.
You can write a logic to get nth pageresult but, you might have to run search uselessly n-1 times.
Also, I would suggest to use nlapiCreateSearch().runSearch() as it can return up to 4000 records
Here is another way to get more than 1000 results on a search:
function getItems() {
var columns = ['internalid', 'itemid', 'salesdescription', 'baseprice', 'lastpurchaseprice', 'upccode', 'quantityonhand', 'vendorcode'];
var searchcolumns = [];
for(var col in columns) {
searchcolumns.push(new nlobjSearchColumn(columns[col]));
}
var search = nlapiCreateSearch('item', null, searchcolumns);
var results = search.runSearch();
var items = [], slice = [], i = 0;
do {
slice = results.getResults(i, i + 1000);
for (var itm in slice) {
var item = {};
for(var col in columns) { item[columns[col]] = slice[itm].getValue(columns[col]); } // convert nlobjSearchResult into simple js object
items.push(item);
i++;
}
} while (slice.length >= 1000);
return items;
}
I'm new in CRM development. I know a basic thing like "best practice for crm 2011"
I wanna understand now how to work with lookup fields. And I think I chose the easiest way for my self.
I have an costum entity "contract" it has 5 more field, 2 of these are lookups.
First lookup (agl_contractId) - it is a link by it self
Second lookup (agl_ClientId) - link to Client.
What do I need?
When I choose fill First lookup (agl_contractId), script should find in this contract a Client and copy-past it to current form.
I've done script but it isn't work... (((
function GetAccountFromContract()
{
XrmServiceToolkit.Rest.Retrieve(Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue(),
'agl_osnovnoy_dogovoridSet',
null,null,
function (result) {
var Id = Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue();
if (result.Id != null) {
var LookupData = new Array();
var LookupItem = new Object();
var lookuptextvalue = lookupvalue[0].name;
var lookupid = lookupvalue[0].id;
var lokupType = lookupvalue[0].entityType;
alert(lookupvalue);
alert(lookupData);
Xrm.Page.getAttribute("agl_accountid").setValue(lookupData);
}
},
function (error) {
equal(true, false, error.message);
},
false
);
}
If I understand you well: When you select Contract in agl_osnovnoy_dogovorid field, you want to pull Client property from that Contract and put it in agl_accountid field?
If that is right:
First, get Id of selected Contract (from agl_osnovnoy_dogovorid field)
var selectedContract = new Array();
selectedContract = Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue();
{
var guidSelectedContract = selectedContract[0].id;
//var name = selectedContract[0].name;
//var entType = selectedContract[0].entityType;
}
Second, retrieve Client from agl_osnovnoy_dogovorid. Your oData query will be like:
http://crmserver/org/XRMServices/2011/OrganizationData.svc/ContractSet(guid'" + guidSelectedContract + "')/CustomerId
(In example I'm using CustomerId field. For your case enter Schema Name of Client field).
Now, execute query and put result into agl_accountid field:
$.getJSON(
Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/ContractSet(guid'" + guidSelectedContract + "')/CustomerId",
function(data){
if(data.d.CustomerId != null && data.d.CustomerId.Id != null && data.d.CustomerId.Id != "undefined")
{
//set agl_accountid field
Xrm.Page.getAttribute("agl_accountid").setValue([{id:data.d.CustomerId.Id, name:data.d.CustomerId.Name, typename:data.d.CustomerId.LogicalName}]);
}
});
Your using REST to retrieve data but also using FetchXml example to setup the agl_accoutid lookup.
Also some of the conditions are not clear … anyway … I’ve incorporated the change to your original post.
function GetAccountFromContract()
{
var aodLookupValue = Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue();
if (!aodLookupValue) return;
XrmServiceToolkit.Rest.Retrieve( aodLookupValue[0].id ,
'agl_osnovnoy_dogovoridSet', null,null,
function (result) {
var customer = result.d["your attribute name"];
if (customer) {
var LookupData = new Array();
var LookupItem = new Object();
var lookuptextvalue = customer.Name;
var lookupid = customer.Id;
var lokupType = customer.LogicalName;
alert(lookupvalue);
alert(lookupData);
Xrm.Page.getAttribute("agl_accountid").setValue(lookupData);
}
},
function (error) {
equal(true, false, error.message);
}, false );
}
Is it possible to automatically set adjustment alternate SKU values for a product in Ubercart?
Basically every product will have a suffix added to it's original SKU based on the adjustment, so it would save a lot of time to populate the adjustment SKU's automatically when the product node is created.
Here's a JavaScript version - it provides a link to automatically generate the SKUs as well as a 'default stock' option on the stock page.
Drupal.behaviors.autoSKU = function(){
//if we're on the product adjustments page, add a button to automatically set sku's
if($('#uc-product-adjustments-form').length > 0){
$('#uc-product-adjustments-form').before($('<a>Automatically set SKU\'s</a>').css('cursor', 'pointer').click(function(){
$base = $('#uc-product-adjustments-form').attr('action').substr(6, 4) + '-';
$('#uc-product-adjustments-form .form-text').each(function(){
$(this).attr('value', $base + $(this).parents('tr').attr('title').toLowerCase().replace(new RegExp(' ', 'g'),'-'));
});
}));
}
//if we're on the stock page, automatically set as active and set default stock level
if($('#uc-stock-edit-form').length > 0){
$('#uc-stock-edit-form').before($('<a>Activate and Set Default Stock</a>').css('cursor', 'pointer').click(function(){
$first = true;
$('#uc-stock-edit-form .form-checkbox').each(function(){
if($first){
$(this).attr('checked', false);
$first = false;
}
else{
$(this).attr('checked', true);
}
});
$set_stock = $('#edit-stock-0-stock').attr('value');
$odd = true;
$('#uc-stock-edit-form .form-text').each(function(){
if($odd){
$(this).attr('value', $set_stock);
}
$odd = !$odd;
});
}));
}
}
This may not be the -right- way to do it, but I created a small module that taps into the nodeapi insert operation:
<?php
function photo_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'photo_node_form'){
$form['base']['model']['#default_value'] = 'placeholder';
}
}
function photo_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch($op){
case 'presave':
if($node->model == 'placeholder')
$node->model = $node->field_image_cache2[0]['filename'];
break;
case 'insert':
$nid = $node->nid;
$sku_dl = $node->model.'d';
//====== Setup Adjustments ======
db_query('INSERT INTO {uc_product_adjustments} (nid,combination,model) VALUES'
.'('.$nid.',"%s","'.$sku_dl.'"),'
.'('.$nid.',"%s","'.$sku_dl.'"),'
.'('.$nid.',"%s","'.$sku_dl.'"),'
.'('.$nid.',"%s","'.$sku_dl.'"),'
.'('.$nid.',"%s","'.$sku_dl.'")'
,serialize(array('1'=>'1'))
,serialize(array('1'=>'3'))
,serialize(array('1'=>'4'))
,serialize(array('1'=>'5'))
,serialize(array('1'=>'6'))
);
//====== Add file download on purchase ======
$file_name = $node->field_image_cache2[0]['filename'];
db_query("INSERT INTO {uc_files} (filename) VALUES ('%s')",$file_name);
db_query("INSERT INTO {uc_file_products} (pfid, fid, model, description, shippable) VALUES (%d, LAST_INSERT_ID(), '%s', '%s', %d)", 0, $sku_dl, '', 1);
db_query('UPDATE {uc_file_products} SET pfid = LAST_INSERT_ID() WHERE fpid = LAST_INSERT_ID() LIMIT 1');
db_query("INSERT INTO {uc_product_features} (pfid, fid, nid, description) VALUES (LAST_INSERT_ID(), '%s', %d, '%s')", 'file', $nid, '<b>Filename</b><br/>'.$file_name.'<br/> <b>Reference</b> : '.$sku_dl);
break;
}
}
Have a look at http://drupal.org/project/uc_product_power_tools
Appears this can be done off the shelf.