Marty Zigman - The NetSuite Expert

Conversations with Marty Zigman

Certified Administrator • ERP • SuiteCloud

Prolecto Labs Accelerator Templates

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

Holding all three official certifications, Marty is regarded as the top NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. He is a former Deloitte & Touche CPA and has held CTO roles. For over 30 years, Marty has produced leadership in ERP, CRM and eCommerce business systems. Contact Marty to set up a conversation.

More Posts - Website - Twitter - Facebook - LinkedIn - YouTube

About Marty Zigman

Marty Zigman

Holding all three official certifications, Marty is regarded as the top NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. He is a former Deloitte & Touche CPA and has held CTO roles. For over 30 years, Marty has produced leadership in ERP, CRM and eCommerce business systems. Contact Marty to set up a conversation.

Biography • Website • X (Twitter) • Facebook • LinkedIn • YouTube

15 thoughts on “NetSuite Saved Search Running Totals Sublist Challenge

  1. Mike says:

    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

  2. Marty Zigman says:

    Hello Mike,

    Are you suggesting that your records, at the detail level, have the data you need and you simply want a running total? We still need to go to SuiteScript to get the job done.

    Perhaps you can offer more explanation.

    Marty

  3. John says:

    Hey Marty,

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

  4. Marty Zigman says:

    Yes, Main Line = False returns only the detail. That’s the level we want. But there is no way to maintain a cumulative total with the SQL functions provided. Do you see a way?

    We really need a Javascript Layer or a way to make a second pass on the data.

  5. David says:

    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

  6. Marty Zigman says:

    Hi David,

    It’s been over 18 months since we solved for this so my memory is vague. In case of inventory, yes, you will need to pull over all transaction records that affect inventory. Besides Item Fulfillments and receipts, consider Transfers. Given NetSuite is now supporting new “inventory detail” lists, I might try to approach it from a different angle. I suggest testing all your assumptions to see if you can write queries that can reproduce the inventory balance on hand.

    Good luck!

    Marty

  7. ramya says:

    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???

  8. Marty Zigman says:

    Hello Ramya,

    The work you need to do typically entails working with the Sublist API. There are mutliple ways this API works and it depends on the context for which you are trying to accomplish your goal.

    Did you see this article which shows some use of the Sublist API?

    https://blog.prolecto.com/2013/05/01/how-to-script-to-automate-netsuite-journal-entries/

    Marty

  9. Reuben says:

    Is it possible to show column totals on top of the search or in the ‘Filters’ area of a dashboard search?

  10. Marty Zigman says:

    Hello Ruben,

    Not really. NetSuite has its own ways of doing things and the column totals will show at the bottom. However, you can program a portlet with Suitescript to get the view you want. Here is a simple portlet code example: https://blog.prolecto.com/2014/07/09/netsuite-portlet-code-example-get-last-invoice-number/

    Marty

  11. Reuben says:

    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.

  12. Marty Zigman says:

    Hello Reuben,

    I suspect the Analytics function can’t be used in the case statement that way. Try Decode. See this article: https://community.oracle.com/thread/453335?start=15&tstart=0

    Marty

  13. Jason Carney says:

    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.

  14. Marty Zigman says:

    Hello Jason,

    Yes, have a look at this portion: “TO_CHAR({trandate}, ‘YYYYMMDD’) || to_char({internalid}, ‘00000000000000009’)”. It is concatenating the internal ID and the date together. Remove the “|| to_char({internalid}, ‘00000000000000009’)” to see if that helps.

    Marty

Leave a Reply

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