feat: automatización de cotizaciones, contratos, actas y cuentas de cobro con IA

Implementa las 4 fases de la especificación de automatización: módulo de
plantillas/tarifas editable por el equipo, generación de PDF (HTML+JS vía
Chrome headless) para cotizaciones/contratos/arquitecturas/cuentas de cobro,
chat propio en el dashboard reutilizando el mismo motor y tools del bot de
Telegram, y nuevas tools del agente para crear estos documentos end-to-end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro GD
2026-08-03 00:45:58 +00:00
co-authored by Claude Sonnet 5
parent 772a4a5656
commit 516220a8a1
32 changed files with 2272 additions and 132 deletions
+14 -3
View File
@@ -24,11 +24,11 @@ type AiConfig struct {
// "" = global (disponible para todos como fallback)
// "landing" = exclusivo para Landing Generator
// "query_runner" = exclusivo para Query Runner SQL
Modulo string `gorm:"size:50;default:''" json:"modulo"`
Modulo string `gorm:"size:50;default:''" json:"modulo"`
// Agente Telegram: si EsAgenteBot=true, esta config es el cerebro del bot administrador.
// Solo debe haber una config activa como agente a la vez.
EsAgenteBot bool `gorm:"default:false" json:"es_agente_bot"`
TelegramConfigID *uint `gorm:"index" json:"telegram_config_id"`
EsAgenteBot bool `gorm:"default:false" json:"es_agente_bot"`
TelegramConfigID *uint `gorm:"index" json:"telegram_config_id"`
}
func (AiConfig) TableName() string { return "ai_configs" }
@@ -127,6 +127,17 @@ func GetAgenteBotConfig() (*AiConfig, *TelegramConfig, error) {
return &ai, tg, nil
}
// GetAgenteBotAiConfig retorna solo la config de IA marcada como agente (el mismo
// "cerebro" que usa el bot de Telegram), sin exigir que tenga un bot de Telegram
// asignado. La usa el chat propio del dashboard para compartir el mismo motor.
func GetAgenteBotAiConfig() (*AiConfig, error) {
var ai AiConfig
if err := app.Http.Database.DB.Where("es_agente_bot = ? AND is_active = ?", true, true).First(&ai).Error; err != nil {
return nil, fmt.Errorf("no hay agente configurado: %w", err)
}
return &ai, nil
}
// GetAiConfigForService retorna la config activa asignada al módulo indicado.
// Lógica de prioridad:
// 1. Config activa con modulo conteniendo service (puede ser comma-separated)