Marty Zigman

Conversations with Marty Zigman

Certified Administrator • ERP • SuiteCloud

NetSuite Saved Search Running Totals Sublist Challenge

ERP NetSuite Reporting Technical

Tags: , , , , , ,

Background

A common request is to look at transactional information with a cumulative total in mind. A good example is the inventory on hand balance. In NetSuite, every transaction that affects the inventory quantity serves to either increment or decrement the total on hand for that item.  Accordingly, it may be valuable to determine what the inventory balance was at any particular point in time.

NetSuite’s Saved Search offers good capacities to generate detail that can be used to attached to specific records and act as a child list. This is NetSuite’s sublist feature. To continue our example, we can create a saved search that accounts for all the transactions that affect the inventory item quantity on hand. For each of these transactions, we can see the positive and negative affects of the transaction. Wouldn’t it be great to have a column that is the cumulative amount, or sometimes referred to as the running balance or running total, of each transaction?

Here is a sample of the transaction output we are seeking:

Date Type Item# Quantity On Hand
1/2/2012 Receipt A350 10 10
1/3/2012 Fulfillment A350 -1 9
1/4/2012 Fulfillment A350 -2 7
1/6/2012 Receipt A350 5 12

NetSuite excels as making it easy to get transaction data out of the environment for the first 4 (Date, Type, Item# and Quantity) columns.   It is challenging though to get the “On Hand” quantity which represents a running total.  You can deem the Saved Search as a Sublist which allows you to attach the results to a master entity (specific record with in a form view).   In the above example, we can hook the Saved Search to the Item Form which will then show only records that are of type “A350”. This is exactly what one of our clients wanted: an ability to see the quantity on hand at any time when they performed an item lookup.

Saved Search Summary Lookup Column Reference Limitation

When working with Saved Searches, the general approach is to use the Summarize feature to group and sum information. For those that have SQL query language background, NetSuite is effectively performing a “Group By” type SQL Select statement behind the scenes. In our example, however, we don’t really need to use an aggregate “Group By” function to get our result. That would work well if we wanted to have a single answer up to a particular date in time. Instead, we want to see the detail transactions yet we want to have one column contain summarized information.

The power of the NetSuite Saved Search tool typically lies with the formula functions. It allows you to get closer to NetSuite’s underyling Oracle database by performing PL/SQL function calls.  Oracle offers a nice function to produce this running total:

sum({expression1})
OVER(ORDER BY {expression1}
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) "Running Total"

Unfortunately, this special syntax is not supported within NetSuite.   And there is another key weakness: the tool does not allow you to name a formula column so you can reference it in another formula column. This is the “Running Total” portion of the SQL syntax above. The ability to create a calculated and named column is easily supported in SQL yet is missing in the Saved Search function.  Even though NetSuite supports the capacity to define calculated fields as custom fields, you can’t get close enough to the underlying Oracle database to produce the definition you need.

Addendum — Solved nearly 3 year later!

See updated article on how to solve this with Saved Search.

Basic Running Total Algorithm

The basic running total algorithm logic is as follows assuming we are seeking transaction output as illustrated above:

  1. Get all the data that fits the criteria you need.
  2. Define a integer variable, such as “onhand”
  3. Organize the transactions list sorted by date
  4. Start at the top of the list and iterate through each row
  5. For each row, increment the value of “onhand” variable by the value of the quantity column
  6. Output the “onhand” value as a separate column

Key NetSuite Saved Search Running Total Wish Lists Features

The algorithm above is very common when working with business databases. As such, here is an item to add to my NetSuite Saved Search wish lists:

1. The ability to reference a forumla field by a name
2. The ability to connect SuiteScript to a formula.  Combine the power of SuiteScript with Oracle PLSQL.
3. The ability to define when the SuiteScript would execute: before query start, before get row, after get row, after query end.

While I have many other Saved Search wishes, these capacities would allow for a great deal of flexibility and solve our running total problem.

How to Solve the Running Total Challenge

Finally, in order to solve the running total inventory on hand challenge, we alas must use SuiteScript and couple this to the Sublist API to output the results. Below is basic SuiteScript pattern take a manipulated search result  and place the values in a sublist to output the result. While we have solved the problem, it demands more of the user and is often outside the reach of a typical NetSuite Administrator.

// assumes you setup the search and results which
// include any preprocessing to add running totals    
if ( searchresults.length > 0 )
    {
        // first, add the columns to the sublist based on the columns in the results
        var result = searchresults[0];
        var column_list = result.getAllColumns();
        var col_len = column_list.length;
        for (i=0; i<col_len; i++)
        {
            var col = column_list[i];
            var col_name = col.getName();
            var col_label= col.getLabel();
            var col_form = col.getFormula();
            var col_func = col.getFunction();
            nlapiLogExecution('DEBUG', 'column name, label, formula, function', col_name + '|'+ col_label + '|'+ col_form + '|'+ col_func);

            // if there is no label, use the field name
            if (!col_label)
            {
                col_label = col_name;
            }
            var fld_name = 'custpage_fld_' + i;

        }


        // now, show the results; loop through each result
        var rlen= searchresults.length;

        for (ctr=0;ctr<rlen;ctr++)
        {
            var result = searchresults[ctr];

            // for each result, loop the columns
            for (i=0; i<col_len; i++)
            {
                var col = column_list[i];
                var col_name = col.getName();
                var col_label= col.getLabel();
                // if there is no label, use the field name
                if (!col_label)
                {
                    col_label = col_name;
                }
                var fld_name = 'custpage_fld_' + i;
                var value = result.getText(col);
                if (!value)
                {
                    value = "";
                }
                if (value.length == 0)
                {
                    value = result.getValue(col);
                }

                var lin = parseInt(ctr) + parseInt(1);
                if (value)
                {
                    YOURLIST.setLineItemValue(fld_name, lin, value);
                }
            }
        }
    }

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)

15 thoughts on “NetSuite Saved Search Running Totals Sublist Challenge

  1. Can you show how to use the SQL Group By in your example?

    In our example, however, we don’t really need to use an aggregate “Group By” function to get our result

    Reply
  2. Hey Marty,

    Have you tried an SQL Formula that copies the header details to the rows and the criteria is “Main Line = False’?

    Reply
  3. I was able to get this module working correctly, but was wondering what transaction types did you use as the criteria in your saved search to define on-hand/running total counts. Based on this article, I assumed it was Item Fulfillment and Item Receipts. Can you please clarify. Thanks

    Reply
  4. hey …I have to read an entire line item from one sales order and add that into another sales order. Could you please help me with this???

    Reply
  5. Hi,

    I’d love to use this function on a customer search to show total sales for that customer – I currently have this – which produces an error? I feel like I’m missing something.

    case when {transaction.type}=’Tax Invoice’ then (sum/* comment */({transaction.amount})) else 0 end

    Appreciate any help at all.

    Reply
  6. Marty – attempted to build out a saved search based on your terrific guidance, to be able to see point in time inventory. (ie, pick a particular product/SKU, and a specific date or date range, and see what the total inventory on hand was each day). Seeing the movement/transactions – item receipt, inventory adjustment, itself is key as well. Unfortunately my results are showing cumulative counts over time… versus showing what the count was on a particular day/range of days.
    Is it even possible to calculate point in time inventory like that ?
    This is the formula that I have currently:

    TO_CHAR(sum/* comment */( {quantity}) OVER(PARTITION BY {item} ORDER BY TO_CHAR({trandate}, ‘YYYYMMDD’) || to_char({internalid}, ‘00000000000000009’) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), ‘9,999,999,999’)

    Any guidance would be great.

    Reply

Leave a Reply

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