microsoft / microsoft/BCApps

[Bug]: [Subscription Billing] Payment discount on contract invoices comes from the customer, not from the contract's payment terms

Open
#10,095 1 comment 0 reactions 1 assignee View on GitHub

@djukicmilica is already working on this.

Since Aug 10, 2026.

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

Description

Describe the issue

When a Subscription Contract uses payment terms that differ from the ones on the customer, the invoice created from that contract shows the contract's payment terms, but the payment discount that goes with them is ignored.

A typical case: the customer is set up with payment terms that grant no discount, and on the contract the payment terms were changed manually to terms that do grant an early-payment discount. The contract invoice then carries the contract's payment terms and the matching discount date, but the discount percentage stays at 0. The customer never gets the discount they were promised in the contract, and the receivable is settled without it.

The mirror image is just as wrong: if the customer's terms grant a discount and the contract's terms do not, the invoice keeps granting the customer's discount, so money is given away that the contract does not allow.

The same happens on the purchase side for invoices created from vendor subscription contracts.

Expected behavior

Payment discount percentage and payment discount date on a document created from a subscription contract must both follow the payment terms stored on the contract, exactly as if a user had entered those payment terms on the document by hand.

Cause

In codeunit "Create Billing Documents", CreateSalesHeaderFromContract first validates "Sell-to Customer No." / "Bill-to Customer No." — which sets "Payment Terms Code" and "Payment Discount %" from the customer — and then overwrites the terms code through SalesHeader.TransferFields(CustomerContract, false). TransferFields assigns without validation, so "Payment Discount %" is left at the customer's value.

The later SalesHeader.Validate("Document Date", DocumentDate) does re-run the "Payment Terms Code" trigger, but that trigger only refreshes the discount under

if not UpdateDocumentDate and (xRec."Payment Terms Code" <> Rec."Payment Terms Code") then
    Validate("Payment Discount %", PaymentTerms."Discount %")

Both conditions fail here: validating a changed document date sets UpdateDocumentDate := true, and after TransferFields the record already holds the contract's terms code, so xRec and Rec are equal. "Due Date" and "Pmt. Discount Date" sit outside that guard and are recalculated correctly — which is why the document looks right apart from the percentage.

CreatePurchaseHeaderFromContract has the same pattern for vendor contracts (Purchase Header only carries the not UpdateDocumentDate guard, so it breaks whenever the requested document date differs from the work date).

Proposed fix

After the document date has been set, re-assign the customer-derived terms code and validate the contract's code, so the base trigger sees a real change and recalculates the discount:

SalesHeader.Validate("Document Date", DocumentDate);
SalesHeader.Validate("Currency Code");
if SalesHeader."Payment Terms Code" <> OldSalesHeader."Payment Terms Code" then begin
    SalesHeader."Payment Terms Code" := OldSalesHeader."Payment Terms Code";
    SalesHeader.Validate("Payment Terms Code", CustomerContract."Payment Terms Code");
end;

and the equivalent in CreatePurchaseHeaderFromContract using VendorContract."Payment Terms Code". The order matters: the payment terms trigger reads "Document Date", so this has to run after the document date is assigned.

Steps to reproduce
  1. Open Payment Terms and make sure two codes exist, e.g. "14 DAYS" with Discount % = 0, and "1M(8D)" with Discount % = 2 and a discount date calculation of 8D.
  2. Open a customer card, and on the Payments FastTab set Payment Terms Code = "14 DAYS".
  3. Create a Customer Subscription Contract for that customer, and on the Payments FastTab change Payment Terms Code to "1M(8D)".
  4. Add a subscription line to the contract and let it become billable.
  5. Run Create Billing Documents (or Create Contract Invoice) for the contract, with a document date different from the contract's creation date.
  6. Open the resulting sales invoice and look at the Invoice Details / Payments FastTab.

Result: Payment Terms Code is "1M(8D)" and Pmt. Discount Date is calculated from it, but Payment Discount % is 0.
Expected: Payment Discount % is 2.

Additional context

Related, same root cause in the same procedure: "Payment Method Code" is also copied by TransferFields without validation, so the payment method's balancing account and its direct-debit payment terms are not applied to the created document either. Happy to include that in the same fix if preferred, or to keep the change limited to the payment discount.

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.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.