propuesta · sep 2026 · r3
Admin · Fletes FCL · multicontenedor y multiproveedor

¿Cuántos proveedores? ¿Cuántos contenedores? De un vistazo.

Un cliente pide ocho contenedores a tres fábricas, una naviera, un BL y una sola factura. El admin de hoy sabe de un contenedor por flete, un equipo por flete, la naviera como texto libre y ninguna relación entre la orden y su proveedor. La propuesta: el alta entiende 8x40HQ, los números se pegan en bloque, la naviera es un catálogo, y los dos contadores viven en la cabecera de cada flete.

Notación
6x40HQ + 2x20
Contenedores por flete
1 → N
BL · factura
1 para todos
Fases
1 · 2 · 3 (4 opcional)
Base
development · fe12d13c9

01Hoy: un contenedor, un equipo, una naviera escrita a mano

evidencia · plan §1–§2

El FCL v1 (PRs #618 a #624) hizo bien una cosa: un contenedor exclusivo por flete, con reserva, sello, VGM y evidencias. Lo que no puede decir es cuántos son. Freight.containerId apunta a uno; requestedEquipmentType es un solo valor; la naviera es un campo de texto en el contenedor; la orden no sabe quién la despacha.

Como es hoy · detalle de flete · bloque de carga
Como es hoy · alta FCL y detalle de contenedor

Copy tomado de apps/admin/lib/i18n/locales/es.json: freights.fields.equipment, freights.create.fcl.containerCode*, containers.detail.context.carrier*, containers.reservation.*. Los bloques son freight-cargo-block.tsx, fcl-equipment-picker.tsx y container-context-block.tsx.

Hoy

Las dos preguntas no tienen dónde vivir

  1. Un contenedor por flete. Freight.containerId único; el trigger exige exactamente uno.
  2. Un equipo por flete. requestedEquipmentType no puede decir 6x40HQ + 2x20.
  3. Naviera en texto libre sobre el contenedor; sin catálogo, sin SCAC, sin filtro.
  4. La orden no tiene proveedor. Order.supplierId no existe; Supplier es catálogo de sourcing.
  5. No hay BL. La única mención es el copy de subida de evidencias.
  6. Contar es abrir. Para saber cuántos son, se abren las órdenes una por una.
Proveedores
Contenedores
1
Fletes por 8 cajas
8
Propuesta

Un flete, un cliente, una factura. N contenedores.

  1. El contenedor apunta al flete. Container.freightId para FCL; Freight.containerId queda para LCL (opción C).
  2. Equipo por contenedor. El alta entiende 8x40HQ y crea ocho reservas; el texto nunca se guarda.
  3. Naviera como catálogo (Carrier), espejada al contenedor para que la búsqueda no se rompa.
  4. Proveedor en la orden y ubicación en la ficha: ciudad, provincia, dirección, lat/long.
  5. BL con sus contenedores. Un BL ampara 1..N contenedores del mismo flete; booking antes del número.
  6. Dos contadores en la cabecera de todo flete FCL, siempre visibles.
Proveedores
3
Contenedores
8
Fletes por 8 cajas
1

02Alta: la notación de operaciones, tal cual se escribe

plan §4.2 · §5.1

Samuel escribe 8x40HQ en WhatsApp. El campo Equipo acepta exactamente eso, y también 6x40HQ + 2x20; debajo aparece lo que entendió, como chips con stepper, y el resumen en vivo. Los números de contenedor se pegan como llegan en el correo de la naviera: uno por línea, con comas o con espacios. Cada fila se valida sola; una inválida no frena a las otras siete.

Propuesta · /freights/create · toggle FCL

Un solo POST con Idempotency-Key: flete + cotización + 8 reservas + BL (booking) + carga + outbox. Todo o nada. La respuesta trae containers: [{ id, reservationReference, code, requestedEquipmentType, status, version }]. Tope propuesto por alta: 60 contenedores (pregunta 10).

03Resumen: los dos contadores, en sus tres estados

plan §3.1 · §5.2

Los contadores van en la cabecera, antes del estado y de la tarifa, porque son la pregunta que se hace primero. Proveedores se cuenta por orden (distintos supplierId) o se lee de la declaración cuando la carga es DECLARED. Contenedores es el mismo número en ambas fuentes, con el desglose que operaciones necesita: identificados, reservas pendientes, y por equipo. Cuando no se sabe, se muestra : nunca un cero inventado.

Los mismos dos números se repiten en /freights como columnas «Prov.» y «Cont.», en el PDF del flete («Proveedores declarados: 3» · tabla «Contenedores (8)») y en el resumen del cliente («8 contenedores · 5 identificados»).

04Contenedores: la pestaña nueva del flete

plan §5.2

Una fila por contenedor. La referencia siempre existe; el número aparece cuando la naviera lo asigna. Equipo solicitado y confirmado van juntos porque la regla de v1 sigue: la solicitud nunca se copia como confirmación. Desde aquí se pegan números (mismo componente que el alta) y se añade una reserva más, siempre antes de LOADING y con revalidación de tarifa.

En /containers/[id] no hay rediseño: se añade el bloque «Flete y BL» (flete vinculado · contenedor 3 de 8 · BL y naviera) y «Equipo solicitado» de solo lectura junto al confirmado. Identificar equipo, sello, VGM, evidencias, escalas y cierre ya son por contenedor.

05Capacidad: el contenedor se llena con las órdenes

plan §4.9 · §5.7

La suma de los CBM de las órdenes que van dentro de un contenedor es su presupuesto de volumen. En vez de una cifra, la caja se dibuja de lado y se llena desde el piso con cada orden asignada. Cuatro estados, siempre con la cifra al lado: vacío, en curso, casi lleno a partir del 85 % y sobre capacidad cuando el sobrante asoma por encima del techo. La capacidad es la útil de planificación por equipo (28 · 58 · 68 m³); la nominal queda en el tooltip.

Decisión de Carlos · 22 sep 2026«Me gusta una mezcla de estos dos»: la silueta en la pestaña Contenedores y la pila al asignar una orden quedan cerradas como patrón. Sobre capacidad nunca bloquea: motivo obligatorio, guardado en la asignación, rojo hasta que cambie; no toca el estado operativo ni la cotización (pregunta 19, decidida). Siguen abiertas 16, 17, 18 y 20: las cifras de capacidad y los umbrales son provisionales hasta Samuel.
Decidido · pestaña Contenedores · una silueta por caja · los cuatro estados

Vista lateral: puertas a la derecha, corrugado vertical, el nivel marcado con la cifra en marino. El relleno es una altura en porcentaje (--h); el sobrante es un bloque rayado en rojo que asoma por encima del techo. Sin JavaScript: los estados son CSS.

Decidido · asignar una orden · la orden se apila como un bloque
Propuesta · cabecera del flete · presupuesto de volumen
ReglaPropuesta
Qué CBM cuentaOrder.cbm (medido en recepción, el que ya suman los rollups) manda; si es null, Order.enteredCbm (declarado) como estimado, en tono claro y con «est.»; sin ninguno, la orden no llena nada y se cuenta como «sin CBM». En DECLARED, FreightCargoDeclaration.volumeM3 a nivel de flete.
Capacidad por equipoConstante en packages/shared/src/fcl.ts, sin migración. Útil de planificación 28 · 58 · 68 m³ (nominal 33,2 · 67,7 · 76,4, fichas ISO 668). Cifras provisionales hasta que Samuel las confirme.
Con N contenedoresLa orden llena el contenedor al que se asigna (OrderContainerAllocation + cbm). Entera por defecto; reparto opcional por m³. Lo no asignado se ve como bolsa a nivel de flete, nunca se reparte solo. Con N = 1 la asignación es implícita.
UmbralesVacío 0 · En curso < 85 % · Casi lleno 85–100 % · Sobre capacidad > 100 %. Mismos umbrales para el rollup del flete.
Sobre capacidad decididoAviso blando con motivo obligatorio; el rojo se queda. Nunca bloqueo duro, nunca afecta al estado del contenedor ni a la tarifa. Decisión de Carlos, 22 sep.

06BL y naviera: un documento que ampara ocho cajas

plan §4.3 · §5.2

El BL nace como booking cuando se elige la naviera y se completa con su número al zarpar: es el mismo registro. Ampara 1..N contenedores del mismo flete; un contenedor solo puede estar en un BL. La naviera del BL se espeja a Container.carrier para que la búsqueda global y el índice trigram sigan funcionando. La factura comercial es una sola para el flete y vive donde ya vivía: Freight.invoiceFiles.

07Proveedores: la orden sabe quién despacha, y desde dónde

plan §4.4 · §5.5 · fase 1

Es la pieza más pequeña y la primera: Order.supplierId opcional, y la ficha del proveedor gana ubicación propia (ciudad, provincia, dirección, lat/long). No pasa por Address, que exige la geografía venezolana sembrada. El combobox ya existe (supplier-combobox.tsx) y hoy solo lo usan cotizaciones y búsquedas. Aplica a LCL y AIR también: responde la misma pregunta en todos los modos.

Las métricas del proveedor (getMetrics) hoy solo cuentan opciones de sourcing; pasan a sumar órdenes. La asignación orden ↔ contenedor (qué proveedor va en qué caja) queda para la fase 4, si la pregunta 4 lo pide.

08Listas: las dos columnas donde se busca primero

plan §5.4

En /freights, «Prov.» y «Cont.» para filas FCL; LCL y AIR muestran «—» en Cont. y el filtro por naviera aplica a todos. En /containers, las filas FCL dicen a qué flete pertenecen y en qué posición («3/8»), con la naviera y el filtro por BL.

Búsqueda global: el número de BL y el nombre de la naviera entran en SearchService. La naviera ya está indexada en containers.carrier; por eso se espeja en vez de moverse.

09Decisiones, fases y lo que Carlos tiene que contestar

plan §4 · §7 · §8

Nada de esto se construye hasta que las preguntas tengan respuesta. La fase 1 es aditiva y responde ya la pregunta de los proveedores: se propone arrancarla mientras se decide el resto.

Decisión de diseñoPor qué
Dos contadores fijos en la cabecera del fleteSon las dos preguntas de operaciones; van antes que el estado y la tarifa. Se repiten en listas, PDF y cliente.
Equipo como texto 6x40HQ + 2x20 + chips con stepperLa notación es la de Samuel; el stepper cubre a quien no la conoce. Se persiste por contenedor, nunca como texto.
Pegar números con validación por filaUn BL trae ocho números; el error de uno no puede frenar los otros siete. Duplicado y dígito de control se explican en la fila.
Naviera = catálogo Carrier con creación en línea, espejada al contenedor«La naviera importa»: catálogo para filtrar y buscar; espejo para no romper el índice trigram ni la búsqueda global.
Un BL con sus contenedores; una factura por fleteHechos de Samuel. El BL nace como booking y se completa al zarpar. La factura ya vive en Freight.invoiceFiles.
Proveedor por orden y ubicación en la ficha del proveedorIdea 1 de Carlos. Address exige geografía venezolana; una fábrica en Yiwu no cabe ahí.
«—» cuando no se sabe; «pendiente» en reservasRegla del contrato v1: null es desconocido, nunca 0 por defecto.
Silueta en Contenedores + pila al asignar; sobrecapacidad con motivo y sin bloqueo decidido · 22 sepCarlos: «me gusta una mezcla de estos dos». El llenado se lee de un vistazo, no en una cifra. Quedan provisionales la capacidad útil por equipo (28 · 58 · 68 m³), el CBM autoritativo y el umbral del 85 %.
Estado del flete = contenedor menos avanzadoEvita que el flete oscile cuando un contenedor avanza y otro retrocede. Incidencias como badge, no como estado.
1
Proveedor–orden
Order.supplierId, ubicación en Supplier, supplierCount en la declaración, combobox en órdenes, contador Proveedores.
solo aditivo · preguntas 9, 11, 15
2
N contenedores
Container.freightId, equipo por contenedor, trigger v2, parser 8x40HQ, pestaña Contenedores, pegar números, tarifa por tipo, PDF con tabla.
preguntas 2, 3, 8, 10, 13, 14
3
BL y naviera
Carrier + BillOfLading, espejo al contenedor, pestaña BL, filtros, búsqueda, PDF, cliente y notificación.
preguntas 1, 5, 6, 12
4
Orden ↔ contenedor
OrderContainerAllocation con cbm: qué órdenes van dentro de cada caja y cuánto la llenan. Deja de ser opcional si el llenado se quiere con N > 1.
preguntas 4, 20 · 19 decidida
5
Aceptación v2
Concurrencia con N contenedores, no regresión LCL/AIR, QA visual es/en/zh, evidencia bajo verification/v2/.
cierra 2–4
  1. ¿Un flete puede repartir contenedores en varios zarpes / BL? Este diseño lo permite. Si siempre es un zarpe, el BL cuelga del flete.
  2. ¿Vínculo en el contenedor (C) o tabla de unión (B)?recomendado C
  3. Estado del flete con N contenedores: ¿el menos avanzado? ¿DELIVERED exige todos?recomendado mínimo
  4. ¿Hace falta saber qué proveedor va en qué caja o bastan los dos conteos?
  5. Lista inicial de navieras y quién puede crear una desde el combobox.
  6. ¿Solo MBL o también HBL? ¿El booking se captura en el mismo registro?
  7. Factura única: ¿en Freight.invoiceFiles con órdenes opcionales, o una orden por proveedor?
  8. Alias de notación además de 40HQ (40HC, 40'HC, 20GP, 40DV). ¿Reefer y open top se rechazan con mensaje?
  9. Proveedores en DECLARED: ¿basta el conteo o hay que nombrarlos?
  10. Tope por alta: propuesta 60. ¿Casos reales por encima?
  11. Ubicación del proveedor: ¿pin manual, geocodificación automática o solo texto? ¿Para qué se usará lat/long?
  12. Visibilidad al cliente: ¿ve BL, naviera, buque y estado por contenedor? ¿Ve el nombre de sus proveedores?
  13. Reutilización de un número físico en un viaje nuevo: v1 lo prohíbe. ¿Se reabre?
  14. Tarifa: ¿una fila base por tipo con cantidad, o una sola fila con importe total?recomendado por tipo
  15. ¿Autorizas arrancar la fase 1 mientras se deciden las demás?
  16. CBM autoritativo: ¿Order.cbm medido manda y enteredCbm solo estima, o al revés hasta que la orden llegue al almacén? ¿Y una orden sin ninguno?recomendado cbm
  17. Tabla de capacidades: ¿valen 28 · 58 · 68 m³ útiles (nominal 33,2 · 67,7 · 76,4) o operaciones planifica con otras? ¿Override por contenedor?
  18. Umbral de «casi lleno»: ¿85 % o 90 %? ¿Distinto para el 20'?recomendado 85
  19. Sobre capacidad: aviso blando con motivo obligatorio, sin bloqueo; el rojo se queda hasta que la asignación cambie.decidida · 22 sep
  20. Reparto de una orden entre contenedores: ¿entera por defecto con reparto opcional por m³, o siempre entera? ¿El «sin asignar» lo ve el cliente?
  • Lo que no se propone — conversión FCL↔LCL, equipos especiales (reefer, open top, flat rack), mercancía peligrosa, demoras automáticas, integración API con navieras, cambios estructurales a QuotationLineItem. Todo sigue fuera de alcance como en v1.
  • Lo que se conserva de v1 — idempotencia, outbox, versiones optimistas, pricingState, evidencias por contenedor, FCL_PENDING. Se reutiliza por contenedor sin tocarlo.

Un flete, un cliente, una factura. Ocho contenedores.

Tres proveedores y ocho cajas se leen en la cabecera antes de abrir nada. La notación de operaciones entra tal cual se escribe, los números se pegan en bloque, la naviera se elige, el BL sabe qué ampara y cada caja muestra cuánto le cabe todavía. Cinco fases; la primera, sin riesgo.