Skip to content

[EPIC] Logística de transporte: actores, capacidad y expediciones #103

Description

@vgpastor

Estado (jun 2026): la base #104#108 ✅ completada y en producción (actor transportista, TransportCapacity, Shipment, matching capacidad↔traslado y scope DAG hub/corredor) — backend y frontend. En curso → Fase 5: la carga adopta el modelo de insumos de #131 y gana empaquetado rastreable (#140#143, ver abajo).

🎯 Objetivo

Modelar de forma genérica y escalable la oferta y ejecución de transporte de la ayuda: quién transporta (ciudadano con vehículo, operador logístico, naviera, aerolínea…), qué capacidad ofrece (de un punto a otro, en toneladas/volumen, en una ventana) y el trabajo de mover la carga (expedición de un nodo a otro, con seguimiento y manifiesto). El ciudadano con su vehículo (ya cubierto vía volunteers) es el caso más simple; operadores logísticos / navieras / aerolíneas son el extremo transversal multi-emergencia.

Origen (feedback de campo): un vecino ofrece "si alguien tiene donaciones y no tiene cómo trasladarlas al hospital central de Valencia, mi camioneta está a la orden". Extrapolando: "¿y si mañana una aerolínea nos ofrece X toneladas de carga de un punto a otro, o una naviera, o más gente con motos, coches…?". Hace falta un modelo de transportista/capacidad que no sea un parche por tipo de vehículo.

Concepto clave: no es un "transportista", son tres capas que conviene no mezclar — (1) QUIÉN transporta (un Principal: voluntario u organización, con un rol), (2) QUÉ capacidad ofrece (oferta de servicio logístico, distinta de la oferta de material DonationOffer), y (3) EL TRABAJO (la expedición/Shipment que mueve ítems de un nodo a otro). El "quién" se queda polimórfico; lo que se construye de primera clase es la capacidad y la expedición.

🧱 Enfoque técnico

Casi todo el roadmap logístico es configuración, no reingeniería — ya está probado en docs/features/13-roles-permisos-y-autenticacion.md §16 ("Prueba de escalabilidad: actores logísticos transversales — navieras, aerolíneas, hubs, aduanas"):

  • QUIÉN (data): ciudadano = Volunteer con vehicle (none/car/van/truck, ya existe). Empresa = Organization con nuevo OrganizationType.transport_operator genérico (el modo aéreo/marítimo/carretera vive en la capacidad Capacidad de transporte (TransportCapacity): oferta de servicio logístico #105, no en el tipo de org; hoy solo ngo/company/public_admin/association/other) + acreditación global (ya existe) + rol logístico del catálogo (transportista/hub_manager). Integración por API = ServiceAccount + API key (ya diseñado, §8).
  • QUÉ (nuevo): agregado TransportCapacity (oferta de servicio): proveedor (Volunteer|Organization), modo (carretera/marítimo/aéreo), capacidad (peso/volumen), corredor (origen→destino o área), ventana temporal, restricciones (refrigerado…). No es DonationOffer (eso es material).
  • EL TRABAJO (nuevo, Fase 4): agregado Shipment/expedición: mover ítems de un resource (origen) a otro (destino), estados planned→assigned→in_transit→delivered/failed, manifiesto. Generaliza el ciclo de entrega de F07 (docs/features/07) y encaja con traslados/recepciones del EPIC de inventario.
  • Autorización transversal (único endurecimiento): una naviera/hub cruza emergencias; se resuelve con scope = DAG de tipos abiertos (hub/corridor), ya previsto en §3.2/§3.3/§16.3.

📦 Incluye (sub-issues)

Fase base — ✅ completada y desplegada:

📦 Fase 5 — Carga estructurada: insumos (#131) + empaquetado rastreable

Tras cerrar #104#108, la logística adopta el modelo de insumos unificado de #131 (SupplyLine / Category) y gana una capa de empaquetado rastreable (palet/caja/lote). Decisiones PM: (1) agregado rastreable (identidad propia, se mueve entre hubs/expediciones, reutilizable como inventario), no un VO embebido; (2) vive en el contexto supplies (reutilizable por inventario y logística); (3) reusa SupplyLine. Realiza el sub-punto "cajas/lotes (agregado Box/Lote)" del EPIC de inventario #1 (UI en #14).

✅ #131  supplies (SupplyLine / Category)      ── base (en main)
      │
      ▼
   #140  Container rastreable (en supplies)    ── arrancable ya
      │
      ▼
   #141  Shipment usa SupplyLine + Containers
      ├──────▼  #142  Matching por carga real (peso/volumen)
      └──────▼  #143  Frontends (empaquetar + expedir desde contenedores)

🔢 Secuencia / dependencias

#104  Actor (orgs + roles)        ┐
#108  Scope DAG hub/corredor      ┤  independientes — arrancables ya
#105  TransportCapacity (núcleo)  ┤  monta el contexto `logistics`
#106  Shipment (núcleo)           ┘  coordina scaffolding con #105; se apoya en #108
                 │
                 ▼
#107  Matching capacidad ↔ traslado   ← bloqueado por #105 + #106

Decisiones zanjadas (pendientes de confirmar por PM):

  1. Contexto logistics propio (no dentro de offers) — no contaminar el agregado material.
  2. OrganizationType.transport_operator genérico + mode en la capacidad (no un enum por aerolínea/naviera; se añaden como data si hace falta filtrar/marcar).
  3. Shipment único con carrier opcional — el traslado interno es un Shipment sin transportista externo.

✅ Criterios de aceptación

  • Un ciudadano con vehículo y un operador logístico/naviera/aerolínea se modelan con el mismo núcleo (capacidad + expedición), sin un tipo "transportista" ad-hoc; el "quién" es un Principal polimórfico.
  • Añadir un tipo de operador o un rol logístico no toca el núcleo de autorización (es data del catálogo/enum).
  • Una capacidad ("X t de A a B en tal ventana") se puede publicar, casar con un traslado necesario y seguir hasta delivered.
  • Un operador puede ver/operar carga que cruza varias emergencias vía scope hub/corridor, sin ser coordinador de ninguna.

🔗 Relacionado

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions