Marty Zigman

Conversations with Marty Zigman

Certified Administrator • ERP • SuiteCloud

NetSuite Restlet Sample Program Exploits New Power

NetSuite Technical

Tags: , , , , , , , , , , , , , , , ,

NetSuite’s new Restlet API is promising for developing external software applications that interact with NetSuite’s rich data and business functionality.  For example, imagine a large professional services organization that needs to track timesheets in the NetSuite Advanced Projects module.  Most professionals are highly mobile.  Instead of logging into NetSuite to do your timesheet via a web browser, imagine a small iPhone or Android app that allows you to quickly enter data.  Restlet is the key to make this happen without making a big investment.

This article illustrates how to connect up and create timesheet entries from a Linux Perl program.  This example should help bridge the key concepts to hook up to NetSuite through the new Restlet API.  The article assumes you have a good understanding of how to create and deploy scripts in the NetSuite environment.  The example consists of three files:

  1. restlet.js: NetSuite program to receive an insert time entry request.  It validates data and produces information in the execution log.
  2. timebill.pl: Perl program that reads timesheet entry data from timebill.csv file.  This file has hard coded NetSuite credential information.
  3. timebill.csv: tab delimited file in the following format: Date <tab> Client: Project <tab> Task <tab> Time in Decimal format <tab> Memo <newline – for new record>

Step 1: Deploy restlet.js

After enabling the NetSuite Restlet API create a new NetSuite Script as type Restlet.  Set it up with the following parameters:

  • Post Function: “CreateTimebills”
  • Deploy the function with a Log Level of “Debug”
  • Get the External URL.  In our case, it was “https://rest.netsuite.com/app/site/hosting/restlet.nl?script=73&deploy=1 “

Here is the restlet.js code:

function CreateTimebills(datain) {
    var output = '';
    nlapiLogExecution('DEBUG','createRecord',(typeof datain.timebill));
    var msg = validateTimeBills(datain);
    if (msg) {
        var err = new Object();
        err.status = "failed";
        err.message = msg;
        return err;
    }
    var timebills = datain.timebill;
    for (var timebillobject in timebills) {
        var timebill = timebills[timebillobject];
        var trandate = timebill.trandate;
        var customer = timebill.customer;
        var casetaskevent = timebill.casetaskevent;
        var hours = timebill.hours;
        var memo = timebill.memo;
        var timebill = nlapiCreateRecord('timebill');
        timebill.setFieldValue('trandate', trandate);
        timebill.setFieldText('customer', customer);
        timebill.setFieldText('casetaskevent', casetaskevent);
        timebill.setFieldValue('memo', memo);
        timebill.setFieldValue('hours', hours);
        var timebillid = nlapiSubmitRecord(timebill);
        nlapiLogExecution('DEBUG', 'Timebill ' + timebillid + ' successfully created', timebillid);
    }
    return;
}

function validateTimeBills(datain) {
    var timebills = datain.timebill;
    var returnMessage = "";
    for (var timebillobject in timebills) {
        var timebill = timebills[timebillobject];
        var trandate = timebill.trandate;
        var customer = timebill.customer;
        var casetaskevent = timebill.casetaskevent;
        var hours = timebill.hours;
        var memo = timebill.memo;
        if (isNaN(nlapiStringToDate(trandate))) {
            returnMessage += "Invalid date: '" + trandate + "'\n";
        }
        if (customer == '') {
            returnMessage += "Customer entry cannot be blank.'\n";
        }
        if (casetaskevent == '') {
            returnMessage += "Case Task Event entry cannot be blank.'\n";
        }
        if (hours == '') {
            returnMessage += "Hours cannot be blank.'\n";
        }
        if (memo == '') {
            returnMessage += "Memo cannot be blank.'\n";
        }
    }
    if (returnMessage) {
        nlapiLogExecution('DEBUG', 'Validation Error', returnMessage);
        return returnMessage;
    }
}

Step 2: Edit timebill.pl

Edit timebill.pl with your specific NetSuite account ID, username, password, and role.  Here is the code:

