Jump to content

Calculador de gastos de envío


Recommended Posts

Estoy intentando hacer en el carrito un calculador de los gastos de envío, en principio los gastos de envío van según el peso del envío, transportista y zona, pero además tengo un módulo llamado 'advanced shipping cost' (orderfees_shipping en la carpeta modules) al que puedes arreglar excepciones. no se si alguien lo ha usado alguna vez.
De momento con un ajax envío a la función public function hookActionCartGetPackageShippingCost(&$params)
Los parámetros que necesita que entre otros coge el carrito para acceder a varias cosas como los pesos o las direcciones, como quiero hacer calcular el envío, el formulario te permite poner un pais, provincia y codigo postal al darle enviar actualiza una dirección creada aposta para esto y falsea el carro cambiando el id_address_delivery y id_address_invoice por la dirección creada para esta función, este sería el ajax:

 

<?php
// Incluye el entorno de Prestashop
include(dirname(__FILE__) . '/../config/config.inc.php');
include(dirname(__FILE__) . '/../init.php');

header('Content-Type: application/json');

// Obtener valores

$id_country = Tools::getValue('id_country');
$id_state = Tools::getValue('id_state');
$postal = Tools::getValue('postal');
$id_cart = Tools::getValue('id_cart');

if (!$id_country || !$id_state || !$postal || !$id_cart) {
    echo json_encode([]);
    exit;
}

//actualizar la dirección falsa
$sql = 'UPDATE `' . _DB_PREFIX_ . 'address`
SET `id_country` = ' . $id_country . ',
`id_state` = '. $id_state .',
`postcode` = '. $postal .'
WHERE  `id_address` = 1';

Db::getInstance()->execute($sql);


//Obtener carrito
$cart = new Cart((int) $id_cart);

//falsear Carrito
$cart->id_address_delivery = '1';
$cart->id_address_invoice = '1';

//calcular id_zone

$id_zone = $provinces = State::getIdZone((int)$id_country);

/* CONSTRUIR PARAMETROS */
$params = [
    'use_tax' => true,
    'id_carrier' => 169,
    'default_country' => null,
    'keepOrderPrices' => false,
    'total' => 0,
    'return' => false,
    'altern' => 1,
    'product_list' => null,
    'cart' => $cart,
    'object' => $cart,
    'id_zone' => $id_zone,
    'custom' => true
];

// Obtener costo de envío
$result = Hook::exec('actionCartGetPackageShippingCost', $params);

// Si no hay resultado, maneja el caso
if ($result === null ) {
    $result = ['error' => 'No se pudo calcular el costo de envío'];
}

// Devuelve el resultado como JSON
echo json_encode(['shipping_cost' => $result]);
exit;

y esto según la lógica debería funcionar, pero en la función a la que llama para comprobar el precio, primero lista todas las reglas y luego las recorre una a una para comprobar si el carro coincide con ella "hace un check" y si es false pasa a la siguiente, el problema es que me está haciendo false en todas, incluso en reglas que deberían saltar y no entiendo porqué, es en esta parte:
 

            if($custom){
                $shipping_rule_checked = $shipping_rule->checkCustom($object);
            }else{
                $shipping_rule_checked = $shipping_rule->check();
            }
            
            
            self::$disable_calculation = false;
                
            if (!$shipping_rule_checked) {
                continue;
            }

al principio pensaba que era porque en $shipping_rule->check() cogía el carro del $context, por eso se lo paso como $object en la función checkCustom que entra cuando viene del ajax, pero sigue sin funcionar, alguien puede ayudar?

Link to comment
Share on other sites

he hecho algunos cambios este es el aspecto de mi ajax actual:
 

<?php
// Incluye el entorno de Prestashop
include(dirname(__FILE__) . '/../config/config.inc.php');
include(dirname(__FILE__) . '/../init.php');

header('Content-Type: application/json');

// Obtener valores

$id_country = Tools::getValue('id_country');
$id_state = Tools::getValue('id_state');
$postal = Tools::getValue('postal');
$id_cart = Tools::getValue('id_cart');
$delivery_by_truck = Tools::getValue('weight') >= 15 ? true : false ;

