Saltearse al contenido

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 InputJelou VariableType
”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

// CreateOrderDto
interface 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 ScenarioDetectionRecoveryUser Experience
Invalid service typeGPT-4 returns unknown/nullAsk user to select from predefined list”No entendí el servicio. Elige una opción:
1. HVAC
2. Plomería
3. Eléctrico”
Missing required fieldsAPI Gateway validation failsReturn 400 Bad Request to JelouJelou prompts user: “Por favor proporciona [campo faltante]“
Photo upload failureJelou storage returns errorRetry 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 failureMongoDB throws exceptionReturn 500 to Jelou, rollback transaction”Error creando orden. Por favor intenta de nuevo.”
External API failure (Asana, Qsystems)HTTP error or timeoutLog error, continue order creation (non-blocking)Order created successfully, integration happens async
Notification delivery failureSendGrid or Jelou API errorRetry notification in background taskOrder created, notification retried later

State Transitions

Order Estado After Creation

Order Created → Status: PENDING

Next possible states:

  1. PUBLISHED - Agent publishes order to marketplace auction
  2. ASSIGNED - Agent manually assigns provider (skip auction)
  3. 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: CreateOrderDto schema with class-validator
  • Rate limiting: 10 requests per minute per phone number
  • Response: 201 Created with order ID

Orders Microservicio Command Handler

CreateOrderHandler:

  1. Validate command
  2. Query/create Asset entity (if serial provided)
  3. Create Order entity with Estado Pendiente
  4. Save to MongoDB
  5. Publish OrderCreatedEvent to message broker
  6. Integrate with external systems (Asana, Qsystems) - async
  7. 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-created topic → Notifications MS listens
  • Event contains: orderId, clientId, serviceType, Prioridad

Performance Considerations

Expected Latency

StepExpected TimeNotes
User input collection (Jelou)30-60 secondsUser interaction time
GPT-4 classification1-2 secondsOpenAI API call
Photo upload to Jelou2-5 secondsDepends on photo size and network
OCR processing (Tesseract)1-3 secondsImage preprocessing + OCR
API Gateway validation< 100msDTO validation
Order creation in DB< 200msMongoDB insert
External API calls (Asana, Qsystems)500ms - 2sAsync, non-blocking
Event publishing< 50msRedis/Kafka publish
Notification delivery1-3 secondsSendGrid + 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)

Referencias Cruzadas