#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Headers;
my $inputfilelocation = "timebill.csv";
my $scriptdeployment = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=73&deploy=1";
my $account = "TSTDRV365788";
my $email = "developer\@prolecto.com";
my $password = "";
my $role = "15";
my $jsonString = & getJSONStringFromFile($inputfilelocation);
my $result = & submitRestlet($account, $email, $password, $role, "POST", $scriptdeployment, $jsonString);
print $result;
exit;
sub submitRestlet() {
    (my $account, my $email, my $password, my $role, my $method, my $deploymentURL, my $request) = @_;#
    define the HTTP header
    my $objHeader = HTTP::Headers - > new;
    $objHeader - > push_header('Authorization' => "NLAuth nlauth_account=$account, nlauth_email=$email, nlauth_signature=$password, nlauth_role=$role");
    $objHeader - > push_header('Content-Type' => 'application/json');#
    make the call
    my $objRequest = HTTP::Request - > new(
        $method,
        $deploymentURL,
        $objHeader,
        $request
    );
    my $content = "";#
    deal with the response
    my $objUserAgent = LWP::UserAgent - > new;
    my $objResponse = $objUserAgent - > request($objRequest);
    if (!$objResponse - > is_error) {
        return $objResponse - > content;
    } else {
        return $objResponse - > error_as_HTML;
    }
}
sub getJSONStringFromFile() {
    (my $inputfilelocation) = @_;
    open(FILE, $inputfilelocation);
    my $output = "";
    $output = qq {
        "timebill": [
        };
        while ( < FILE > ) {
            chomp;
            (my $trandate, my $customer, my $casetaskevent, my $hours, my $memo) = split("\t");
            $output. = "{";
            $output. = qq {
                "trandate": "$trandate",
                "customer": "$customer",
                "casetaskevent": "$casetaskevent",
                "hours": "$hours",
                "memo": "$memo"
            };
            $output. = "},";
        }
        close(FILE);
        chop($output);
        $output. = qq {]
    };
    $output = "{$output}";
    return $output;
}

Step 3: Create Timesheet Entry Data

In timebill.csv, create some data as input to insert as NetSuite timesheet entries.  Here are a couple sample entries.  Note the clients: projects, and tasks must match what is in already in NetSuite to work:

12/05/2011        SmartTech : Test Project 005      Test Task 005 (Task)     .75        Meeting on Specifications
12/05/2011        SmartTech : Test Project 005      Test Task 005 (Task)     1          Meeting with Management

The timebill.csv file should be placed in the same local directory as timebill.pl.

Step 4: Execute timebill.pl

Now you can run timebill.pl to see the program work.  If all goes right, it will take a few moments and return a code.  Go to the NetSuite script deployment log and see if the timesheet entries were created.  If so, check the timesheet system to find the new entries.

This article should help you kickstart your restlet system into a working prototype.  Stay tuned as we will be writing another article on how we are using restlets to create an Android / iOS app.

Marty Zigman LinkedIn

Marty Zigman

Holding three official certifications, Marty is widely recognized as a top NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. A former Deloitte & Touche CPA and technology executive with CTO roles, he brings over 35 years of leadership in ERP, CRM, and eCommerce business systems. Contact Marty to engage directly.

BiographyYouTubeLinkedInX (Twitter)

