Performing a Backward or Forward Item Trace in X++ Programming Language

By Deovandski Skibinski | May 22, 2025

Backward or Forward Item Trace in X++

If you are reading this blog, you have likely been scratching your head trying to figure out how to item trace through code since there is no helper class, interface, or something like it to make it simple.

Don't worry! Stoneridge Software has a solution for you. In this blog, we will outline how you can perform both backward and forward item traces using code. What you will see in the sections below acts as a wrapper to the code you need, with two distinct classes: Custom processing class and InventingTrackingBatchSummary Filter Extension. 

Let's dive into it:

//Custom Processing Class

As you can see in the code below, these base classes feed into each other, with the code flow being quite similar to how the user clicks Item trace, fills in information on the dialog, and then on the traced item, clicks "Batches" to see related batches.

InventBatch _inventBatch; // TODO parameterize

 // Setup
 InventTrackingDimTracingRelations traceRelations;
 inventTrackingDimTracingCriteria traceCriteria = inventTrackingDimTracingCriteria::construct();
 InventTrackingDimTracingHierarchy traceHierarchy = InventTrackingDimTracingHierarchy::construct();
 InventTrackingBatchSummaryFilter traceFilter;
 // InventDim Setup
 InventDim traceInventDim;
 traceInventDim.inventBatchId = _inventBatch.inventBatchId;
 traceInventDim = InventDim::findOrCreate(traceInventDim);
 // Criteria Setup
 traceCriteria.parmItemIdCriteria(_inventBatch.itemId);
 traceCriteria.parmTraceDirection(ForwardBackward::Backward); // TODO parameterize if needed.
 traceCriteria.parmInventDimCriteria(traceInventDim);
 // Relation setup
 traceRelations = InventTrackingDimTracingSearch::searchNoPack(traceCriteria);
 if (traceRelations)
 {
     // Hierarchy Setup
     traceHierarchy = InventTrackingDimTracingHierarchy::newFromTracingResults(traceRelations);
     traceHierarchy.childNodes(0);
     // Trace setup
     traceFilter = InventTrackingBatchSummaryFilter::newHierarchy(traceHierarchy);
     traceFilter.create();
     // Extract filtered InventBatches
     List retInventBatches = traceFilter.getFilteredInventBatches(true);
     ListEnumerator iterator = retInventBatches.getEnumerator();
     while (iterator.moveNext())
     {
         InventBatch process = iterator.current() as InventBatch;
         // TODO process related InventBatch
     }
else {
     // No Trace Relations found.
}

// Ext Class (InventTrackingBatchSummaryFilter

You will need this extension class if you are using the above from a custom class. If you are using a form instead, you might be able to get away with using applyfilter() found on the base class and then create a custom method to expose mainDataSource to your form.

[ExtensionOf(classStr(InventTrackingBatchSummaryFilter))]
final class InventTrackingBatchSummaryFilter_Extension
{
    public List getFilteredInventBatches()
    {
        List retList = new List(Types::Record);
        // Not strictly necessary to check but better be safe than to generate a runtime error.
        if(filterTmp.tableId == TableNum(InventItemDimTmpFilter))
        {
            InventDim inventDim;
            InventBatch inventBatch;
            InventItemDimTmpFilter flt = filterTmp as InventItemDimTmpFilter;

            while select flt
                join inventDim where inventDim.inventDimID == flt.inventDimID
               // TODO Remove if no filtering or action is needed on the InventBatch table.
                join inventBatch where inventBatch.inventBatchId == inventDim.inventBatchId
            {
                    retList.addEnd(inventBatch);
                }
            }
        }
        return retList;
    }
}

Talk to the Stoneridge Team Today to Learn More!

If you need help developing smart solutions to complex issues within your software systems, contact our team of experts!

Deovandski Skibinski
Our Verified Expert
Deovandski Skibinski

Deovandski Skibinski is a developer with experience across multiple programming languages and recent expertise in X++ development for Dynamics 365 Finance and Supply Chain. He brings a passion for problem solving client challenges and enjoys sharing knowledge with fellow developers. His work spans retail, distribution, inventory, and finance, where he builds reliable, efficient solutions that help businesses run smarter. Deo holds a bachelor’s degree in Computer Science from North Dakota State University.

Read More from Deovandski Skibinski

Related Posts


Under the terms of this license, you are authorized to share and redistribute the content across various mediums, subject to adherence to the specified conditions: you must provide proper attribution to Stoneridge as the original creator in a manner that does not imply their endorsement of your use, the material is to be utilized solely for non-commercial purposes, and alterations, modifications, or derivative works based on the original material are strictly prohibited.

Responsibility rests with the licensee to ensure that their use of the material does not violate any other rights.

Start the Conversation

It’s our mission to help clients win. We’d love to talk to you about the right business solutions to help you achieve your goals.

Subscribe To Our Blog

Sign up to get periodic updates on the latest posts.

Thank you for subscribing!