Giter VIP home page Giter VIP logo

rest_suite's Introduction

[ New Maintainer ]

This repository is no longer being updated, but the project has received updates on a fork. Please visit https://github.com/hayden-t/rest_suite for the latest and greatest code.

rest_suite

Server-side Javascript library that wraps parts of the Netsuite SuiteScript API (v2010.1). This interface should be more performant than the SOAP based interface as it allows 50 simultaneous connections per set of login credentials. Note that NetSuite's point system is seemingly arbitrary and we've tried to provide better error handling wherever possible.

NOTE: This is being designed as a replacement for netsuite-rest-client.

Brought to you by the NetSuite Liberation Front

Contributing to rest_suite

rest_suite is built on vanilla JavaScript, using node and jasmine to provide a testing environment. We suspect that NetSuite is using a version of Mozilla's JavaScript interpreter, but we can't be entirely sure. This is the reason that we chose vanilla JavaScript over an alternative like CoffeeScript. Cross compliation issues could be a nightmare as NetSuite is not to be trusted. Where possible, be explicit and direct with your code.

Getting Up and Running

  • Install node.js and npm
  • Run ./jspec

General Contribution Process

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch and commit atomically
  • Commit and push until you are happy with your contribution
  • Be sure to test your code and make sure that all tests pass before submitting a pullrequest.

Copyright

Copyright (c) 2012 Acumen Brands, Inc. See LICENSE.txt for further details.

Usage

Generally, each individual script is to be uploaded to NetSuite as a single endpoint with a single function being exposed. These functions are documented throughout the project and should be relatively easy to ferret out.

Uploading to NetSuite

The process of deployment is a somewhat involved manual process at the moment. It is possible to wrap all files into a zip and automate the process via a manifest, but this has not yet been implemented. Many files contain multiple classes that would normally exist in their own files specifically for this reason. The deploy process is painful enough as it is.

In the NetSuite web interface, go to the documents dropdown and select:

  • Documents->Files->SuiteScripts

Upload all .js files in lib here. Now go to Setup -> Customization -> Scripts -> New.

Create a new Script record using each operation file. List netsuite_toolkit.js as an included library on each. The script record also assigns each HTTP function to a provided function name. In each Script, reference the appropriate post handler function in the "POST" text box. The function names should be provided without parentheses: deletePostHandler() just becomes deletePostHandler.

From each Script record, generate a Script Deployment with an appropriate role/employee/account access for the credentials your client will be using. NetSuite calculates these permissions inclusively, so if one criteria out of any of them matches your credentials, it will provide access.

The Script Deployment will list the endpoint URL to which you will send requests with the JSON body for the script's parameters.

Making Requests

The Script Deployment records will list endpoint URLs that you POST your JSON objects to. Simply build the JSON object and include it as the request body. The authentication header must include your account credentials assigned to the following variables in a string assigned to 'authorization' in your request header.

"NLAuth nlauth_account=<business account id>,nlauth_email=<login email>,nlauth_signature=<password>,nlauth_role=<role_id>"

jspec

We've added some handy tools in jspec to perform most of the mundane tasks associated with the project. Here's a quick reference:

  • ./jspec Set up your environment and run all tests
  • ./jspec --doc Generate HTML documentation in doc/ with JSDoc3
  • ./jspec --reset Glear out installed node modules
  • ./jspec --mono Run tests without color
  • ./jspec --debug Fire up a node debugger with jasmine

Documentation

HTML formatted documentation can be found in doc. This has been generated with JSDoc3 and includes documentation provided by NetSuite for SuiteScript v2010.1 for easy reference. Documentation is re-generated for each tagged release. If you'd like to generate docs on the fly, simply run ./jspec --doc

  • Generally, anywhere you see id mentioed, it can safely be assumed to be internal_id in netsuite
  • Each script has one endpoint and only one endpoint. This is due to the nature of NetSuite's RESTlet interface.
  • Furthermore, each endpoint should respond to a POST request
  • All actions for a given endpoint are taken based on the request body of the POST

