Saltar a contenido

Relevamiento de la configuración de envíos (2026-09-15)

Foto de la configuración vigente y de sus inconsistencias, tomada sobre la base local de desarrollo (localhost:5432/medusa-store, 14 clientes y 150 pedidos, último pedido del 2026-09-14). No es la base de producción: antes de dar por buena esta foto hay que repetir las consultas del anexo contra producción. El diseño funcional está en RF-005 y RF-006; el paso a paso operativo en la guía de configuración de envíos.

1. Estructura vigente

Sólo hay un depósito activo y dos conjuntos de fulfillment colgados de él. Todo lo demás que aparece en la base (depósitos European Warehouse, Multiplaza y Suppliers, 5 conjuntos, 16 zonas y 21 opciones de envío) está borrado lógicamente entre el 2025-12-16 y el 2025-12-22: son restos de las pruebas de diciembre y no afectan al checkout.

Nivel Registro Detalle
Región Nacional (pyg) País py. Es la única que usa la tienda
Región Europe (eur) dk, fr, de, es, se, it, gb. Resto del seed de Medusa, ver §3
Depósito Casa Central Vinculado a los 4 sales channels (Compulandia, Online B2B, Default, Test)
Proveedores manual_manual, mc-group_mc-group Ambos habilitados y vinculados a Casa Central
Perfil de envío Default Shipping Profile Único perfil; los 17.605 productos lo usan
Conjunto Aviadores pick up (retiro) 1 zona: Gran Asunción (todo py)
Conjunto Aviadores shipping (envío) 6 zonas: Zona 0 a Zona 5; guarda los tipos de caja en su metadata

Retiro en sucursal (conjunto Aviadores pick up, zona Gran Asunción)

Opción Proveedor Precio Nota
Aviadores manual 0 Gs Disponible para cualquier ciudad del país
Multiplaza manual 0 Gs Ídem. El depósito Multiplaza fue borrado; la opción sigue colgada de Casa Central

Envío a domicilio (conjunto Aviadores shipping)

Zona Ciudades Opción Proveedor Precio
Zona 0 Areguá, Asunción, Benjamín Aceval, Capiatá Envio Local manual 29.000 Gs fijo
Zona 0 ídem Transportadora mc-group calculado por caja
Zona 1 Carapeguá, Carmen del Paraná, Coronel Bogado, Encarnación, Itá, Paraguarí, Quiindy Transportadora mc-group calculado
Zona 2 Altos, Atyra, Ayolas, Caazapá, Tobati Transportadora mc-group calculado
Zona 3 Arroyos y Esteros, Bella Vista Sur, Capiibary, Guarambaré, Ybycui Transportadora mc-group calculado
Zona 4 Alberdi, Fulgencio Yegros, Itacuá ninguna — sin envío (sólo retiro)
Zona 5 Colonia Obligado, Nueva Esperanza Transportadora mc-group calculado

Todas las opciones tienen las reglas enabled_in_store = true e is_return = false.

Tipos de caja (metadata de Aviadores shipping)

Código Lado máx. (cm) Peso máx. (kg)
caja_1 33 10
caja_2 40 10
caja_3 50 15
caja_4 58 20
caja_5 66 25
caja_6 75 25
caja_7 83 30
caja_default — — (marcada is_default, se usa cuando nada entra)

Tarifa de MC Group por zona y caja (Gs)

Caja Zona 0 Zona 1 Zona 2 Zona 3 Zona 5
caja_1 25.000 28.500 33.000 71.000 50.000
caja_2 25.000 28.500 45.000 88.000 60.000
caja_3 25.000 28.500 58.000 default 70.000
caja_4 28.000 28.500 default default 80.000
caja_5 default 55.000 default default 90.000
caja_6 default 60.000 default default 100.000
caja_7 default 70.000 default default 120.000
caja_default 55.000 99.000 86.000 120.000 150.000
Silla / Mesa Gamer (por unidad) 30.000 33.000 55.000 85.000 —

default = esa caja no tiene precio en la zona, así que el producto cae en caja_default.

De 17.682 productos publicados, 17.654 tienen largo, ancho, alto y peso cargados a nivel producto, en milímetros y gramos (ej. notebook 450×350×70 mm, 3.000 g; silla gamer 650×350×850 mm, 20.000 g), que es lo que asume el cálculo. Con las cajas actuales el catálogo se reparte así: caja_1 62 %, caja_3 21 %, caja_2 5 %, caja_4 a caja_7 6 %, caja_default 5 %.

2. Cómo se resuelve el envío en el checkout

  1. El cliente elige departamento y ciudad de una lista que sale de GET /store/geozones (las geozonas de tipo city). La dirección guarda el código de departamento en province (PY11) y el nombre de ciudad en city.
  2. Medusa filtra las opciones de envío cuya zona contenga una geozona que matchee país, provincia o ciudad de la dirección. Por eso las dos opciones de retiro (geozona country = py) aparecen siempre, y las de Transportadora sólo en las ciudades cargadas.
  3. Para la opción calculada, el storefront pide POST /store/shipping-options/:id/calculate. El provider mc-group busca la geozona por nombre de ciudad, comprueba mc_available, toma la opción MC de esa zona, calcula la caja del producto más voluminoso del carrito y suma las categorías especiales por unidad.
  4. Si el provider falla por cualquier motivo, el storefront muestra la opción deshabilitada con "-" y sin mensaje.

