I had to block store owners from editing orders in Commerce after they're completed. I used hook_entity_access(), or more specifically hook_ENTITY_TYPE_access(), with the type commerce_order.
I put this function in my module file. It gets the order state and checks if it is completed, and if the operation is update. If so, it returns \Drupal\Core\Access\AccessResult::forbidden(). You can see more available responses here: AccessResult.
/**
* Block access to order edit if state is completed.
*
* Implements hook_ENTITY_TYPE_access().
*/
function block_access_commerce_order_access(
\Drupal\Core\Entity\EntityInterface $entity,
$operation,
\Drupal\Core\Session\AccountInterface $account) {
$order = $entity;
$properties = $order->getState()->getProperties();
$state = $properties['value']->getValue();
if ($state === 'completed' && $operation === 'update') {
return \Drupal\Core\Access\AccessResult::forbidden();
}
}
This has the effect of showing access denied on the edit page and hiding the edit tab on the order.