Basic Input Reference

This is a basic overview of the JSON object payload for each request. A '+' next to a row indicates an array; a '-' indicates a key in a hash.

Initialize

Description

Initialize returns a blank record of the given type with all mandatory keys pre-populated with null or default values. This does not expose non-mandatory fields in the returned hash, those must be filled in manually client-side.

Request Structure

-record_type

Load

Description

Load will request a given record from the Netsuite database by internalid. It will return the requested record will all mandatory and populated schema. Non-mandatory and custom fields with blank values will not be populated in the returned hash.

Request Structure

+ single record action
  - id
  - record_type

Delete

Description

Delete will destroy records in Netsuite's database. If successful, the id of the removed record will be returned. Otherwise, an exception will be raised.

Request Structure

+ single record action
  - id
  - record_type

Upsert

Description

Upsert requests a new records be written to the database or an existing record be altered. If an internalid is present id the 'id' field, then it will attempt to update a record loaded using the type and id, otherwise throwing an exception if it does not exists. If no id is present, it will attempt to create a new record using the values given.

Request Structure

+ single record action
  - id
  - record_type
  + literals
    + sublists
      - name
      + line_items
        + create_or_update
          - match_field
          - literals
        + excise
          - match_field (unique field to search against)
          - value

Transform

Description

Transform initializes a new transaction from another transaction record in a workflow. In this case sublist items can be filtered (altered somewhat or removed if need be) but cannot be added if they do not exist on the original transaction. A record is is mandatory for transform.

Request Structure

+ single record action
  - id
  - source_type
  - result_type
  + literals
    + sublists
      - name
      + line_items
        + create_or_update
          - match_field
          - literals
        + excise
          - match_field (unique field to search against)
          - value

Saved Search

Description

Saved search will request the results of an already created saved search from Netsuite. Results must be sorted by internalid of the records returned in order to properly paginate the results. This is a limitation of the SuiteScript environment that we have not yet found a workaround for.

Request Structure

- record_type
- search_id
- lower_bound
- batch_size

Search (Ad-Hoc)

Description

Search allows you to build a search on the fly. As with saved searches, results generally should be filtered by internalid, however with ad-hoc search this is not mandatory. If another criteria could reasonably be used to sort, the sort boolean is exposed for the client to use. If multiple result columns have this set to true, only the last column in the list will be processed. A column to sort by internalid is always added, so if no sort is provided the search will always be sorted by internalid.

Formula filtering is also exposed and is a required alternative to explicit string matching in RESTlet operation to avoid hitting the execution limit. It produces a SQL function that results in 1 or 0. In the event a formula search is used, the name of the filter must be 'formulanumeric', the value must be 'IS', and the value will be 1 or 0.

For the formula:

  • name: The field on which the script is filtering
  • values: An array of possible values, the comparison is
  • comparison: A valid SQL comparison or equality operator
  • join: 'AND' or 'OR' to join all comparisons of 'field' to a single value

Request Structure

- record_type
- batch_size
- lower_bound
+ search_filters
  - name
  - operator
  - value
  - formula (optional)
    - field
    + values
    - comparison
    - join
+ search_columns
  - name
  - join
  - sort (boolean)

rest_suite's People

Contributors

bradediger avatar fastjames avatar jameschristie avatar mperham avatar therubymug avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rest_suite's Issues

"exports" is not defined

I'm eager to try some of this out. I'm attempting to use delete.js with netsuite_toolkit.js as a library file, submitting this (or similar with different record types) as my post data: [{'record_type' : 'inventoryadjustment', 'internalid' : 7739344}].

