docs: Actualizar README con documentacion completa
Documentacion completa incluyendo: - Arquitectura del proyecto con estructura de carpetas - Instalacion con Docker y manual - Variables de entorno completas (Mattermost, NocoDB, OCR, Reportes) - Uso del dashboard web y PWA - Todos los comandos de Mattermost - API endpoints completos (Dashboard, Analytics, Reportes, OCR) - Sistema de comisiones y bonos por racha - OCR: formatos soportados, preprocesamiento adaptativo, patrones - Analytics: algoritmo de prediccion, metricas, comparativas - Reportes PDF: diario y ejecutivo - Estructura de codigo y dependencias - Troubleshooting comun Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,186 +1,501 @@
|
|||||||
# Sales Bot - Aplicación Principal
|
# Sales Bot
|
||||||
|
|
||||||
Bot de automatización de ventas para Mattermost con procesamiento OCR de tickets.
|
Sistema de automatizacion de ventas para Mattermost con procesamiento OCR, analytics avanzados, reportes PDF y PWA.
|
||||||
|
|
||||||
|
## Caracteristicas
|
||||||
|
|
||||||
|
- **Bot de Mattermost**: Registro de ventas via chat con confirmacion
|
||||||
|
- **OCR Inteligente**: Extraccion automatica de datos de tickets con preprocesamiento adaptativo
|
||||||
|
- **Dashboard PWA**: Aplicacion web instalable con soporte offline
|
||||||
|
- **Analytics**: Graficas interactivas, predicciones y comparativas
|
||||||
|
- **Reportes PDF**: Generacion automatica de reportes diarios y ejecutivos
|
||||||
|
- **Sistema de Comisiones**: Calculo automatico con bonos por racha
|
||||||
|
- **Notificaciones Programadas**: Recordatorios y resumenes automaticos
|
||||||
|
|
||||||
## Arquitectura
|
## Arquitectura
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
sales-bot/
|
||||||
│ Sales Bot │
|
├── app.py # Aplicacion Flask principal
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
├── handlers.py # Manejadores de eventos de ventas
|
||||||
│ │
|
├── mattermost_client.py # Cliente API Mattermost
|
||||||
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
├── nocodb_client.py # Cliente API NocoDB
|
||||||
│ │ Flask │ │ WebSocket │ │ OCR Processor │ │
|
├── websocket_listener.py # Listener tiempo real
|
||||||
│ │ (app.py) │ │ Listener │ │ │ │
|
├── scheduler.py # Tareas programadas
|
||||||
│ └──────┬──────┘ └──────┬───────┘ └────────┬─────────┘ │
|
├── utils.py # Utilidades
|
||||||
│ │ │ │ │
|
├── export_utils.py # Exportacion Excel/CSV
|
||||||
│ └──────────────────┼──────────────────────┘ │
|
│
|
||||||
│ │ │
|
├── analytics/ # Modulo de analytics
|
||||||
│ ┌───────┴───────┐ │
|
│ ├── __init__.py
|
||||||
│ │ Handlers │ │
|
│ ├── predictions.py # Predicciones ML (promedio movil + regresion)
|
||||||
│ │ (handlers.py) │ │
|
│ ├── trends.py # Analisis de tendencias
|
||||||
│ └───────┬───────┘ │
|
│ └── comparisons.py # Comparativas temporales
|
||||||
│ │ │
|
│
|
||||||
│ ┌──────────────────┼──────────────────┐ │
|
├── reports/ # Modulo de reportes PDF
|
||||||
│ │ │ │ │
|
│ ├── __init__.py
|
||||||
│ ┌──────┴──────┐ ┌─────┴──────┐ ┌─────┴──────┐ │
|
│ └── pdf_generator.py # Generador con ReportLab
|
||||||
│ │ Mattermost │ │ NocoDB │ │ Utils │ │
|
│
|
||||||
│ │ Client │ │ Client │ │ │ │
|
├── ocr/ # Modulo OCR mejorado
|
||||||
│ └─────────────┘ └────────────┘ └────────────┘ │
|
│ ├── __init__.py
|
||||||
│ │
|
│ ├── processor.py # Procesador principal
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
│ ├── preprocessor.py # Preprocesamiento adaptativo
|
||||||
|
│ ├── patterns.py # Patrones de tickets
|
||||||
|
│ └── amount_detector.py # Detector de montos
|
||||||
|
│
|
||||||
|
├── templates/ # Templates HTML
|
||||||
|
│ ├── base.html # Template base con navbar
|
||||||
|
│ ├── dashboard.html # Dashboard principal
|
||||||
|
│ ├── analytics.html # Dashboard analytics
|
||||||
|
│ └── executive.html # Dashboard ejecutivo
|
||||||
|
│
|
||||||
|
├── static/ # Archivos estaticos
|
||||||
|
│ ├── css/main.css # Estilos principales
|
||||||
|
│ ├── js/
|
||||||
|
│ │ ├── app.js # Logica principal
|
||||||
|
│ │ ├── charts.js # Integracion Chart.js
|
||||||
|
│ │ ├── camera.js # Captura de camara
|
||||||
|
│ │ └── pwa.js # Service Worker
|
||||||
|
│ ├── manifest.json # Manifest PWA
|
||||||
|
│ └── service-worker.js # Cache offline
|
||||||
|
│
|
||||||
|
├── compose.yaml # Docker Compose
|
||||||
|
├── Dockerfile # Imagen Docker
|
||||||
|
├── requirements.txt # Dependencias Python
|
||||||
|
└── .env.example # Variables de entorno ejemplo
|
||||||
```
|
```
|
||||||
|
|
||||||
## Módulos
|
## Instalacion
|
||||||
|
|
||||||
### app.py
|
### Con Docker (Recomendado)
|
||||||
Aplicación Flask principal con los siguientes endpoints:
|
|
||||||
|
|
||||||
- `GET /health` - Health check
|
|
||||||
- `POST /webhook/mattermost` - Recibe webhooks de Mattermost
|
|
||||||
- `POST /webhook/nocodb` - Recibe webhooks de NocoDB
|
|
||||||
- `POST /comando/metas` - Comando slash /metas
|
|
||||||
- `POST /comando/ranking` - Comando slash /ranking
|
|
||||||
|
|
||||||
### handlers.py
|
|
||||||
Manejadores de eventos de ventas:
|
|
||||||
|
|
||||||
- `handle_venta_message()` - Procesa mensajes de venta
|
|
||||||
- `generar_reporte_diario()` - Genera reportes diarios
|
|
||||||
|
|
||||||
### mattermost_client.py
|
|
||||||
Cliente para la API de Mattermost:
|
|
||||||
|
|
||||||
```python
|
|
||||||
client = MattermostClient(url, token)
|
|
||||||
client.test_connection()
|
|
||||||
client.post_message(channel_id, message)
|
|
||||||
client.add_reaction(post_id, emoji)
|
|
||||||
client.get_file(file_id)
|
|
||||||
```
|
|
||||||
|
|
||||||
### nocodb_client.py
|
|
||||||
Cliente para la API de NocoDB:
|
|
||||||
|
|
||||||
```python
|
|
||||||
client = NocoDBClient(url, token)
|
|
||||||
client.crear_vendedor(username, nombre, email)
|
|
||||||
client.registrar_venta(vendedor, monto, cliente, imagen)
|
|
||||||
client.get_ventas_dia(vendedor, fecha)
|
|
||||||
client.get_ranking_vendedores(mes)
|
|
||||||
```
|
|
||||||
|
|
||||||
### ocr_processor.py
|
|
||||||
Procesador OCR para tickets:
|
|
||||||
|
|
||||||
```python
|
|
||||||
processor = OCRProcessor()
|
|
||||||
resultado = processor.procesar_imagen(imagen_bytes)
|
|
||||||
# Retorna: monto, fecha, productos, tubos_detectados
|
|
||||||
```
|
|
||||||
|
|
||||||
### websocket_listener.py
|
|
||||||
Listener para eventos en tiempo real de Mattermost:
|
|
||||||
|
|
||||||
```python
|
|
||||||
listener = MattermostWebsocketListener(url, token, callback)
|
|
||||||
listener.start() # Inicia en thread separado
|
|
||||||
```
|
|
||||||
|
|
||||||
### utils.py
|
|
||||||
Funciones de utilidad:
|
|
||||||
|
|
||||||
```python
|
|
||||||
extraer_monto(texto) # "@monto 1500" → 1500.0
|
|
||||||
extraer_cliente(texto) # "@cliente Juan" → "Juan"
|
|
||||||
extraer_tubos(texto) # "@tubos 5" → 5
|
|
||||||
formatear_moneda(1500) # → "$1,500.00"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Instalación con Docker
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Clonar repositorio
|
||||||
|
git clone https://git.consultoria-as.com/consultoria-as/sales-bot-stacks.git
|
||||||
|
cd sales-bot-stacks/sales-bot
|
||||||
|
|
||||||
|
# Configurar variables de entorno
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env # Editar con tus credenciales
|
||||||
|
|
||||||
|
# Construir e iniciar
|
||||||
|
docker compose build
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
|
# Verificar
|
||||||
|
curl http://localhost:5000/health
|
||||||
```
|
```
|
||||||
|
|
||||||
## Instalación Manual
|
### Instalacion Manual
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Instalar Tesseract
|
# Instalar Tesseract OCR
|
||||||
apt-get install tesseract-ocr tesseract-ocr-eng tesseract-ocr-spa
|
apt-get update
|
||||||
|
apt-get install -y tesseract-ocr tesseract-ocr-spa tesseract-ocr-eng
|
||||||
|
|
||||||
# Instalar dependencias Python
|
# Instalar dependencias Python
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Configurar variables
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env
|
||||||
|
|
||||||
# Ejecutar
|
# Ejecutar
|
||||||
python app.py
|
python app.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## Variables de Entorno
|
## Configuracion
|
||||||
|
|
||||||
| Variable | Descripción | Ejemplo |
|
### Variables de Entorno
|
||||||
|
|
||||||
|
| Variable | Descripcion | Ejemplo |
|
||||||
|----------|-------------|---------|
|
|----------|-------------|---------|
|
||||||
| MATTERMOST_URL | URL de Mattermost | http://192.168.10.204:8065 |
|
| **Mattermost** | | |
|
||||||
| MATTERMOST_BOT_TOKEN | Token del bot | xxx |
|
| `MATTERMOST_URL` | URL de Mattermost | `http://192.168.10.204:8065` |
|
||||||
| MATTERMOST_TEAM_NAME | Nombre del team | sales |
|
| `MATTERMOST_BOT_TOKEN` | Token del bot | `abc123...` |
|
||||||
| MATTERMOST_WEBHOOK_SECRET | Secret del webhook | xxx |
|
| `MATTERMOST_TEAM_NAME` | Nombre del equipo | `sales` |
|
||||||
| NOCODB_URL | URL de NocoDB | http://192.168.10.204:8080 |
|
| `MATTERMOST_WEBHOOK_SECRET` | Secret del webhook | `xyz789...` |
|
||||||
| NOCODB_TOKEN | Token de API | xxx |
|
| **NocoDB** | | |
|
||||||
| NOCODB_TABLE_* | IDs de tablas | xxx |
|
| `NOCODB_URL` | URL de NocoDB | `http://192.168.10.204:8080` |
|
||||||
| FLASK_PORT | Puerto de Flask | 5000 |
|
| `NOCODB_TOKEN` | Token de API | `abc123...` |
|
||||||
| LOG_LEVEL | Nivel de logging | INFO |
|
| `NOCODB_TABLE_VENDEDORES` | ID tabla vendedores | `tbl_xxx` |
|
||||||
| TZ_OFFSET | Offset de zona horaria | -6 |
|
| `NOCODB_TABLE_VENTAS` | ID tabla ventas | `tbl_xxx` |
|
||||||
|
| `NOCODB_TABLE_VENTAS_DETALLE` | ID tabla detalles | `tbl_xxx` |
|
||||||
|
| `NOCODB_TABLE_METAS` | ID tabla metas | `tbl_xxx` |
|
||||||
|
| **Flask** | | |
|
||||||
|
| `FLASK_PORT` | Puerto del servidor | `5000` |
|
||||||
|
| `FLASK_DEBUG` | Modo debug | `False` |
|
||||||
|
| **Scheduler** | | |
|
||||||
|
| `SCHEDULER_ENABLED` | Habilitar tareas | `True` |
|
||||||
|
| `RECORDATORIO_MEDIODIA_HORA` | Hora recordatorio | `12` |
|
||||||
|
| `RESUMEN_DIARIO_HORA` | Hora resumen diario | `18` |
|
||||||
|
| **Comisiones** | | |
|
||||||
|
| `META_DIARIA_TUBOS_DEFAULT` | Meta diaria tubos | `3` |
|
||||||
|
| `COMISION_POR_TUBO_DEFAULT` | Comision por tubo | `10` |
|
||||||
|
| `BONUS_3_DIAS` | Bonus 3 dias racha | `20` |
|
||||||
|
| `BONUS_5_DIAS` | Bonus 5 dias racha | `50` |
|
||||||
|
| `BONUS_10_DIAS` | Bonus 10 dias racha | `150` |
|
||||||
|
| **OCR** | | |
|
||||||
|
| `OCR_ENABLE_DESKEW` | Correccion rotacion | `true` |
|
||||||
|
| `OCR_MAX_ROTATION_ANGLE` | Angulo max rotacion | `15` |
|
||||||
|
| `OCR_CONFIDENCE_THRESHOLD` | Umbral confianza | `0.6` |
|
||||||
|
| `OCR_USE_ADAPTIVE_PIPELINE` | Pipeline adaptativo | `true` |
|
||||||
|
| **Reportes** | | |
|
||||||
|
| `REPORTS_OUTPUT_DIR` | Directorio reportes | `/app/reports` |
|
||||||
|
| `SCHEDULED_PDF_REPORT_ENABLED` | PDF automatico | `true` |
|
||||||
|
| `SCHEDULED_PDF_REPORT_HOUR` | Hora PDF diario | `18` |
|
||||||
|
|
||||||
## Formato de Mensajes de Venta
|
## Uso
|
||||||
|
|
||||||
El bot reconoce varios formatos:
|
### Dashboard Web
|
||||||
|
|
||||||
|
Accede al dashboard en: `http://tu-servidor:5000/dashboard`
|
||||||
|
|
||||||
|
**Funcionalidades del Dashboard:**
|
||||||
|
- KPIs en tiempo real (ventas hoy/mes, vendedores activos)
|
||||||
|
- Grafica de tendencias (7/14/30 dias) con predicciones
|
||||||
|
- Comparativas semanales y mensuales
|
||||||
|
- Ranking de vendedores con tubos y comisiones
|
||||||
|
- Tabla de Top Performers con % de meta
|
||||||
|
- Generacion de reportes PDF
|
||||||
|
- Captura de tickets desde camara (mobile)
|
||||||
|
|
||||||
|
**PWA (Progressive Web App):**
|
||||||
|
- Instalable en celular desde Chrome/Safari
|
||||||
|
- Funciona offline con datos cacheados
|
||||||
|
- Notificaciones push (futuro)
|
||||||
|
|
||||||
|
### Comandos de Mattermost
|
||||||
|
|
||||||
|
**Comandos Basicos:**
|
||||||
|
```
|
||||||
|
/metas - Ver tu progreso del mes
|
||||||
|
/ranking - Ver ranking de vendedores
|
||||||
|
/ayuda - Mostrar ayuda completa
|
||||||
|
```
|
||||||
|
|
||||||
|
**Comandos de Gestion:**
|
||||||
|
```
|
||||||
|
/cancelar <id> [motivo] - Cancelar una venta
|
||||||
|
/editar <id> @monto X @cliente Y - Editar una venta
|
||||||
|
/deshacer - Deshacer ultima venta (5 min)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Comandos de Comisiones:**
|
||||||
|
```
|
||||||
|
/comisiones - Ver historial de comisiones
|
||||||
|
/racha - Ver racha actual y bonos
|
||||||
|
/exportar [csv] [mes] - Exportar ventas a Excel/CSV
|
||||||
|
```
|
||||||
|
|
||||||
|
**Comandos de Reportes:**
|
||||||
|
```
|
||||||
|
/reporte diario - Generar PDF del dia
|
||||||
|
/reporte semanal - Generar PDF de la semana
|
||||||
|
/reporte ejecutivo - Generar PDF ejecutivo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Registro de Ventas
|
||||||
|
|
||||||
|
**Formatos Soportados:**
|
||||||
```
|
```
|
||||||
# Formato con @
|
# Formato con @
|
||||||
venta @monto 1500 @cliente Juan @tubos 5
|
venta @monto 1500 @cliente Juan Perez @tubos 5
|
||||||
|
|
||||||
# Formato con etiquetas
|
# Formato con etiquetas
|
||||||
venta monto: 1500 cliente: Juan
|
venta monto: 1500 cliente: Juan
|
||||||
|
|
||||||
# Formato natural
|
# Formato natural
|
||||||
venta $1,500 a Juan
|
venta $1,500 a Juan Perez
|
||||||
|
|
||||||
|
# Con foto de ticket (OCR automatico)
|
||||||
|
[Adjuntar imagen del ticket]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Procesamiento OCR
|
**Flujo de Confirmacion:**
|
||||||
|
1. Envias mensaje de venta o foto de ticket
|
||||||
|
2. El bot muestra preview con datos extraidos
|
||||||
|
3. Respondes **si** para confirmar o **no** para cancelar
|
||||||
|
4. Timeout de 2 minutos si no respondes
|
||||||
|
|
||||||
El procesador OCR detecta automáticamente:
|
## API Endpoints
|
||||||
- Monto total
|
|
||||||
- Fecha del ticket
|
### Dashboard
|
||||||
- Lista de productos
|
| Metodo | Endpoint | Descripcion |
|
||||||
- Cantidad de tubos de tinte
|
|--------|----------|-------------|
|
||||||
|
| GET | `/dashboard` | Dashboard principal |
|
||||||
|
| GET | `/dashboard/analytics` | Dashboard analytics |
|
||||||
|
| GET | `/dashboard/executive` | Dashboard ejecutivo |
|
||||||
|
|
||||||
|
### API Dashboard
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/dashboard/resumen` | KPIs del dia y mes |
|
||||||
|
| GET | `/api/dashboard/ranking` | Ranking vendedores |
|
||||||
|
| GET | `/api/dashboard/ventas-recientes` | Ultimas ventas |
|
||||||
|
| GET | `/api/dashboard/metas` | Estado de metas |
|
||||||
|
|
||||||
|
### API Analytics
|
||||||
|
| Metodo | Endpoint | Params | Descripcion |
|
||||||
|
|--------|----------|--------|-------------|
|
||||||
|
| GET | `/api/analytics/trends` | `days`, `vendedor` | Tendencias de ventas |
|
||||||
|
| GET | `/api/analytics/predictions` | `days`, `predict` | Predicciones ML |
|
||||||
|
| GET | `/api/analytics/comparisons` | `type` (weekly/monthly/yearly) | Comparativas |
|
||||||
|
| GET | `/api/analytics/performance/<username>` | - | Rendimiento vendedor |
|
||||||
|
|
||||||
|
### API Reportes
|
||||||
|
| Metodo | Endpoint | Body | Descripcion |
|
||||||
|
|--------|----------|------|-------------|
|
||||||
|
| POST | `/api/reports/generate` | `{type, vendedor}` | Generar PDF |
|
||||||
|
| GET | `/api/reports/download/<id>` | - | Descargar PDF |
|
||||||
|
|
||||||
|
### API OCR
|
||||||
|
| Metodo | Endpoint | Body | Descripcion |
|
||||||
|
|--------|----------|------|-------------|
|
||||||
|
| POST | `/api/capture/ticket` | `{image, user_name}` | Procesar ticket base64 |
|
||||||
|
|
||||||
|
### Webhooks
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| POST | `/webhook/mattermost` | Webhook saliente Mattermost |
|
||||||
|
| POST | `/webhook/nocodb` | Webhook NocoDB |
|
||||||
|
|
||||||
|
### Comandos Slash
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| POST | `/comando/metas` | Comando /metas |
|
||||||
|
| POST | `/comando/ranking` | Comando /ranking |
|
||||||
|
| POST | `/comando/ayuda` | Comando /ayuda |
|
||||||
|
| POST | `/comando/cancelar` | Comando /cancelar |
|
||||||
|
| POST | `/comando/editar` | Comando /editar |
|
||||||
|
| POST | `/comando/deshacer` | Comando /deshacer |
|
||||||
|
| POST | `/comando/comisiones` | Comando /comisiones |
|
||||||
|
| POST | `/comando/racha` | Comando /racha |
|
||||||
|
| POST | `/comando/exportar` | Comando /exportar |
|
||||||
|
| POST | `/comando/reporte` | Comando /reporte |
|
||||||
|
|
||||||
|
### Utilidades
|
||||||
|
| Metodo | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/health` | Health check |
|
||||||
|
| GET | `/manifest.json` | PWA manifest |
|
||||||
|
| GET | `/service-worker.js` | Service worker |
|
||||||
|
| POST | `/reporte/diario` | Generar reporte manual |
|
||||||
|
| GET | `/test/mattermost` | Test conexion Mattermost |
|
||||||
|
| GET | `/test/nocodb` | Test conexion NocoDB |
|
||||||
|
|
||||||
|
## Sistema de Comisiones
|
||||||
|
|
||||||
|
### Calculo de Comisiones
|
||||||
|
```
|
||||||
|
Meta diaria: 3 tubos
|
||||||
|
Comision: $10 por tubo despues de meta
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
- Vendiste 7 tubos
|
||||||
|
- Tubos comisionables: 7 - 3 = 4
|
||||||
|
- Comision: 4 x $10 = $40
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bonos por Racha
|
||||||
|
| Dias Consecutivos | Bonus |
|
||||||
|
|-------------------|-------|
|
||||||
|
| 3 dias | $20 |
|
||||||
|
| 5 dias | $50 |
|
||||||
|
| 10 dias | $150 |
|
||||||
|
|
||||||
|
### Niveles de Racha
|
||||||
|
- **CONSTRUYENDO**: 0-2 dias
|
||||||
|
- **RACHA ACTIVA**: 3-4 dias
|
||||||
|
- **EN FUEGO**: 5-9 dias
|
||||||
|
- **LEGENDARIO**: 10+ dias
|
||||||
|
|
||||||
|
## OCR - Procesamiento de Tickets
|
||||||
|
|
||||||
|
### Formatos Soportados
|
||||||
|
- OXXO
|
||||||
|
- Walmart / Bodega Aurrera
|
||||||
|
- Soriana
|
||||||
|
- 7-Eleven
|
||||||
|
- Farmacias (Guadalajara, Similares, etc.)
|
||||||
|
- Tiendas de pintura/tinte (Cromatique, etc.)
|
||||||
|
- Tickets genericos
|
||||||
|
|
||||||
|
### Preprocesamiento Adaptativo
|
||||||
|
El sistema detecta automaticamente la mejor configuracion:
|
||||||
|
- **Standard**: Tickets con buena iluminacion
|
||||||
|
- **Low Contrast**: Tickets deslavados
|
||||||
|
- **Noisy**: Tickets con ruido/manchas
|
||||||
|
- **Rotated**: Tickets inclinados (hasta 15 grados)
|
||||||
|
- **Dark**: Tickets oscuros
|
||||||
|
- **Light**: Tickets sobreexpuestos
|
||||||
|
|
||||||
|
### Patrones de Monto Detectados
|
||||||
|
1. `TOTAL A PAGAR: $X,XXX.XX`
|
||||||
|
2. `GRAN TOTAL: $X,XXX.XX`
|
||||||
|
3. `TOTAL: $X,XXX.XX`
|
||||||
|
4. `IMPORTE: $X,XXX.XX`
|
||||||
|
5. `A COBRAR: $X,XXX.XX`
|
||||||
|
6. `SUMA: $X,XXX.XX`
|
||||||
|
7. `SUBTOTAL: $X,XXX.XX`
|
||||||
|
|
||||||
### Marcas de Tinte Reconocidas
|
### Marcas de Tinte Reconocidas
|
||||||
- Alfaparf Evolution
|
- Alfaparf Evolution
|
||||||
- Wella Koleston
|
- Wella Koleston
|
||||||
- Loreal
|
- Loreal Majirel
|
||||||
- Matrix
|
- Matrix SoColor
|
||||||
- Schwarzkopf
|
- Schwarzkopf Igora
|
||||||
- Revlon
|
- Revlon
|
||||||
- Igora
|
- Cromatique
|
||||||
- Majirel
|
|
||||||
|
|
||||||
## Sistema de Comisiones
|
## Analytics y Predicciones
|
||||||
|
|
||||||
|
### Algoritmo de Prediccion
|
||||||
|
Combina dos metodos:
|
||||||
|
1. **Promedio Movil**: Ultimos 7 dias
|
||||||
|
2. **Regresion Lineal**: Tendencia historica
|
||||||
|
|
||||||
```python
|
```python
|
||||||
META_DIARIA_TUBOS = 3
|
prediccion = (promedio_movil + prediccion_lineal) / 2
|
||||||
COMISION_POR_TUBO = 10 # $10 MXN
|
|
||||||
|
|
||||||
def calcular_comision(tubos_vendidos):
|
|
||||||
if tubos_vendidos > META_DIARIA_TUBOS:
|
|
||||||
return (tubos_vendidos - META_DIARIA_TUBOS) * COMISION_POR_TUBO
|
|
||||||
return 0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Logs
|
### Metricas Disponibles
|
||||||
|
- **Tendencia**: Increasing / Stable / Decreasing
|
||||||
|
- **Confianza**: 0-100% (basado en R-squared)
|
||||||
|
- **Predicciones**: Siguiente dia, 3 dias, semana
|
||||||
|
|
||||||
Los logs se escriben en `/app/logs/sales-bot.log` con formato:
|
### Comparativas
|
||||||
|
- **Semanal**: Esta semana vs anterior
|
||||||
|
- **Mensual**: Este mes vs anterior (3 meses)
|
||||||
|
- **Anual**: YTD actual vs YTD anterior
|
||||||
|
|
||||||
|
## Reportes PDF
|
||||||
|
|
||||||
|
### Reporte Diario
|
||||||
|
- Resumen de KPIs del dia
|
||||||
|
- Grafica de tendencias
|
||||||
|
- Top 5 vendedores
|
||||||
|
- Detalle de ventas
|
||||||
|
|
||||||
|
### Reporte Ejecutivo
|
||||||
|
- KPIs del mes
|
||||||
|
- Comparativas mensuales
|
||||||
|
- Ranking completo
|
||||||
|
- Graficas de rendimiento
|
||||||
|
- Proyecciones
|
||||||
|
|
||||||
|
## Desarrollo
|
||||||
|
|
||||||
|
### Estructura de Codigo
|
||||||
|
|
||||||
|
**app.py** - Aplicacion principal
|
||||||
|
```python
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Rutas del dashboard
|
||||||
|
@app.route('/dashboard')
|
||||||
|
@app.route('/dashboard/analytics')
|
||||||
|
@app.route('/dashboard/executive')
|
||||||
|
|
||||||
|
# API endpoints
|
||||||
|
@app.route('/api/dashboard/...')
|
||||||
|
@app.route('/api/analytics/...')
|
||||||
|
@app.route('/api/reports/...')
|
||||||
|
|
||||||
|
# Comandos slash
|
||||||
|
@app.route('/comando/...')
|
||||||
```
|
```
|
||||||
2024-01-15 10:30:45 INFO [app] Venta registrada: $1,500.00 - Juan - vendedor1
|
|
||||||
|
**analytics/predictions.py** - Predicciones
|
||||||
|
```python
|
||||||
|
def prediccion_basica(ventas_diarias, dias_prediccion=7):
|
||||||
|
# Promedio movil + regresion lineal
|
||||||
|
return {
|
||||||
|
'predicciones': [...],
|
||||||
|
'tendencia': 'increasing|stable|decreasing',
|
||||||
|
'confidence': 0.85
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**ocr/processor.py** - OCR
|
||||||
|
```python
|
||||||
|
processor = OCRProcessor()
|
||||||
|
result = processor.process(image_bytes)
|
||||||
|
# result: {texto, monto, cliente, fecha, tubos, formato, confianza}
|
||||||
|
```
|
||||||
|
|
||||||
|
**reports/pdf_generator.py** - PDFs
|
||||||
|
```python
|
||||||
|
pdf = SalesReportPDF(ventas, stats)
|
||||||
|
content = pdf.generar_reporte_diario()
|
||||||
|
# content: bytes del PDF
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencias Principales
|
||||||
|
|
||||||
|
```txt
|
||||||
|
# Web Framework
|
||||||
|
Flask==3.0.0
|
||||||
|
gunicorn==21.2.0
|
||||||
|
|
||||||
|
# OCR
|
||||||
|
pytesseract==0.3.10
|
||||||
|
Pillow==10.2.0
|
||||||
|
opencv-python==4.9.0.80
|
||||||
|
|
||||||
|
# PDF
|
||||||
|
reportlab==4.1.0
|
||||||
|
matplotlib==3.8.2
|
||||||
|
|
||||||
|
# Analytics
|
||||||
|
scipy==1.12.0
|
||||||
|
pandas==2.1.4
|
||||||
|
numpy==1.26.3
|
||||||
|
|
||||||
|
# OCR Mejorado
|
||||||
|
imutils==0.5.4
|
||||||
|
deskew==1.1.0
|
||||||
|
|
||||||
|
# Mattermost
|
||||||
|
mattermostdriver==7.3.2
|
||||||
|
|
||||||
|
# Scheduler
|
||||||
|
APScheduler==3.10.4
|
||||||
|
|
||||||
|
# Excel
|
||||||
|
openpyxl==3.1.2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### El dashboard no carga
|
||||||
|
```bash
|
||||||
|
# Verificar que el contenedor esta corriendo
|
||||||
|
docker ps | grep sales-bot
|
||||||
|
|
||||||
|
# Ver logs
|
||||||
|
docker logs sales-bot --tail 100
|
||||||
|
|
||||||
|
# Reconstruir imagen
|
||||||
|
docker compose build --no-cache
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### OCR no detecta el monto
|
||||||
|
- Verificar que la imagen tenga buena iluminacion
|
||||||
|
- Probar con imagen de mayor resolucion
|
||||||
|
- El ticket no debe estar muy inclinado (max 15 grados)
|
||||||
|
|
||||||
|
### Predicciones muestran 0
|
||||||
|
- Se requieren al menos 3 dias de datos historicos
|
||||||
|
- Verificar que hay ventas registradas
|
||||||
|
|
||||||
|
### PDF no se genera
|
||||||
|
```bash
|
||||||
|
# Verificar que reportlab esta instalado
|
||||||
|
docker exec sales-bot pip list | grep reportlab
|
||||||
|
|
||||||
|
# Si no esta, reconstruir imagen
|
||||||
|
docker compose build --no-cache
|
||||||
```
|
```
|
||||||
|
|
||||||
## Health Check
|
## Health Check
|
||||||
@@ -193,7 +508,15 @@ Respuesta:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"status": "healthy",
|
"status": "healthy",
|
||||||
"timestamp": "2024-01-15T10:30:45",
|
"timestamp": "2026-01-19T10:30:45",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Licencia
|
||||||
|
|
||||||
|
Proyecto privado - Consultoria AS
|
||||||
|
|
||||||
|
## Contacto
|
||||||
|
|
||||||
|
Para soporte tecnico contactar al equipo de desarrollo.
|
||||||
|
|||||||
Reference in New Issue
Block a user