Forum Discussion
AR Aging Buckets (Dynamic Based on User Selected CutOff Date)
Thanks v-yulgu-msft
Let's see if I can better communicate this:
- User selects the desired EOM date from the slicer - this is the cut-off date from which the report is being run.
- Desired goal is to show the AR Aging balance from the account's creation date up to the selected EOM date
- All charges applied to the AR Account with a transaction_date on or prior to the selected EOM should be summed
- We then age the charges based how many days have passed from the transaction's due_date to the selected EOM date
- Similarly, all payments applied to the AR Account with a transaction_date prior to or on the selected EOM date should be summed
- We then need to apply the summed payments made in the selection scope to the aged charges, only we need to apply payments to the oldest charges first (i.e. start at 91+ bucket) and if there is any remainder, it will then be applied to the next oldest charges that are available (i.e. 61-90 bucket, then 31-60 bucket and so on).
From what I can tell looking at other posts for aged debtors, their models normally have a "cleared_date" of some sort associated with the transaction charges. So they have trans_date, or when the charge actually took place, and then a clear_date, or when the charge was indicated as being paid. If I had a cleared_date in my data that would make this exercise trivial, unfortunately all I have are transaction dates - there is no separate field that contains the date when the charge has officially been considered paid. It all has to be calculated on the fly.
I've linked to a newer version of the PBIX which has some small changes to hopefully make my needs clearer. It includes some cards to show all the charges that were made prior to the cut off date as well as all the payments made prior to the cut off date. I'm using 5/31/2013 for my example here.
As you can see the $1,964.29 for the charges card in the picture above is simply all the charges shown in the table below added ($337.26 due 3/31/2013 + $928.96 due 4/30/2013 + $356.84 due 5/31/2013 = $1,623.06 + $341.23 due 6/30/2013 = $1,964.29)
Additionally, the payments shown in green above add correctly up to show that this account paid their balances due by 5/31/2013 in full. (Remember the $341.23 charged to the account between 5/17/2013 adn 5/31/2013 are not due until the following month 6/30/2013).
And here is a really bad mock-up of what I was hoping I could achieve. I'd basically want another row underneath the charges row for the account id that shows the payments being applied. In this case, since this account has paid all charges on time they all zero out - but not all accounts will be like this; there will be times where underpayments and/or over-payments are made. I've broken it down in to three additional rows only to show how were taking the total available payments for the period (in red text) and applying them to the buckets in reverse order of age (oldest first).
One last mock up of my desired end visual - this is just typed up in Excel not based on any real data, but should give a good idea of what I'm aiming for:
So after thinking about this some more, I realized the only way to do this was to actually do it. :\
I was able to cobble this together which works so far for the accounts I've tested it on. I've been limiting the account_ids to a few at a time, but will start testing it on the entire table. I'm interested to see what the performance will be like.
I'm sure there's a better way to approach and would love any suggestions from the field.
GBF =
VAR _Credits = [Payments in Selected Scope]
VAR _Debits = [Charges in Selected Scope]
VAR _SelectedEOM = [Selected Month End Date]
VAR _Current = [Current Charges]
VAR _30 = CALCULATE ( [Aging Value], FILTER ( ALL ( Aging_Bands ), Aging_Bands[band_name] = "0 - 30" ) )
VAR _60 = CALCULATE ( [Aging Value], FILTER ( ALL ( Aging_Bands ), Aging_Bands[band_name] = "31 - 60" ) )
VAR _90 = CALCULATE ( [Aging Value], FILTER ( ALL ( Aging_Bands ), Aging_Bands[band_name] = "61 - 90" ) )
VAR _91 = CALCULATE ( [Aging Value], FILTER ( ALL ( Aging_Bands ), Aging_Bands[band_name] = "91+" ) )
VAR _Remainder91 = IF ( _91 <> 0, _Credits + _91, _Credits )
VAR _Result91 = IF ( _Remainder91 <= 0, 0, _Remainder91 )
VAR _Remainder90 = IF ( _90 <> 0, _Remainder91 + _90, _Remainder91 )
VAR _Result90 = IF ( _Remainder90 <= 0, 0, _Remainder90 )
VAR _Remainder60 = IF ( _60 <> 0, _Remainder90 + _60, _Remainder90 )
VAR _Result60 = IF ( _Remainder60 <= 0, 0, _Remainder60 )
VAR _Remainder30 = IF ( _30 <> 0, _Remainder60 + _30, _Remainder60 )
VAR _Result30 = IF ( _Remainder30 <= 0, 0, _Remainder30 )
VAR _RemainderCurrent =
IF (
_Current <> 0
&& _Result30 > 0,
_Current,
IF (
_Current <> 0
&& _Remainder30 <= 0,
_Remainder30 + _Current,
IF ( _Current = 0 && _Remainder30 < 0, _Remainder30, 0 )
)
)
VAR _ResultCurrent = IF ( _RemainderCurrent <= 0, 0, _RemainderCurrent )
VAR _Total = _Result91 + _Result90 + _Result60 + _Result30 + _RemainderCurrent
RETURN
IF (
HASONEVALUE ( Aging_Bands[band_name] ),
SWITCH (
VALUES ( Aging_Bands[band_name] ),
"91+", IF ( ISBLANK ( _Result91 ), 0, _Result91 ),
"61 - 90", IF ( ISBLANK ( _Result90 ), 0, _Result90 ),
"31 - 60", IF ( ISBLANK ( _Result60 ), 0, _Result60 ),
"0 - 30", IF ( ISBLANK ( _Result30 ), 0, _Result30 ),
"Current", _RemainderCurrent,
0
),
_Total
)