I keep getting ReferenceError: "exports" is not defined. (netsuite_toolkit.js#500).

Any advice would be great!

Thanks

Unable to Upsert

I have deployed rest_suite but am unable to use the upsert request. I am trying to update the memo field on a purchase order. Based on the README I have built the following cURL request:

curl -H "Authorization: NLAuth nlauth_account=12345,[email protected],nlauth_signature=mys3cr3tpass,nlauth_role=123" -H "Content-Type: application/json" -d '[{"internalid": "12345", "record_type": "purchaseorder", "literal_fields": {"memo": "test"}}]' https://rest.netsuite.com/app/site/hosting/restlet.nl\?script\=100\&deploy\=1

This fails to make any change to the purchase order record. However, the script appears to return a successful response:

{
    "params": [
        {
            "internalid": "12345",
            "literal_fields": {
                "memo": "test"
            },
            "record_type": "purchaseorder"
        }
    ],
    "success": true
}

If I change the internal ID and record type to nonexistent gibberish, I still get the same success message.

Is there something wrong with the format of the data I am posting, or is the upsert script somehow broken?

Search Example

Hello,

I have gotten the Saved Search to work but after several days I haven't been able to successfully upload params for a Custom Search. The puzzling part is the arrays of Search filters and columns. Can someone post a json example to return a Search?

I have tried several versions, here is what I have been sending:

{
"record_type": "item",
"lower_bound": "0",
"batch_size": "100",
"searchFilters": [
{
"name":"department" ,
"operator":"is",
"value":"my : department"
}
],
"searchColumns": [
"Name",
"Description"
]
}

Here is a small sample of what is returned:

"Result: {"params":{"record_type":"item","batch_size":"100","lower_bound":"0"},"result":[{"id":"7","recordtype":"inventoryitem","columns":{"internalid":{"name":"7","internalid":"7"}}},{"id":"8","recordtype":"inventoryitem","columns":{"internalid":{"name":"8","internalid":"8"}}},{"id":"10","recordtype":"inventoryitem","columns":{"internalid":{"name":"10","internalid":"10"}}},

It seems to pick up the first 3 params but then ignores the rest.

Thanks

new concurrency limits will affect this, read for details.

So in case you didnt know , Netsuite have cracked down on this connection method's ability to have up to 50 concurrent connections at one time, and for example ours is dropping down to 5 total for all methods combined. My work around for this has been to install a message queue with 5 workers and have all calls via this api routed via the queue.

nlapiInitializeRecord

The function to instantiate a new record in NS...where did you get this from? This is not in Netsuite API. What is the intention here..am I missing something?

NetsuiteToolkit.initializeRecord = function(record_type) {
return nlapiInitializeRecord(record_type);
}

My testing code is just:

var options = {
uri:'https://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=293&deploy=1',
method: 'POST',
headers: headers,
json:{
'record_type': 'salesorder'
}
};

request(options, function(error, res, body) {
res.setEncoding('utf8');
console.log(prettyjson.render(body));

}).end();

Netsuite response:

params:
record_type: salesorder
result: null
exception:
message: "nlapiInitializeRecord" is not defined.
trace: Cannot find function getStackTrace in object ReferenceError: "nlapiInitializeRecord" is not defined..
success: false

Saved Search Example

Can anyone provide an example request for the Saved Search request? I have not been able to get it working. Based on the request structure provided in the readme, I am trying the following curl request to receive the results of the saved search of 321 (ie, the search is available at https://system.netsuite.com/app/common/search/searchresults.nl?searchid=321):

curl -H "Authorization: NLAuth nlauth_account=12345678,[email protected],nlauth_signature=s3cr3t,nlauth_role=123" -H "Content-Type: application/json" -d '[{"search_id": "321", "record_type": "search", "lower_bound": "0", "batch_size": "20"}]' https://rest.netsuite.com/app/site/hosting/restlet.nl\?script\=101\&deploy\=1 | python -m json.tool

This results in the following error:

{
    "params": {},
    "result": {
        "message": "The record type [UNDEFINED] is invalid.",
        "trace": [
            "restletwrapper(null$lib:4)"
        ]
    },
    "success": true
}

I built this request based on the readme and my successful curl requests for the Load end-point. For instance, this results in a successful request to load a vendor with ID 47434:

curl -H "Authorization: NLAuth nlauth_account=12345678,[email protected],nlauth_signature=s3cr3t,nlauth_role=123" -H "Content-Type: application/json" -d '[{"internalid": "47434", "record_type": "vendor"}]' https://rest.netsuite.com/app/site/hosting/restlet.nl\?script\=100\&deploy\=1 | python -m json.tool

What should the proper JSON request look like for the saved search?

Wiki and Documentation

A user was kind enough to add this additional documentation to our wiki: https://github.com/acumenbrands/netsuite-rest-client/wiki/Beginner-Documentation

We should pull the relevant bits out and move them over here. Also, it might be worth moving some of the stuff in the README to the wiki.

Beyond that, should we braindump some of our NetSuite lore into the wiki as well? @JamesChristie you're quite the font of knowledge. Things like the arbitrary point system and the way records are handled would be handy to have available.

Accessing Subrecords

Is it possible to access subrecords for an item?

I am successfully able to use the load request to return an Inventory Item record, but the response does not include any inventory levels or locations. I believe this is because the inventory details are considered subrecords. How can I get all the subrecords associated with the Inventory Item?

Question: Would rest_suite suffice to post a CashSale order getting NetSuite to process transaction?

Would rest_suite suffice to post a CashSale order (create customer, add line items, card details) getting NetSuite to process transaction and create a record of the order for shipping?
Or does one need to use the SOAP based API to access advanced functionality.

http://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2016_2/schema/record/cashsale.html?mode=package

If rest_suite is indeed capable enough for the job a bit of example code to get us started would be greatly appreciated. Thank you

JSON examples for subrecords, sublists, etc.

I'm just starting to learn the complexity of NetSuite's domain model. We're struggling to upsert a complex object (in our case, a PurchaseOrder) and could use some real examples of inserting a complex object including sublists with subrecords.

You do have some abstract documentation on the request structure but it's difficult for us to map that onto a real world example.

NetsuiteToolkit.setLineItemValue parameters order

Hello, I had an issue where I couldn't move past this line:
record.setLineItemValue(sublist_name, index, field_name, value);

By looking at the SuiteScript API doc, I noticed that the order of the parameters is wrong (field_name is before index). Here's the function definition:

/**

  • Set the value of a sublist field.
    *
  • @param {string} group sublist name
  • @param {string} name sublist field name
  • @param {int} line line number (1-based)
  • @param {string} value sublist field value
    *
  • @method
  • @memberof nlobjRecord
    *
  • @SInCE 2008.1
    */
    nlobjRecord.prototype.setLineItemValue = function( group, name, line, value ) { ; }

Return Filters and columns for Saved searches?

One big hassle to figuring out custom searches is figuring out the names and structure of the json criteria.

Is there a way to have the filters and columns returned with "saved searches" to get how exactly how Netsuite wants to expects the format?

It returns the ones you send during an exception error using "search" but it would be nice to be able to create a search in Netsuite then pull it using "Saved search" to see the filter and column it used. Would save a bunch of trial and error.

Thanks

Document POST body data structure.

A skeleton exists in the README, but it needs to be fleshed out. Several things could be stuffed in there beyond what we see already.

Search filters not working

It seems that the operator isn't getting passed in when create the search filter object:

https://github.com/acumenbrands/rest_suite/blob/master/lib/netsuite_toolkit.js#L177-L179

Receiving this error:

"result" : {
    "params" : null,
    "result" : null,
    "success" : false,
    "exception" : {
      "trace" : [
        "restletwrapper(null$lib:4)"
      ],
      "message" : "An nlobjSearchFilter contains an invalid operator, or is not in proper syntax: internalidnumber."
    }
  },

Even if I pass the operator in to seemingly properly create the filter, it fails.

For some context, i'm using the following request body:

{
  "record_type": "customer",
  "search_filters": [
    {
      "name": "email",
      "operator": "is",
      "value": "[email protected]"
    }
  ]
}

Usage with Ruby

How do I use rest_suite with a Rails app? Am I supposed to use the netsuite-rest-client Ruby API in my Rails app talking to the JS in this project?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.