Initial commit: Documentación completa del proyecto WhatsApp Centralizado
- README principal con descripción del proyecto - Documento de diseño completo (arquitectura, DB, flujos) - Documentación de API REST y WebSocket - Guía del Flow Builder (30+ tipos de nodos) - Documentación de integración con Odoo - Guía de despliegue con Docker - Esquema de base de datos - Estructura de carpetas del proyecto - Archivo .env.example con todas las variables Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
572
docs/odoo-integration/README.md
Normal file
572
docs/odoo-integration/README.md
Normal file
@@ -0,0 +1,572 @@
|
||||
# Integración con Odoo
|
||||
|
||||
## Visión General
|
||||
|
||||
La integración con Odoo es bidireccional:
|
||||
- **WhatsApp → Odoo**: Crear leads, consultar pedidos, verificar stock, etc.
|
||||
- **Odoo → WhatsApp**: Notificaciones automáticas de eventos (pedido enviado, factura vencida, etc.)
|
||||
|
||||
## Configuración
|
||||
|
||||
### 1. Crear Usuario API en Odoo
|
||||
|
||||
1. En Odoo, ir a **Configuración → Usuarios y Compañías → Usuarios**
|
||||
2. Crear nuevo usuario:
|
||||
- Nombre: `API WhatsApp`
|
||||
- Email: `api-whatsapp@tuempresa.com`
|
||||
- Tipo de usuario: `Usuario interno`
|
||||
3. Asignar permisos según módulos a usar:
|
||||
- CRM: Usuario
|
||||
- Ventas: Usuario
|
||||
- Inventario: Usuario (lectura)
|
||||
- Helpdesk: Usuario
|
||||
- Facturación: Contable (lectura)
|
||||
4. Generar API Key:
|
||||
- Ir a Preferencias del usuario
|
||||
- En "Claves API", crear nueva clave
|
||||
- Guardar la clave de forma segura
|
||||
|
||||
### 2. Configurar en WhatsApp Central
|
||||
|
||||
```bash
|
||||
# .env
|
||||
ODOO_URL=https://odoo.tuempresa.com
|
||||
ODOO_DB=production
|
||||
ODOO_USER=api-whatsapp@tuempresa.com
|
||||
ODOO_API_KEY=tu_api_key_aqui
|
||||
```
|
||||
|
||||
### 3. Probar Conexión
|
||||
|
||||
```http
|
||||
POST /api/odoo/test-connection
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Módulos Soportados
|
||||
|
||||
### Contactos (res.partner)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Buscar | `odoo_search_partner` | Buscar por teléfono, email o nombre |
|
||||
| Crear | `odoo_create_partner` | Crear nuevo contacto |
|
||||
| Actualizar | `odoo_update_partner` | Modificar datos |
|
||||
| Sincronizar | Automático | Sync bidireccional |
|
||||
|
||||
**Ejemplo: Buscar cliente**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_search_partner",
|
||||
"data": {
|
||||
"search_by": "phone",
|
||||
"value": "{{contact.phone}}",
|
||||
"output_variable": "odoo_partner"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{odoo_partner.id}}
|
||||
{{odoo_partner.name}}
|
||||
{{odoo_partner.email}}
|
||||
{{odoo_partner.phone}}
|
||||
{{odoo_partner.street}}
|
||||
{{odoo_partner.city}}
|
||||
{{odoo_partner.credit}} // Saldo a favor
|
||||
{{odoo_partner.debit}} // Deuda
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CRM (crm.lead)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Crear lead | `odoo_create_lead` | Nueva oportunidad |
|
||||
| Actualizar etapa | `odoo_update_lead_stage` | Mover en pipeline |
|
||||
| Agregar nota | `odoo_add_lead_note` | Agregar actividad/nota |
|
||||
|
||||
**Ejemplo: Crear lead**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_create_lead",
|
||||
"data": {
|
||||
"name": "Interés en {{variables.producto}}",
|
||||
"contact_name": "{{contact.name}}",
|
||||
"phone": "{{contact.phone}}",
|
||||
"email": "{{variables.email}}",
|
||||
"description": "Cliente contactó por WhatsApp.\nProducto: {{variables.producto}}\nPresupuesto: {{variables.presupuesto}}",
|
||||
"expected_revenue": "{{variables.presupuesto}}",
|
||||
"team_id": 1,
|
||||
"user_id": 5,
|
||||
"output_variable": "lead"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Ejemplo: Mover etapa**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_update_lead_stage",
|
||||
"data": {
|
||||
"lead_id": "{{lead.id}}",
|
||||
"stage": "qualified"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Etapas disponibles:
|
||||
- `new` - Nuevo
|
||||
- `qualified` - Calificado
|
||||
- `proposition` - Propuesta
|
||||
- `negotiation` - Negociación
|
||||
- `won` - Ganado
|
||||
- `lost` - Perdido
|
||||
|
||||
---
|
||||
|
||||
### Ventas (sale.order)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Buscar pedidos | `odoo_search_orders` | Pedidos del cliente |
|
||||
| Crear cotización | `odoo_create_quotation` | Nueva cotización |
|
||||
| Confirmar pedido | `odoo_confirm_order` | Cotización → Pedido |
|
||||
| Enviar PDF | `odoo_send_quotation_pdf` | Enviar por WhatsApp |
|
||||
|
||||
**Ejemplo: Buscar pedidos**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_search_orders",
|
||||
"data": {
|
||||
"partner_id": "{{odoo_partner.id}}",
|
||||
"states": ["sale", "done"],
|
||||
"limit": 5,
|
||||
"output_variable": "orders"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{orders}} // Array de pedidos
|
||||
{{orders[0].id}}
|
||||
{{orders[0].name}} // SO-2024-001
|
||||
{{orders[0].state}}
|
||||
{{orders[0].amount_total}}
|
||||
{{orders[0].date_order}}
|
||||
{{orders[0].commitment_date}} // Fecha compromiso
|
||||
```
|
||||
|
||||
**Ejemplo: Crear cotización**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_create_quotation",
|
||||
"data": {
|
||||
"partner_id": "{{odoo_partner.id}}",
|
||||
"lines": [
|
||||
{
|
||||
"product_id": "{{variables.producto_id}}",
|
||||
"quantity": "{{variables.cantidad}}"
|
||||
}
|
||||
],
|
||||
"validity_days": 30,
|
||||
"output_variable": "quotation"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Ejemplo: Enviar PDF**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_send_quotation_pdf",
|
||||
"data": {
|
||||
"order_id": "{{quotation.id}}",
|
||||
"message": "Aquí está tu cotización {{quotation.name}}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Inventario (stock)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Verificar stock | `odoo_check_stock` | Disponibilidad |
|
||||
| Estado envío | `odoo_tracking_status` | Tracking de pedido |
|
||||
|
||||
**Ejemplo: Verificar stock**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_check_stock",
|
||||
"data": {
|
||||
"search_by": "name",
|
||||
"value": "{{variables.producto}}",
|
||||
"location_id": 8,
|
||||
"output_variable": "stock"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{stock.product_id}}
|
||||
{{stock.product_name}}
|
||||
{{stock.qty_available}} // Stock disponible
|
||||
{{stock.virtual_available}} // Stock proyectado
|
||||
{{stock.incoming_qty}} // Por recibir
|
||||
{{stock.outgoing_qty}} // Por enviar
|
||||
```
|
||||
|
||||
**Ejemplo: Estado de envío**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_tracking_status",
|
||||
"data": {
|
||||
"order_id": "{{order.id}}",
|
||||
"output_variable": "tracking"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{tracking.state}} // assigned, done, cancel
|
||||
{{tracking.carrier}} // Nombre paquetería
|
||||
{{tracking.tracking_ref}} // Número de guía
|
||||
{{tracking.tracking_url}} // URL de rastreo
|
||||
{{tracking.scheduled_date}}
|
||||
{{tracking.date_done}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Helpdesk (helpdesk.ticket)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Crear ticket | `odoo_create_ticket` | Nuevo ticket soporte |
|
||||
| Estado ticket | `odoo_ticket_status` | Consultar estado |
|
||||
|
||||
**Ejemplo: Crear ticket**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_create_ticket",
|
||||
"data": {
|
||||
"name": "{{variables.asunto}}",
|
||||
"description": "Reporte desde WhatsApp:\n\n{{variables.descripcion}}\n\n---\nConversación: {{conversation.id}}",
|
||||
"partner_id": "{{odoo_partner.id}}",
|
||||
"team_id": 1,
|
||||
"priority": "2",
|
||||
"attach_conversation": true,
|
||||
"output_variable": "ticket"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{ticket.id}}
|
||||
{{ticket.number}} // TICKET-001
|
||||
{{ticket.name}}
|
||||
{{ticket.stage}} // Nombre de etapa
|
||||
{{ticket.user_id}} // Asignado a
|
||||
{{ticket.priority}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Facturación (account.move)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Saldo cliente | `odoo_check_balance` | Deuda/crédito |
|
||||
| Enviar factura | `odoo_send_invoice_pdf` | PDF por WhatsApp |
|
||||
|
||||
**Ejemplo: Verificar saldo**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_check_balance",
|
||||
"data": {
|
||||
"partner_id": "{{odoo_partner.id}}",
|
||||
"output_variable": "balance"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{balance.total_due}} // Total adeudado
|
||||
{{balance.total_overdue}} // Vencido
|
||||
{{balance.credit}} // A favor
|
||||
{{balance.last_payment_date}}
|
||||
{{balance.last_payment_amount}}
|
||||
{{balance.invoices}} // Lista de facturas pendientes
|
||||
```
|
||||
|
||||
**Ejemplo: Enviar factura**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_send_invoice_pdf",
|
||||
"data": {
|
||||
"invoice_id": "{{variables.invoice_id}}",
|
||||
"message": "Aquí está tu factura. Total: ${{invoice.amount_total}}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Productos (product)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Buscar productos | `odoo_search_products` | Catálogo |
|
||||
| Detalles producto | `odoo_product_details` | Info completa |
|
||||
|
||||
**Ejemplo: Buscar productos**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_search_products",
|
||||
"data": {
|
||||
"search": "{{message.text}}",
|
||||
"category_id": null,
|
||||
"available_only": true,
|
||||
"limit": 5,
|
||||
"output_variable": "products"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{products}} // Array
|
||||
{{products[0].id}}
|
||||
{{products[0].name}}
|
||||
{{products[0].list_price}}
|
||||
{{products[0].qty_available}}
|
||||
{{products[0].image_url}}
|
||||
{{products[0].description}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Calendario (calendar.event)
|
||||
|
||||
| Acción | Nodo | Descripción |
|
||||
|--------|------|-------------|
|
||||
| Disponibilidad | `odoo_check_availability` | Horarios libres |
|
||||
| Crear cita | `odoo_create_appointment` | Agendar evento |
|
||||
|
||||
**Ejemplo: Verificar disponibilidad**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_check_availability",
|
||||
"data": {
|
||||
"user_id": 5,
|
||||
"date_from": "{{system.date}}",
|
||||
"date_to": "{{system.date}}+7days",
|
||||
"duration_hours": 1,
|
||||
"output_variable": "slots"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Variables resultantes:**
|
||||
```
|
||||
{{slots}} // Array de horarios
|
||||
{{slots[0].date}}
|
||||
{{slots[0].start_time}}
|
||||
{{slots[0].end_time}}
|
||||
```
|
||||
|
||||
**Ejemplo: Crear cita**
|
||||
```json
|
||||
{
|
||||
"type": "odoo_create_appointment",
|
||||
"data": {
|
||||
"name": "Cita con {{contact.name}}",
|
||||
"start": "{{variables.fecha}} {{variables.hora}}",
|
||||
"duration": 1,
|
||||
"partner_id": "{{odoo_partner.id}}",
|
||||
"user_id": 5,
|
||||
"description": "Cita agendada desde WhatsApp",
|
||||
"send_invitation": true,
|
||||
"output_variable": "appointment"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Automatizaciones Odoo → WhatsApp
|
||||
|
||||
### Configuración de Webhooks
|
||||
|
||||
1. Instalar módulo de webhooks en Odoo o usar Automated Actions
|
||||
2. Configurar URL de webhook:
|
||||
```
|
||||
https://chat.tuempresa.com/api/odoo/webhook
|
||||
```
|
||||
3. Configurar secret para validación
|
||||
|
||||
### Eventos Disponibles
|
||||
|
||||
#### Pedido Confirmado
|
||||
```json
|
||||
{
|
||||
"event": "sale.order.confirmed",
|
||||
"trigger": "state changed to 'sale'",
|
||||
"template": {
|
||||
"message": "✅ ¡Tu pedido ha sido confirmado!\n\nPedido: {{order.name}}\nTotal: ${{order.amount_total}}\n\nTe notificaremos cuando sea enviado.",
|
||||
"attach_pdf": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Pedido Enviado
|
||||
```json
|
||||
{
|
||||
"event": "stock.picking.done",
|
||||
"trigger": "state changed to 'done'",
|
||||
"template": {
|
||||
"message": "🚚 ¡Tu pedido está en camino!\n\nNúmero de guía: {{picking.tracking_ref}}\nPaquetería: {{picking.carrier}}\n\nRastrear: {{picking.tracking_url}}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Pago Recibido
|
||||
```json
|
||||
{
|
||||
"event": "account.payment.posted",
|
||||
"trigger": "state changed to 'posted'",
|
||||
"template": {
|
||||
"message": "💰 ¡Gracias por tu pago!\n\nMonto: ${{payment.amount}}\nReferencia: {{payment.name}}\n\nTu saldo actual es: ${{partner.balance}}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Factura Vencida
|
||||
```json
|
||||
{
|
||||
"event": "account.move.overdue",
|
||||
"trigger": "invoice_date_due < today AND state = 'posted'",
|
||||
"delay": "3 days",
|
||||
"template": {
|
||||
"message": "⚠️ Recordatorio de pago\n\nFactura: {{invoice.name}}\nMonto: ${{invoice.amount_residual}}\nVencimiento: {{invoice.invoice_date_due}}\n\n¿Necesitas ayuda con el pago?"
|
||||
},
|
||||
"retry": {
|
||||
"interval_days": 7,
|
||||
"max_attempts": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Recordatorio de Cita
|
||||
```json
|
||||
{
|
||||
"event": "calendar.event.reminder",
|
||||
"trigger": "start - 24 hours",
|
||||
"template": {
|
||||
"message": "📅 Recordatorio: Tienes una cita mañana\n\n📍 {{event.location}}\n🕐 {{event.start_time}}\n\n¿Confirmas tu asistencia?",
|
||||
"buttons": [
|
||||
{"id": "confirm", "text": "Confirmar"},
|
||||
{"id": "reschedule", "text": "Reagendar"},
|
||||
{"id": "cancel", "text": "Cancelar"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Ticket Resuelto
|
||||
```json
|
||||
{
|
||||
"event": "helpdesk.ticket.closed",
|
||||
"trigger": "stage.is_close = true",
|
||||
"template": {
|
||||
"message": "✅ Tu ticket #{{ticket.number}} ha sido resuelto.\n\n¿Cómo calificarías la atención recibida?",
|
||||
"send_csat": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sincronización de Contactos
|
||||
|
||||
### WhatsApp → Odoo
|
||||
- Al recibir mensaje de número nuevo, buscar en Odoo
|
||||
- Si no existe, opcionalmente crear partner
|
||||
- Vincular `contact.odoo_partner_id`
|
||||
|
||||
### Odoo → WhatsApp
|
||||
- Importar partners con campo `mobile` lleno
|
||||
- Filtrar por categoría/etiqueta si se desea
|
||||
- Ejecutar sync programado o manual
|
||||
|
||||
### Mapeo de Campos
|
||||
|
||||
| WhatsApp | Odoo |
|
||||
|----------|------|
|
||||
| phone_number | mobile |
|
||||
| name | name |
|
||||
| email | email |
|
||||
| company | parent_id.name |
|
||||
| tags | category_id |
|
||||
| custom.rfc | vat |
|
||||
| custom.direccion | street + city |
|
||||
|
||||
---
|
||||
|
||||
## Módulo Odoo
|
||||
|
||||
### Instalación
|
||||
|
||||
```bash
|
||||
# Copiar módulo a addons
|
||||
cp -r odoo_whatsapp_hub /odoo/addons/
|
||||
|
||||
# Actualizar lista de apps
|
||||
# En Odoo: Apps → Actualizar lista de aplicaciones
|
||||
|
||||
# Instalar módulo
|
||||
# Buscar "WhatsApp Hub" e instalar
|
||||
```
|
||||
|
||||
### Funcionalidades
|
||||
|
||||
1. **Tab WhatsApp en Partner**
|
||||
- Ver conversaciones del cliente
|
||||
- Historial de mensajes
|
||||
- Enviar mensaje rápido
|
||||
|
||||
2. **Widget de Chat**
|
||||
- Chat en tiempo real desde Odoo
|
||||
- Ver estado de conversación
|
||||
- Transferir a agente
|
||||
|
||||
3. **Acciones Automáticas**
|
||||
- Enviar WhatsApp al confirmar pedido
|
||||
- Notificar cambios de estado
|
||||
- Recordatorios automáticos
|
||||
|
||||
4. **Envío Masivo**
|
||||
- Seleccionar partners
|
||||
- Usar templates
|
||||
- Programar envío
|
||||
|
||||
---
|
||||
|
||||
## Mejores Prácticas
|
||||
|
||||
1. **Usa cache** para consultas frecuentes (productos, stock)
|
||||
2. **Limita llamadas** a Odoo para no saturar
|
||||
3. **Maneja errores** con fallback a agente humano
|
||||
4. **Valida permisos** del usuario API
|
||||
5. **Loguea transacciones** para auditoría
|
||||
6. **Sincroniza en horarios** de baja demanda
|
||||
Reference in New Issue
Block a user