guys!
I'm writing an email template for the invoices. On the invoice form I have a "Project" (internalId: Job) field -> on the "Project" form I have a "custom entity" field with employee-type. I can get an employee's name with ${transaction.job.custentity5}. But I can't get access to related fields such as email, phone number and etc. The code ${transaction.job.custentity5.email} gives me nothing. The code ${transaction.job.custentity5.mobilephone} gives me a strange error like "field job.mobilephone not found" (netsuite hides custentity5 in this objects chain), but I see this field in employee's profile.
How do i get child values from custentity field?
Unfortunately, you can't go into such a deep level with the standard data provided.
You can however fetch the data with a search.lookupFields during a beforeLoad and set it as default value on a custom field of the form.
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
*/
define(['N/ui/serverWidget', 'N/search'], function(serverWidget, search) {
function beforeLoad(context) {
var invoice = context.newRecord;
var form = context.form;
var type = context.type;
var UserEventType = context.UserEventType;
// only execute during printing...
if (type != UserEventType.PRINT) return
var jobID = invoice.getValue({fieldId: 'job'});
// return when no job/project is set on the invoice...
if (!jobID) return
var job = search.lookupFields({
type: search.Type.JOB,
id: jobID,
columns: ["custentity5"]
})
// return when no employee is set on the project...
if (!(job.custentity5 && job.custentity5[0] && job.custentity5[0].value)) return
var employee = search.lookupFields({
type: search.Type.JOB,
id: job.custentity5[0].value,
columns: ["email", "phone"]
})
var field = form.addField({
id : 'custpage_custom_data_employee',
label: 'Employee',
type : serverWidget.FieldType.LONGTEXT
});
field.defaultValue = JSON.stringify(employee);
}
return {
beforeLoad: beforeLoad
};
})
You can access the data within the template through:
<#if record.custpage_custom_data_employee?has_content>
<#assign employee = record.custpage_custom_data_employee?eval />
</#if>
Netsuite doesn't drill down that far for you. Generally you get one step away from the primary record so you see a name using ${transaction.job.custentity5} because you'd see a name if you opened the associated job record.
How you can show the details from custentity5 depends on a bunch of factors like who is sending this email? Is is special enough to have its own button? Is the email being sent batch etc.
Options:
A before load user event script can check whether the record is being printed or emailed the standard way. That script can load and populate custom fields on the main record so you may be able to reference ${transaction.custpage_ent5.mobilephone} where you'd added the job's custom entity to the transaction
fully script your email using n/Render. You'll likely need to script everything but you can look up and add arbitrary records and datastructures to your renderer. This would be triggered by a custom button or batched script.
Related
Is there any way to get the current company name when on a transaction entry page? Either some session object, global object, or some sort. Kind of like how you can get the user name from the runtime module? I see country name, but cannot seem to get the company name. Using a client script for this.
How I get the user name:
runtime.getCurrentUser().name
thank you
Here is the working code now, but trying to figure a way to get this on a client script. Possible to pass this value?
var companyInfo = config.load({
type: config.Type.COMPANY_INFORMATION
});
var compname = companyInfo.getValue({
fieldId: 'companyname'
});
log.debug(compname);
scriptContext.form.addButton({
id: "custpage_mybutton",
label: "View Documents",
functionName: "onButtonClick"
});
scriptContext.form.clientScriptModulePath = "SuiteScripts/dl_cs_vendorbill.js";
In server side scripts you can do this:
require(['N/config'], config=>{
const info = config.load({type:config.Type.COMPANY_INFORMATION});
log.debug({title:'Current company Info', details:info.getValue({fieldId:'companyname'}));
});
For a client script you could use that code in a paired user event script.
In the before phase of the UE you'd do the lookup and then add a hidden field to the form with the company name as a value. Your client script can then look that up like any normal getValue
I wish to change the subsidiary which is being represented by a certain entity, as I have used a dummy subsidiary before.
Is there a way to do this? I cannot change the field via the UI and I cannot find the field in the import functionality
You can find the "subsidiary" field in the UI by completing the following: go to a entity record in edit mode, un-layer all tabs (or add "&unlayered=T" to the url bar), use the browser Find feature (normally Ctrl + F) and search for subsidiary. If it does not come up this way identify the form used and open that for editing, un-layer all tabs, and use the find feature for subsidiary, elect to show or change the display settings then return to the record in edit mode to change.
OR via suitescript, if you have the field id (if native/standard NetSuite field id = subsidiary) you can run the following code in the browser console
require(['N/record'], function(record){
var Ids = [
//enter all entity internal ids here
];
for (var i=0; i<Ids.length; i++){
record.submitFields({
type: record.Type.______, //ref Suite Answer Id: 45161
id: Ids[i],
values: {
subsidiary: 1 //the internal id for the subsidiary you want to set
},
options: {
enableSourcing: false, //default is true
ignoreMandatoryFields : true //default is false
}
});
console.log('done', 'updated id: '+Ids[i]);
}
console.log('done', '# of records updated: '+i);
});
OR you can try Mass Updates (ref Suite Answer 8429), or CSV Imports (ref Suite Answer 10022).
I have the id field on a netsuite object. Can I change use the id column as the external id in Netsuite, something like in Salesforce?
You can definitely write a user event script to populate the internal id of any record to it's external ID field. The "externalid" field is exposed via SuiteScript or via csv import
The internal id is a unique auto-generated number which identifies a unique NetSuite record and hence the sequence would change if deletion/inactivation happens For eg.if there are records with internal Ids 1, 2 and 3 in system and 2 gets deleted, then IDs that remain in the system are 1 and 3. User does not have the ability to alter these internal Ids since they are system generated. Hence, they cannot be customized (acc to developer's preference) specially if you want to follow a specific convention.
External Id should contain a value which should be unique across multiple integrated systems.Eg. SFDC (Salesforce). The recommended way is to write an afer submit user event script to populate external ID on all the integrated records and keep these synced in both systems
Here is a sample code in SuiteScript 2.0 which populated external ids for subsidiary, account and department:
var recordType = context.newRecord.type;
log.debug({ title: 'Record Type', details: recordType })
var recordId = context.newRecord.id;
log.debug({ title: 'Record ID', details: recordId })
var rec = record.load({
type: recordType,
id: recordId
});
//Setting External ID on subsidiary
if (recordType == record.Type.SUBSIDIARY)
{
var subExID
=rec.setValue('externalid'(rec.getValue('tranprefix').substring(0, 3)))
log.debug({ title: 'TranPrefix', details: subExID })
}
//Setting External ID on account
if (recordType == record.Type.ACCOUNT)
{
var accExID = rec.setValue('externalid',
rec.getValue('acctnumber'))
log.debug({ title: 'External ID', details: accExID })
}
//Setting External ID on department
if (recordType == record.Type.DEPARTMENT)
{
var deptExID = rec.setValue('externalid', rec.getValue('custrecord_dept_code'))
log.debug({ title: 'External ID', details: deptExID })
}
Please let me know if this is helpful !!!
I have a button on the Purchase Order record that performs a saved search query on the current record and then uses the http module to send that data via a POST to a url. That url then sends the data posted back as part of the success confirmation. The idea with the saved search is to create a javascript object that contains all the data that I want from the purchase order (main record and items sublist with subrecords) and then to use JSON.stringify to create a JSON payload for the http POST. I can't do this with the currentRecord because if you inspect it it only contains the internal id. This would also prevent me from having to go to the great lengths of writing a lot of code to manually build up a JSON string from the currentRecord.
Unfortunately I don't really understand how to specify the column names in the dynamically created saved search. Sometimes it looks to me like the column names are those from the NetSuite Records Browser and other times the script gives an error (column not found) if I use a column name from the NetSuite Records Browser (for example currencysymbol).
I'm also not sure how to specify columns that appear in sublists or subrecords in sublists. I tried to use item.itemtype but this gave me a column not found error. Just item completes successfully but I'm not sure whether this was really successfull since it is difficult to decode the returned result after the JSON.stringify (it adds a lot of backslashes). Using console.log (for some reason I don't get anything back using the NetSuite log.audit) is also quite difficult, although it looks like it is returning an array with 5 rows. So using item might sort of be successful. I say sort of because I have 3 item lines and it is returning 5 array rows.
So basically I would like to know where one can find the names of the columns to use in NetSuite for a saved search; and also how to specify sublist column names and sublist subrecord column names in a saved search.
/**
* #NApiVersion 2.0
* #NScriptType ClientScript
* #NModuleScope SameAccount
*/
define(['N/ui/dialog', 'N/currentRecord', 'N/record', 'N/url', 'N/http', 'N/search'], function (dialog, rec, record, url, http, s) {
function pageInit(context) {
// All client scripts need at least one dummy function.
} // pageInit
function onButtonClick() {
var currentRecord = rec.get();
// Create a saved search dynamically.
var rs = s.create({
type: s.Type.PURCHASE_ORDER,
filters: [
["mainline", s.Operator.IS, "F"], "and",
["internalid", s.Operator.IS, currentRecord.id]
],
columns: [
"internalid",
"currency",
{
name: "item",
sort: s.Sort.ASC // DESC
}
]
});
var myPostDataObj = rs.run().getRange(0, 1000);
console.log(myPostDataObj);
var headers = {
'Content-Type': 'application/json; charset=utf-8',
};
http.post.promise({
url: 'http://httpbin.org:80/post',
body: JSON.stringify(myPostDataObj),
headers: headers
})
.then(function(response){
console.log('SUCCESS: ' + JSON.stringify(response));
})
.catch(function onRejected(reason) {
console.log('ERROR: ' + JSON.stringify(reason));
})
}
return {
pageInit: pageInit,
onButtonClick: onButtonClick
};
}); // Define
There are two Chrome extensions I suggest you get;
NetSuite Field Explorer. This extension will show you the ids (and values) of all the fields in a NetSuite record.
NetSuite Search Export. This extension will convert/export a saved search to SuiteScript.
For what you're doing, I would create your saved search in the UI, and then export it using the Saved Search Export extension, paste that into your code (where s.create is), and work from there.
The first extension is nice to get to the sublist field ids. Saves a lookup in the record browser.
I am trying to call the Netsuite SuiteScript 2.0 N/record module's load function, but I am unsure as to what to pass for the parameters. Basically I would like a N/record with the same id (primary key) of the current record in the UI, that I can use to loop through the sublist items.
I'm not sure how to use the Records Browser in order to find the correct type and id. The Records Browser does not have the type, so I guessed at the name. There are also multiple fields that could be the primary key id. Is it tranid or externalid or some other field? I'm specifically interested in the Inventory Adjustment form. externalid is undefined and tranid is To Be Generated.
Is it possible to get a N/Record based on the currentRecord in this manner or will it also suffer from the same issues I have with currentRecord (I can't use selectLine to step through the sublist items, sublist items have not been saved yet and the last one is partially completed)?
/**
* #NApiVersion 2.0
* #NScriptType ClientScript
* #NModuleScope SameAccount
*/
define(['N/search', 'N/record'], function (s, r) {
function fieldChanged(context) {
var currentRecord = context.currentRecord;
var sublistName = context.sublistId;
var sublistFieldName = context.fieldId;
var currentLine = context.line;
var recordId = currentRecord.getValue({fieldId: "externalid"});
var record = r.load({
type: r.Type.INVENTORY_ADJUSTMENT,
id: recordId,
isDynamic: true
});
Is it possible to get a N/Record based on the currentRecord
Yes, although N/record module is used to load/create records. So in order to use N/record module, you need to make sure that your record already exists or you are creating new.
InternalId specified at the top of the Records Browser page is the recordType that you need to pass as type to record module.
Also try using async version of record load. i.e record.load.promise in client script.