3. Inconsistencias detectadas

Ordenadas por impacto. "Rompe" = afecta hoy a un cliente; "deuda" = no rompe nada.

# Hallazgo Impacto Corrección propuesta
1 Sólo 27 ciudades en todo el país. Faltan San Lorenzo, Luque, Lambaré, Fernando de la Mora, Ñemby, Ciudad del Este, Villarrica, Coronel Oviedo, Pedro Juan Caballero… Rompe: el cliente de esas ciudades no puede elegir su ciudad, o la elige con "(sin envío)" y sólo puede retirar Necesita info: lista de cobertura y tarifa de MC Group por ciudad
2 Zona 4 (Alberdi, Fulgencio Yegros, Itacuá) sin opción de envío y con mc_available = false Rompe si era cobertura real; si es "sin cobertura" a propósito, la zona sobra Necesita info: confirmar con operaciones
3 Huecos en la tarifa: Zona 0 sin caja_5-7, Zona 2 sin caja_4-7, Zona 3 sin caja_3-7. El salto a caja_default es abrupto (Zona 0: 28.000 → 55.000; Zona 3: 88.000 → 120.000) Rompe: cobra de más a 1 de cada 10 productos en esas zonas Necesita info: tarifario completo de MC Group
4 Región Europe en euros con 7 países, y precios en euros en las opciones de retiro Deuda: no se ofrece en la tienda; ensucia el panel y la API de regiones. Hay 1 carrito viejo asociado, 0 pedidos Borrar la región desde el panel (Settings → Regions)
5 Provider CLX y AEX no existen; las geozonas y el formulario del admin igual guardan clx_available/aex_available Deuda hoy (todas en false salvo Zona 0 con clx_available = true, que no hace nada). Si alguien marca CLX en una ciudad sin MC, el checkout la muestra "con envío" y no hay opción Ocultar CLX/AEX del formulario hasta que exista el provider, o documentar que no se usan
6 city_code vacío en 7 ciudades y malformado en Colonia Obligado (PY01201) Deuda: el campo es informativo, nadie lo lee Completar o dejar de pedirlo en el formulario
7 El provider busca la geozona sólo por nombre de ciudad, ignorando departamento Deuda hoy (los 27 nombres son únicos). Rompe el día que se carguen dos ciudades homónimas en distinto departamento (ej. San Juan Bautista, San Pedro, Santa Rosa) Cambiar findGeoZoneByCity para filtrar también por province_code
8 Sin dimensiones el código usa la caja más chica (boxTypes[0]), no la is_default; RF-005 dice lo contrario Deuda: 28 productos publicados sin dimensiones pagan caja_1 Alinear el código con RF-005 o corregir el RF
9 Opción de retiro Multiplaza colgada del depósito Casa Central, que ya no tiene un depósito Multiplaza Deuda: funciona, pero el pedido nace como "retiro en Multiplaza" con stock de Casa Central Decidir si Multiplaza vuelve a ser depósito o si la opción se renombra
10 Errores del provider (CITY_NOT_FOUND, MC_NOT_AVAILABLE, MISSING_PRICES…) llegan al cliente como "-" Deuda: no se distingue "sin cobertura" de "falla del sistema" Mostrar un mensaje según el error
11 El callout de docs/analisis/widgets-admin-envios.md dice que los widgets no existen en las ramas publicadas; hoy sí existen en el working tree Deuda documental Quitar el callout al commitear

Detalles técnicos del código (hardcodeo de mc-group_mc-group, escritura por SQL crudo a la metadata, hooks del admin sin uso, logs verbosos en cada cálculo) están en las limitaciones conocidas de RF-005 y RF-006 y no se repiten aquí.

Anexo: consultas usadas

-- zonas y ciudades vigentes
select sz.name zona, gz.city, gz.province_code, gz.metadata
from geo_zone gz join service_zone sz on sz.id = gz.service_zone_id
where gz.deleted_at is null and sz.deleted_at is null order by 1, 2;

-- opciones vigentes con su tarifa
select so.name, sz.name zona, so.price_type, so.provider_id, so.metadata
from shipping_option so join service_zone sz on sz.id = so.service_zone_id
where so.deleted_at is null and sz.deleted_at is null order by 2, 1;

-- precios fijos
select so.name, p.currency_code, p.amount
from shipping_option so
join shipping_option_price_set l on l.shipping_option_id = so.id
join price p on p.price_set_id = l.price_set_id and p.deleted_at is null
where so.deleted_at is null;

-- tipos de caja
select metadata from fulfillment_set where name = 'Aviadores shipping';