microsoft / microsoft/BCApps

[Bug][Subscription Billing] Supplier charge period is ignored when crediting usage-based vendor subscription lines

Open
#10,033 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Approved Team: Finance
Dominant language
AL
Stars
683
Forks
459
Avg merge
3d 26m
Merged PRs (30d)
633

Description

Describe the issue

A subscription is billed on the basis of usage data and has both a customer line and a vendor line. It is invoiced a year in advance, 1 January to 31 December. The customer cancels as of 1 October, so usage data for the remaining three months is delivered with a negative quantity in order to credit the unused part of the year.

Two things go wrong:

  1. While the usage data is processed, the user is told that the quantity must not be negative, even though the credited quantity is fully covered by the quantity that is currently subscribed. The message is misleading — nothing is actually wrong, and the data is processed anyway — but it makes users doubt whether the credit was created correctly.

  2. The resulting vendor credit memo credits the whole year instead of the three cancelled months. The customer side gets this right: there the credit is limited to the period the usage data actually covers. On the vendor side the charge start and end dates of the delivered usage data are not taken into account at all, so the amount comes out roughly four times too high. Since this ends up in a posted purchase credit memo, the vendor account and the contract margin are both wrong, and the error is only found when someone reconciles the vendor invoice by hand.

Affected objects:

  • src/Apps/W1/Subscription Billing/App/Usage Based Billing/Codeunits/ProcessUsageDataBilling.Codeunit.al
  • src/Apps/W1/Subscription Billing/App/Usage Based Billing/Tables/UsageDataBilling.Table.al
  • src/Apps/W1/Subscription Billing/App/Billing/Codeunits/BillingProposal.Codeunit.al
  • src/Apps/W1/Subscription Billing/App/Service Objects/Tables/SubscriptionHeader.Table.al
Expected behavior

1 — Negative quantity warning

The warning should only appear when the negative quantity delivered is larger in absolute terms than the quantity currently subscribed on the Subscription Line (a quantity of -2 is legitimate for a subscription with quantity 3; -5 is not).

Today the message originates from QtyNegativeErr in Subscription Header, raised via Process Usage Data Billing.UpdateServiceObjectQuantity() when the recalculated total quantity is validated. The check should compare the incoming negative quantity against the currently subscribed quantity before raising anything, and stay silent when the credit is covered by it. If a message is still warranted, it should also be raised consistently — either it blocks processing or it does not; right now it is shown and the record is processed regardless.

2 — Supplier charge period on the vendor side

Charge Start Date / Charge End Date of the usage data (and the Supplier Charge Start Date / Supplier Charge End Date mirrored into Usage Data Billing Metadata) must be honoured for vendor Subscription Lines exactly as they are for customer lines, so the vendor credit memo covers only 01.10.2026–31.12.2026.

Where it currently breaks:

  • Process Usage Data Billing.Code() restricts the repricing loop to Partner::Customer, and CalculateCustomerUsageDataBillingPrice() exits immediately for any other partner. The period-aware calculation — CalculateUsageDataPrices()Subscription Line.UnitPriceForPeriod("Charge Start Date", "Charge End Date") — therefore never runs for vendor lines.
  • As a result the vendor Unit Cost / Cost Amount stay at the raw imported Unit Cost × Quantity produced by Usage Data Billing.CalculateAmounts(), which does not consider the charge period at all.
  • Billing Proposal.SetBillingLineUnitPriceAndServiceAmountsFromUsageDataBilling() then takes Usage Data Billing."Cost Amount" as the base amount for Partner::Vendor, so the un-prorated full-year amount lands on the billing line and on the purchase credit memo.

Proposed fix: apply the same period-based cost calculation to vendor Subscription Lines — i.e. give vendor lines a counterpart to CalculateCustomerUsageDataBillingPrice that derives Unit Cost / Cost Amount from the charge period via UnitPriceAndCostForPeriod (or extend the existing routine to run for both partners, using Unit Cost/Cost Amount instead of Unit Price/Amount for vendors), keeping Unit Cost from Import-style supplier settings respected. Usage Data Billing Metadata is already written for both partners, so no new data is needed.

Steps to reproduce
  1. Create a Subscription with a customer Subscription Line and a vendor Subscription Line, both with Usage Based Billing enabled and a yearly billing rhythm.
  2. Import usage data for that subscription with Charge Start Date = 01.01.2026, Charge End Date = 31.12.2026, Quantity = 10, Unit Cost = 1200, and process the import.
  3. Create and post the billing documents from both the customer subscription contract and the vendor subscription contract — the customer invoice and the purchase invoice cover the full year.
  4. Import a second usage data file for the same subscription with Charge Start Date = 01.10.2026, Charge End Date = 31.12.2026, Quantity = -10, Unit Cost = 1200 (the cancellation as of 1 October).
  5. Process the usage data.
    → A message appears saying the quantity must not be negative, although the subscription currently has quantity 10 and only 10 is being credited. The lines are processed regardless. (Defect 1)
  6. Open the vendor subscription contract, create the billing proposal and the credit memo.
    → Expected credited amount: 3,600 (01.10.2026–31.12.2026). Actual credited amount: 12,000 (full year). (Defect 2)
  7. Repeat step 6 on the customer subscription contract — there the credit is limited to the cancelled period, which shows the two sides behave differently.
Additional context

No response

I will provide a fix for a bug
  • I will provide a fix for a bug

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with ProcessUsageDataBilling.Codeunit.al, especially UpdateServiceObjectQuantity() and the customer-only repricing path, then trace BillingProposal.Codeunit.al and UsageDataBilling.Table.al. Compare the customer period calculation with vendor handling and review SubscriptionHeader.Table.al for QtyNegativeErr. Done means covered negative quantities no longer warn incorrectly and vendor credits use the delivered charge period, with the affected billing flow verified.

Written by the indexing model from the issue text.

Assessment

Domain
backend, payments
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.