Hola @inmahub64 y @manueldeco,
@manueldeco lo ha clavado. El problema no es tanto que Validate::isLoadedObject($cart) falle, sino que el $cart se construye de una manera que puede ser un objeto Cart vacío si el id_cart no existe en la base de datos, incluso si es un número válido. El constructor de Cart no valida la existencia al instanciar.
La solución es asegurarse de que, si se proporciona un id_cart, este no solo sea un número, sino que también corresponda a un objeto Cart cargado correctamente. Podrías modificar esa línea así para que el objeto $cart solo se cree si realmente existe un carrito con ese ID, o si no, usar el carrito de contexto:
function postProcess()
{
if (!$this->context->employee || !(int) $this->context->employee->id) {
$this->ajaxDie(json_encode(['success' => false, 'error' => 'Unauthorized']));
}
$idCart = (int) Tools::getValue('id_cart');
$cart = ($idCart > 0 && Validate::isLoadedObject(new Cart($idCart))) ? new Cart($idCart) : $this->context->cart;
if (!Validate::isLoadedObject($cart)) {
Con este cambio, solo se intentará cargar el new Cart($idCart) si idCart es positivo Y si ese ID de carrito existe y se puede cargar. Si no, se usará $this->context->cart como fallback. Esto debería solucionar los errores JSON por carritos no cargados.
Para una gestión más avanzada de reglas de envío y para no tener que tocar el código del módulo (lo cual no es ideal si vienen actualizaciones), te recomiendo echar un vistazo a soluciones dedicadas que te permitan ocultar transportistas en el carrito o aplicar tarifas condicionales de forma más robusta y sin overrides manuales.