Calculating Customer Aging Balances in X++

by | May 23, 2017 | 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.


  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


08apr10:00 am10:30 amLicensing Preparedness for Dynamics 365 Customer Engagement

08apr12:00 pm1:00 pmMaking Project Information Management (PIM) a Priority

08apr2:00 pm2:30 pmFeatures in the Spring Release of Dynamics 365 Customer Engagement Users Can Take Advantage of Immediately

09apr11:00 am12:00 pmConfab With Stoneridge - Livestream - Portals

13apr11:30 am12:30 pmStoneridge Connect Online Keynote: Business Transformations Throughout History

14apr8:00 am5:00 pmStoneridge Connect Online - Day 1

15apr8:00 am5:00 pmStoneridge Connect Online - Day 2

15apr1:15 pm5:00 pmWhat’s New for Developers in Dynamics 365 Finance and Supply Chain Management – Online Workshop

16apr8:00 am5:00 pmStoneridge Connect Online - Day 3

22apr11:00 am12:00 pmPower BI and Reporting with Dynamics 365 Business Central

22apr2:00 pm2:30 pmNew Features for Power Apps Users

23apr11:00 am12:00 pmConfab With Stoneridge - Livestream - Internet of Things (IoT)

29apr10:00 am11:00 amStreamlining Customer Service and Enabling Your Sales Team with a Self-Service Portal

29apr12:00 pm12:30 pmUpdates to the Dynamics 365 Customer Engagement User Experience - What Technical Resources Need to Know


06may12:00 pm12:30 pmPower Apps Telemetry and AI Builder - Power Platform Updates

06may2:00 pm2:30 pmImprove Customer Experience with a Mobile Workforce Management Solution

07may11:00 am12:00 pmConfab With Stoneridge - Livestream - Manufacturing

13may12:00 pm1:00 pm3 Simple Sets Your Business Can Take to Embrace the Future of B2B E-Commerce

21may11:00 am12:00 pmEnterprise Asset Management and Manufacturing

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!