32 thoughts on “NetSuite Restlet Sample Program Exploits New Power

  1. Indeed. Perl is wonderful. Just rarely see it any more, especially in blog posts. I rather miss working with it.

    On a semi-related note, have you created file cabinet hosted applications that interface with RESTlets? For example, a static HTML page which utilizes jQuery or Javascript to format the POST data and sends it off? I’m debating between an externally vs. internally hosted page for some sales order interaction.

    Reply
  2. Hi, I’m trying to write a RESTlet that will create a new employee. So far I have:

    var employeeRec = nlapiCreateRecord(’employee’);
    employeeRec.setFieldValue(‘lastname’, ‘Test’);
    employeeRec.setFieldValue(‘firstname’, ‘Frank’);
    employeeRec.setFieldValue(’email’, ‘test9475@frank.org’);
    employeeRec.setFieldValue(‘subsidiary’, 3);
    var id = nlapiSubmitRecord(employeeRec);
    nlapiLogExecution(‘DEBUG’,’bitium: ‘ + id + ‘ employee’,id);

    and it works great! But when I try and add:

    employeeRec.setFieldValue(‘giveAccess’, true);
    employeeRec.setFieldValue(‘password’, ‘somePassword1!’);
    employeeRec.setFieldValue(‘password2’, ‘somePassword1!’);

    it doesn’t have any effect. How do I make the employee have access to login and set their password after I create the employee? From netsuite web interface I select the “Access” tab.

    Reply
  3. Hi,

    Im trying to submit the record inside PUT method in restlet, but it gives me an error?
    Here is the code:

    function putRESTlet(dataIn) {

    nlapiSubmitField(‘invoice’, dataIn.id, ‘custbody202’, ‘T’, true);
    }

    what seems to be the problem?

    Another question, does Restlet issue a submit behind the scene causing my code to fail?

    Note: my get request in success. It’s just this put request is giving me hard time.

    Thank you in advance.

    Reply
  4. Hi,

    How to write the Restlet POST Function in NetSuite to set the lineitem values for records like sales order and customer and what would be the JSON request for those ?

    Thanks.

    Reply
  5. Hi Marty,

    I found your blog very helpful.
    Thanks for sharing your knowledge with us.

    Having query:
    Scenario is i am using scheduled script to call a url.
    This url is used to fetch currency details.

    But problem is Netsuie automatically converts HTML entities into punctuations.
    Please refer code below…
    Problem scenario is as :

    var date1 = new Date();
    nlapiLogExecution(‘DEBUG’, ‘Daily Exchange rate’,’date1 is ‘+date1 );

    date1 = nlapiDateToString(date1);
    nlapiLogExecution(‘DEBUG’, ‘Daily Exchange rate’,’after nlapiDateToString date1 is ‘+date1 );

    var url = “https://www.testname.com/rates/api/v1/rates/USD.csv?”

    // ************* we required url in following format
    // https://www.testname.com/rates/api/v1/rates/USD.csv?quote=EUR&quote=USD&quote=CAN&quote=IND&date=2015/02/20

    var toCurrency = ”;

    // ******* arr_toCurrencies contains values like EUR,CAN,IND,USD. *************************
    for( var i=0; i < arr_toCurrencies.length ; i++)
    {
    toCurrency = arr_toCurrencies[i];
    nlapiLogExecution('DEBUG', 'Daily Exchange rate','toCurrency is '+toCurrency );

    if(i == 0)
    {
    url +="quote="+toCurrency;
    }
    else
    {
    url += "&quote="+toCurrency;

    nlapiLogExecution('DEBUG', 'Daily Exchange rate','url is '+url );
    }
    //nlapiLogExecution('DEBUG', 'Daily Exchange rate','herererererer url is '+url );

    }

    nlapiLogExecution('DEBUG', 'Daily Exchange rate','currency url is vname'+url );

    url += '&date='+date1+'&api_key='+oandaApiKey

    nlapiLogExecution('DEBUG', 'Daily Exchange rate','final url is '+url );

    // By above code we are able to get the url, but Netsuite automatically converts &quot into " and we are not getting required url.
    // URL which gets generated is :
    // https://www.testname.com/rates/api/v1/rates/USD.csv?quote=EUR"e=USD"e=CAN"e=IND&date=2015/02/20

    Reply
  6. Hi Marty,

    Thanks for your valuable response…
    I tried following solution.
    Rather than using &quote to create a url. i used %26quote and then while calling url thorugh nlapiRequestURL i replaced %26 with &.
    It works…

    Thanks…

    Reply
  7. Hello Marty, thanks for your code, I’ve been looking for how to update a record with restlet, your help can be useful, thanks

    Reply
  8. Hi Marty,

    thank you for your great tutorial here. Helps a lot. Especially that you are using perl code for your example is nice since we are using perl for our systems, too.

    Hope for more!
    Paul

    Reply
  9. While trying to run this example, its giving error in perl script in accepting the password as:– it should require explicit package.plz resolve the same.

    Reply
  10. This is great stuff. Can you share the JSON format for your code?

    Does it look like this?
    [
    {
    “trandate”: “12/01/2017”,
    “customer”: “NetSuite IMP Project”,
    “casetaskevent”: “SIT”,
    “hours”: “5:00”,
    “memo”: “Timesheet approval routing”,
    }
    ]

    Reply
  11. I am trying the pull the data for a estimate record by hardcoding the value in restlet through restful web services,but i want to pass that hard code value in java.

    How to pass the value in Java,can you please help me

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *