💰 Calculo de tarifas de envio — peso, precio y reglas
Actualizado: 2024-12-01
Un modulo de transportista debe implementar getOrderShippingCost() y/o getOrderShippingCostExternal(). PrestaShop llama a estos metodos para calcular el coste de envio durante el checkout.
#getOrderShippingCost() — implementacion
Implementar getOrderShippingCost() en el modulo
php
<?php
class MyCarrierModule extends CarrierModule
{
/**
* Calcula el coste de envio usando los rangos definidos en el BO.
*
* @param Cart $params El carrito actual
* @param float $shipping_cost Coste calculado por PrestaShop (rangos del BO)
* @return float|bool El coste final, o false si no aplica
*/
public function getOrderShippingCost($params, $shipping_cost)
{
// $shipping_cost ya viene calculado por PS segun los rangos del BO
// Podemos modificarlo o simplemente devolverlo
if ($shipping_cost === false) {
return false; // Fuera de rango → no disponible
}
// Ejemplo: aplicar un recargo por entrega en domicilio
$extraCharge = (float) Configuration::get('MYCARRIER_EXTRA');
return (float) $shipping_cost + $extraCharge;
}
/**
* Calcula el coste con logica completamente propia (ignora rangos del BO).
* Se usa cuando la tarifa viene de una API externa.
*
* @param Cart $params El carrito actual
* @return float|bool
*/
public function getOrderShippingCostExternal($params)
{
$cart = $params; // $params es el objeto Cart
$weight = (float) $cart->getTotalWeight();
$total = (float) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
// Llamada a API externa para obtener la tarifa
$rate = $this->fetchRateFromApi($weight, $total, $cart->id_address_delivery);
return $rate !== null ? (float) $rate : false;
}
}
#Calcular por peso
Logica de calculo por peso sin usar rangos del BO
php
<?php
private function calculateByWeight(Cart $cart): float
{
$weight = (float) $cart->getTotalWeight(); // en kg por defecto
// Tarifa escalonada por peso
$rates = [
['max' => 1.0, 'price' => 3.99],
['max' => 5.0, 'price' => 5.99],
['max' => 10.0, 'price' => 7.99],
['max' => 20.0, 'price' => 9.99],
['max' => PHP_FLOAT_MAX, 'price' => 14.99], // >20kg
];
foreach ($rates as $rate) {
if ($weight <= $rate['max']) {
return (float) $rate['price'];
}
}
return false; // No deberia llegar aqui por el ultimo catch-all
}
// ── Obtener peso del carrito ──
$weight = $cart->getTotalWeight(); // Total en unidad del sistema
$products = $cart->getProducts();
foreach ($products as $product) {
// $product['weight'] = peso unitario
// $product['cart_quantity'] = cantidad
$lineWeight = (float) $product['weight'] * (int) $product['cart_quantity'];
}
#Calcular por importe del pedido
Envio gratuito a partir de un importe minimo
php
<?php
private function calculateByOrderTotal(Cart $cart): float
{
// Importe sin impuestos ni envio
$total = (float) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
$freeShippingThreshold = (float) Configuration::get('MYCARRIER_FREE_FROM');
$baseRate = (float) Configuration::get('MYCARRIER_BASE_RATE');
// Envio gratis a partir del umbral
if ($freeShippingThreshold > 0 && $total >= $freeShippingThreshold) {
return 0.0;
}
// Tarifa porcentual sobre el pedido
$percentageRate = (float) Configuration::get('MYCARRIER_PERCENT_RATE');
if ($percentageRate > 0) {
return round($total * $percentageRate / 100, 2);
}
return $baseRate;
}
#Rangos y zonas en el BO
Si usas getOrderShippingCost() (sin External), PrestaShop aplica los rangos configurados en el BO (Transporte > Transportistas > Editar > Rangos de precio/peso) antes de llamar al modulo. El valor $shipping_cost que recibe el metodo ya tiene la tarifa calculada segun esos rangos.
Configurar rangos de peso al instalar el transportista
php
<?php
// En install() del modulo, crear rangos de peso automaticamente:
private function createWeightRanges(int $idCarrier): void
{
$ranges = [
['delimiter1' => 0, 'delimiter2' => 1],
['delimiter1' => 1, 'delimiter2' => 5],
['delimiter1' => 5, 'delimiter2' => 10],
['delimiter1' => 10, 'delimiter2' => 20],
];
foreach ($ranges as $rangeData) {
$range = new RangeWeight();
$range->id_carrier = $idCarrier;
$range->delimiter1 = $rangeData['delimiter1'];
$range->delimiter2 = $rangeData['delimiter2'];
$range->add();
}
}
#Tarifas dinamicas via API externa
Obtener tarifa de API externa con cache
php
<?php
private function fetchRateFromApi(float $weight, float $total, int $idAddress): ?float
{
// Cache por session para no llamar a la API en cada renderizado
$cacheKey = 'mycarrier_rate_' . $idAddress . '_' . round($weight, 2);
if (Cache::isStored($cacheKey)) {
return (float) Cache::retrieve($cacheKey);
}
$address = new Address($idAddress);
$country = new Country($address->id_country);
try {
$response = file_get_contents(
'https://api.mycarrier.com/rate?'
. http_build_query([
'weight' => $weight,
'country' => $country->iso_code,
'postal' => $address->postcode,
'api_key' => Configuration::get('MYCARRIER_API_KEY'),
])
);
$data = json_decode($response, true);
$rate = (float) ($data['price'] ?? 0);
Cache::store($cacheKey, $rate, 300); // Cache 5 minutos
return $rate;
} catch (\Exception $e) {
PrestaShopLogger::addLog(
'MyCarrier API error: ' . $e->getMessage(),
3, null, 'MyCarrierModule'
);
return null;
}
}
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.