How to Find the NetSuite Web Services Account Number

Finding the account number for NetSuite’s SuiteTalk WebService API isn’t very straightforward. This number is required for any applications with connect to NetSuite via their SuiteTalk API.

Navigate to the SuiteTalk preferences via "Setup > Integration > Web Services Preferences", by searching for "page: Web Services Preferences" in the global search bar, or by visiting this URL (may not work depending on your NetSuite data center). You’ll see the following screen containing the Account Number (also called the Account ID):

Some things to keep in mind:

The account number is not always a number. It can be a string of letters. A sandbox and production account number is identical The “Disable Service SuiteScript and Workflow Triggers” checkbox can have massive effects on your SuiteTalk integration. SuiteScripts and Workflows can trigger fatal errors in your SuiteTalk calls which are impossible to debug without diving into the SuiteScripts embedded within a NetSuite instance.

Continue Reading

Resolving the NetSuite LIST_ID_REQD Deposit Record Error

Creating deposit records in NetSuite using the SuiteTalk API can sometimes result in the following error:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Header> <platformMsgs:documentInfo xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com"> <platformMsgs:nsId>REDACTED</platformMsgs:nsId> </platformMsgs:documentInfo> </soapenv:Header> <soapenv:Body> <upsertResponse xmlns="urn:messages_2015_1.platform.webservices.netsuite.com"> <writeResponse> <platformCore:status xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com" isSuccess="false"> <platformCore:statusDetail type="ERROR"> <platformCore:code>LIST_ID_REQD</platformCore:code> <platformCore:message>Required field missing in a related list. You must set lineId.</platformCore:message> </platformCore:statusDetail> </platformCore:status> <baseRef xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com" externalId="external_id" type="deposit" xsi:type="platformCore:RecordRef"/> </writeResponse> </upsertResponse> </soapenv:Body> </soapenv:Envelope>

This error is not well documented at all and does not point to a single issue. In order to properly handle and prevent this error from occurring you need to implementation validation before upserting (or adding, updating, etc) the record.

Here are the various causes of the error:

The included refund’s (CashRefund, CustomerRefund) account field is not set to the NetSuite instance’s “Undeposited Funds” account. The easiest way to determine what the “Undeposited Funds” account internalId is to search for the account by name and grab the first search result. The name of the “Undeposited funds account can be customized. If this is the case, you need to hard code the internalId in your app’s config. The payment (CustomerPayment, CashPayment, CustomerDeposit) is already deposited. You can test this through the status field on these record. The status field will have a value of Deposited or Not Deposited. The payment sublist filters in the deposit sublist are causing the given payment record to be unavailable for the deposit. For example, if your GUI payment sublist date filters are configured to only show payments for the current day, and your deposit request using SuiteTalk includes a record created yesterday. In this case, the GUI settings (which cannot be modified or inspecting by SuiteTalk) are causing a fatal error in SuiteTalk. Instructions on how to resolve this error are detailed below. The subsidiary or bank account restrictions are causing your included payment to be unavailable. The best way to see if this is the case is to attempt to mimic the SuiteTalk request in the GUI. Clearing the Deposit Payment Sublist Filters

Here’s how you clear the deposit payment sublist date filters.

Go to the new deposit record page: https://system.netsuite.com/app/accounting/transactions/deposit.nl. Note that this URL can be different depending on your data center URL. Choose “All” on the date filter drop down. The From/To filters should disappear. Press cancel Go to the new deposit page again and ensure that the changes “stuck” Logout Wait 8-24 hours for the NetSuite user cache to invalidate. This is an internal cache that you cannot monitor.

In addition to clearing the date filter, click the customize button and ensure that no additional filters have been added to the payment sublist filters. You are aiming for a completely stock configuration.

Continue Reading

How to Close a NetSuite SalesOrder Using SuiteTalk

Many things in NetSuite’s SuiteTalk XML API are not intuitive or obvious: closing a SalesOrder is one of them.

When you create a SalesOrder using upsert or add you can set the order_status to _pendingFulfillment or _pendingApproval directly through the order_status field. However, you can’t simply update the order_status field on a SalesOrder to close the record, you need to set is_closed field on each line item in the SalesOrder.

ns_order.item_list.items do |item| item.is_closed = true end ns_order.update({ item_list: ns_order.item_list })

Other SalesOrder states work in a similar way: _partiallyFulfilled, _fulfilled, etc are only achieved by modified the item_list sublist or by creating a separate record (ItemFulfillment, Invoice, etc).

Continue Reading

NetSuite SuiteTalk User & Role Edits Are Delayed

If you work with NetSuite’s SuiteTalk API, you know that:

You must access the API via employee/user record in NetSuite API calls specify the user role to use You will get different results based on which user and which user role you are accessing the API with. For instance, if the employee record has the “Sales Rep” option checked, all Sales Orders created using that employee/user credentials will have the “Sales Rep” field assigned to the user’s record. Each role has a different set of permissions. You will get different fatal error messages depending on which user role you are operating under.

