Operaciones
Guías (Dispatch)

Sincronización de Guías (Dispatch)

Importante: A diferencia de los demás endpoints de sync, /transportes/sync/dispatch trabaja 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.

POST/transportes/sync/dispatch

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

CampoTipoDescripción
driver_idintID del chofer
vehicle_idintID del vehículo
total_weightnumberPeso total del despacho
dispatch_stepsobjectMapa de paradas de la guía

Opcionales

CampoTipoDescripción
dispatch_idintPara actualizar una guía existente
hub_idintSede de salida
userstringUsuario que crea la guía
uber / is_uberbooleanIndica si es despacho por Uber
default_pickup_notesstringNotas de recolección por defecto
extra_pickup_notesstringNotas adicionales de recolección
dropoff_notes / return_detailstringNotas de entrega o devolución
removed_receipts_ids / removed_receipt_idsint[]Facturas a remover de la guía
removed_returns_ids / removed_return_idsint[]Devoluciones a remover
removed_transfers_ids / removed_transfer_idsint[]Traslados a remover
dispatch_modestringNORMAL_DELIVERY (default) o PICKUP_ONLY
validate_hub_pickups_on_create / validate_pickups_on_createbooleanValida pickups al crear
source_idstringID 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_systemstringSistema 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:

TipoCampos requeridos en itemDescripción
hubhub_id, name, latitude, longitudeParada en sede
receiptreceipt_id, receipt_code, hub_id, latitude, longitudeParada de entrega de factura
pickuppickup_type, document_id, receipt_idParada de recolección
returnreturn_id, receipt_idParada de devolución
transferpickup_type: "TRANSFER", document_id, receipt_idParada de traslado

Todos los IDs en item (receipt_id, hub_id, return_id, etc.) son IDs internos de Smartfleet, no source_id.

Notas Importantes

  • Para PICKUP_ONLY, el stop final de entrega de recolecciones usa ENT_REC cuando corresponde.
  • Si se intenta crear otra guía PICKUP_ONLY con 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
Casotypeitem.deliver_to_hubitem.latitude/longitudeStop generado
Entrega normal al clientereceiptomitircoords del clienteENT_FAC
Depósito en sede tras recolecciónreceipttruecoords del hub destino (recomendado)ENT_REC
Depósito en sede sin coordsreceiptomitiromitir ambosENT_REC (fallback)

Cuando el chofer ejecuta el stop:

  • POST /transportes/sync/dispatch/task/start con task_type: "ENT_REC", document_id = receipt_id.
  • POST /transportes/sync/dispatch/task/complete con task_type: "ENT_REC". Las cantidades reportadas en lines[*] se acumulan en returned_quantity (vuelven al hub) en lugar de delivered_quantity.

Efecto al cerrar el stop ENT_REC:

  • receipts.status_id queda en SIN_ASIGNAR (1) — la entrega al cliente queda pendiente.
  • Se setean pickup_stored_hub_id (= item.hub_id enviado en el step) y pickup_stored_at.
  • En una guía posterior se podrá crear un step receipt ENT_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

POST /transportes/sync/dispatch — solicitar cancelación
{
  "dispatch_id": 501,
  "sync_operation": "CANCELLATION_REQUEST",
  "reason": "El cliente canceló el pedido",
  "detail": "Detalle opcional adicional",
  "user": "erp-sync"
}

Response:

Response — CANCELLATION_REQUEST
{
  "ok": true,
  "code": "SYNC_OK",
  "meta": {
    "upsert_action": "cancellation_requested",
    "sync_operation": "CANCELLATION_REQUEST"
  }
}

Paso 2 — Reenviar solicitud (si está pendiente)

POST /transportes/sync/dispatch — reenviar solicitud
{
  "dispatch_id": 501,
  "sync_operation": "CANCELLATION_RESEND"
}

Paso 3 — Aprobar o rechazar la cancelación

POST /transportes/sync/dispatch — aprobar
{
  "dispatch_id": 501,
  "sync_operation": "CANCELLATION_DECISION",
  "action": "APPROVED",
  "comment": "Confirmado por supervisor"
}
POST /transportes/sync/dispatch — rechazar
{
  "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:

AliasOperación
CANCELLATION_REQUEST, CANCEL_REQUEST, REQUEST_CANCELLATION, REQUESTED, CREATESolicitar cancelación
CANCELLATION_RESEND, CANCEL_RESEND, RESENDReenviar solicitud
CANCELLATION_DECISION, CANCEL_DECISION, DECISION, APPROVED, REJECTEDAprobar / 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 a ASIGNADA para reprogramarlo; la cancelación de guía la lleva a ANULADA tras aprobación.