Change record status: 
Project: 
Introduced in branch: 
8.x-2.x
Introduced in version: 
8.x-2.10
Description: 

Orders now have a total_paid field (with getTotalPaid() and setTotalPaid() methods), which is used by getBalance() to calculate the order balance (total_price - total_paid).

Sites can potentially have too many orders to be feasible for an update hook to resave, so there is no update hook, all existing orders have a total_paid of "0". Adding or refunding a payment for an existing order will rebuild the total_paid field.
Developers can use the commerce_payment.order_manager service to update orders without having to modify payments:

$order_storage = \Drupal::entityTypeManager()->getStorage('commerce_order');
// Load all placed orders.
$order_query = $order_storage->getQuery();
$order_query->condition('state', 'draft', '<>');
$order_ids = $order_query->execute();
$orders = $order_storage->loadMultiple($order_ids);

$payment_order_manager = \Drupal::service('commerce_payment.order_manager');
foreach ($orders as $order) {
  $payment_order_manager->updateTotalPaid($order);
}

An OrderEvents::ORDER_PAID event is dispatched the first time an order is paid in full (balance reaches zero).
This event is guaranteed to run once (refunding a payment then adding a new one won't re-trigger it).

Impacts: 
Site builders, administrators, editors
Module developers