Often, when developing a NetSuite integration, you’ll need to make edits to the SuiteTalk user/employee record or the role.

Changes to the role or user do not take effect immediately. They can take anywhere from a couple minutes to a couple hours to take effect. This destroys the developer feedback loop and makes it exponentially harder to track down the source of specific NetSuite SuiteTalk errors.

This means that if you make a change in your sandbox or production account relating to either employee or user records there is no way to know if the change fixed the issue you were debugging aside from waiting a couple hours and retrying the operation.

Often, what I’ve done, is write a failing feature test for my NetSuite integration issue I’m encountering and then rerun the test in the morning after making user or role tweaks.

If you have access to the private NetSuite forums, you can read this post for more information.

Continue Reading

Split Shipment Fulfillment with NetSuite

NetSuite natively supports partially fulfilling a SalesOrder. However, updating an ItemFulfillment record (NetSuite’s equivalent to a ‘package’ or ‘shipment’ in other systems nomenclature) after it’s been created comes with some unique edge cases in NetSuite.

Here’s the NetSuite state that I was operating in:

Sales Order is created. order_status = _partiallyFulfilled An ItemFulfillment exists with ship_status = _picked A CustomerDeposit representing the payment coming from an external system is associated with the SalesOrder The contents of the created ItemFulfillment need to be adjusted and a second ItemFulfillment needs to be created.

Here is some key information on how NetSuite’s ItemFulfillments work:

The order_line field is not set on an ItemFulfillments item list elements if the item is a “member” of another item in the item list. In other words, if you are fulfilling a KitItem or AssemblyItem the components of those items will appear on the ItemFulfillment’s item list but will not have a key (unique ID to reference them on the sub lisT) and thus cannot be updated. The item_receive flag is equivalent to the “Fulfill” column in the GUI. The replace_all flag on item_list must be set to false when updating an item list containing KitItems or AssemblyItems. Also, all items without an order line must be removed from the item_list. If they are not removed, the following fatal error will be thrown: “Adding new line to sublist item is not allowed.”

Using the NetSuite SuiteTalk ruby gem, here’s how to remove items from an existing ItemFulfillment:

item_fulfillment.item_list.item.each do |i| i.item_receive = false i.quantity = 0 end item_fulfillment.item_list.replace_all = false item_fulfillment.item_list.items.reject! { |i| i.order_line.blank? } item_fulfillment.update(item_list: item_fulfillment.item_list)

Continue Reading

NetSuite Global Search Shortcuts for Alfred.app

I’ve done a lot of NetSuite development in ruby over the last couple years. It’s very challenging to integrate NetSuite with external applications. During the process of completing several NetSuite integration projects I’ve developed a set of tools and shortcuts to speed up the NetSuite development workflow.

One key tool is search shortcuts for Alfred.app.  I have a production and sandbox search shortcut which drops my search query directly in the NetSuite global search bar.

This search shortcut allows me to just type in NetSuite customer number, sales order number etc and jump right to the record in the NetSuite environment. Many times if you go to the NetSuite homepage directly you are required to login again. This makes it incredibly simple to go into the NetSuite environment and find the information you’re looking for.

NetSuite Sandbox Global Search

NetSuite Production Global Search

If you don’t use Alfred, you can use the URLs below to build the search query into other applications:

https://system.sandbox.netsuite.com/app/common/search/ubersearchresults.nl?quicksearch=T&searchtype=Uber&frame=be&Uber_NAMEtype=KEYWORDSTARTSWITH&Uber_NAME={query}

https://system.netsuite.com/app/common/search/ubersearchresults.nl?quicksearch=T&searchtype=Uber&frame=be&Uber_NAMEtype=KEYWORDSTARTSWITH&Uber_NAME={query}

Continue Reading

NetSuite PHPToolkit & Uncaught Empty Search Results Error

So far my experience with NetSuite has been less than favorable. Their developer resources aren’t bad, but they aren’t terribly good either. I’m working on a project that involves searching through contacts & selectively modifying contact data based on search results. In some cases the search will return an empty result set – just like any normal search should. I would have thought that the PHP developer kit was mature enough to handle an empty search set, but apparently not. With the most recent "v2009.2" framework I receive the following error when attempting to perform a basic ContactSearchBasic:

[code] PHPtoolkit.php [416]:

Undefined property: stdClass::$pageSize [/code]

I’m guessing that most of their third party developers are using .NET or Java which would explain this extreme oversight in the PHP framework. Heck, it might be resulting from some obscure PHP compilation configuration option on my local machine (although I’m doubtful that it is). For those are experiencing the same issue I’ve uploaded a patch which fixes the issue in your PHPToolkit.php file.

Continue Reading