Personalización y Configuración
Esta guía explica cómo personalizar y configurar OmniCRM para que coincida con la identidad de su marca, los requisitos operativos y las necesidades de integración.
Variables de Entorno (.env Files)
OmniCRM utiliza variables de entorno para configurar tanto la API del backend como la interfaz de usuario del frontend. Hay dos archivos .env separados que controlan diferentes aspectos del sistema.
Configuración de la API del Backend (.env)
Ubicado en la raíz del directorio de OmniCRM, este archivo configura las conexiones a la base de datos y la integración de CGRates.
Ubicación: /OmniCRM/.env
Configuración de la Base de Datos:
# Base de Datos MySQL/MariaDB (Datos del CRM)
MYSQL_ROOT_PASSWORD=your_secure_password
MYSQL_USER=omnitouch
MYSQL_PASSWORD=your_database_password
MYSQL_DATABASE=crm
DB_SERVER=db
# Base de Datos PostgreSQL (Datos de CGRates)
POSTGRES_USER=cgrates
POSTGRES_PASSWORD=cgrates_password
POSTGRES_DB=cgrates_db
Configuración de CGRates:
# Credenciales de la API de CGRates
CGRATES_API_USER=admin
CGRATES_API_PASS=secret
CGRATES_DB_USER=cgrates
CGRATES_DB_PASS=cgrates_password
CGRATES_DB_NAME=cgrates_db
CGRATES_DB_PORT=5432
Consideraciones de Seguridad:
- Nunca comprometa archivos .env en el control de versiones - Use
.env.examplecomo plantilla - Use contraseñas fuertes - Mínimo 16 caracteres con mezcla de mayúsculas, minúsculas, números y símbolos
- Gire las credenciales regularmente - Especialmente para implementaciones en producción
- Restringa el acceso a la base de datos - Use listas blancas de IP y reglas de firewall
Configuración de la Interfaz de Usuario del Frontend (.env)
Ubicado en el directorio OmniCRM-UI, este archivo controla la marca, la apariencia, las integraciones y las banderas de características.
Ubicación: /OmniCRM/OmniCRM-UI/.env
Claves API e Integración:
# API de Google Maps (para autocompletar direcciones y geocodificación)
REACT_APP_GOOGLE_API_KEY=your_google_api_key
# Pasarela de Pago Stripe
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_test_xxxxx
# Deshabilitar el lanzamiento automático del navegador al iniciar npm
BROWSER=none
Información de Marca y Empresa:
# Marca de la Empresa
REACT_APP_COMPANY_NAME="ShellFone"
REACT_APP_PORTAL_NAME="ShellManager"
REACT_APP_SELF_CARE_NAME="ShellCare"
REACT_APP_COMPANY_TAGLINE="Phones with Shells"
Estos valores aparecen en toda la interfaz de usuario:
COMPANY_NAME- Mostrado en títulos de página, correos electrónicos y comunicaciones con clientesPORTAL_NAME- Nombre del portal de administración/personal (por ejemplo, "ShellManager")SELF_CARE_NAME- Nombre del portal de autoservicio para clientes (por ejemplo, "ShellCare")COMPANY_TAGLINE- Aparece en pantallas de inicio de sesión y materiales de marketing
Localización y Configuraciones Regionales:
# Idioma y Localidad
# Idiomas soportados: ar, ch, en, fr, gr, it, ru, sp
REACT_APP_DEFAULT_LANGUAGE=en
REACT_APP_LOCALE="en-GB"
# Ubicación Predeterminada (para autocompletar direcciones)
REACT_APP_DEFAULT_LOCATION="Sydney, Australia"
REACT_APP_DEFAULT_COUNTRY="Australia"
# Configuraciones de Moneda
REACT_APP_CURRENCY_CODE="GBP"
REACT_APP_CURRENCY_SYMBOL="£"
Personalización del Esquema de Color:
# Color Primario (color principal de la marca)
REACT_APP_PRIMARY_COLOR=#405189
# Opciones de Color Adicionales (ejemplos comentados)
# REACT_APP_SECONDARY_COLOR=#2bFFcf
# REACT_APP_TERTIARY_COLOR=#1a9fbf
# REACT_APP_SUCCESS_COLOR=#28a745
# REACT_APP_INFO_COLOR=#17a2b8
# REACT_APP_WARNING_COLOR=#ffc107
# REACT_APP_DANGER_COLOR=#dc3545
El color primario se aplica a:
- Encabezados de navegación
- Botones de acción
- Enlaces y resaltados
- Estados activos
- Elementos de marca
Integraciones de Aplicaciones Web:
Configure hasta 6 aplicaciones web de acceso rápido que aparecen en el panel de administración:
# Aplicación Web 1: GitHub
REACT_APP_WEB_APP_1_NAME="GitHub"
REACT_APP_WEB_APP_1_URL="https://github.com"
REACT_APP_WEB_APP_1_ICON_PATH="resources/webapp_icons/github.png"
# Aplicación Web 2: Xero
REACT_APP_WEB_APP_2_NAME="Xero"
REACT_APP_WEB_APP_2_URL="https://go.xero.com/"
REACT_APP_WEB_APP_2_ICON_PATH="resources/webapp_icons/xero.png"
# Aplicación Web 3-6: Integraciones adicionales
# (Configurar de manera similar con NAME, URL y ICON_PATH)
Monitoreo y Análisis:
# Integración del Panel de Grafana
REACT_APP_GRAFANA_URLS=url1,url2,url3
REACT_APP_GRAFANA_LABELS=label1,label2,label3
REACT_APP_GRAFANA_API_KEY=your-api-key
Banderas de Características:
# URLs de Soporte y Documentación
REACT_APP_FAQS_URL=https://docs.yourcompany.com/faqs
REACT_APP_SUPPORT_URL=https://support.yourcompany.com
# Inicio de sesión social (Google, Facebook, etc.)
REACT_APP_ALLOW_SOCIAL_LOGINS=yes
Personalización del Logo y de la Imagen de Carga
OmniCRM le permite reemplazar las imágenes de marca predeterminadas con el logo y las pantallas de carga de su empresa sin modificar el código.
Archivos de Logo
Los logos se almacenan en /OmniCRM-UI/src/assets/images/omnitouch/ y utilizan un sistema de respaldo:
Logos Predeterminados (siempre presentes):
DefaultLogoDark.png- Logo de tema oscuro (utilizado en fondos claros)DefaultLogoLight.png- Logo de tema claro (utilizado en fondos oscuros)
Logos Personalizados (opcional, tienen prioridad cuando están presentes):
logoSm.png- Logo pequeño para la barra lateral colapsada (recomendado: 100x100px)logoDark.png- Logo oscuro de tamaño completo para encabezados (recomendado: 200x50px)logoLight.png- Logo claro de tamaño completo para pantallas de autenticación (recomendado: 200x50px)
Cómo Funciona el Respaldo de Logos:
El sistema intenta cargar primero los logos personalizados. Si no existe un archivo de logo personalizado, se recurre al predeterminado:
// Desde Header.js
const tryImport = (filename) => {
try {
return require(`../assets/images/omnitouch/${filename}`);
} catch (err) {
return null; // Recurre al predeterminado
}
};
const userLogoSm = tryImport("logoSm.png");
const userLogoDark = tryImport("logoDark.png");
const userLogoLight = tryImport("logoLight.png");
Dónde Aparecen los Logos:
- logoSm.png - Barra lateral colapsada, navegación móvil, pantallas de encabezado pequeñas
- logoDark.png - Barra de encabezado principal (modo claro), encabezado del panel de administración
- logoLight.png - Pantallas de inicio de sesión/registro, fondos oscuros, carrusel de autenticación
Reemplazo de Logos:
-
Cree Sus Archivos de Logo:
- Use formato PNG para soporte de transparencia
- Coincida con las dimensiones recomendadas arriba
- Asegúrese de que los logos sean claros tanto en resoluciones regulares como en retina
-
Agregue a OmniCRM:
# Copie sus archivos de logo al directorio de imágenes de omnitouch
cp /path/to/your/logoSm.png OmniCRM-UI/src/assets/images/omnitouch/
cp /path/to/your/logoDark.png OmniCRM-UI/src/assets/images/omnitouch/
cp /path/to/your/logoLight.png OmniCRM-UI/src/assets/images/omnitouch/ -
Reconstruya la Interfaz de Usuario:
cd OmniCRM-UI
npm run build -
Verifique los Cambios:
- Verifique el encabezado en modo claro (debería mostrar
logoDark.png) - Verifique el encabezado en modo oscuro (debería mostrar
logoLight.png) - Verifique la barra lateral colapsada (debería mostrar
logoSm.png) - Verifique la pantalla de inicio de sesión (debería mostrar
logoLight.png)
- Verifique el encabezado en modo claro (debería mostrar
Mejores Prácticas para el Diseño de Logos:
- Contraste - Asegúrese de que los logos sean visibles tanto en fondos claros como oscuros
- Simplicidad - Los logos deben ser reconocibles en tamaños pequeños
- Formato - Use PNG con fondos transparentes
- Retina - Proporcione resolución 2x para pantallas de alta DPI
- Consistencia - Use los mismos colores de marca en todas las variantes de logos
Pantallas de Carga y Fondos de Autenticación
Las pantallas de autenticación (inicio de sesión, registro, restablecimiento de contraseña) utilizan un fondo de carrusel con imágenes personalizables.
Ubicación:
/OmniCRM-UI/src/pages/AuthenticationInner/authCarousel.js
Configuración Predeterminada:
import logoLight from "../../assets/images/logo-light.png";
// Logo mostrado en pantallas de autenticación
<img src={logoLight} alt="" height="18" />
Personalizando Pantallas de Autenticación:
- Reemplace
logo-light.pngen/OmniCRM-UI/src/assets/images/ - Agregue CSS de fondo personalizado a la clase
.auth-one-bg - Modifique las citas del carrusel en
authCarousel.jspara que coincidan con la voz de su marca
Ejemplo de Personalización:
/* Agregue a su CSS personalizado */
.auth-one-bg {
background-image: url('/assets/images/custom-auth-bg.jpg');
background-size: cover;
background-position: center;
}
Archivo de Configuración del CRM (crm_config.yaml)
El archivo crm_config.yaml es la configuración central para la API de OmniCRM, controlando integraciones, aprovisionamiento, plantillas de correo electrónico y servicios externos.
Ubicación: /OmniCRM/OmniCRM-API/crm_config.yaml
Configuración de la Base de Datos
database:
username: omnitouch
password: omnitouch2024
server: localhost
Nota: Esto debe coincidir con sus credenciales de base de datos en .env. En implementaciones en contenedores, el servidor es típicamente db (nombre del servicio de Docker).
Tipos de Servicio
Defina tipos de servicio válidos para su implementación:
service_types:
- omnicharge
- mobile
- fixed
- fixed-voice
- hotspot
- dongle
Estos se utilizan en todo el sistema para:
- Categorización de productos
- Filtrado de complementos (los complementos coinciden con los tipos de servicio)
- Flujos de trabajo de aprovisionamiento
- Informes y análisis
Integración HSS (Home Subscriber Server)
Para operadores de redes móviles con integración HSS:
hss:
hss_peers:
- 'http://10.179.2.140:8080'
apn_list: "1,2,3,4,5,6"
Configuración:
hss_peers- Lista de puntos finales HSS para aprovisionamiento de suscriptoresapn_list- Lista separada por comas de IDs de APN disponibles para aprovisionamiento
Configuración de Plantillas de Correo Electrónico de Mailjet
OmniCRM utiliza Mailjet para correos electrónicos transaccionales. Cada tipo de correo electrónico tiene su propia configuración de plantilla:
mailjet:
api_key: your_mailjet_api_key
api_secret: your_mailjet_api_secret
# Correo Electrónico de Bienvenida al Cliente
api_crmCommunicationCustomerWelcome:
from_email: "support@yourcompany.com"
from_name: "Soporte de Su Empresa"
template_id: 5977509
subject: "Bienvenido a YourCompany"
# Correo Electrónico de Factura al Cliente
api_crmCommunicationCustomerInvoice:
from_email: "billing@yourcompany.com"
from_name: "Facturación de Su Empresa"
template_id: 6759851
subject: "Su Factura - "
# Recordatorio de Factura
api_crmCommunicationCustomerInvoiceReminder:
from_email: "billing@yourcompany.com"
from_name: "Facturación de Su Empresa"
template_id: 5977570
subject: "Recordatorio de Pago de Factura"
# Correo Electrónico de Bienvenida al Usuario (Personal/Admin)
api_crmCommunicationUserWelcome:
from_email: "admin@yourcompany.com"
from_name: "Admin de Su Empresa"
template_id: 6118112
subject: "Bienvenido al Equipo"
# Solicitud de Restablecimiento de Contraseña
api_crmCommunicationUserPasswordReset:
from_email: "security@yourcompany.com"
from_name: "Seguridad de Su Empresa"
template_id: 6735666
subject: "Solicitud de Restablecimiento de Contraseña"
# Confirmación de Éxito en el Restablecimiento de Contraseña
api_crmCommunicationUserPasswordResetSuccess:
from_email: "security@yourcompany.com"
from_name: "Seguridad de Su Empresa"
template_id: 6118378
subject: "Restablecimiento de Contraseña Exitoso"
# Notificación de Cambio de Contraseña
api_crmCommunicationUserPasswordChange:
from_email: "security@yourcompany.com"
from_name: "Seguridad de Su Empresa"
template_id: 6118423
subject: "Contraseña Cambiada"
# Verificación de Correo Electrónico
api_crmCommunicationEmailVerification:
from_email: "verify@yourcompany.com"
from_name: "Verificación de Su Empresa"
template_id: 6267350
subject: "Verifique Su Dirección de Correo Electrónico"
# Notificación de Saldo Expirado
api_crmCommunicationsBalanceExpired:
from_email: "alerts@yourcompany.com"
from_name: "Alertas de Su Empresa"
template_id: 7238252
subject: "Saldo de Servicio Expirado"
# Advertencia de Bajo Saldo
api_crmCommunicationsBalanceLow:
from_email: "alerts@yourcompany.com"
from_name: "Alertas de Su Empresa"
template_id: 7238263
subject: "Advertencia de Bajo Saldo"
Creando Plantillas de Mailjet:
- Inicie sesión en el panel de Mailjet (<https://app.mailjet.com>)
- Navegue a Transaccional → Plantillas
- Cree una nueva plantilla o clone una existente
- Anote el ID de Plantilla (valor numérico)
- Agregue variables de plantilla que coincidan con la estructura de datos de OmniCRM
- Actualice
crm_config.yamlcon el ID de plantilla
Variables de Plantilla Disponibles:
Cada tipo de correo electrónico recibe variables específicas. Ejemplos comunes:
{{customer_name}}- Nombre del cliente o usuario{{service_name}}- Nombre del servicio o producto{{invoice_id}}- Número de factura{{invoice_amount}}- Monto total de la factura{{due_date}}- Fecha de vencimiento del pago{{reset_link}}- URL de restablecimiento de contraseña{{verification_link}}- URL de verificación de correo electrónico{{balance}}- Saldo actual de la cuenta{{expiry_date}}- Fecha de vencimiento del saldo o servicio
Configuración de Aprovisionamiento
provisioning:
failure_list: ['admin@yourcompany.com', 'ops@yourcompany.com']
Propósito:
failure_list- Direcciones de correo electrónico notificadas cuando falla el aprovisionamiento de Ansible- Las notificaciones incluyen el nombre del playbook, detalles del error y la información del cliente
- Permite al equipo de operaciones responder rápidamente a problemas de aprovisionamiento
Configuración de Facturas
invoice:
template_filename: 'yourcompany_invoice_template.html'
Propósito:
Especifica qué plantilla HTML de Jinja2 utilizar para la generación de facturas en PDF.
Ubicación de la Plantilla: /OmniCRM-API/invoice_templates/
Consulte la sección Generación de PDF de Factura a continuación para obtener detalles sobre cómo crear plantillas personalizadas.
URL Base del CRM
crm:
base_url: 'http://localhost:5000'
Propósito:
- Utilizado por los playbooks de Ansible para hacer llamadas a la API
- Utilizado en plantillas de correo electrónico para generar enlaces al CRM
- Debe ser la URL accesible públicamente de su API (no nombres de contenedor internos)
Ejemplos:
- Desarrollo:
http://localhost:5000 - Producción:
https://api.yourcompany.com - Docker:
http://omnicrm-api:5000(comunicación interna entre contenedores)
Configuración de OCS y CGRates
ocs:
ocsApi: 'http://10.179.2.142:8080/api'
ocsTenant: 'mnc380.mcc313.3gppnetwork.org'
cgrates: 'localhost:2080'
Configuración:
ocsApi- Punto final de la API de OCS para gestión de suscriptoresocsTenant- Identificador de inquilino para implementaciones OCS multi-inquilinocgrates- Punto final de la API JSON-RPC de CGRates (host:port)
Configuración de SMSC (Puerta de Enlace SMS)
smsc:
source_msisdn: 'YourCompany'
smsc_url: 'http://10.179.2.216/SMSc/'
api_key: 'your_smsc_api_key'
Propósito:
- Enviar notificaciones SMS a los clientes (bajo saldo, alertas de servicio, códigos 2FA)
source_msisdn- ID del remitente mostrado a los destinatarios (alfanumérico o número de teléfono)smsc_url- Punto final de la API de la puerta de enlace SMSCapi_key- Autenticación para la API de SMSC
Clave Secreta JWT
jwt_secret: '2b93110f723db60172c8e9a1eaa80027a9a9c3f05b44e50dc3fcf38dba68d87e'
Seguridad:
- Utilizado para firmar y verificar tokens de autenticación
- DEBE ser cambiado del valor predeterminado en producción
- Genere una cadena aleatoria segura (mínimo 64 caracteres)
- Nunca comparta ni comprometa en el control de versiones
Generando una Nueva Clave Secreta JWT:
# Generar una clave aleatoria segura criptográficamente
python3 -c "import secrets; print(secrets.token_hex(32))"
Configuración de Pagos de Stripe
stripe:
secret_key: 'sk_live_xxxxxxxxxx'
publishable_key: 'pk_live_xxxxxxxxxx'
currency: 'aud'
statement_descriptor_suffix: 'YOURCOMPANY'
Configuración:
secret_key- Clave API secreta de Stripe (lado del servidor, mantenga confidencial)publishable_key- Clave publicable de Stripe (lado del cliente, seguro para exponer)currency- Código de moneda ISO 4217 (aud, usd, gbp, eur, etc.)statement_descriptor_suffix- Aparece en los estados de cuenta de tarjetas de crédito de los clientes
Uso del Descriptor de Estado:
- Mostrado en los estados de cuenta bancarios de los clientes como "YOURCOMPANY"
- Máximo 22 caracteres
- Ayuda a los clientes a identificar los cargos
- También se utiliza en los nombres de archivo de PDF de facturas (por ejemplo,
YOURCOMPANY_12345.pdf)
Claves API y Listado Blanco de IP
Defina claves API con acceso basado en roles y restricciones de IP:
api_keys:
"YOUR_API_KEY_1":
roles: ["admin"]
ips: ["127.0.0.1", "::1"]
"YOUR_API_KEY_2":
roles: ["customer_service_agent_1"]
ips: ["127.0.0.1", "::1", "10.0.1.0/24"]
# Lista Blanca de IP (independiente, sin clave API)
ip_whitelist:
"10.179.2.142":
roles: ["admin"]
Propósito:
- Permitir que sistemas externos se autentiquen a través de la clave API
- Restringir el acceso por dirección IP
- Conceder roles específicos a los consumidores de la API
- Útil para integraciones (sistemas de facturación, monitoreo, automatización)
Mejores Prácticas de Seguridad:
- Use claves API largas y aleatorias (mínimo 32 caracteres)
- Restringa las IPs a fuentes conocidas solamente
- Conceda los roles mínimos necesarios
- Gire las claves API regularmente
- Monitoree el uso de claves API en los registros
Generación de PDF de Factura
OmniCRM genera facturas PDF profesionales utilizando plantillas HTML de Jinja2 y renderizado PDF de WeasyPrint.
Cómo Funciona la Generación de PDF
- Selección de Plantilla:
- El nombre del archivo de plantilla se especifica en
crm_config.yamlbajoinvoice.template_filename - La plantilla se carga desde el directorio
/OmniCRM-API/invoice_templates/
- El nombre del archivo de plantilla se especifica en
- Preparación de Datos:
- Los datos de la factura (ID, fechas, montos, estado) se obtienen de la base de datos
- La información del cliente (nombre, dirección) se recupera
- Se compila la lista de transacciones (todos los cargos/créditos en la factura)
- Renderizado de Plantilla:
- Jinja2 renderiza la plantilla HTML con los datos de la factura
- Variables como
{{ invoice_number }},{{ total_amount }}, etc. son reemplazadas - El HTML renderizado se guarda en
invoice_templates/rendered/para depuración
- Generación de PDF:
- WeasyPrint convierte el HTML renderizado a PDF
- El PDF admite estilos CSS, imágenes, saltos de página, encabezados/pies de página
- Los datos binarios del PDF se generan en memoria
- Caché:
- El PDF se codifica en Base64 y se almacena en la tabla
Invoice_PDF_Cache - Se calcula un hash SHA256 para verificación de integridad
- Las solicitudes subsiguientes devuelven el PDF en caché (entrega instantánea)
- El PDF se codifica en Base64 y se almacena en la tabla
- Invalidación de Caché:
- La caché se invalida cuando la factura se modifica, anula o reembolsa
- Los cambios en la plantilla no invalidan automáticamente las cachés existentes
Estructura de Plantilla de Factura
Las plantillas de factura son archivos HTML de Jinja2 con variables y lógica incrustadas.
Ubicación de la Plantilla:
/OmniCRM-API/invoice_templates/yourcompany_invoice_template.html
Variables Disponibles:
{
'invoice_number': 12345,
'date': '2025-01-04',
'client': {
'name': 'John Smith',
'address': {
'address_line_1': '123 Main St',
'city': 'Sydney',
'state': 'NSW',
'zip_code': '2000',
'country': 'Australia'
}
},
'transaction_list': [
[
{
'transaction_id': 1,
'title': 'Servicio Móvil - Cuota Mensual',
'retail_cost': 30.00,
'wholesale_cost': 10.00,
'created': '2025-01-01'
},
{
'transaction_id': 2,
'title': 'Complemento de Datos - 5GB',
'retail_cost': 15.00,
'wholesale_cost': 5.00,
'created': '2025-01-15'
}
]
],
'total_amount': 45.00,
'due_date': '2025-01-31',
'start_date': '2025-01-01',
'end_date': '2025-01-31',
'paid': False,
'void': False
}
Fragmento de Plantilla de Ejemplo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Factura {{ invoice_number }}</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.invoice-details {
margin-bottom: 20px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
th {
background-color: #405189;
color: white;
}
.total {
text-align: right;
font-size: 18px;
font-weight: bold;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="header">
<img src="file:///path/to/logo.png" alt="Logo de la Empresa" height="60">
<h1>FACTURA</h1>
</div>
<div class="invoice-details">
<p><strong>Número de Factura:</strong> {{ invoice_number }}</p>
<p><strong>Fecha:</strong> {{ date }}</p>
<p><strong>Fecha de Vencimiento:</strong> {{ due_date }}</p>
<p><strong>Período de Facturación:</strong> {{ start_date }} a {{ end_date }}</p>
</div>
<div class="customer-details">
<h3>Facturar a:</h3>
<p>{{ client.name }}</p>
<p>{{ client.address.address_line_1 }}</p>
<p>{{ client.address.city }}, {{ client.address.state }} {{ client.address.zip_code }}</p>
<p>{{ client.address.country }}</p>
</div>
<table>
<thead>
<tr>
<th>Descripción</th>
<th>Fecha</th>
<th>Monto</th>
</tr>
</thead>
<tbody>
{% for transaction in transaction_list[0] %}
<tr>
<td>{{ transaction.title }}</td>
<td>{{ transaction.created }}</td>
<td>${{ "%.2f"|format(transaction.retail_cost) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="total">
<p>Total a Pagar: ${{ "%.2f"|format(total_amount) }}</p>
</div>
{% if paid %}
<div style="text-align: center; color: green; font-weight: bold;">
PAGADO
</div>
{% endif %}
{% if void %}
<div style="text-align: center; color: red; font-weight: bold;">
ANULADO
</div>
{% endif %}
</body>
</html>
Mejores Prácticas para Plantillas:
- Use rutas absolutas para imágenes -
file:///absolute/path/to/image.png - CSS en línea - WeasyPrint no carga hojas de estilo externas de manera confiable
- Pruebe con datos de muestra - Use
invoice_templates/rendered/para inspeccionar HTML - Saltos de página - Use
<div style="page-break-after: always;"></div>para facturas de varias páginas - Encabezados y pies de página - Use reglas CSS
@pagepara elementos repetidos - Formato de moneda - Use filtros de Jinja2:
{{ "%.2f"|format(amount) }}
Creando una Plantilla de Factura Personalizada
-
Copie la Plantilla de Ejemplo:
cd /OmniCRM/OmniCRM-API/invoice_templates
cp norfone_invoice_template.html yourcompany_invoice_template.html -
Edite la Plantilla:
- Reemplace el nombre de la empresa, el logo, la información de contacto
- Ajuste el estilo (colores, fuentes, diseño) para que coincida con la marca
- Agregue o elimine secciones según sea necesario (desglose de impuestos, instrucciones de pago, etc.)
-
Actualice la Configuración:
Edite
crm_config.yaml:invoice:
template_filename: 'yourcompany_invoice_template.html' -
Pruebe la Generación de Facturas:
- Cree una factura de prueba en el CRM
- Descargue el PDF y verifique el formato
- Verifique
invoice_templates/rendered/{invoice_id}.htmlpara depuración
-
Invalidar Cachés Antiguos (si es necesario):
Si ha cambiado la plantilla y desea regenerar facturas existentes:
-- Limpiar todos los PDFs en caché (fuerza la regeneración)
DELETE FROM Invoice_PDF_Cache;
Sistema de Caché de PDF
Para mejorar el rendimiento, OmniCRM almacena en caché los PDFs generados:
Comportamiento de Caché:
- Primera Solicitud - Se genera, almacena en caché y devuelve el PDF
- Solicitudes Subsiguientes - Se devuelve inmediatamente el PDF en caché (sin regeneración)
- Invalidación de Caché - Ocurre cuando la factura se modifica, anula o reembolsa
- Limpieza de Caché - Las cachés antiguas se purgan automáticamente después de 30 días de inactividad
Almacenamiento de Caché:
- PDF codificado en Base64 almacenado en la tabla
Invoice_PDF_Cache - Hash SHA256 del contenido para verificación de integridad
- Incluye nombre de archivo, marca de tiempo de creación, marca de tiempo de último acceso
Gestión Manual de Caché:
# En la API de OmniCRM o en el shell de Python
from services.invoice_service import cleanup_old_pdf_cache, invalidate_invoice_cache
from utils.db_helpers import get_db_session
session = get_db_session()
# Limpiar cachés más antiguas de 30 días
result = cleanup_old_pdf_cache(session, days_old=30)
print(result) # {'status': 'success', 'deleted_count': 15}
# Invalidar caché de factura específica
invalidate_invoice_cache(session, invoice_id='12345')
Puntos Finales de la API:
Generar/descargar PDF de factura:
GET /invoice/pdf/{invoice_id}
Respuesta: Descarga del archivo PDF con nombre de archivo del descriptor de estado de Stripe
Encabezados de Caché:
- Primera solicitud: Respuesta más lenta (tiempo de generación)
- Solicitudes en caché: Respuesta instantánea
- El acierto/fallo de caché es transparente para el usuario
Solución de Problemas
La Generación de PDF Falla:
- Verifique que WeasyPrint esté instalado:
pip install weasyprint - Verifique que el nombre del archivo de plantilla coincida con
crm_config.yaml - Verifique
invoice_templates/rendered/en busca de errores de renderizado HTML - Revise los registros de la API en busca de errores de plantilla Jinja2
Las Imágenes No Aparecen en el PDF:
- Use rutas de archivo absolutas:
file:///full/path/to/image.png - Asegúrese de que los archivos de imagen existan y sean legibles
- Verifique el formato de imagen (PNG y JPEG funcionan mejor)
- Verifique que las rutas de imagen no contengan caracteres especiales
Problemas de Estilo:
- Inline todo el CSS (no se admiten hojas de estilo externas)
- Evite características CSS complejas (flexbox, grid pueden no renderizarse correctamente)
- Pruebe primero con diseños simples, agregue complejidad gradualmente
- Use tablas para el diseño en lugar de divs cuando sea posible
La Caché No se Invalida:
- Verifique que
invalidate_invoice_cache()se llame cuando se modifique la factura - Verifique que las actualizaciones de transacciones desencadenen la invalidación de caché
- Elimine manualmente de la tabla
Invoice_PDF_Cachesi es necesario
Lista de Verificación de Configuración
Use esta lista de verificación al implementar OmniCRM:
Configuración del Backend
- [ ] Copie
.env.examplea.env - [ ] Establezca contraseñas de base de datos fuertes
- [ ] Configure las credenciales de CGRates
- [ ] Actualice
crm_config.yamlcon su configuración:- [ ] Conexión a la base de datos
- [ ] Tipos de servicio
- [ ] Claves API de Mailjet e IDs de plantilla
- [ ] Correos electrónicos de notificación de fallos de aprovisionamiento
- [ ] Nombre de archivo de plantilla de factura
- [ ] URL base del CRM (accesible públicamente)
- [ ] Puntos finales de OCS/CGRates
- [ ] Configuración de SMSC
- [ ] Genere una nueva clave secreta JWT
- [ ] Claves de Stripe (en vivo, no de prueba)
- [ ] Claves API y listado blanco de IP
Configuración del Frontend
- [ ] Copie
OmniCRM-UI/.env.exampleaOmniCRM-UI/.env - [ ] Establezca la clave de API de Google Maps
- [ ] Establezca la clave publicable de Stripe
- [ ] Actualice la marca de la empresa:
- [ ] Nombre de la empresa
- [ ] Nombre del portal
- [ ] Nombre de autoservicio
- [ ] Lema de la empresa
- [ ] Configure la localización:
- [ ] Idioma predeterminado
- [ ] Localidad
- [ ] Ubicación y país predeterminados
- [ ] Código y símbolo de moneda
- [ ] Establezca el color primario de la marca
- [ ] Configure integraciones de aplicaciones web (opcional)
- [ ] Agregue URLs de soporte y FAQ (opcional)
Activos de Marca
- [ ] Cree archivos de logo (logoSm.png, logoDark.png, logoLight.png)
- [ ] Cargue los logos en
OmniCRM-UI/src/assets/images/omnitouch/ - [ ] Cree HTML de plantilla de factura personalizada
- [ ] Cargue la plantilla de factura en
OmniCRM-API/invoice_templates/ - [ ] Actualice
crm_config.yamlcon el nombre de archivo de la plantilla de factura - [ ] Pruebe la generación de PDF de factura
- [ ] Reconstruya la interfaz de usuario:
npm run build
Seguridad
- [ ] Cambie todas las contraseñas predeterminadas
- [ ] Genere un secreto JWT único
- [ ] Use claves de Stripe en producción (no claves de prueba)
- [ ] Gire las claves API de Mailjet
- [ ] Habilite reglas de firewall
- [ ] Configure el listado blanco de IP para el acceso a la API
- [ ] Configure certificados SSL/TLS
- [ ] Habilite HTTPS para todos los puntos finales
- [ ] Revise la configuración de CORS
- [ ] Implemente limitación de tasa
- [ ] Configure procedimientos de respaldo y recuperación
Pruebas
- [ ] Pruebe el flujo de registro de clientes
- [ ] Pruebe el aprovisionamiento de servicios de extremo a extremo
- [ ] Verifique que las notificaciones por correo electrónico se envíen correctamente
- [ ] Pruebe la generación de facturas y la descarga de PDF
- [ ] Verifique el procesamiento de pagos (Stripe)
- [ ] Verifique la autenticación de usuarios y 2FA
- [ ] Pruebe la suplantación y el registro de auditoría
- [ ] Verifique que los datos de uso se sincronicen desde OCS
- [ ] Pruebe la creación y renovación de ActionPlan
- [ ] Confirme que la asignación de inventario funcione correctamente
Implementación
- [ ] Construya imágenes de Docker o implemente en servidores
- [ ] Inicie contenedores de base de datos (MySQL, PostgreSQL)
- [ ] Inicie CGRates
- [ ] Inicie la API de OmniCRM
- [ ] Inicie la interfaz de usuario de OmniCRM
- [ ] Configure el proxy inverso (nginx, traefik)
- [ ] Configure monitoreo (Grafana, Prometheus)
- [ ] Configure agregación de registros
- [ ] Configure respaldos automáticos
- [ ] Documente la arquitectura de implementación
- [ ] Capacite al personal en el uso del sistema