OnOrderInvoiceCancelled
This hook runs after an actor message has transitioned one or more of the order's invoices to cancelled. It is the right place to react to reversed invoicing activity, such as voiding the corresponding document in an external accounting system or notifying the customer that an invoice no longer applies.
An invoice is cancelled either by the cancelInvoice order command, or by rewinding the order to a checkpoint that predates the invoice. Because invoices are never removed from an order — only cancelled — both paths produce the same transition and fire this hook. Apps therefore don't need to know anything about checkpoints to stay consistent with the order.
Firing semantics
The hook fires once per actor message that cancelled invoices, regardless of how many were cancelled during that message. The invoices field carries only the invoices whose isCancelled flipped false → true in this message; invoices that were already cancelled before the message never fire again. All invoices on the order, cancelled or not, can be accessed through order.invoices.
State is already committed when this hook runs, so it cannot change the order. Returning orderCommand or validationError effects has no effect and produces a warning in the application logs.
Re-activation is not a creation
Rewinding forward — to a checkpoint after an earlier rewind — can flip an invoice back to isCancelled = false. This re-activation fires neither OnOrderInvoiceCancelled nor OnOrderInvoiceCreated. See the note on the OnOrderInvoiceCreated page.
Type
{
hook: 'OnOrderInvoiceCancelled'
order: Order // The order, including the cancelled invoices
invoices: [Invoice] // Only the invoices that were cancelled in this message
}