diff --git a/docs/AB_TESTING.md b/docs/AB_TESTING.md new file mode 100644 index 0000000..06dc880 --- /dev/null +++ b/docs/AB_TESTING.md @@ -0,0 +1,297 @@ +# A/B Testing + +Sistema de pruebas A/B para optimizar contenido y maximizar engagement. + +## Descripción + +El A/B Testing permite comparar diferentes versiones de contenido para determinar cuál tiene mejor rendimiento. El sistema: + +1. Crea múltiples variantes de contenido +2. Publica cada variante +3. Recopila métricas de cada una +4. Determina estadísticamente el ganador + +## Modelos de Datos + +### ABTest + +```python +ABTest: + id: int + name: str + description: str + test_type: str # content, timing, hashtags, image + + platform: str # x, threads, instagram, facebook + status: str # draft, running, completed, cancelled + + started_at: datetime + ended_at: datetime + duration_hours: int # Duración del test (default 24) + + winning_variant_id: int (FK) + confidence_level: float # Nivel de confianza estadística + + min_sample_size: int # Mín impresiones por variante (default 100) + success_metric: str # engagement_rate, likes, comments, shares +``` + +### ABTestVariant + +```python +ABTestVariant: + id: int + test_id: int (FK -> ab_tests) + name: str # A, B, C, D + + content: str + hashtags: JSON + image_url: str + + post_id: int (FK -> posts) + + # Métricas + impressions: int + reach: int + likes: int + comments: int + shares: int + clicks: int + engagement_rate: float + + is_winner: bool + published_at: datetime +``` + +## API Endpoints + +### GET /api/ab-tests/ +Lista todos los tests A/B. + +**Parámetros:** +- `status`: draft, running, completed, cancelled +- `platform`: x, threads, etc. +- `limit` (int, default=20) + +**Respuesta:** +```json +{ + "tests": [ + { + "id": 1, + "name": "Test de copies", + "platform": "x", + "status": "running", + "variants": [...] + } + ], + "count": 5 +} +``` + +### GET /api/ab-tests/{test_id} +Obtiene un test específico con sus variantes. + +### POST /api/ab-tests/ +Crea un nuevo test A/B. + +**Body:** +```json +{ + "name": "Test de copies para tips", + "platform": "x", + "variants": [ + { + "name": "A", + "content": "💡 Tip: Automatiza tus procesos con IA...", + "hashtags": ["#IA", "#Automatización"] + }, + { + "name": "B", + "content": "¿Sabías que la IA puede ahorrarte 10 horas semanales?...", + "hashtags": ["#Productividad", "#Tech"] + } + ], + "test_type": "content", + "duration_hours": 24, + "min_sample_size": 100, + "success_metric": "engagement_rate" +} +``` + +**Validaciones:** +- Mínimo 2 variantes, máximo 4 +- Cada variante debe tener contenido + +### POST /api/ab-tests/{test_id}/start +Inicia un test A/B. + +**Proceso:** +1. Crea posts para cada variante +2. Programa publicación (escalonada cada 5 min) +3. Cambia status a "running" +4. Registra start_time + +**Respuesta:** +```json +{ + "message": "A/B test started successfully", + "success": true, + "test_id": 1, + "post_ids": [101, 102], + "variants_count": 2 +} +``` + +### POST /api/ab-tests/{test_id}/evaluate +Evalúa resultados y determina ganador. + +**Proceso:** +1. Actualiza métricas de cada variante +2. Verifica tamaño de muestra mínimo +3. Ejecuta test estadístico (chi-square) +4. Determina ganador y confianza +5. Si duration_hours pasó, marca como completed + +**Respuesta:** +```json +{ + "success": true, + "winner": { + "variant_id": 1, + "name": "A", + "engagement_rate": 4.5, + "impressions": 1500 + }, + "runner_up": { + "variant_id": 2, + "name": "B", + "engagement_rate": 3.2, + "impressions": 1400 + }, + "confidence_level": 95.5, + "p_value": 0.045, + "test_status": "completed" +} +``` + +**Si datos insuficientes:** +```json +{ + "success": true, + "status": "insufficient_data", + "min_impressions": 50, + "required": 100 +} +``` + +### GET /api/ab-tests/{test_id}/results +Obtiene resultados actuales (sin determinar ganador). + +### POST /api/ab-tests/{test_id}/cancel +Cancela un test en progreso. + +## Tareas Programadas + +### evaluate_ab_tests +- **Frecuencia:** Cada hora +- **Función:** + - Busca tests en estado "running" + - Si pasó duration_hours, evalúa y completa + - Si no, solo actualiza métricas + +## Tipos de Test + +| Tipo | Descripción | +|------|-------------| +| `content` | Prueba diferentes textos | +| `timing` | Prueba diferentes horarios | +| `hashtags` | Prueba diferentes conjuntos de hashtags | +| `image` | Prueba diferentes imágenes | + +## Métricas de Éxito + +| Métrica | Descripción | +|---------|-------------| +| `engagement_rate` | (likes + comments + shares) / impressions | +| `likes` | Total de likes | +| `comments` | Total de comentarios | +| `shares` | Total de compartidos | +| `clicks` | Total de clics (si aplica) | + +## Análisis Estadístico + +El sistema usa el **test chi-cuadrado** para determinar significancia estadística: + +```python +# Tabla de contingencia +[ + [engagements_A, non_engagements_A], + [engagements_B, non_engagements_B] +] + +chi2, p_value, dof, expected = scipy.stats.chi2_contingency(tabla) +confidence = (1 - p_value) * 100 +``` + +### Interpretación + +| p-value | Confianza | Interpretación | +|---------|-----------|----------------| +| < 0.01 | > 99% | Muy significativo | +| < 0.05 | > 95% | Significativo | +| < 0.10 | > 90% | Marginalmente significativo | +| ≥ 0.10 | < 90% | No significativo | + +## Flujo de Trabajo + +``` +1. Crear Test (status: draft) + ↓ +2. Iniciar Test (status: running) + - Crea posts para variantes + - Programa publicación + ↓ +3. Esperar duración + - Sistema recopila métricas cada 15 min + - Evalúa cada hora + ↓ +4. Evaluar Resultados (status: completed) + - Determina ganador estadístico + - Calcula nivel de confianza +``` + +## Ejemplo de Uso + +```python +from app.services.ab_testing_service import ab_testing_service + +# Crear test +test = await ab_testing_service.create_test( + name="Test de engagement", + platform="x", + variants=[ + {"name": "A", "content": "Versión corta y directa"}, + {"name": "B", "content": "Versión más elaborada con detalles"} + ], + duration_hours=48, + min_sample_size=200 +) + +# Iniciar +result = await ab_testing_service.start_test(test.id) + +# Evaluar (después de publicado) +results = await ab_testing_service.evaluate_test(test.id) +if results.get("winner"): + print(f"Ganador: Variante {results['winner']['name']}") + print(f"Confianza: {results['confidence_level']:.1f}%") +``` + +## Mejores Prácticas + +1. **Tamaño de muestra:** Espera al menos 100 impresiones por variante +2. **Una variable:** Prueba solo un elemento a la vez +3. **Duración:** Mínimo 24 horas para datos representativos +4. **Horarios:** Publica variantes en horarios similares +5. **Confianza:** Busca > 95% antes de tomar decisiones diff --git a/docs/ANALYTICS.md b/docs/ANALYTICS.md new file mode 100644 index 0000000..c40d2cf --- /dev/null +++ b/docs/ANALYTICS.md @@ -0,0 +1,264 @@ +# Analytics y Reportes + +Sistema completo de métricas y análisis de rendimiento para optimizar tu estrategia de contenido. + +## Modelos de Datos + +### PostMetrics +Registra métricas de cada post a lo largo del tiempo. + +```python +PostMetrics: + id: int + post_id: int (FK -> posts) + platform: str # x, threads, instagram, facebook + likes: int + comments: int + shares: int + impressions: int + reach: int + saves: int + clicks: int + replies: int + quotes: int + engagement_rate: float + recorded_at: datetime +``` + +### AnalyticsReport +Reportes agregados (diarios, semanales, mensuales). + +```python +AnalyticsReport: + id: int + report_type: str # daily, weekly, monthly + period_start: date + period_end: date + platform: str (opcional) + total_posts: int + total_impressions: int + total_engagements: int + avg_engagement_rate: float + top_posts: JSON # Lista de mejores posts + best_times: JSON # Mejores horarios + content_performance: JSON # Por tipo de contenido + platform_breakdown: JSON # Por plataforma + summary_text: str # Texto para Telegram +``` + +## API Endpoints + +### GET /api/analytics/dashboard +Obtiene datos del dashboard principal. + +**Parámetros:** +- `days` (int, default=30): Período a analizar +- `platform` (str, opcional): Filtrar por plataforma + +**Respuesta:** +```json +{ + "period_days": 30, + "total_posts": 45, + "total_impressions": 125000, + "total_engagements": 3500, + "total_likes": 2800, + "total_comments": 450, + "total_shares": 250, + "avg_engagement_rate": 2.8, + "platform_breakdown": { + "x": {"posts": 20, "engagements": 1500}, + "threads": {"posts": 25, "engagements": 2000} + }, + "content_breakdown": { + "tip_tech": {"posts": 15, "engagements": 1200}, + "producto": {"posts": 10, "engagements": 800} + }, + "pending_interactions": 12 +} +``` + +### GET /api/analytics/top-posts +Obtiene los posts con mejor rendimiento. + +**Parámetros:** +- `days` (int, default=30): Período a analizar +- `limit` (int, default=10): Máximo de posts +- `platform` (str, opcional): Filtrar por plataforma + +**Respuesta:** +```json +{ + "posts": [ + { + "id": 123, + "content": "Tip: Usa IA para...", + "content_type": "tip_tech", + "platforms": ["x", "threads"], + "published_at": "2025-01-15T10:00:00", + "likes": 150, + "comments": 25, + "shares": 30, + "impressions": 5000, + "engagement_rate": 4.1 + } + ], + "count": 10 +} +``` + +### GET /api/analytics/optimal-times +Calcula los mejores horarios para publicar basado en datos históricos. + +**Parámetros:** +- `platform` (str, opcional): Filtrar por plataforma +- `days` (int, default=90): Días de datos a analizar + +**Respuesta:** +```json +{ + "optimal_times": [ + { + "day": 1, + "day_name": "Mar", + "hour": 12, + "hour_formatted": "12:00", + "avg_engagement_rate": 4.5, + "sample_size": 15 + } + ], + "analysis_period_days": 90, + "platform": "x" +} +``` + +### GET /api/analytics/engagement-trend +Obtiene tendencia de engagement para gráficos. + +**Parámetros:** +- `days` (int, default=30): Período +- `platform` (str, opcional): Plataforma + +**Respuesta:** +```json +{ + "trend": [ + { + "date": "2025-01-01", + "posts": 3, + "impressions": 5000, + "engagements": 200 + } + ], + "period_days": 30, + "platform": null +} +``` + +### GET /api/analytics/reports +Obtiene reportes históricos. + +**Parámetros:** +- `report_type` (str): daily, weekly, monthly +- `limit` (int, default=10): Máximo de reportes + +### POST /api/analytics/reports/generate +Genera un nuevo reporte. + +**Parámetros:** +- `report_type` (str): weekly (otros tipos próximamente) + +### POST /api/analytics/reports/send-telegram +Genera y envía reporte por Telegram. + +### GET /api/analytics/posts/{post_id}/metrics +Obtiene métricas detalladas de un post específico. + +**Respuesta:** +```json +{ + "post_id": 123, + "current_metrics": {"likes": 150, "comments": 25}, + "published_at": "2025-01-15T10:00:00", + "platforms": ["x", "threads"], + "metrics_history": [ + { + "recorded_at": "2025-01-15T12:00:00", + "likes": 50, + "comments": 10, + "engagement_rate": 2.5 + } + ] +} +``` + +## Tareas Programadas + +### fetch_post_metrics +- **Frecuencia:** Cada 15 minutos +- **Función:** Obtiene métricas actualizadas de las APIs de cada plataforma +- **Posts afectados:** Publicados en los últimos 7 días + +### generate_weekly_analytics_report +- **Frecuencia:** Domingos a las 9:00 AM +- **Función:** Genera reporte semanal completo +- **Acciones:** + - Calcula métricas agregadas + - Compara con semana anterior + - Genera texto para Telegram + - Envía notificación (si está configurado) + +### recalculate_optimal_times +- **Frecuencia:** Lunes a las 2:00 AM +- **Función:** Recalcula mejores horarios basado en últimos 90 días + +## Dashboard + +Accede al dashboard de analytics en `/dashboard/analytics`. + +### Características: +- **Cards de métricas:** Posts, impresiones, engagements, tasa +- **Gráfico de tendencia:** Chart.js con impresiones y engagements +- **Desglose por plataforma:** Comparativa visual +- **Top posts:** Lista de mejores performers +- **Mejores horarios:** Mapa de calor visual +- **Rendimiento por contenido:** Por tipo de publicación + +## Configuración + +```bash +# .env +ANALYTICS_FETCH_INTERVAL=15 # minutos +TELEGRAM_REPORT_ENABLED=true +TELEGRAM_REPORT_DAY=6 # 0=Lunes, 6=Domingo +``` + +## Ejemplo de Uso + +```python +from app.services.analytics_service import analytics_service + +# Obtener stats del dashboard +stats = await analytics_service.get_dashboard_stats(days=30, platform="x") + +# Obtener top posts +top = await analytics_service.get_top_posts(days=7, limit=5) + +# Generar reporte semanal +report = await analytics_service.generate_weekly_report() +print(report.summary_text) # Texto formateado para Telegram +``` + +## Cálculos + +### Engagement Rate +``` +engagement_rate = (likes + comments + shares) / impressions * 100 +``` + +### Score de Horario Óptimo +``` +Para cada combinación (día, hora): + promedio_engagement = sum(engagement_rates) / count(posts) + ordenar por promedio_engagement descendente +``` diff --git a/docs/CONTENT_RECYCLING.md b/docs/CONTENT_RECYCLING.md new file mode 100644 index 0000000..0a7d7dc --- /dev/null +++ b/docs/CONTENT_RECYCLING.md @@ -0,0 +1,267 @@ +# Reciclaje de Contenido + +Sistema para republica contenido exitoso y maximizar su alcance. + +## Descripción + +El reciclaje de contenido permite: +- Identificar posts con alto engagement +- Republicarlos con modificaciones opcionales +- Trackear rendimiento de versiones recicladas +- Automatizar el proceso de reciclaje + +## Modelo de Datos + +### RecycledPost + +```python +RecycledPost: + id: int + original_post_id: int (FK -> posts) + new_post_id: int (FK -> posts) + + recycle_number: int # 1, 2, 3... (veces reciclado) + + modifications: JSON + # {"content_changed": true, "hashtags_updated": true, "image_changed": false} + + modification_notes: str + + original_engagement_rate: float + new_engagement_rate: float + + status: str # pending, published, cancelled + reason: str # high_performer, evergreen, seasonal, manual + + recycled_at: datetime + scheduled_for: datetime +``` + +### Campos en Post + +```python +# Campos añadidos al modelo Post +is_recyclable: bool # Si puede ser reciclado (default True) +recycled_from_id: int (FK -> posts) # Post original si es reciclado +recycle_count: int # Veces que este post ha sido reciclado +``` + +## Configuración + +```python +# En recycling_service.py +MIN_DAYS_SINCE_PUBLISH = 30 # No reciclar posts recientes +MIN_ENGAGEMENT_RATE = 2.0 # Mínimo 2% engagement +MAX_RECYCLE_COUNT = 3 # Máximo 3 veces por post +``` + +## API Endpoints + +### GET /api/recycling/candidates +Obtiene posts candidatos para reciclar. + +**Parámetros:** +- `platform` (str): Filtrar por plataforma +- `content_type` (str): Filtrar por tipo de contenido +- `min_engagement_rate` (float, default=2.0): Engagement mínimo +- `min_days` (int, default=30): Días desde publicación +- `limit` (int, default=20): Máximo candidatos + +**Respuesta:** +```json +{ + "candidates": [ + { + "id": 123, + "content": "Tip: Usa IA para automatizar...", + "full_content": "...", + "content_type": "tip_tech", + "platforms": ["x"], + "published_at": "2024-12-01T10:00:00", + "days_since_publish": 58, + "engagement_rate": 4.5, + "recycle_count": 0, + "score": 3.8, + "metrics": {"likes": 150, "comments": 30} + } + ], + "count": 10, + "filters": { + "min_engagement_rate": 2.0, + "min_days": 30 + } +} +``` + +### POST /api/recycling/{post_id} +Recicla un post específico. + +**Body (opcional):** +```json +{ + "content": "Versión actualizada del contenido...", + "hashtags": ["#nuevo", "#hashtag"], + "image_url": "https://...", + "scheduled_for": "2025-02-01T10:00:00", + "platforms": ["x", "threads"], + "reason": "high_performer" +} +``` + +**Respuesta:** +```json +{ + "message": "Post recycled successfully", + "success": true, + "new_post_id": 456, + "recycle_record_id": 1, + "scheduled_for": "2025-02-01T10:00:00", + "platforms": ["x", "threads"] +} +``` + +### POST /api/recycling/auto +Reciclaje automático de mejores posts. + +**Parámetros:** +- `platform` (str, opcional): Plataforma específica +- `count` (int, default=1, max=5): Cantidad a reciclar +- `min_engagement_rate` (float, default=2.0) + +**Respuesta:** +```json +{ + "success": true, + "recycled": 2, + "posts": [ + { + "original_id": 123, + "new_post_id": 456, + "engagement_rate": 4.5 + } + ] +} +``` + +### GET /api/recycling/history +Obtiene historial de reciclaje. + +**Parámetros:** +- `original_post_id` (int, opcional): Filtrar por post original +- `limit` (int, default=50) + +### POST /api/recycling/{post_id}/disable +Marca un post como no reciclable. + +## Sistema de Puntuación + +Los candidatos se puntúan con la fórmula: + +```python +score = engagement_rate * recency_factor * recycled_penalty + +donde: + recency_factor = min(days_since_publish / 90, 1.0) + recycled_penalty = 1 - (recycle_count * 0.2) +``` + +### Ejemplo + +| Post | Engagement | Días | Reciclajes | Score | +|------|------------|------|------------|-------| +| A | 4.0% | 60 | 0 | 4.0 × 0.67 × 1.0 = 2.68 | +| B | 5.0% | 90 | 1 | 5.0 × 1.0 × 0.8 = 4.00 | +| C | 3.0% | 45 | 0 | 3.0 × 0.5 × 1.0 = 1.50 | + +Post B tiene el score más alto. + +## Tareas Programadas + +### auto_recycle_content +- **Frecuencia:** Diario a las 2:00 AM +- **Función:** + - Busca 1 post por plataforma con engagement > 3% + - Programa reciclaje automático +- **Plataformas:** x, threads + +## Flujo de Reciclaje + +``` +1. Identificar Candidatos + - Posts con > 30 días de antigüedad + - Engagement rate > 2% + - recycle_count < 3 + - is_recyclable = true + ↓ +2. Seleccionar por Score + - Ordenar por score descendente + ↓ +3. Crear Post Reciclado + - Clonar contenido (o modificar) + - Establecer recycled_from_id + - Programar publicación + ↓ +4. Registrar en RecycledPost + - Guardar relación + - Incrementar recycle_count del original + ↓ +5. Publicar y Trackear + - Comparar new_engagement_rate vs original +``` + +## Razones de Reciclaje + +| Razón | Descripción | +|-------|-------------| +| `high_performer` | Post con engagement alto | +| `evergreen` | Contenido atemporal relevante | +| `seasonal` | Contenido de temporada que regresa | +| `manual` | Reciclado manualmente | + +## Ejemplo de Uso + +```python +from app.services.recycling_service import recycling_service + +# Buscar candidatos +candidates = await recycling_service.find_recyclable_posts( + platform="x", + min_engagement_rate=3.0, + limit=10 +) + +for candidate in candidates: + print(f"Post {candidate['id']}: {candidate['engagement_rate']}% - Score {candidate['score']}") + +# Reciclar manualmente +result = await recycling_service.recycle_post( + post_id=123, + modifications={"content": "Versión actualizada..."}, + reason="evergreen" +) + +# Reciclaje automático +result = await recycling_service.auto_recycle( + platform="x", + count=2 +) +``` + +## Mejores Prácticas + +1. **Esperar suficiente tiempo:** Mínimo 30 días entre reciclajes +2. **Modificar ligeramente:** Actualiza hashtags o intro +3. **No abusar:** Máximo 3 reciclajes por post +4. **Monitorear:** Compara rendimiento nuevo vs original +5. **Contenido evergreen:** Prioriza contenido atemporal + +## Tipos de Contenido Ideales para Reciclar + +| Tipo | Ideal | Razón | +|------|-------|-------| +| Tips técnicos | ✅ | Siempre relevantes | +| Tutoriales | ✅ | Valor educativo permanente | +| Productos | ⚠️ | Si stock disponible | +| Promociones | ❌ | Fechas específicas | +| Efemérides | ❌ | Fechas específicas | +| Noticias | ❌ | Se vuelven obsoletas | diff --git a/docs/FEATURES_OVERVIEW.md b/docs/FEATURES_OVERVIEW.md new file mode 100644 index 0000000..c64c55a --- /dev/null +++ b/docs/FEATURES_OVERVIEW.md @@ -0,0 +1,218 @@ +# Features Overview + +Sistema de automatización de redes sociales para Consultoría AS. + +## Tabla de Contenidos + +1. [Analytics y Reportes](#analytics-y-reportes) +2. [Integración Odoo](#integración-odoo) +3. [A/B Testing](#ab-testing) +4. [Reciclaje de Contenido](#reciclaje-de-contenido) +5. [Thread Series](#thread-series) +6. [Image Templates](#image-templates) + +--- + +## Analytics y Reportes + +Sistema completo de métricas y análisis de rendimiento. + +**Documentación completa:** [ANALYTICS.md](./ANALYTICS.md) + +### Características principales: +- Dashboard interactivo con métricas en tiempo real +- Tracking de engagement por post y plataforma +- Análisis de mejores horarios para publicar +- Reportes semanales automáticos vía Telegram +- Histórico de métricas por post + +### Endpoints API: +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/api/analytics/dashboard` | Datos del dashboard | +| GET | `/api/analytics/top-posts` | Posts con mejor rendimiento | +| GET | `/api/analytics/optimal-times` | Mejores horarios | +| GET | `/api/analytics/engagement-trend` | Tendencia de engagement | +| GET | `/api/analytics/reports` | Reportes históricos | +| POST | `/api/analytics/reports/generate` | Generar reporte | +| POST | `/api/analytics/reports/send-telegram` | Enviar reporte a Telegram | + +--- + +## Integración Odoo + +Sincronización bidireccional con Odoo ERP. + +**Documentación completa:** [ODOO_INTEGRATION.md](./ODOO_INTEGRATION.md) + +### Características principales: +- Sincronización de productos desde Odoo +- Sincronización de servicios desde Odoo +- Exportación de leads al CRM de Odoo +- Gestión de leads desde interacciones sociales +- Logs de sincronización + +### Endpoints API: +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/api/odoo/status` | Estado de conexión | +| POST | `/api/odoo/sync/products` | Sincronizar productos | +| POST | `/api/odoo/sync/services` | Sincronizar servicios | +| POST | `/api/odoo/sync/leads` | Exportar leads | +| GET | `/api/odoo/sync/logs` | Historial de sync | +| GET | `/api/leads/` | Listar leads | +| POST | `/api/leads/` | Crear lead | +| POST | `/api/leads/from-interaction/{id}` | Lead desde interacción | + +--- + +## A/B Testing + +Sistema de pruebas A/B para optimizar contenido. + +**Documentación completa:** [AB_TESTING.md](./AB_TESTING.md) + +### Características principales: +- Crear tests con 2-4 variantes +- Publicación automática de variantes +- Seguimiento de métricas por variante +- Análisis estadístico (chi-square) +- Determinación automática de ganador + +### Endpoints API: +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/api/ab-tests/` | Listar tests | +| POST | `/api/ab-tests/` | Crear test | +| POST | `/api/ab-tests/{id}/start` | Iniciar test | +| POST | `/api/ab-tests/{id}/evaluate` | Evaluar resultados | +| GET | `/api/ab-tests/{id}/results` | Ver resultados | +| POST | `/api/ab-tests/{id}/cancel` | Cancelar test | + +--- + +## Reciclaje de Contenido + +Republica contenido exitoso automáticamente. + +**Documentación completa:** [CONTENT_RECYCLING.md](./CONTENT_RECYCLING.md) + +### Características principales: +- Identificación de posts reciclables por engagement +- Sistema de puntuación para candidatos +- Modificaciones opcionales al reciclar +- Límite de reciclajes por post +- Reciclaje automático programado + +### Endpoints API: +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/api/recycling/candidates` | Posts candidatos | +| POST | `/api/recycling/{post_id}` | Reciclar post | +| POST | `/api/recycling/auto` | Reciclaje automático | +| GET | `/api/recycling/history` | Historial | +| POST | `/api/recycling/{post_id}/disable` | Deshabilitar reciclaje | + +--- + +## Thread Series + +Publica hilos de múltiples posts programados. + +**Documentación completa:** [THREAD_SERIES.md](./THREAD_SERIES.md) + +### Características principales: +- Crear series de posts conectados +- Generación con IA +- Programación con intervalos configurables +- Soporte para reply chains +- Seguimiento de progreso + +### Endpoints API: +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/api/threads/` | Listar series | +| POST | `/api/threads/` | Crear serie manual | +| POST | `/api/threads/generate` | Generar con IA | +| POST | `/api/threads/{id}/schedule` | Programar serie | +| POST | `/api/threads/{id}/publish-next` | Publicar siguiente | +| POST | `/api/threads/{id}/cancel` | Cancelar serie | + +--- + +## Image Templates + +Sistema de plantillas para generar imágenes. + +**Documentación completa:** [IMAGE_TEMPLATES.md](./IMAGE_TEMPLATES.md) + +### Características principales: +- Plantillas HTML/CSS inline +- Variables dinámicas +- Múltiples tamaños de salida +- Categorías y tipos de plantillas +- Preview antes de generar + +### Endpoints API: +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/api/templates/` | Listar plantillas | +| POST | `/api/templates/` | Crear plantilla | +| PUT | `/api/templates/{id}` | Actualizar | +| DELETE | `/api/templates/{id}` | Eliminar | +| POST | `/api/templates/preview` | Previsualizar | + +--- + +## Tareas Programadas (Celery Beat) + +| Tarea | Frecuencia | Descripción | +|-------|------------|-------------| +| `check_scheduled_posts` | Cada minuto | Publica posts programados | +| `check_thread_schedules` | Cada minuto | Publica posts de hilos | +| `fetch_post_metrics` | Cada 15 min | Actualiza métricas | +| `sync_interactions` | Cada 15 min | Sincroniza interacciones | +| `export_leads_to_odoo` | Cada hora | Exporta leads | +| `evaluate_ab_tests` | Cada hora | Evalúa tests A/B | +| `generate_daily_content` | 6:00 AM | Genera contenido | +| `sync_products_from_odoo` | 6:00 AM | Sincroniza productos | +| `sync_services_from_odoo` | 6:05 AM | Sincroniza servicios | +| `auto_recycle_content` | 2:00 AM | Recicla contenido | +| `recalculate_optimal_times` | Lunes 2:00 AM | Recalcula horarios | +| `generate_weekly_report` | Domingo 9:00 AM | Genera reporte | +| `send_daily_summary` | 9:00 PM | Resumen diario | +| `cleanup_old_data` | Domingo 3:00 AM | Limpieza de datos | + +--- + +## Configuración + +Variables de entorno requeridas en `.env`: + +```bash +# Analytics +ANALYTICS_FETCH_INTERVAL=15 +TELEGRAM_REPORT_ENABLED=true +TELEGRAM_REPORT_DAY=6 + +# Odoo +ODOO_URL=https://tuempresa.odoo.com +ODOO_DB=nombre_bd +ODOO_USERNAME=usuario +ODOO_PASSWORD=api_key +ODOO_SYNC_ENABLED=false +``` + +--- + +## Dashboard URLs + +| URL | Descripción | +|-----|-------------| +| `/dashboard` | Panel principal | +| `/dashboard/analytics` | Analytics | +| `/dashboard/leads` | Gestión de leads | +| `/dashboard/posts` | Gestión de posts | +| `/dashboard/calendar` | Calendario | +| `/dashboard/interactions` | Interacciones | +| `/api/docs` | Documentación Swagger | diff --git a/docs/IMAGE_TEMPLATES.md b/docs/IMAGE_TEMPLATES.md new file mode 100644 index 0000000..0b1f6c6 --- /dev/null +++ b/docs/IMAGE_TEMPLATES.md @@ -0,0 +1,350 @@ +# Image Templates + +Sistema de plantillas para generar imágenes dinámicas. + +## Descripción + +Las plantillas de imagen permiten: +- Definir diseños reutilizables en HTML/CSS +- Insertar variables dinámicas +- Generar imágenes para diferentes plataformas +- Mantener consistencia visual + +## Modelo de Datos + +### ImageTemplate + +```python +ImageTemplate: + id: int + name: str + description: str + + category: str # tip, producto, servicio, promocion, etc. + template_type: str # tip_card, product_card, quote, promo, announcement + + # Plantilla + template_file: str # Ruta a archivo (opcional) + html_template: str # HTML inline + + preview_url: str # URL de imagen preview + + # Variables + variables: [str] # ["title", "content", "accent_color"] + + # Configuración de diseño + design_config: JSON + # { + # "width": 1080, + # "height": 1080, + # "background_color": "#1a1a2e", + # "accent_color": "#d4a574", + # "font_family": "Inter" + # } + + # Tamaños de salida + output_sizes: JSON + # { + # "instagram": {"width": 1080, "height": 1080}, + # "x": {"width": 1200, "height": 675}, + # "facebook": {"width": 1200, "height": 630} + # } + + is_active: bool +``` + +## API Endpoints + +### GET /api/templates/ +Lista todas las plantillas. + +**Parámetros:** +- `category`: tip, producto, servicio, etc. +- `template_type`: tip_card, product_card, etc. +- `active_only` (bool, default=true) +- `limit` (int, default=50) + +**Respuesta:** +```json +{ + "templates": [ + { + "id": 1, + "name": "Tip Card Oscuro", + "description": "Tarjeta para tips con fondo oscuro", + "category": "tip", + "template_type": "tip_card", + "variables": ["title", "content", "emoji"], + "preview_url": "/uploads/previews/tip_card_dark.png" + } + ], + "count": 10 +} +``` + +### GET /api/templates/{template_id} +Obtiene una plantilla con detalles completos. + +Incluye `full_html_template` con el HTML completo. + +### POST /api/templates/ +Crea una nueva plantilla. + +**Body:** +```json +{ + "name": "Quote Card", + "description": "Tarjeta para frases motivacionales", + "category": "frase", + "template_type": "quote", + "html_template": "
{{content}}
+{{content}}
+ +{{content}}
+