Loading

Cancel or Post Invoice Lines in Draft status while Invoice is in 'Posted' status

Udgivelsesdato: Sep 27, 2025
Beskrivelse
Under certain conditions, an invoice can post with the invoice lines remaining in Draft status. When this happens, the order products are not updated and are not available to create another invoice. The order is effectively stuck. Learn how to recover from this situation and how to maintain data integrity.

Posting an Invoice touches at least four objects. It is possible to experience an invoice being posted and the invoice lines remain in Draft status when combinations of custom validations and/or automation result in the process failing without completing. This invoice is now in a state where Cancel and Rebill does not work, and the invoice lines can not be posted separately. Since the status of the Invoice Lines control the updating of the related Order Product, this invoice must be fixed before additional invoices can be created from the order.

Note that Salesforce Billing has validations that prevent changing the Invoice Status from posted or to post the invoice lines separately. This is by design. 
 
When the Invoice Line posts, the following fields on the Order Product are updated:
  • Invoice Run Processing Status moves from In Progress to Pending Billing or Completed
  • Next Billing Date, Next Charge Date and Last Charge To Date are updated for the next period
  • Billing Metrics fields such as Billed Amount (without tax), Pending Billing Amount (without tax), Billed Tax, and Total Billings are calculated
Løsning

The only way to fix this while preserving data integrity is to update the Invoice Status from Posted to Draft and set the Invoice Posted Date field to null with the Billing triggers off. This can be done with the package settings, but is better done through anonymous apex using the global Apex API TriggerControl to manually disable CPQ and Billing triggers.  

Following is a sample code to do this. Please verify in sandbox before using in production. Replace <record id of invoice> with the record id of the invoice. 

List<blng__Invoice__c> invoice2Update = new list<blng__Invoice__c>();
for(blng__Invoice__c inv : [SELECT id, blng__InvoiceStatus__c from blng__Invoice__c 
               WHERE id = '<record id of invoice>' and blng__InvoiceStatus__c = 'Posted' LIMIT 1 ]){

inv.blng__InvoiceStatus__c = 'Draft';
inv.blng__InvoicePostedDate__c = null;
invoice2Update.add(inv);
}
try {
    SBQQ.TriggerControl.disable();
    update invoice2Update;
    SBQQ.TriggerControl.enable();
} catch (DmlException e) {
   System.debug(e);
}

NOTE: Do not update the Status field on the Invoice Line with the triggers disabled. This can cause data integrity problems and may result in future incorrect invoice lines for that order product. One exception to this is updating invoice lines from Draft to Cancelled after using Clean Up on an invoice run. This is a valid change as long as the Invoice successfully had the status change to Cancelled.
Vidensartikelnummer

000380799

 
Indlæser
Salesforce Help | Article