SuiteScript 2 can send pdf statements - netsuite

I am having a hard time getting a statement to render in SS2, I had found an answer is SS1 and hadn't used it sometime back but it doesn't seem to work in ss2. I am using the SS2 render.statement method but I am getting an "error.SuiteScriptError","name":"UNEXPECTED_ERROR","message":null,"stack":["renderStatement(N/render.js)" I am unclear as to what some of the arguments actually are. the entityid I think is the customer id, the printMode is the pdf enum, the formId I have no idea, it says it wants a number but I don't see internal ids next to the forms in the list like other objects in NetSuite, I have the InternalIds on. StartDate is a date before you want to start pulling in transactions from? Statement date? Todays Date? OpentransactionOnly true. Any help with this is appreciated.
thanks

Many of the parameters in this API call mimic the UI options on the 'Print Individual Statement' page. I've copied some of the field level help there to help explain each setting.
entityId - internal ID of the customer. NOTE: I have had errors in the past which were solved by using parseInt(customer).
printMode - the print mode to render this statement in (eitherrender.PrintMode.HTML or render.PrintMode.PDF)
formId - internal ID of the form to use to print the statement. Leave this option off to use the default statement form.
startDate - If you choose to enter a date, this is the date of the oldest transaction that appears on the statement. If you choose to note enter a date, all transactions in the customer's history appear on the statement.
statementDate - Statement date. The date in this field is the date used to calculate aging and the date that appears on the statement form.
openTransactionsOnly - Select this option to include only open transactions on statements. If you have entered a start date, open transactions from that start date appear. If you have not entered a start date, all open transactions appear. The Show Only Open Transaction option is most useful for statements printed as of your current today date. If you select Show Only Open Transactions and are using a date other that today’s date, you may have balance discrepancies.
Here is an code snippet. It uses the moment.js for calculating the dates of the first and last day of the previous month.
var startDate = format.format({
value: moment().subtract(1, 'months').startOf('month').toDate(),
type: format.Type.DATE
});
var statementDate = format.format({
value: moment().subtract(1, 'months').endOf('month').toDate(),
type: format.Type.DATE
});
var statement = render.statement({
entityId: parseInt(customer),
printMode: render.PrintMode.PDF,
startDate: startDate,
statementDate: statementDate
});

Related

NetSuite Search formula for items that have no open transactions

I am trying to create a formula to obtain a list of items that have no open transactions.
I cant just filter out by status as this filters out transactions that are open, as opposed to showing me only items with nothing open.
So basically if an item has anything open then i dont want it on the search. I do need it on the search if it has all closed or it has no transactions at all.
Hoping someone can help put me in the right direction.
I am a little bit stuck at where to start with the formulas and tried a case formula.
You can use item saved search adding under criteria as "Transaction Fields-status-anyOf-select all closed/rejected/declined statuses" not in filter reason of saved search.
Thanks.
To get the value of non transaction items as well, You need to check the check box use expression under criteria in standard subtab use parens() with OR expression.
And add one more condition as "Transaction Fields-Internal Id-anyOf-none with
"Transaction Fields-status-anyOf-select all closed/rejected/declined statuses".
Add both condition with OR logic.
It will work for both items condition if it has transaction status with closed or with none of transaction internal ids.
Thanks.
I think this is possible in a saved search, and requires a change in the way the filtering is done. Rather than filtering on the "Filters", using grouping and summary calculations to determine if an item qualifies, basically :
Create the item saved search as you would normally, but don't include a "Standard" filter for the openness of the transaction.
In the results, group by item name (or internalid), and another fields you want to include in the top-level results.
In the Criteria - Summary list, add a Formula (Number) condition :
Summary Type= Sum (Count won't work here)
Formula = case when {transaction.status} = 'Open' then 1 else 0 end
Equal to 0
Whether this is more or less elegant than bknight's answer is debatable.
I don't think this is the sort of thing you can do with a single saved search.
It would be fairly easy to do with SuiteQL though.
The script below runs in the console and finds items that are not on any Pending Billing Sales Orders. It's adapted from a script with a different purpose but illustrates the concept.
You can get a list of the status values to use by creating a saved search that finds all the transactions with open statuses you want to exclude , take note of that saved search's id and running the second script in the console
require(['N/query'], query => {
const sqlStr = `
select item.id, itemid, count(po.tranid) as po, count(bill.tranId) as bill, max(bill.tranDate) as lastBilled, count(sale.tranId) as sales, count(tran.tranId) as trans
from item
left outer join transactionLine as line
on line.item = item.id
left outer join transaction as tran on line.transaction = tran.id
left outer join transaction as po on line.transaction = po.id and po.type = 'PurchOrd'
left outer join transaction as bill on line.transaction = bill.id and bill.type = 'VendBill'
left outer join transaction as sale on line.transaction = sale.id and sale.type in ('CustInvc', 'CashSale')
where item.id not in (select otl.item from transactionLine otl, transaction ot where
otl.transaction = ot.id and ot.status in ('SalesOrd:F'))
group by item.id, item.itemid
`;
console.log(sqlStr);
console.log(query.runSuiteQL({
query: sqlStr
}).asMappedResults().map((r, idx)=>{
if(!idx) console.log(JSON.stringify(r));
return `${r.id}\t${r.itemid}\t${r.po}\t${r.bill}\t${r.lastBilled}\t${r.sales}\t${r.trans}`;
}).join('\n'));
});
require(['N/search'], search=>{
const filters = search.load({id:304}).filters;
console.log(JSON.stringify(filters.find(f=>f.name == 'status'), null, ' '));
});
In terms of doing something with this you could run this in a saved search and email someone the results, show the results in a workbook in SuiteAnalytics or build a portlet to display the results - for this last Tim Dietrich has a nice write up on portlets and SuiteQL

(Google Documents) Way to create custom documents based on certain input variables?

Is there a way to have a paragraph of text get spit out when you have a certain input, from say a google questionnaire?
And make it so you could have say 5 inputs, and it would spit out 5 paragraphs of information, into one document?
For example:
If someone fills out a questionnaire where the first question is year of birth, the tool would spit out the first paragraph with a description of what the year they were born was like.
Second question would be their birth country, the tool would place a paragraph of text about their birth country into the document.
etc etc
Many thanks in advance for any help
It is possible to create documents using a specific criteria based in form responses. I created the following sample script using Google Apps Script so you can get the idea:
function docCreation() {
var ss = SpreadsheetApp.getActive().getSheetByName("Form Responses 1");
var range = ss.getDataRange();
var values = range.getValues().reverse(); //reverses the array to get the last value in the first position
var doc = DocumentApp.create("Testing doc"); // You can change the name to match a username or any other variable instead
switch (getMonth(values[0][1].toString())) {
case 'Aug':
doc.getBody().appendParagraph("This is a sample body for August");
break;
case 'Jul':
doc.getBody().appendParagraph("This is a sample body for July");
break;
}
}
// Second function that returns the month value of the date introduced by the user
// I separated it because it is not that relevant to the main goal
function getMonth(val){
var month = val.split(" ");
return month[1];
}
It is a very simple script that checks if the month of the date introduced by the user is August or July, and if so, it creates a doc with a simple text as paragraph.
The script is bounded to the Google Sheet of the form responses and you can create a trigger so that every time a user fills out the form, the script starts running to create the needed documents. Now as I mentioned, this is just a sample, and the logic and docs format would depend on your specific needs and usage.
References:
Class Body
Create document

How to insert Adjustment record with Contract API

I'm trying to insert an adjustment record via the SOAP API using the following code.
Dim NewAdjustment As Adjustment = New Adjustment With {
.ExternalRef = New StringValue With {.Value = "TEST1234"},
.Description = New StringValue With {.Value = "1234TEST"},
.[Date] = New DateTimeValue With {.Value = "12/20/2018"},
.Details = {New AdjustmentDetail With {
.BranchID = New StringValue With {.Value = "PRODWHOLE"},
.InventoryID = New StringValue With {.Value = "18r.5"},
.WarehouseID = New StringValue With {.Value = "RETAIL"},
.Qty = New DecimalValue With {.Value = 100}
}}
}
Dim InsertAdjustment As Adjustment = CType(soapClient.Put(NewAdjustment), Adjustment)
I get an error px.data.pcexception: Error: 'Branch' cannot be empty. Error: 'Post Period' cannot be empty. Error Inserting 'Receipt' record raised at least one error.
I'm guessing I need to fill those values but I'm not sure how to do that. I see them in the table but not the API interface. I'm new to Acumatica, so I'm guessing this is just something I'm missing.
Thanks in advance.
I have never seen the usage of the Date property as [Date], but that does not mean it will not work. The Posting period is defaulted based on the value of the date property. Make sure that the December 2018 posting period is open on the company that you are logged into with the API. I have seen this error from time to time when the accounting department does not open the period in a timely fashion.
The BranchID is defaulted based on the login parameters of the soapClient. One thing to be aware of is that your API login user needs to have permissions to the BranchID being used, or you will definitely get an error about the Branch being invalid.
Depending on the Inventory costing methodology used by your company, Inventory Adjustments might require that they be processed against an inventory Receipt. This can be tricky to figure out what to do, especially if you have never received anything for this Item in a new implementation, and you want to increase inventory levels. For positive Adjustments in your business case, you might want to consider creating Inventory Receipts instead of Adjustments. The entity is very similar to the Adjustments. For negative Adjustments you might want to consider using Inventory Issues which is again, quite similar.
If you decide to use adjustments, you will have to search the Inventory Receipts for an appopriate Receipt number to use when populating the transaction details. One for each line you insert.

How truncate time while querying documents for date comparison in Cosmos Db

I have document contains properties like this
{
"id":"1bd13f8f-b56a-48cb-9b49-7fc4d88beeac",
"name":"Sam",
"createdOnDateTime": "2018-07-23T12:47:42.6407069Z"
}
I want to query a document on basis of createdOnDateTime which is stored as string.
query e.g. -
SELECT * FROM c where c.createdOnDateTime>='2018-07-23' AND c.createdOnDateTime<='2018-07-23'
This will return all documents which are created on that day.
I am providing date value from date selector which gives only date without time so, it gives me problem while comparing date.
Is there any way to remove time from createdOnDateTime property or is there any other way to achieve this?
CosmosDB clients are storing timestamps in ISO8601 format and one of the good reasons to do so is that its lexicographical order matches the flow of time. Meaning - you can sort and compare those strings and get them ordered by time they represent.
So in this case you don't need to remove time components just modify the passed in parameters to get the result you need. If you want all entries from entire date of 2018-07-23 then you can use query:
SELECT * FROM c
WHERE c.createdOnDateTime >= '2018-07-23'
AND c.createdOnDateTime < '2018-07-24'
Please note that this query can use a RANGE index on createdOnDateTime.
Please use User Defined Function to implement your requirement, no need to update createdOnDateTime property.
UDF:
function con(date){
var myDate = new Date(date);
var month = myDate.getMonth()+1;
if(month<10){
month = "0"+month;
}
return myDate.getFullYear()+"-"+month+"-"+myDate.getDate();
}
SQL:
SELECT c.id,c.createdOnDateTime FROM c where udf.con(c.createdOnDateTime)>='2018-07-23' AND udf.con(c.createdOnDateTime)<='2018-07-23'
Output :
Hope it helps you.

Netsuite Suitescript: How to retrieve records based on last modified date?

I am trying to retrieve records in Netsuite via SuiteScript. I would like to use the lastmodifieddate column to fetch record after a certain timestamp.
I am currently doing:
var filters = [new nlobjSearchFilter('lastmodifieddate', null, 'notbefore', time)];
var columns = [new nlobjSearchColumn('lastmodifieddate')];
var newSearch = nlapiCreateSearch(table, filters, columns);
var searchResultSet = newSearch.runSearch();
var back = nextEndIndex - 1000
var results = searchResultSet.getResults(back, nextEndIndex);
Where time is a datetime JS, nextEndIndex index counter for results.
This works for some objects but majority of Netsuite objects do not have the lastmodifieddate column in the record browser. Is there a built in variable for the lastmodifieddate? And if there is, how can I use it in nlapiCreateSearch? If you have better ways to do it, I would be grateful for the info.
Here is a simple example for SuiteScript 2.0.
define(['N/search'],function(search){
function test(chkDate){
log.debug(chkDate);
var empSearch=search.create({
type:search.Type.EMPLOYEE,
columns:['internalid','firstname','lastmodifieddate'],
filters:['lastmodifieddate','after',chkDate]
}).run().each(function(result){
log.debug(JSON.stringify(result));
return true;
});
}
test('05/30/2017');
});
This example is searching for employees, since I was not sure which record type you were looking at. Below are links to the information you can use to build out your searches:
Records Browser (look at the bottom of each section in the filters and columns):
Search Operators (shows which ones to use for which field types)
API Docs
Transactions are slightly different than entities. Transactions have lines. If you are trying to determine the true last modified date of a transaction, you may need to consider using the "Line Last Modified" field in place of "Last Modified Date." Try writing a simple search to pull Sales orders. Include "Last Modified Date" and "Line Last Modified." Then write a simple formula to show those that don't match. When I did this, there were a number of mismatches, with instances of "Line Last Modified" being more than 1 month later than "Last Modified Date." So if you are looking for the true last modified date, you may need to use the max "Line Last Modified."
You could use a 'Max' Summary Filter on {systemnotes.date} - you will of course need to Group by record (document number or internal id for example) for this to show correct results.

Resources