🌍 Zonas de envio y restricciones geograficas
Actualizado: 2024-12-01
Las zonas de envio agrupan paises o regiones que comparten las mismas tarifas. Una buena estructura de zonas permite ofrecer precios competitivos para cada destino sin sobrecargar el checkout con demasiadas opciones.
#Zonas de envio
Gestionar zonas programaticamente
php
<?php
// ── Obtener todas las zonas activas ──
$zones = Zone::getZones(true); // true = solo activas
// [
// ['id_zone' => 1, 'name' => 'Europa'],
// ['id_zone' => 2, 'name' => 'Norteamerica'],
// ...
// ]
// ── Crear zona personalizada ──
$zone = new Zone();
$zone->name = 'Peninsula Iberica';
$zone->active = true;
$zone->add();
// ── Asignar pais a zona ──
$country = new Country(6); // 6 = España
$country->id_zone = $zone->id;
$country->update();
// ── Obtener zona de una direccion ──
$address = new Address($id_address);
$zone_id = Address::getZoneById($address->id);
// Usa el estado/provincia si existe, si no el pais
// ── En el calculo de envio, PS hace esto internamente ──
// 1. Obtiene la direccion de entrega del carrito
// 2. Busca la zona de esa direccion
// 3. Filtra transportistas que operan en esa zona
// 4. Calcula el coste segun el rango (peso/precio) y la zona
#Asignar paises a zonas
Asignar paises y estados a zonas
php
<?php
// ── Asignar todos los paises de la UE a una zona ──
$euCountries = ['ES', 'FR', 'DE', 'IT', 'PT', 'BE', 'NL', 'AT', 'IE', 'LU'];
foreach ($euCountries as $iso) {
$idCountry = Country::getByIso($iso);
if ($idCountry) {
$country = new Country($idCountry);
$country->id_zone = $zoneEuropa->id;
$country->update();
}
}
// ── Asignar estados/provincias a zonas diferentes ──
// Util para Espana: Peninsula vs Baleares vs Canarias
$states = State::getStatesByIdCountry(Country::getByIso('ES'));
foreach ($states as $state) {
$s = new State($state['id_state']);
// Canarias
if (in_array($s->iso_code, ['TF', 'GC'])) {
$s->id_zone = $zoneCanarias->id;
}
// Baleares
elseif ($s->iso_code === 'PM') {
$s->id_zone = $zoneBaleares->id;
}
// Peninsula
else {
$s->id_zone = $zonePeninsula->id;
}
$s->update();
}
// ── Verificar que el pais tiene estados activos ──
$country = new Country(Country::getByIso('ES'));
$country->contains_states = true;
$country->update();
#Zonas personalizadas para Espana
| Zona | Provincias/ISO | Tarifa tipica |
|---|---|---|
| Peninsula | Todas excepto TF, GC, PM, CE, ML | 4.95€ |
| Baleares | PM (Illes Balears) | 7.95€ |
| Canarias | TF (Tenerife), GC (Las Palmas) | 12.95€ + IGIC |
| Ceuta y Melilla | CE (Ceuta), ML (Melilla) | 14.95€ + IPSI |
| Portugal | PT | 6.95€ |
| Europa Zona 1 | FR, DE, IT, BE, NL, AT, LU | 9.95€ |
| Europa Zona 2 | UK, SE, DK, FI, PL, CZ, RO | 14.95€ |
#Rangos de peso y precio
Definir rangos de envio en el install() del modulo
php
<?php
// ── Crear un transportista con rangos por peso ──
$carrier = new Carrier();
$carrier->name = 'Correos Express';
$carrier->active = true;
$carrier->need_range = true; // Necesita rangos para calcular
$carrier->shipping_method = Carrier::SHIPPING_METHOD_WEIGHT; // Por peso
// Alternativa: Carrier::SHIPPING_METHOD_PRICE (por precio)
$carrier->range_behavior = Carrier::RANGE_BEHAVIOR_LARGEST_WEIGHT;
// Si el peso excede el rango mas alto: usar tarifa del rango mayor
// Alternativa: Carrier::RANGE_BEHAVIOR_DEACTIVATE (desactivar)
$carrier->add();
// ── Añadir rangos de peso ──
$ranges = [
['min' => 0, 'max' => 2],
['min' => 2, 'max' => 5],
['min' => 5, 'max' => 10],
['min' => 10, 'max' => 30],
];
foreach ($ranges as $r) {
$range = new RangeWeight();
$range->id_carrier = $carrier->id;
$range->delimiter1 = $r['min'];
$range->delimiter2 = $r['max'];
$range->add();
// Asignar precio por zona para este rango
$prices = [
$zonePeninsula->id => 4.95,
$zoneBaleares->id => 7.95,
$zoneCanarias->id => 12.95,
];
foreach ($prices as $zoneId => $price) {
Db::getInstance()->insert('delivery', [
'id_carrier' => $carrier->id,
'id_range_weight' => $range->id,
'id_zone' => $zoneId,
'price' => $price,
]);
}
}
#Restricciones por grupo y pais
Restringir transportistas
php
<?php
// ── Asignar transportista a grupos de clientes ──
// Por defecto, un transportista esta disponible para todos los grupos
// Para restringir:
Db::getInstance()->execute(
'DELETE FROM `' . _DB_PREFIX_ . 'carrier_group`
WHERE `id_carrier` = ' . (int) $carrier->id
);
// Asignar solo a grupo "Cliente" (id=3) y "Mayorista" (id=4)
foreach ([3, 4] as $groupId) {
Db::getInstance()->insert('carrier_group', [
'id_carrier' => $carrier->id,
'id_group' => $groupId,
]);
}
// ── Asignar transportista a zonas ──
$carrier->addZone($zonePeninsula->id);
$carrier->addZone($zoneBaleares->id);
// No añadir Canarias = este transportista no envia a Canarias
// ── En el BO se configura desde: ──
// Transporte → Transportistas → Editar → Paso 2 (destinos)
// Marcar/desmarcar zonas donde opera
// Modulos → Transportistas → Restricciones por grupo
// ── Hook para filtrar transportistas dinamicamente ──
public function hookActionCarrierProcess(array $params): void
{
// $params['cart'] contiene el carrito actual
// Puedes modificar la lista de transportistas disponibles
// basandote en el contenido del carrito, direccion, etc.
}
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.