NetSuite script to update one line level field from another after submit - javascript

First, I'm very new to scripting in NetSuite, so please forgive the scrappy code.
I'm trying to create a script (yes, I know this can be done in a workflow) that loops back through the lines of a sales order and copies the line 'amount' over to the 'altsalesamt' field after the order is saved. The script runs okay but doesn't actually do anything.
function afterSubmit_setASA(){
var soItemCount = nlapiGetLineItemCount('item');
for (var i = 1; i <= soItemCount; ++i) {
var lineamt = nlapiGetLineItemValue('item', 'amount', i);
if (lineamt != null && lineamt != '') {
nlapiSetLineItemValue('item', 'altsalesamt', i, lineamt);
}
}
}
Can anyone point me in the right direction of what I may need to change or do? Any help is greatly appreciated!!

You are doing this in the After Submit event. At this point, the record has already been submitted to the database. You have two options:
As #eliseobeltran said, you can load and submit the record first.
Move your exact existing code to the Before Submit event instead.
I would recommend option 2, as this will use less governance, be more performant, and result in less database queries.

You forgot to submit: nlapiSubmitRecord(...);
You can also try this code:
var record = nlapiLoadRecord(nlapiGetRecordType(), nlapiGetRecordId());
var soItemCount = record.getLineItemCount('item');
for (var i = 1; i <= soItemCount; ++i) {
var lineamt = record.getLineItemValue('item', 'amount', i);
if (lineamt != null && lineamt != '') {
record.setLineItemValue('item', 'altsalesamt', i, lineamt);
}
}
var id = nlapiSubmitRecord(record, true);

Related

Google Script - Forms - Issues Deleting Page Breaks/Sections - "Invalid data updating form"

I am having an issue with the following code when trying to iterate through the items in a form and delete them to make way for new sections/questions. However, I sometimes get the following error "Invalid data updating form". I have worked around this multiple times now, but it keeps coming back up. My current workaround has been to set the section title to "", which made it available to delete. Previously, I didn't need to do this until today.
My question: What is the best way to iterate through the items in a form and delete them from a starting point and not encounter this error?
Reference:
f = the current active form
f_items = all of the items of the form in an array
function clearForm()
{
var clearQ = find(f_items, "Select Appointment Date/Time")+1;
var f_i_len = f.getItems().length-1;
var clear = clearQ;
while(clear <= f_i_len && clear >= clearQ)
{
var item = f.getItems()[clear];
Logger.log(item.getTitle() + " | " + item.getType());
Logger.getLog();
if(item.getType() == "PAGE_BREAK")
{ item.asPageBreakItem().setTitle(""); }
f.deleteItem(clear);
f_i_len = f.getItems().length-1;
clear++;
}
}
function find(src, name)
{
var s_len = src.length;
for(var iter = 0; iter < s_len; iter++)
{
var s = src[iter].getTitle();
if(s == name)
{ return iter; }
}
return -1;
}
The issue I had with this was that the PageBreakItem I was trying to delete was the destination for a conditional answer earlier in the form.
Below is my code where I needed to delete everything after a certain item, which linked to the sections I needed to delete, so I was able to iterate backwards with a while loop.
function getParentNameItem_(form, form_items){
//finds the item with conditional navigation to what you want to delete
var parent_name_item = find_(form_items, "Your Name");
parent_name_item = parent_name_item.asListItem();
//clears all choices which breaks the navigation dependency
//this frees up the items to be deleted
parent_name_item.setChoices([parent_name_item.createChoice("")]);
var size = form_items.length - 1;
//iterates from the end back to the last question I want to keep
while(form_items[size].getTitle() != "Your Name"){
//this can take either the item itself or the index as I've done
form.deleteItem(size);
size--;
}
/*I rebuild the choices for parent_name_item
later based on information from a spreadsheet
which I also use to determine the content of
the PageBreakItems I just deleted*/
return parent_name_item;
}
I found out the issue! It was the clear++ at the end of the loop. With the number of items in the going down with each iteration, the clear++ was causing it to skip over the page break items. Below is my finished code:
function clearForm()
{
var clearQ = find(f_items, "Select Appointment Date")+1;
var f_i_len = f.getItems().length-1;
var clear = clearQ;
while(clear <= f_i_len && clear >= clearQ)
{
var item = f.getItems()[clear];
if(item.getType() == "PAGE_BREAK")
{ item.asPageBreakItem().setTitle(""); }
f.deleteItem(clear); //}
f_i_len = f.getItems().length-1;
}
}

Google apps script - Broken for loop

