Sin impuesto Con impuesto

Cambiar el estado de un pedido desde un módulo sin romper nada

Un compañero cambiaba el estado de los pedidos de su módulo de pago escribiendo en la tabla orders, y el correo y los procesos del estado no se lanzaban. La solución fue usar changeIdOrderState y addWithemail de OrderHistory. Explicamos qué hace cada uno y tres detalles que evitan pagos y correos duplicados.

Equipo Rekire
Actualizado: 09/05/2025 7
Cambiar el estado de un pedido desde un módulo sin romper nada
Compartir:

Un compañero estaba terminando un módulo de pago por enlace. Cuando la pasarela respondía «pago correcto», el pedido cambiaba de estado en el listado, pero no salía el correo al cliente ni pasaba nada de lo asociado a «Pago aceptado». El motivo: cambiaba el estado escribiendo directamente en la tabla orders. La solución fue usar los métodos de OrderHistory, que son los que lanzan todo lo demás.

Lo que no hay que hacer

Su primera versión hacía esto (resumido):

Db::getInstance()->update('orders', [
    'current_state' => $newState,
    'date_upd' => date('Y-m-d H:i:s'),
], 'id_order = ' . (int) $order->id);

$history = new OrderHistory();
$history->id_order = (int) $order->id;
$history->id_order_state = $newState;
$history->add(true);

Así el pedido parece pagado, pero te saltas lo que PrestaShop hace al cambiar de estado: los hooks que escuchan otros módulos (el ERP, el transportista, las alertas), el registro del pago, la factura si el estado la genera y el correo del estado. En el listado está bien; en todo lo demás, no.

Lo que funcionó

Otro miembro del grupo le sugirió changeIdOrderState(). Su segundo intento tampoco iba: metía changeIdOrderState() dentro de un if, pero ese método no devuelve nada, así que la condición nunca se cumplía y el historial no llegaba a guardarse. La versión buena sigue este orden: recargar el pedido, cambiar el estado con changeIdOrderState() y guardar el historial con addWithemail(). Este es el patrón, limpio:

$order = new Order((int) $idOrder);
$newState = (int) Configuration::get('MIMODULO_ESTADO_PAGADO');

if (!Validate::isLoadedObject($order) || $newState <= 0) {
    PrestaShopLogger::addLog('MiModulo: pedido o estado no válidos', 3);
    return false;
}

// Si ya está en ese estado, no lo repitas
if ((int) $order->getCurrentState() === $newState) {
    return true;
}

$history = new OrderHistory();
$history->id_order = (int) $order->id;
$history->id_employee = 0; // cambio automático, sin empleado
$history->changeIdOrderState($newState, $order, !$order->hasInvoice());
$history->addWithemail();

El tercer parámetro reaprovecha el pago ya registrado si el pedido aún no tiene factura; es lo mismo que hace el núcleo en Order::setCurrentState(). Pruébalo antes en una copia de la tienda.

  • changeIdOrderState() aplica el estado nuevo, hace lo que ese estado tenga configurado (pago, factura, stock) y lanza los hooks de cambio de estado.
  • addWithemail() guarda la línea del historial y envía el correo si el estado tiene plantilla.

Si no necesitas nada especial, $order->setCurrentState($newState) hace esas dos cosas en una sola llamada.

Tres detalles que evitan sustos

  1. Comprueba el estado actual antes de cambiarlo. Las pasarelas pueden notificar dos veces. Sin esa comprobación, el cliente recibe dos correos y el pedido puede acumular dos pagos.
  2. No inventes el estado si falta la configuración. El compañero usaba el id 2 si el estado no estaba configurado. Los id pueden cambiar entre tiendas; es más seguro registrar el error y no tocar el pedido.
  3. Registra cada paso con PrestaShopLogger::addLog(). Cuando un pago no cuadre, ese registro es lo único que tendrás para saber qué pasó.

¿Para qué versión?

El módulo del hilo era para PrestaShop 1.6, pero OrderHistory::changeIdOrderState(), addWithemail() y Order::setCurrentState() siguen en 1.7, 8 y 9. Para crear el pedido desde un módulo de pago se usa validateOrder(); esto es para los cambios posteriores.

Cómo comprobar que lo has hecho bien

  • En la ficha del pedido, el historial muestra una línea nueva con el estado y sin empleado asignado.
  • El cliente recibe el correo del estado, si ese estado tiene plantilla. Si no llega, mira el registro de correos antes de tocar el código.
  • Si el estado genera factura, el pedido tiene factura y el pago aparece registrado.
  • Los módulos que dependen del cambio de estado (el que avisa al almacén, el del ERP) reaccionan igual que cuando lo cambias a mano desde el back-office. Esa es la prueba definitiva.
  • Lanza la misma notificación dos veces seguidas: el pedido no debe cambiar ni enviar nada la segunda vez.

Si lo que te preocupa son los pedidos duplicados o los estados de pago repetidos, en Rekire tenemos Order Guard, que los evita.

Esto salió en @PrestashopEsp, la mayor comunidad PrestaShop de España en Telegram. Ver la conversación

Cargando...
Cookies
Volver arriba