if (!$id_country || !$id_state || !$postal || !$id_cart) {
    echo json_encode([]);
    exit;
}

//actualizar la dirección falsa
$sql = 'UPDATE `' . _DB_PREFIX_ . 'address`
SET `id_country` = ' . $id_country . ',
`id_state` = '. $id_state .',
`postcode` = '. $postal .'
WHERE  `id_address` = 1';

Db::getInstance()->execute($sql);


//Obtener carrito
$cart = new Cart((int) $id_cart);


//Obtener carrier
$correos = 167;
$correos_internacional = 158;
$camion = 168;
$camion_internacional = 169;
$delivery_by_truck = Tools::getValue('weight') >= 15 ? true : false ;

$id_carrier = $delivery_by_truck ? $camion_internacional : $correos_internacional;

if ($id_country == 6) {//Envío en españa
    $id_carrier = $delivery_by_truck ? $camion : $correos;
}

//falsear Carrito
$cart->id_carrier = ''.$id_carrier.'';
$cart->id_address_delivery = '1';
$cart->id_address_invoice = '1';
$cart->id_customer = '2';
$cart->delivery_option = '{"1":"'.$id_carrier.'"}';

$object = $cart;
//calcular id_zone

$id_zone = $provinces = State::getIdZone((int)$id_state);

/* CONSTRUIR PARAMETROS */
static $cache = [];
$total = 0;
$return = false;
$use_tax = true;
$default_country = null;
$keepOrderPrices = false;
$product_list = null;
Hook::exec('actionCartGetPackageShippingCost', [
    'object' => &$object,
    'id_carrier' => &$id_carrier,
    'use_tax' => &$use_tax,
    'default_country' => &$default_country,
    'product_list' => &$product_list,
    'id_zone' => &$id_zone,
    'keepOrderPrices' => &$keepOrderPrices,
    'total' => &$total,
    'return' => &$return,
    'custom' => true
]);


if ($return) {
    $result = ($total !== false ? (float) Tools::ps_round((float) $total, 2) : false);
} else {
    $shipping_cost = $cart->getParentPackageShippingCost(
        $id_carrier,
        $use_tax,
        $default_country,
        $product_list,
        $id_zone,
        $keepOrderPrices
    );
    if ($shipping_cost !== false) {
        $result = $shipping_cost + (float) Tools::ps_round((float) $total, 2);
    }

}


// Si no hay resultado, maneja el caso
if ($result === null ) {
    $result = ['error' => 'No se pudo calcular el costo de envío'];
}

// Devuelve el resultado como JSON
echo json_encode([
    'shipping_cost' => $result,
]);
exit;


me pasa lo siguiente si tengo la dirección guardada en la sesión, me va perfectamente, pero si lo hago hago sin una dirección en la sesión entonces el calculo aunque es muy apróximado no es exacto y no lo entiendo ya que tanto con dirección como si no, los parámetros que envío son los mismos, el carrito sería el mismo, pero lo que me devuelve la función es un resultado distinto, tanto en la función que saca el valor que añade el módulo como en la que recibe el coste de envío normal, recibo 2 cantidades distintas, envíando los mismos parámetros, lo que me hace pensar que al guardar una dirección debe de haber una variable que se me está pasando 

Link to comment
Share on other sites

Insisto en lo anterior, sigue las recomendaciones de la documentación de Prestashop para hacerlo desde un método ajax de controller. Esa implementación no es la mas segura, ni funcional .

Link to comment
Share on other sites

hace 18 horas, ventura dijo:

Insisto en lo anterior, sigue las recomendaciones de la documentación de Prestashop para hacerlo desde un método ajax de controller. Esa implementación no es la mas segura, ni funcional .

No se de que me hablas, he encontrado el error, es por tema del impuesto, porque aplica el iva del país que tiene en sesión en el carrito, así que lo que he hecho al final es traerme el precio sin impuesto y le cargo el del país que se selecciona. Ahora funciona perfectamente

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...