I'm working in Google apps script and seem to have screwed up one of my for loops. I'm sure that I am missing something trivial here, but I can't seem to spot it.
Code Snippet:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var lastRow = sheets[3].getLastRow();
var zw = sheets[3].getRange(2, 1, lastRow - 1, 26).getValues();
for (var j = 0; j < zw.length; ++j) {
if (zw[j][9] === 'Yes') {
var masterEmail = [];
var firstLetterLastName = [];
var first2Letter = [];
var masterEmail.push(zw[j][22]);
var firstLetterLastName.push(zw[j][1].charAt(0).toLowerCase());
var first2Letter.push(zw[j][1].charAt(0).toLowerCase() + zw[j][1].charAt(1).toLowerCase());
//The rest of the function follows...
}
}
What's Not Working:
The for loop doesn't increment. When running the code in a debugger, var j stays at a value of 0.0, and the rest of the function only runs based of off the values in the 0 position of zw.
What I need it to do (AKA - How I thought I had written it:)
The ZW variable is holding a 2 dimensional array of cell values from a Google sheet. I'm looping through that, checking the 9th value of each array entry for a string of "Yes" and then running the rest of the function (for each column with a "Yes") if the condition is true.
I thought I had this working before, but recently had to restructure and optimize some things. Now I'm starting to think I may need to rethink things and use a different loop method. Can anyone educate me?
Edit: Here's a bit more context as requested:
function menuItem1() {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Are you sure you want to send emails?', ui.ButtonSet.YES_NO);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var lastRow = sheets[3].getLastRow();
var zw = sheets[3].getRange(2, 1, lastRow - 1, 26).getValues();
if (response === ui.Button.YES) {
for (var j = 0; j < zw.length; j++) {
if (zw[j][9] === 'Yes') {
var firstLetterLastName = [];
firstLetterLastName.push(zw[j][1].charAt(0).toLowerCase());
//Other Stuff....
}
}
}
}
I have a menu item attached to a simple onOpen, that calls menuItem1(). Calling the function prompts the user with a warning that they are about to send emails, then goes about getting data to assign email addresses based on the contents of the sheets. firstLetterLastName is an example.
I'm still not getting the loop to function, is it because I have it between two if statements? (Here is a link to the sheet)
Indeed it is quite trivial. You have mixed up your increment. You wrote
for (var j = 0; j < zw.length; ++j)
which means that you do 1 + i (and we know that at the start i = 0 which means your value will always be 1) instead of using the usual
for (var j = 0; j < zw.length; j++)
which would mean that you do i + 1 and update i, so you will get the expected 0 + 1 1 + 1 etc
EDIT:
First, I recommend instead of something like
if (responseMir === ui.Button.YES) {
// Your For loop
doing
if (responseMir !== ui.Button.YES) {
return
}
and in a similar fashion in the for loop
if (zw[j][9] !== 'Yes') {
break
}
It mostly helps increase readability by not including large blocks of code under a single if, when all you want to do is to stop execution.
Your for loop gets broken because of the mistake here:
teacherEmailMir.push(selValsMir[j][7]);
So your loop will go over once. However on the next itteration, you try to push selValsMir[1][7] which does not exist. Note that each itteration you have var selValsMir = []; inside the loop, which means that for every j selValsMir will always be an empty array. So with the following line
selValsMir.push([zw[j][0], zw[j][1], zw[j][2], zw[j][3], zw[j][4], zw[j][5], zw[j][7], zw[j][22], zw[j][23], zw[j][24]]);
your array will always have selValsMir.lenght = 1 and selValsMir[0].length = 10. So obviously trying to access anything from selValsMir[1] will throw you an error and stop the script right there.
I also recommend looking over the if statements that look at the first and first 2 letters of the name as I believe you can accomplish the same with less code. Always try to streamline. Consider using switch() where you end up using a lot of else if

Radio Button Validation: I could validate it but I cant figure out the reason

I was stuck trying to validate if a radiobutton was selected or not and, in consequence, show alerts. Well, I found the mistake (I was putting the conditional statement inside the loop).
Even I solved the problem, I can’t figure out yet why my code works correctly outside the loop but doesn’t work inside it. Now I'm stuck with this.
I appreciate if anyone can tell me what’s the reason.
Below you'll see both JS codes, but here you have the fiddles examples:
JSFiddle that doesn't work
JSFiddle that works
This is the JS code that doesn’t work:
var getForm = document.getElementById('formX');
var putForm = getForm.onsubmit = showIt;
function showIt(){
var getNames = document.getElementsByName('season');
var result = false;
for(var i = 0; i < getNames.length; i++){
if(getNames[i].checked){
result = true;
break;
}
if(result === false){
alert('Please, choose an option');
return false;
}else{
alert('You\'ve choosen ' + getNames[i].value)
}
}//Loop ends here.
}
And this is the JS code that works without problems:
var getForm = document.getElementById('formX');
var putForm = getForm.onsubmit = showIt;
function showIt(){
var getNames = document.getElementsByName('season');
var result = false;
for(var i = 0; i < getNames.length; i++){
if(getNames[i].checked){
result = true;
break;
}
}//Loop ends here.
if(result === false){
alert('Please, choose an option');
return false;
}else{
alert('You\'ve choosen ' + getNames[i].value)
}
}
Maybe the for loop in JS code that doesn’t work has a wrong logic, it means that if the first radiobutton checked, the for loop stops; if the first radiobutton does not checked, it will alert 'Please, choose an option' and stops the for loop. The logic only validates the first radiobutton. Maybe thats the problem.
It's because of your break; line.
When it's inside the loop you're breaking it out on true before it has a chance to hit the following code: if(result === false)
break is breaking out of the entire loop which means it never hit's your if(result===false)
Hope that helps!
Wrong logic inside the loop, try this:
var getForm = document.getElementById('formX');
var putForm = getForm.onsubmit = showIt;
function showIt(){
var getNames = document.getElementsByName('season');
var result = false;
for(var i = 0; i < getNames.length; i++){
if(getNames[i].checked){
alert('You\'ve chosen ' + getNames[i].value)
result = true
}
if (i == getNames.length - 1 && !result)
{
alert('Please, choose an option')
}
}
}
If your question is how do I make it work, there are several good suggestions in the answers.
If you want to know: "Why didn't it work using the first method?" The best answer is that the break; line was causing your loop to terminate immediately, and therefore preventing the alert("You've chosen...") from having the opportunity to trigger.

How can i know its valid in JS?

I am developing an Adobe interactive form with LiveCycle LC designer with JavaScript.
// Identify required fields (it may be a free text field, drop-down, check box, i mean there 3 kinds possibilties) and make yellow colored them
var myArrayYellow = new Array();
var yellowFields;
yellowFields = my_required_fields_list_string.rawValue
myArrayYellow = yellowFields.split(" ");
for (var i = 0; i < myArrayYellow.length; i++) {
===> Here at this point, i want to check the existence of [i] field in the form that its a valid field/objetc or not? bcz, i have chances of getting non-existing fields in the my_required_fields_list_string, hence prior to assigning yellow color to them, i want to check their validity on the form or not? Pls. let me know the JS for this // if its true/found, then only assign yellow color as below
xfa.resolveNode("MY_ADOBE_FORM.." + myArrayYellow [i]).ui.oneOfChild.border.fill.color.value = "255,255,254"
};
For some other purpose, some expert gave me a JS as below, i tried to tune it as per my above requirement, but its not working
function findNodes(vNode){
if (vNode.className === "field"){
if (vNode.isPropertySpecified("name") === true){
var myStateName = new RegExp(vNode.name);
var returnValue = GFL.search(myStateName);
if (returnValue != -1) {
this.ui.oneOfChild.border.fill.color.value = "192,192,192";
this.access = "readOnly";
} else {
this.ui.oneOfChild.border.fill.color.value = "255,255,255"; //whatever colour is open access
this.access = "open";
}
}
}
for (var a=0;a<vNode.nodes.length;a++) {
findNodes(vNode.nodes.item(a));
}
}
findNodes(xfa.form);
if I understand your problem, you need to check if xfa.resolveNode returns something and handle it from there.
var node;
if ( (node=xfa.resolveNode("MY_ADOBE_FORM.." + myArrayYellow[i]) )!==null){
node.ui.oneOfChild.border.fill.color.value = "255,255,254"
}
If I understand correctly, you are trying to check if all of your values in the array are valid before preforming operations on them. Just check and make sure they are not null.
EDIT: You should probably check for empty string as well.
for (var i = 0; i < myArrayYellow.length; i++) {
if (!(myArrayYellow[i] == null || myArrayYellow[i] == "")){
//Do Stuff
}
}

For loop exiting early while updating modified or new records in datatable.net table

I'm using the Datatables jQuery plugin. The table is pulling the data from an AJAX source (a SQL Server query, processed by ASP.NET into a JSON object). I want to create a live view of the table so that changes appear in real time. But rather than reloading the entire table every few seconds with fnReloadAjax() (which, from experience, has proven to be quite burdensome on the browser) I'm only updating the records that are new or modified, using fnAddData() and fnUpdate().
After getting a JSON object of just the new or modified records, here's my code to process the object.
var newData = updatedDataJSON.aaData;
if (newData[0] != null) {
for (i = 0; i < newData.length; i++) { //Loop through each object
if (newData[i].bNewCase === true) { //Process new cases
oTable.fnAddData(newData[i]);
} else { //Process modified cases
var tableArray = oTable.fnGetData();
var index;
var found = false;
var serial = newData[i].serial;
var dataObject = newData[i];
//First gotta find the index in the main table for
// the record that has been modified. This is done
// by matching the serial number of the newData
// object to the original aData set:
for (ii = 0; ii < tableArray.length; ii++) {
var value = tableArray[ii]['serial'];
value = value.replace(/<\/?[^>]+(>|$)/g, "");
if (value === serial) {
index = ii;
found = true;
}
}
if (found) {
oTable.fnUpdate(dataObject, index);
console.log('Updated ' + newData[i].serial);
}
}
}
}
My problem is that even though the newData.length property of the first for loop could be greater than 1, the for loop exits early (after one iteration). I added the console.log statement at the end and it started passing errors saying that newData[i].serial was undefined. This makes me think that the entire newData array was destroyed or something...
I'm really hoping that I've just made a stupid mistake (though I've checked and checked and checked some more but can't find one). Maybe there's something that I'm overlooking. If anyone has any advice, it would be greatly appreciated.
Credit goes to #elclarnrs for the solution, posted above in the comments. The solution was declaring the values of i and ii in the scope of the function. That got everything working smoothly. Good to know for future reference.

Categories