Sincronización de Guías (Dispatch)
Importante: A diferencia de los demás endpoints de sync,
/transportes/sync/dispatchtrabaja con IDs internos de Smartfleet (driver_id,vehicle_id,hub_id,receipt_id). Esto significa que chofer, vehículo, sede y facturas deben estar ya sincronizados antes de crear la guía.
Crea o actualiza una guía de despacho con chofer, vehículo y paradas.
Caso de uso
- Crear guía desde un sistema externo cuando ya se eligieron chofer, vehículo y stops.
- Actualizar una guía existente pasando
dispatch_id. - Crear guías normales o de solo recolección.
Campos del Payload
Requeridos
| Campo | Tipo | Descripción |
|---|---|---|
driver_id | int | ID del chofer |
vehicle_id | int | ID del vehículo |
total_weight | number | Peso total del despacho |
dispatch_steps | object | Mapa de paradas de la guía |
Opcionales
| Campo | Tipo | Descripción |
|---|---|---|
dispatch_id | int | Para actualizar una guía existente |
hub_id | int | Sede de salida |
user | string | Usuario que crea la guía |
uber / is_uber | boolean | Indica si es despacho por Uber |
default_pickup_notes | string | Notas de recolección por defecto |
extra_pickup_notes | string | Notas adicionales de recolección |
dropoff_notes / return_detail | string | Notas de entrega o devolución |
removed_receipts_ids / removed_receipt_ids | int[] | Facturas a remover de la guía |
removed_returns_ids / removed_return_ids | int[] | Devoluciones a remover |
removed_transfers_ids / removed_transfer_ids | int[] | Traslados a remover |
dispatch_mode | string | NORMAL_DELIVERY (default) o PICKUP_ONLY |
validate_hub_pickups_on_create / validate_pickups_on_create | boolean | Valida pickups al crear |
source_id | string | ID externo de la guía (máx. 128 chars). Permite luego lookups por GET /sync/dispatch/{sourceId} e identificación vía dispatch_source_id en /sync/dispatch/start |
source_system | string | Sistema externo (ej. external_erp). Requerido junto con source_id |
Tipos permitidos en dispatch_steps
Cada stop tiene order (entero), type y item. Los campos requeridos en item según tipo:
| Tipo | Campos requeridos en item | Descripción |
|---|---|---|
hub | hub_id, name, latitude, longitude | Parada en sede |
receipt | receipt_id, receipt_code, hub_id, latitude, longitude | Parada de entrega de factura |
pickup | pickup_type, document_id, receipt_id | Parada de recolección |
return | return_id, receipt_id | Parada de devolución |
transfer | pickup_type: "TRANSFER", document_id, receipt_id | Parada de traslado |
Todos los IDs en
item(receipt_id,hub_id,return_id, etc.) son IDs internos de Smartfleet, nosource_id.
Notas Importantes
- Para
PICKUP_ONLY, el stop final de entrega de recolecciones usaENT_RECcuando corresponde. - Si se intenta crear otra guía
PICKUP_ONLYcon pickups ya procesados, el backend bloquea la operación. - Si se crea una guía normal posterior, los pickups ya procesados no se vuelven a crear como stops de recolección.
ENT_REC vs ENT_FAC: cómo derivar el stop de factura
type en dispatch_steps solo acepta los 5 valores listados arriba — no existe ent_rec. Cuando una guía es solo recolección y la mercadería se deposita en una sede en lugar de entregarse al cliente, el integrador envía el step de la factura con type: "receipt" y deliver_to_hub: true en item. El backend convierte ese step en un stop ENT_REC durante buildStopsToCreate con esta regla:
deliverToHub = item.deliver_to_hub === true
|| item.latitude == null
|| item.longitude == null
stop_type_id = deliverToHub ? ENT_REC : ENT_FAC| Caso | type | item.deliver_to_hub | item.latitude/longitude | Stop generado |
|---|---|---|---|---|
| Entrega normal al cliente | receipt | omitir | coords del cliente | ENT_FAC |
| Depósito en sede tras recolección | receipt | true | coords del hub destino (recomendado) | ENT_REC |
| Depósito en sede sin coords | receipt | omitir | omitir ambos | ENT_REC (fallback) |
Cuando el chofer ejecuta el stop:
POST /transportes/sync/dispatch/task/startcontask_type: "ENT_REC",document_id=receipt_id.POST /transportes/sync/dispatch/task/completecontask_type: "ENT_REC". Las cantidades reportadas enlines[*]se acumulan enreturned_quantity(vuelven al hub) en lugar dedelivered_quantity.
Efecto al cerrar el stop ENT_REC:
receipts.status_idqueda enSIN_ASIGNAR (1)— la entrega al cliente queda pendiente.- Se setean
pickup_stored_hub_id(=item.hub_idenviado en el step) ypickup_stored_at. - En una guía posterior se podrá crear un step
receiptENT_FAC normal para entregar al cliente final.
Ejemplos
Request — Guía Normal
{
"hub_id": 3,
"driver_id": 1,
"vehicle_id": 12,
"total_weight": 25.5,
"user": "erp-sync",
"dispatch_mode": "NORMAL_DELIVERY",
"dispatch_steps": {
"1": {
"order": 1,
"type": "hub",
"item": {
"hub_id": 3,
"name": "Cedi",
"latitude": 9.9797944160071,
"longitude": -84.1408946228684
}
},
"2": {
"order": 2,
"type": "receipt",
"item": {
"receipt_id": 2108,
"receipt_type_id": 1,
"receipt_code": "FAC-10001",
"receipt_type_code": "FAC",
"hub_id": 3,
"latitude": 9.93,
"longitude": -84.14
}
}
}
}Request — Solo Recolección (Pickup Only)
{
"hub_id": 3,
"driver_id": 1,
"vehicle_id": 12,
"total_weight": 10,
"user": "erp-sync",
"dispatch_mode": "PICKUP_ONLY",
"dispatch_steps": {
"1": {
"order": 1,
"type": "hub",
"item": {
"hub_id": 2,
"name": "Alajuela",
"latitude": 10.01064731315831,
"longitude": -84.21583404686814
}
},
"2": {
"order": 2,
"type": "pickup",
"item": {
"pickup_type": "OC",
"document_id": 371,
"receipt_code": "FAC-10001",
"receipt_id": 2108,
"origin_description": "Acme Manufacturing",
"latitude": 9.93276239628712,
"longitude": -84.08577070478509
}
},
"3": {
"order": 3,
"type": "hub",
"item": {
"hub_id": 3,
"name": "Cedi",
"latitude": 9.9797944160071,
"longitude": -84.1408946228684
}
}
}
}Response
{
"ok": true,
"code": "SYNC_OK",
"message": "Sync processed successfully.",
"data": {
"statusOk": true,
"message": "Dispatch created successfully.",
"dispatch_id": 501
},
"meta": {
"route": "/transportes/sync/dispatch",
"method": "PostDispatchSync",
"operation": "upsert",
"upsert_action": "created",
"timestamp": "2026-04-07T12:00:00.000Z"
}
}Cancelación de guías desde sistema externo
El mismo endpoint POST /transportes/sync/dispatch maneja el flujo de solicitud y aprobación de cancelación usando el campo sync_operation.
Paso 1 — Solicitar cancelación
{
"dispatch_id": 501,
"sync_operation": "CANCELLATION_REQUEST",
"reason": "El cliente canceló el pedido",
"detail": "Detalle opcional adicional",
"user": "erp-sync"
}Response:
{
"ok": true,
"code": "SYNC_OK",
"meta": {
"upsert_action": "cancellation_requested",
"sync_operation": "CANCELLATION_REQUEST"
}
}Paso 2 — Reenviar solicitud (si está pendiente)
{
"dispatch_id": 501,
"sync_operation": "CANCELLATION_RESEND"
}Paso 3 — Aprobar o rechazar la cancelación
{
"dispatch_id": 501,
"sync_operation": "CANCELLATION_DECISION",
"action": "APPROVED",
"comment": "Confirmado por supervisor"
}{
"dispatch_id": 501,
"sync_operation": "CANCELLATION_DECISION",
"action": "REJECTED",
"comment": "No procede la cancelación"
}Aliases de sync_operation
El campo acepta múltiples variantes para facilitar la integración:
| Alias | Operación |
|---|---|
CANCELLATION_REQUEST, CANCEL_REQUEST, REQUEST_CANCELLATION, REQUESTED, CREATE | Solicitar cancelación |
CANCELLATION_RESEND, CANCEL_RESEND, RESEND | Reenviar solicitud |
CANCELLATION_DECISION, CANCEL_DECISION, DECISION, APPROVED, REJECTED | Aprobar / rechazar |
Nota: La cancelación de guía es distinta de la cancelación de un stop (
task/cancel). La cancelación de stop revierte el dispatch aASIGNADApara reprogramarlo; la cancelación de guía la lleva aANULADAtras aprobación.