Describe the issue
The "Overdue" cue on the Subscription Billing Activities role centre, and the "Overdue Subscription Lines" list behind it, still show contract lines that have an end date in the past and nothing left to bill. Once the work date is moved past the end date, those finished lines keep appearing as overdue together with a next billing date.
The tile is meant to be a to-do list of lines that need billing attention. As long as finished lines are counted, the number is inflated and the tile does not serve its purpose — users cannot tell real arrears from contract lines that simply ran out.
Affected objects:
- src/Apps/W1/Subscription Billing/App/Overdue Service Commitments/Tables/OverdueSubscriptionLine.Table.al
- src/Apps/W1/Subscription Billing/App/Overdue Service Commitments/Pages/OverdueServiceCommitments.Page.al
- src/Apps/W1/Subscription Billing/App/Base/Codeunits/SubBillingActivitiesCue.Codeunit.al
- src/Apps/W1/Subscription Billing/App/Service Objects/Tables/SubscriptionHeader.Table.al
Expected behavior
A subscription line whose "Subscription Line End Date" has passed and which has nothing left to bill must not be counted in the Overdue cue or listed on the "Overdue Subscription Lines" page.
Root cause
Both the count and the list in OverdueSubscriptionLine.Table.al (CountOverdueServiceCommitments and FillOverdueServiceCommitments) filter on exactly two conditions:
ServiceCommitment.SetFilter("Next Billing Date", '<%1', OverdueDate);
ServiceCommitment.SetRange(Closed, false);
So the whole exclusion of finished lines rests on the Closed flag. That flag is only maintained by SubscriptionHeader.UpdateServicesDates():
if (ServiceCommitment."Subscription Line End Date" <> 0D) and
(Today() > ServiceCommitment."Subscription Line End Date") and
ServiceCommitment.IsFullyInvoiced() then begin
...
ServiceCommitment.Closed := true;
Two things follow:
- The guard uses
Today(), while the cue's overdue date is calculated from WorkDate() (CalcOverdueDate → CalcDate(ServiceContractSetup."Overdue Date Formula", WorkDate())). Moving the work date past the end date — the exact repro — therefore makes a line appear overdue without ever making it closable. The two sides of the same question use two different clocks.
UpdateServicesDates runs only from the "Update Subscription Lines Termination Dates" action on the contract or subscription card, from codeunit 8058 "Update Sub. Lines Term. Dates" when it is scheduled as a job queue entry, and from a handful of contract-line paths. Until one of them runs, Closed is stale and the cue is wrong even on a correct clock.
Proposed fix
Make the cue self-sufficient rather than dependent on a flag maintained elsewhere. In both CountOverdueServiceCommitments and FillOverdueServiceCommitments, additionally exclude lines whose billing has passed their end date, along the lines of:
ServiceCommitment.SetFilter(
"Subscription Line End Date", '%1|>=%2', 0D, ServiceCommitment."Next Billing Date");
so that a line with an end date is only overdue while its next billing date still falls inside the term. Lines without an end date keep the current behaviour.
Aligning the clock in UpdateServicesDates — using WorkDate() instead of Today(), or at minimum documenting why it must be Today() — is worth resolving in the same change, since the mismatch is what makes the reported repro possible.
Steps to reproduce
- Make sure Subscription Contract Setup has an "Overdue Date Formula" (so the cue is active).
- Open any customer subscription contract that has an open subscription line.
- On the contract line, enter a Subscription Line End Date in the past relative to the work date you will set in the next step, and bill the line up to that end date.
- Set the work date to a date after that end date.
- Open the Subscription Billing Activities role centre and click the Overdue tile, or open the Overdue Subscription Lines page directly.
- Filter on the contract from step 2.
- The finished line is still listed, with a "Next Billing Date", and is included in the tile count.
I will provide a fix for a bug
Describe the issue
The "Overdue" cue on the Subscription Billing Activities role centre, and the "Overdue Subscription Lines" list behind it, still show contract lines that have an end date in the past and nothing left to bill. Once the work date is moved past the end date, those finished lines keep appearing as overdue together with a next billing date.
The tile is meant to be a to-do list of lines that need billing attention. As long as finished lines are counted, the number is inflated and the tile does not serve its purpose — users cannot tell real arrears from contract lines that simply ran out.
Affected objects:
Expected behavior
A subscription line whose "Subscription Line End Date" has passed and which has nothing left to bill must not be counted in the Overdue cue or listed on the "Overdue Subscription Lines" page.
Root cause
Both the count and the list in
OverdueSubscriptionLine.Table.al(CountOverdueServiceCommitmentsandFillOverdueServiceCommitments) filter on exactly two conditions:So the whole exclusion of finished lines rests on the
Closedflag. That flag is only maintained bySubscriptionHeader.UpdateServicesDates():Two things follow:
Today(), while the cue's overdue date is calculated fromWorkDate()(CalcOverdueDate→CalcDate(ServiceContractSetup."Overdue Date Formula", WorkDate())). Moving the work date past the end date — the exact repro — therefore makes a line appear overdue without ever making it closable. The two sides of the same question use two different clocks.UpdateServicesDatesruns only from the "Update Subscription Lines Termination Dates" action on the contract or subscription card, fromcodeunit 8058 "Update Sub. Lines Term. Dates"when it is scheduled as a job queue entry, and from a handful of contract-line paths. Until one of them runs,Closedis stale and the cue is wrong even on a correct clock.Proposed fix
Make the cue self-sufficient rather than dependent on a flag maintained elsewhere. In both
CountOverdueServiceCommitmentsandFillOverdueServiceCommitments, additionally exclude lines whose billing has passed their end date, along the lines of:so that a line with an end date is only overdue while its next billing date still falls inside the term. Lines without an end date keep the current behaviour.
Aligning the clock in
UpdateServicesDates— usingWorkDate()instead ofToday(), or at minimum documenting why it must beToday()— is worth resolving in the same change, since the mismatch is what makes the reported repro possible.Steps to reproduce
I will provide a fix for a bug