Flujo de Datos - Creación de Orden vía WhatsApp
Descripción General
Este documento describe el flujo de datos de extremo a extremo cuando un cliente crea una orden de mantenimiento vía WhatsApp usando el bot de Jelou. El proceso incluye captura de orden, carga de fotos, OCR con IA para identificación de activos, creación de orden en la base de datos y notificaciones multicanal.
Diagrama de Secuencia
sequenceDiagram
participant Client as Cliente (WhatsApp)
participant Jelou as Bot Jelou
participant GPT as GPT-4 (Clasificación)
participant Tesseract as Tesseract.js (OCR)
participant APIGateway as API Gateway
participant OrdersMS as MS Órdenes
participant OrdersDB as MongoDB Órdenes
participant Broker as Redis/Kafka
participant NotificationsMS as MS Notificaciones
participant SendGrid as SendGrid
participant Asana as API Asana
participant Qsystems as API Qsystems
participant Assets as API Sistema Activos
Client->>Jelou: Envía mensaje "Necesito mantenimiento"
Jelou->>Jelou: Detecta intención (menú principal u órdenes de empresa)
Jelou->>Client: "¿Qué tipo de servicio necesitas?"
Client->>Jelou: "Aire acondicionado no enfría"
Jelou->>GPT: classify_service("Aire acondicionado no enfría")
GPT-->>Jelou: Tipo de servicio: "HVAC_MAINTENANCE"
Jelou->>Client: "Por favor, describe el problema"
Client->>Jelou: "El aire no enfría, hace ruido extraño"
Jelou->>Client: "Envía una foto del equipo"
Client->>Jelou: [Foto de unidad AC]
Jelou->>Jelou: Sube foto a almacenamiento Jelou
Jelou->>Client: "Envía foto de la placa del serial"
Client->>Jelou: [Foto de placa serial]
Jelou->>Tesseract: OCR.process(photo)
Tesseract-->>Jelou: Serial: "AC-12345" (confianza: 85%)
Jelou->>Client: "¿El serial es AC-12345?"
Client->>Jelou: "Sí" (o corrige si es incorrecto)
Jelou->>Client: "¿Cuál es la ubicación?"
Client->>Jelou: "Edificio A, Piso 3, Sala de juntas"
Jelou->>Client: "¿Qué prioridad tiene? (Baja/Media/Alta)"
Client->>Jelou: "Alta"
Jelou->>APIGateway: POST /api/orders<br/>{serviceType, Descripción, photos, assetSerial, location, Prioridad}
APIGateway->>APIGateway: Valida JWT (si autenticado) o crea anónimo
APIGateway->>OrdersMS: MessagePattern: orders.create<br/>CreateOrderCommand
OrdersMS->>OrdersMS: Valida CreateOrderCommand
OrdersMS->>OrdersMS: Crea entidad Order (Estado: PENDING)
OrdersMS->>Assets: GET /api/assets/:serial
alt Activo existe en sistema legado
Assets-->>OrdersMS: Detalles de activo (tipo, ubicación, modelo)
else Activo no encontrado
OrdersMS->>OrdersMS: Crea nueva entidad Asset
end
OrdersMS->>OrdersDB: Inserta documento Order
OrdersDB-->>OrdersMS: Orden guardada (ID: ORD-001)
OrdersMS->>Broker: Publica OrderCreatedEvent
Broker-->>NotificationsMS: OrderCreatedEvent recibido
OrdersMS->>Asana: POST /api/tasks<br/>{title, Descripción, due_date}
Asana-->>OrdersMS: Tarea creada
OrdersMS->>Qsystems: POST /api/orders (si es orden de empresa)
Qsystems-->>OrdersMS: Sincronizado
OrdersMS-->>APIGateway: {orderId: "ORD-001", Estado: "PENDING"}
APIGateway-->>Jelou: 201 Created {orderId}
Jelou->>Client: "✅ Orden creada: ORD-001<br/>Te notificaremos cuando se asigne un proveedor"
NotificationsMS->>NotificationsMS: Renderiza plantilla "order_created_email"
NotificationsMS->>SendGrid: Envía email al cliente
SendGrid-->>NotificationsMS: Email enviado
NotificationsMS->>Jelou: Envía confirmación por WhatsApp
Jelou->>Client: "📧 Te enviamos confirmación por email"
NotificationsMS->>NotificationsMS: Envía notificación al equipo Algesta
NotificationsMS->>SendGrid: Envía email al equipo
SendGrid-->>NotificationsMS: Email enviado al equipo
Figura: Creación de Orden vía WhatsApp - Flujo de Extremo a Extremo - Secuencia completa desde mensaje de WhatsApp hasta creación de orden con clasificación GPT-4 y OCR
Data Transformation
WhatsApp Message → Jelou Variables
| WhatsApp Input | Jelou Variable | Type |
|---|---|---|
| ”Aire acondicionado no enfría” | {{user_message}} | String |
| Classification result | {{service_type}} | Enum (GPT-4 output) |
| “El aire no enfría…” | {{Descripción}} | String |
| Photo of AC unit | {{photo_url}} | URL (Jelou storage) |
| Photo of serial plate | {{serial_photo_url}} | URL |
| OCR result | {{asset_serial}} | String |
| ”Edificio A, Piso 3…” | {{location}} | String |
| ”Alta” | {{Prioridad}} | Enum (BAJA, MEDIA, ALTA) |
Jelou Variables → API Gateway DTO
// CreateOrderDtointerface CreateOrderDto { serviceType: string; // "HVAC_MAINTENANCE" Descripción: string; // "El aire no enfría, hace ruido extraño" photos: string[]; // ["https://jelou.storage/photo1.jpg"] assetSerial: string; // "AC-12345" location: { building: string; // "Edificio A" floor: string; // "Piso 3" room: string; // "Sala de juntas" }; Prioridad: 'BAJA' | 'MEDIA' | 'ALTA'; clientId?: string; // If authenticated clientPhone: string; // WhatsApp phone number source: 'WHATSAPP';}CreateOrderDto → Order Domain Entity
// Order Entity (Domain Layer)class Order { id: string; // Generated UUID or auto-increment orderId: string; // Human-readable ID: "ORD-001" serviceType: string; Descripción: string; photos: string[]; assetId: string; // Reference to Asset entity location: Location; Prioridad: Prioridad; Estado: OrderEstado; // Pendiente clientId: string; providerId?: string; // Null initially createdAt: Date; updatedAt: Date;}Order Entity → MongoDB Documento
{ "_id": "64f8a1b2c3d4e5f6g7h8i9j0", "orderId": "ORD-001", "serviceType": "HVAC_MAINTENANCE", "Descripción": "El aire no enfría, hace ruido extraño", "photos": [ "https://jelou.storage/photo1.jpg" ], "assetId": "64f8a1b2c3d4e5f6g7h8i9j1", "location": { "building": "Edificio A", "floor": "Piso 3", "room": "Sala de juntas" }, "Prioridad": "ALTA", "Estado": "Pendiente", "clientId": "64f8a1b2c3d4e5f6g7h8i9j2", "providerId": null, "createdAt": "2025-11-20T10:00:00Z", "updatedAt": "2025-11-20T10:00:00Z"}Order Entity → OrderCreatedEvent
// OrderCreatedEvent (for message broker)class OrderCreatedEvent { orderId: string; // "ORD-001" serviceType: string; clientId: string; clientEmail: string; clientPhone: string; Descripción: string; location: Location; Prioridad: Prioridad; createdAt: Date;}OrderCreatedEvent → Notification Templates
Email Template Data:
{ clientName: "Juan Pérez", orderId: "ORD-001", serviceType: "Mantenimiento de Aire Acondicionado", Descripción: "El aire no enfría, hace ruido extraño", location: "Edificio A, Piso 3, Sala de juntas", Prioridad: "Alta", createdAt: "20 de Noviembre de 2025"}WhatsApp Template Data:
🎉 _Orden Creada Exitosamente_
Hola Juan Pérez,
Tu orden #ORD-001 ha sido creada.
_Detalles:_
- Servicio: Mantenimiento de Aire Acondicionado- Descripción: El aire no enfría, hace ruido extraño- Ubicación: Edificio A, Piso 3, Sala de juntas- Prioridad: Alta
Te notificaremos cuando se asigne un proveedor.
¡Gracias por elegir Algesta!Error Handling
Error Scenarios and Fallbacks
| Error Scenario | Detection | Recovery | User Experience |
|---|---|---|---|
| Invalid service type | GPT-4 returns unknown/null | Ask user to select from predefined list | ”No entendí el servicio. Elige una opción: 1. HVAC 2. Plomería 3. Eléctrico” |
| Missing required fields | API Gateway validation fails | Return 400 Bad Request to Jelou | Jelou prompts user: “Por favor proporciona [campo faltante]“ |
| Photo upload failure | Jelou storage returns error | Retry upload, fallback to manual Descripción | ”No pudimos subir la foto. ¿Puedes intentar de nuevo?” |
| OCR fails (low confidence) | Tesseract confidence < 70% | Request manual entry | ”No pudimos leer el serial. Por favor escríbelo manualmente.” |
| Base de datos save failure | MongoDB throws exception | Return 500 to Jelou, rollback transaction | ”Error creando orden. Por favor intenta de nuevo.” |
| External API failure (Asana, Qsystems) | HTTP error or timeout | Log error, continue order creation (non-blocking) | Order created successfully, integration happens async |
| Notification delivery failure | SendGrid or Jelou API error | Retry notification in background task | Order created, notification retried later |
State Transitions
Order Estado After Creation
Order Created → Status: PENDINGNext possible states:
- PUBLISHED - Agent publishes order to marketplace auction
- ASSIGNED - Agent manually assigns provider (skip auction)
- CANCELLED - Client or agent cancels order
Integration Points
Jelou Bot Configuration
Skill: Order Creation
- Intent: “create_order”, “necesito mantenimiento”, “solicitar servicio”
- Variables collected:
service_type(via GPT-4 classification)Descripción(free text)photos(file upload)asset_serial(via OCR + user confirmation)location(structured: building, floor, room)Prioridad(buttons: Baja/Media/Alta)
- Webhook:
POST {{API_GATEWAY_URL}}/api/orders
API Gateway Endpoint
POST /api/orders
- Authentication: Optional (JWT token or anonymous)
- Validation:
CreateOrderDtoschema with class-validator - Rate limiting: 10 requests per minute per phone number
- Response:
201 Createdwith order ID
Orders Microservicio Command Handler
CreateOrderHandler:
- Validate command
- Query/create Asset entity (if serial provided)
- Create Order entity with Estado Pendiente
- Save to MongoDB
- Publish OrderCreatedEvent to message broker
- Integrate with external systems (Asana, Qsystems) - async
- Return order ID
External System Integrations
Asana Integration:
- Creates task in “Órdenes Pendientes” project
- Task title: “[ORD-001] HVAC Maintenance - Edificio A”
- Task Descripción: Order details
- Due date: Based on Prioridad (Alta: +1 day, Media: +3 days, Baja: +7 days)
Qsystems Integration (if company order):
- Syncs order to enterprise client system
- Maps Algesta order to Qsystems work order
- Bi-directional sync for Estado updates
Assets System Integration:
- Queries asset by serial number
- If found: Enriches order with asset details (model, location, warranty)
- If not found: Creates new asset record in Algesta system
Message Broker Topics
order.created event published to:
notifications.order-createdtopic → Notifications MS listens- Event contains: orderId, clientId, serviceType, Prioridad
Performance Considerations
Expected Latency
| Step | Expected Time | Notes |
|---|---|---|
| User input collection (Jelou) | 30-60 seconds | User interaction time |
| GPT-4 classification | 1-2 seconds | OpenAI API call |
| Photo upload to Jelou | 2-5 seconds | Depends on photo size and network |
| OCR processing (Tesseract) | 1-3 seconds | Image preprocessing + OCR |
| API Gateway validation | < 100ms | DTO validation |
| Order creation in DB | < 200ms | MongoDB insert |
| External API calls (Asana, Qsystems) | 500ms - 2s | Async, non-blocking |
| Event publishing | < 50ms | Redis/Kafka publish |
| Notification delivery | 1-3 seconds | SendGrid + Jelou WhatsApp |
Total End-to-End: ~40-75 seconds (mostly user interaction)
Circuit Breaker for External APIs
If external APIs (Asana, DocuSign, Qsystems, Assets) are slow or failing:
- Circuit opens after 3 consecutive failures
- Requests fail fast (no waiting)
- Background job retries integration later
- Order creation still succeeds (integration is async)