if (latestpayment == 0) {
var newrecord = nlapiTransformRecord('vendorbill',
results[x][7], 'vendorpayment');
newrecord.setFieldValue('amount', intPayment);
// newrecord.setFieldValue('documentstatus', 'B');
// newrecord.setFieldValue('status', 'Paid In Full');
// newrecord.setFieldValue('statusRef', 'paidInFull');
newrecord.setFieldValue('account', stRAcctId);
newrecord.setFieldValue('trandate', stRPostingDate);
nlapiSubmitRecord(newrecord);
nlapiSubmitRecord(record);
} else {
var newrecord = nlapiTransformRecord('vendorbill',
results[x][7], 'vendorpayment');
newrecord.setFieldValue('amount', intPayment);
newrecord.setFieldValue('debitamount', payment);
newrecord.setFieldValue('paidamount', payment);
nlapiLogExecution('DEBUG', 'payment', payment);
// newrecord.setFieldValue('documentstatus', 'B');
// newrecord.setFieldValue('status', 'Paid In Full');
// newrecord.setFieldValue('statusRef', 'paidInFull');
newrecord.setFieldValue('account', stRAcctId);
newrecord.setFieldValue('trandate', stRPostingDate);
record.setFieldValue('amountpaid', payment);
record.setFieldValue('amountremaining', intlatestpayment);
nlapiLogExecution('DEBUG', 'amountremaining', intlatestpayment);
nlapiSubmitRecord(newrecord);
nlapiSubmitRecord(record);
I have a customized form to submit and all those selected will be transform from vendor bill to vendor payment. I have no issue on this when I do full amount payment and the status will be shown as Paid In Full.
However, when I do partially payment, I cannot do anything and change the status to OPEN. I tried to set the value for both vendor bill and vendor payment record but its doesnt work. Any idea on how to control this partially payment and shown as OPEN with all the amount paid and amount remaining show?
Thank you.
var newrecords = nlapiCreateRecord('vendorpayment', {
recordmode : 'dynamic'
});
newrecords.setFieldValue('entity', aresults[0]
.getValue('internalid'));
newrecords.setFieldValue('account', stRAcctId);
newrecords.setFieldValue('trandate', stRPostingDate);
var lineNum = newrecords.findLineItemValue('apply',
'internalid', results[x][7]);
newrecords.selectLineItem('apply', lineNum);
newrecords.setCurrentLineItemValue('apply', 'apply', 'T');
newrecords.setCurrentLineItemValue('apply', 'amount', payment);
newrecords.commitLineItem('apply');
nlapiSubmitRecord(newrecords, false, false);
nlapiSubmitRecord(record);
Thanks god the above code works. I am able to create a vendor payment record with the code above. Thanks to the link: http://blog.prolecto.com/2013/06/02/automate-creating-checks-to-pay-bills/
It saves my day :)
Related
With Colorado adding a new deliver fee tax, I am in search of a method to call the Avalara recalculation process after updating an invoice in NetSuite. We have to add a new line item associated with this tax and then have it reprocess the Avalara functions to be able to include the new line on the Avalara tax. I have completed a simple workflow to add the new line. However, it does not recall the Avalara scripts, thus, not adding the information to the taxing file. Has anyone been able to call Avalara scripts in NetSuite post workflow or script completions?
Thanks in advance,
Brad
I spent far too much time dealing with this exact issue last week. I tried to go the workflow route as well but ultimately decided a script would be needed. I tried a few methods, but the ultimate solution was to create a non-fulfillable, non-inventory item and use a User Event script deployed on the Sales Orders to add the RDF item to applicable records when they are created. In our case, these SOs are created in the UI, from a CSV import, or imported from our Shopify Webstore through a Suitelet (and Celigo). The basis of the script is as follows:
const beforeSubmit = (context) => {
let salesOrder = context.newRecord;
let shipState = salesOrder.getValue('shipstate');
let channel = salesOrder.getValue('class');
let total = salesOrder.getValue('total');
let customerId = salesOrder.getValue('entity');
if (!rdfExists(salesOrder) && shipState == 'CO' && (channel == '5' || channel == '6') || (channel == '15' && total > 0)) {
if (customerTaxable(customerId)) {
addRDF(salesOrder);
}
}
}
Essentially this is just checking some parameters (that the SO doesn't already have a RDF line item somehow, that the Ship State is CO, and that it is one of our custom channels that meets the criteria for these orders. If the order meets those criteria it will load the Customer record to check if the customer is taxable. And if they are taxable, it adds the RDF line item to the record.
This obviously includes some helper functions, which I will include snippets of, but take them with a grain of salt, we are in a highly customized instance and what works for us may not work for you (also I'm not a professional developer and this was written for completeness, not optimization).
function rdfExists(record) {
//Loop through line items looking for 'Colorado Retail Delivery Fee' item
let numLines = record.getLineCount('item');
const RDFITEM = runtime.getCurrentScript().getParameter('custscript_co_rdf_id');
for (let i = 0; i < numLines; i++) {
let itemId = record.getSublistValue({
sublistId: 'item',
fieldId: 'item',
line: i
});
if (itemId == RDFITEM) {
return true;
}
}
return false;
}
function addRDF(record) {
const RDFITEM = runtime.getCurrentScript().getParameter('custscript_co_rdf_id');
let numLines = record.getLineCount('item');
record.insertLine({
sublistId: 'item',
line: numLines,
ignoreRecalc: false
});
record.setSublistValue({
sublistId: 'item',
fieldId: 'item',
line: numLines,
value: RDFITEM
});
record.setSublistValue({
sublistId: 'item',
fieldId: 'quantity',
line: numLines,
value: 1
});
record.setSublistValue({
sublistId: 'item',
fieldId: 'taxcode',
line: numLines,
value: '5025'
});
}
function customerTaxable(customerId) {
let customerRecord = record.load({
type: record.Type.CUSTOMER,
id: customerId
});
if (customerRecord.getValue('taxable')) {
return true;
} else {
return false;
}
}
This successfully added the line to the Sales Orders but was still not calling Avalara to calculate the tax on the new item. To accomplish this, there were a few more steps:
Set the item's Avatax Tax Code to OF400000 (per Avalara help article here)
Do essentially the opposite of this Avalara help article and move the AVA_TransactionTab_2 UE script to the bottom of the Scripted Record list (Avalara says it goes at the bottom, but ours was first for some reason).
Modify the file /SuiteBundles/Bundle 1894/utility/AVA_TaxLibrary.js to allow for calculation of taxes on the new RDF item. This is the part I'm least excited about. I tried a ton of things, but the tax wouldn't calculate. Very long story short the line item was "failing" the AVA_MainTaxCodeCheck function that was called in the AVA_RequiredFieldsFunction that was called in the AVA_TransactionBeforeSubmit function and therefore not running the AVA_CalculateTax function... confused yet? Basically I just modified that library to include a statement that if it failed to find the lineTaxCode for an item, to check if it was my RDF Item, and if it was to calculate tax regardless (the line item is only added to the orders I want it to taxed on). I don't want to share my hardcoding of that library in public, but message me if you want more info.
From there we modified the SO and Invoice PDF templates to include logic to remove the $.27 from the tax line on these orders and add it as it's own line item:
All in all - it's a solution that works for us. Obviously your buisness case will be different, but this is what worked for us, and hopefully can at least steer you in the right direction! All this for 27 cents...
Is it possible to fill the duedate field based on the terms field? For example, I have a date in the duedate field, but I want to extend it based on the terms field. How can I do it? Through Suitescript or workflow?
The code is incomplete because I don’t know if I’m on the right path.
(NB: It is a user event)
function beforeLoad(context) {
}
function beforeSubmit(context) {
}
function afterSubmit(context) {
var dataEntrega = context.currentRecord
currentRecordRecord.getValue({
fieldId: 'duedate'
})
var dataCondicoes = context.currentRecord
currentRecord.getValue({
fieldId: 'terms'
})
}
return {
beforeLoad: beforeLoad,
beforeSubmit: beforeSubmit,
afterSubmit: afterSubmit
}
Why do you need to script this? I believe the due date is calculated based on the terms out of the box, no need for scripting
The following code should work. Depending on your needs I recommend adding some limitations to when this logic is executed. For example you can only execute based on if the transaction/record mode is create/copy (decide if you want to include edit or not). You can also check the status of the transaction, and only execute if the status is not partially paid/paid in full...
function afterSubmit(context) {
//load record
var curRec = context.newRecord; //can substitute "context.oldRecord", or "currentRecord.get();"
//get current due date
var transDueDate = curRec.getValue({fieldId: 'duedate'});
//get the terms, this will likely come as an internal id. use getText if you want the text.
var transTerms = curRec.getValue({fieldId: 'terms'});
//empty string to hold terms as a number of days
var addtlDays;
//transform the internal id to terms as a number of days
switch (transTerms){
case 1: // Ex: 1 = internal id for term "Net 15"
addtlDays = 15;
break;
case 2: // Ex: 2 = internal id for term "Net 30"
addtlDays = 30;
break;
//add additional case statements as needed
default:
addtlDays = 0;
}
//calculuate the new due date
var d = new Date(transDueDate);
var newDueDate = d.setDate(d.getDate() + addtlDays);
//set the new due date
curRec.setValue({
fieldId: 'duedate',
value: newDueDate,
ignoreFieldChange: true //optional, default is false
});
}
Currently I am able to send data to NS through a Restlet but it seems that I am only able to create a customrecord type but cannot seem to find out how to create a non custom record.
How do I find the name or endpoints. I have added my restlet to the SuiteScript but that is as far as I got.
EDIT
PartOrderREST.postRESTlet = function(dataIn) {
nlapiLogExecution('audit', 'PartOrderREST.postRESTlet', 'JSON=' + JSON.stringify(dataIn));
try {
var nsFields = new PO_OBJ_FIELDS();
var recPO = nlapiCreateRecord(nsFields.purchaseorder, {recordmode: 'dynamic'});
recPO.setFieldValue('entity', dataIn['entity']);
recPO.setFieldValue('name', dataIn['name']);
recPO.setFieldValue('employee', dataIn['employee']);
recPO.setFieldValue('class', dataIn['class']);
recPO.setFieldValue('location', dataIn['location']);
recPO.setFieldValue('exchangerate', '2.15');
recPO.setFieldValue('currency', '2.15');
recPO.setFieldValue('trandate', dataIn['trandate']);
} catch(err) {
nlapiLogExecution('audit', 'PartOrderREST.postRESTlet', err.message);
return {'error': 'error 1' + err.message}
}
try {
recPO.selectNewLineItem('item');
recPO.setCurrentLineItemValue('item', 'quantity', 1);
recPO.setCurrentLineItemValue('item', 'item', dataIn['item']);
recPO.commitLineItem('item');
recPO.selectNewLineItem('item');
recPO.setCurrentLineItemValue('item', 'quantity', 1);
recPO.setCurrentLineItemValue('item', 'item', dataIn['item']);
recPO.commitLineItem('item');
var idPO = nlapiSubmitRecord(recPO, true);
return {'nswoid': idPO};
} catch(err) {
nlapiLogExecution('audit', 'PartOrderREST.postRESTlet', err.message);
return {'error': 'error 2' + err.message}
}
};
This issue is that I get an error saying something along the lines of need line item to create record. I try adding the item to the purchase order but it is removed before it is submitted.
The first part of the code in the first try statement seems to work. I does not seem to successfully add a line item of 'item' given the specific nsid of the item I want to add to the order. 'item' is said to be the only required element of the Purchase order.
Can you hardcode the value in your restlet to see if your restlet works without parameterised data?
I have tried below code and it works:
var recPO=nlapiCreateRecord('purchaseorder', {recordmode: 'dynamic'});
recPO.setFieldValue('customform',formId);
recPO.setFieldValue('entity', entityId);
recPO.setFieldValue('name', 'Name');
recPO.setFieldValue('employee', employeeId);
recPO.selectNewLineItem('item');
recPO.setCurrentLineItemValue('item','item',itemId);
recPO.setCurrentLineItemValue('item', 'amount', 1);
recPO.setCurrentLineItemValue('item', 'quantity',100);
recPO.commitLineItem('item');
var id = nlapiSubmitRecord(recPO, true);
If you still get error after hardcoding the values then there might be some script deployed on PurchaseOrder throwning the error. You can check the scripts deployed on record by following below path:-
Customization->Scripting->Scripted Records->Purchase Order
Code Portion Click Here
I am trying to populate the Department line item field as per the Department Transaction Body Field, please assist to check if my codes are right.. i am new to suitescript.
var itemDepartment = nlapiGetFieldValue('department');
var nlapiSetCurrentLineItemValue = nlapiSetCurrentLineItemValue('item', 'department_display', itemDepartment);
It keeps stating that department_display is not an internal ID.
Please advise.
Thank you.
Can you try setting text instead,if it is a client script.
The id of the department column field is 'department'
var itemDepartment = nlapiGetFieldText('department');
nlapiSetCurrentLineItemText('item', 'department', itemDepartment);
The id of the department column field is also department, same as the header field.
Therefore, the second line of you snippet should be:
nlapiSetCurrentLineItemValue('item','department',itemDepartment);
EDIT
As per the comment below, please find below the full code snippet to populate lines department from the customer on before submit:
function onBeforeSubmit(type) {
if (type == 'create' || type == 'edit') {
var customerId = nlapiGetFieldValue('entity');
var itemDepartment = nlapiLookupField('customer',customerId, 'custentity_department');
var itemCount = nlapiGetLineItemCount('item');
for (var i = 1; i <= itemCount; i++) {
nlapiSetLineItemValue('item', 'department', i, itemDepartment);
}
}
}
Also, as a side note, you don't have to load the whole record in order to get a field value. You should use nlapiLookupField instead. It's much faster, safer and less api usage.
I have created vendor bill with nlapiCreateRecord, I can see the Bill record in the system with all items I want, but I can't relate it / link it to specific Purchase Order natively. When I'm using nlapiTransformRecord I'm deleting all records first from the PO and I'm adding new line items from CSV, but the native link/relationship between PO and Vendor Bill is missing. Here is my code created for the Bill Import from CSV:
function BillImport() {
var fromrecord;
var fromid;
var torecord;
var record;
var qty;
fromrecord = 'purchaseorder';
fromid = 23664;
torecord = 'vendorbill';
var loadedBillFile = nlapiLoadFile(5034);
var loadedBillString = loadedBillFile.getValue();
var BillLines = loadedBillString.split('\r\n'); //split on newlines
record = nlapiTransformRecord(fromrecord, fromid, torecord);
//trecord.setFieldValue('location', 1);
//trecord.setFieldValue('tranid', 'TEST!');
//var record = nlapiCreateRecord('vendorbill');
for (var j = record.getLineItemCount('item'); j>=1; j--)
{
record.removeLineItem('item',j);
}
for (var i = 1; i < BillLines.length; i++) {
var cols = BillLines[i].split(';');
var dsplit = cols[4].split(".");
var date = new Date(dsplit[2],dsplit[1],dsplit[0]);
currentDate = date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear();
var entity = cols[0]; // OK HEAD
var currency = cols[1]; // OK LINE
var taxcode = cols[2]; // SKIP
var tranid = cols[3]; // OK HEAD
var trandate = currentDate; // OK HEAD FORMAT 11/3/2016
var location = 21;//cols[5]; // OK HEAD (ID of Location)
var item = cols[6]; // OK LINE
var quantity = cols[7];
var rate = parseFloat(cols[8]); // FLOAT
var amount = parseFloat(cols[9]);
var po = cols[10];
record.selectNewLineItem('item');
// Head Level
record.setFieldValue('createdfromstatus','');
record.setFieldValue('entity', entity);
record.setFieldValue('tranid', tranid);
record.setFieldValue('trandate', trandate);
record.setFieldValue('location', location);
// Line Level
record.setCurrentLineItemValue('item','item', item);
record.setCurrentLineItemValue('item','quantity', quantity);
record.setCurrentLineItemValue('item','rate', rate);
record.setCurrentLineItemValue('item','amount', amount);
//record.setCurrentLineItemValue('item','orderdoc', po);
//record.setCurrentLineItemValue('item','podocnum', po);
record.commitLineItem('item');
}
var id = nlapiSubmitRecord(record, true);
//trecord.setLineItemValue('item', 'amount', 1, 3 );
//var idl = nlapiSubmitRecord(trecord, true);
}
Here is the example CSV file:
Entity;Currency;Taxcode;Tranid;TranDate;Location;Item;Quantity;Rate;Amount;PO Internal ID
2449;USD;0.00 ;224676;11.3.2016;21;885;1;10;50;23664
2449;USD;0.00 ;224676;11.3.2016;21;870;2;10;120;23664
2449;USD;0.00 ;224676;11.3.2016;21;890;3;3;45;23664
2449;USD;0.00 ;224676;11.3.2016;21;948;4;4,66;38,5;23664
2449;USD;0.00 ;224676;11.3.2016;21;886;5;19,54;720;23664
I'm
If you don't want it to transform into a Vendor Bill (probably to avoid the PO from changing status) then you will need to create a custom relationship. You do this by:
Create a custom field on the Vendor Bill form of type "List/Record" and have the it be of "Transaction" type and check "Record is Parent". Save the Custom Field.
Go back to the custom field and edit it. Go to the display tab and select a "Parent Subtab", I usually select "Related Records". Save.
Now you just need to create a new Vendor Bill from scratch and save the record id of the PO in the Vendor Bill using the new custom field. Leave the "Created From" field blank, otherwise you would be linking them natively. The Bill should be listed under the "Related Records" tab or whichever subtab you selected on the PO.
Vendor bill import via CSV method is doable but you can bill the Purchase Order completely and not partially i.e. if you try to import a bill mentioning any referenced Purchase Order's link in it, it'll create a bill for all the remaining unbilled quantities of the Purchase Order rather than the quantity you have mentioned.
Actually if you mention any quantity AND Purchase Order link BOTH in the CSV file then it will throw an error.
Below is the part I found from the SuiteAnswers with answer id as 10020.
Refer the supporting image here