Hola @martabici y @antonioonline.
@antonioonline tiene razón, el core de PrestaShop, especialmente en la rama 1.7.x (incluyendo la 1.7.6.0), no está preparado de fábrica para gestionar múltiples envíos desde un único carrito de forma nativa. La arquitectura del Cart y Order se basa en un id_carrier principal para todo el pedido o, como mucho, por id_address_delivery si tienes la multi-dirección activada, pero no a nivel de producto o de grupo de productos dentro de una misma dirección.
Tu intento de extender Cart añadiendo $product_carrier_ids es un buen punto de partida para pensar en cómo almacenar esa información, pero como se menciona, el ORM de PrestaShop no persistirá esa propiedad a menos que la definas en $definition['fields'] y tengas una columna para ello, probablemente serializada. Además, incluso si guardaras esa información, el OrderController y el OrderManager seguirían esperando un único id_carrier para la creación de la orden.
Para que PrestaShop realmente maneje envíos separados, no basta con una simple modificación del Cart. Se requiere una lógica compleja que intercepta el proceso de pedido, posiblemente duplicando el Cart original en varios Cart temporales (uno por envío) y luego creando múltiples Order o OrderSlip en función de esos sub-carritos. Esto implica trabajar con hooks como actionValidateOrder o sobrescribir el OrderController o incluso classes/order/Order.php, lo cual es propenso a errores y muy difícil de mantener con las actualizaciones del sistema.
Por ejemplo, para intentar inyectar la lógica de selección de transportistas por producto, tendrías que ir mucho más allá, quizás en un hookActionCarrierProcess o similar, pero la aplicación final al objeto Order seguiría siendo un problema:
// Ejemplo simplificado y conceptual de un hook en un módulo, no una solución completa
public function hookActionCarrierProcess($params)
{
$cart = $params['cart'];
$products_in_cart = $cart->getProducts();
$carriers_for_shipments = [];
foreach ($products_in_cart as $product) {
// Aquí iría la lógica para determinar el transportista ideal para este producto
// Esto es un placeholder, la lógica real es compleja y necesita de bases de datos
$carrier_id_for_product = $this->getSpecificCarrierForProduct($product['id_product'], $cart->id_address_delivery);
Como ves, es una tarea que fácilmente puede llevar cientos de horas de desarrollo y mantenimiento. Dada la complejidad y los riesgos de estabilidad, para una tienda en producción mi recomendación es definitivamente utilizar un módulo preparado para dividir el carrito. Estos módulos están diseñados específicamente para manejar toda esa lógica de backend, incluyendo la creación de múltiples OrderCarrier y la gestión de la visibilidad en el back office, de forma más robusta y compatible con futuras actualizaciones.