Calculating Customer Aging Balances in X++

by | Updated January 29, 2020 | Development, Dynamics AX

I was recently asked to add an Account Summary to the footer of a report in AX 2012, to look something like this:


In my research, I came across a helpful class that allowed me to meet this requirement of calculating customer aging balances in X++ with a minimum of coding effort; the CustVendAgingStatistics class. The calcStatistic method queries StatRepInterval and StatRepIntvervalLine to get the buckets and settings for the calculation, then it writes out the values to tmpAccountSum, which is an InMemory temporary table. Depending on what aging buckets you need, you can use a debugger to figure out which tmpAccountSum records you will want.

For my purpose, I created a new method to calculate the customer’s aging balances using a 30D format (#agingFormat macro). I needed open balances (Balance03) and I opted to store both balance and description in a Map. The integer key was helpful so that I could retrieve the values later and add them to the SalesInvoiceHeaderFooterTmp record in SalesInvoiceDP.insertSalesInvoiceHeaderFooterTmp method. You could easily use a container here, depending on how you are using the aging information.

Obviously, this could be used for Vendor Aging as well. I verified that the values match exactly with the Customer Aging report when it is run with the same parameters.

Related Posts


  1. RLP

    That works great if the you want the balances as of today, but not if you need to apply a statement end date: out of the box, the CustVendAgingStatistics class does not support a date range.

    The CustVendAgingStatistics class could be modified to support an end date, but the same end results can achieved (but with more code) without modifying any out-of-the-box classes. The following works, but might be able to be refactored to be more elegant.

    static void RLP_CustVendAgingAsOfDate(Args _args)
    // These first variables would be passed in as parameters
    SysModule _sysModule = SysModule::Cust;
    AccountNum _accountNum = ‘C16652′;
    TransDate _statementEndDate = 28\03\2017;
    CustVendReportName _agingFormat = ’30/60/90/120’;
    DateTransactionDuedate _dateFieldToUseForAging = DateTransactionDuedate::DocumentDate;

    // These parallel arrays store the results
    str agingHeaders[];
    AmountCur agingAmounts[];

    CustAgingCalculation custAgingCalculation;
    CustVendAgingCalculatedTmp custVendAgingCalculatedTmp;
    CustVendAgingPeriodScaleTmp custVendAgingPeriodScaleTmp;
    Query q;
    QueryRun qr;

    custAgingCalculation = CustVendAgingCalculation::construct

    q = new Query();
    if (_sysModule == SysModule::Cust)
    q.addDataSource(tableNum(CustTable)).addRange(fieldNum(CustTable, AccountNum)).value(queryValue(_accountNum));
    q.addDataSource(tableNum(VendTable)).addRange(fieldNum(VendTable, AccountNum)).value(queryValue(_accountNum));
    qr = new QueryRun(q);

    custVendAgingCalculatedTmp = custAgingCalculation.process(qr);
    custVendAgingPeriodScaleTmp = custAgingCalculation.getCustVendAgingPeriodScaleTmp();

    while select BucketNumber, sum(AmountCur)
    from custVendAgingCalculatedTmp
    group by custVendAgingCalculatedTmp.BucketNumber
    agingAmounts[custVendAgingCalculatedTmp.BucketNumber] = custVendAgingCalculatedTmp.AmountCur;

    while select BucketNumber, BucketDescription
    from custVendAgingPeriodScaleTmp
    group by custVendAgingPeriodScaleTmp.BucketNumber, custVendAgingPeriodScaleTmp.BucketDescription
    agingHeaders[custVendAgingPeriodScaleTmp.BucketNumber] = custVendAgingPeriodScaleTmp.BucketDescription;

  2. Brandon Carmichael

    Hello RLP,

    Thank you for your comment and code. After talking with Laura, she mentioned she didn’t need the date as she needed the ‘balance as of today’. I’m hoping someone will find your code helpful.

    User discretion is advised – Stoneridge Software did not create, use, or test the code above (RLP’s comment).


Submit a Comment

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

Upcoming Events


14jan11:00 am12:00 pmConfab with Stoneridge - Livestream - Looking Forward: Predictions for Technology in 2021

20jan10:00 am10:30 amThe Modern Manufacturer - Demand Forecasting Functionality

27jan12:00 pm12:45 pmFour Keys to Choosing the Best ERP or CRM Solution: Part 1 – Fit

28jan11:00 am12:00 pmConfab with Stoneridge - Livestream - Ask the Experts!


03feb12:00 pm12:45 pmFour Keys to Choosing the Best ERP or CRM Solution: Part 2 – Platform

10feb12:00 pm12:45 pmFour Keys to Choosing the Best ERP or CRM Solution: Part 3 – Implementation Partner

11feb11:00 am12:00 pmConfab with Stoneridge - Livestream - Live Agents, Power Virtual Agents, Omnichannel – Oh My!

16feb12:00 pm12:45 pmFour Keys to Choosing the Best ERP or CRM Solution: Part 4 – Cost

25feb11:00 am12:00 pmConfab with Stoneridge - Livestream - Surfing Through the Dynamics 365 Wave 1 2021 Release

About Stoneridge
Stoneridge Software is a unique Microsoft Gold Partner, with emphasis on partner. With specialties in Microsoft Dynamics 365, Microsoft Dynamics AX, Microsoft Dynamics NAV, Microsoft Dynamics GP and Microsoft Dynamics CRM, we focus on attracting the most knowledgeable experts in the field to our team, and prioritize delivering stellar solutions with maximum impact for your business. At Stoneridge, we are deeply committed to your results. Each engagement is met with a dedicated team, ready to provide thorough, tailored, and expert service. Based in Minnesota, we intentionally “step into your shoes,” wherever you are. We focus on what you care about, and develop trusting, long-term relationships with our clients.

Subscribe To Our Blog

Sign up to get periodic updates on the latest posts.

Thank you for subscribing!