Saltar al contenido principal

Definición de Productos y Configuración de CGRateS

Esta guía explica cómo definir productos en OmniCRM junto con su configuración de facturación asociada de CGRateS.

Los productos y sus Acciones de CGRateS se definen típicamente juntos en scripts de Python que configuran tanto el CRM como el OCS (Sistema de Carga en Línea).

Visión General

Definir un producto completo implica configuración en dos sistemas:

  1. CGRateS/OCS - Definir el comportamiento de facturación (Acciones, Tarifas, Destinos)
  2. OmniCRM - Definir los metadatos del producto (precio, nombre, características)

Estos están intencionalmente vinculados de manera laxa, lo que permite interactuar con CGRateS a través de los Ansible Plays que defines.

Importante: Capacidades de CGRateS

CGRateS es un motor de calificación extremadamente potente y flexible. Esta guía muestra un patrón de configuración común para productos de OmniCRM, pero CGRateS puede hacer mucho más:

  • Escenarios de calificación avanzados: Tarifas por hora del día, niveles de clientes, enrutamiento basado en calidad de llamada, facturación por ráfagas
  • Lógica de roaming compleja: Tarifas diferentes para llamadas/SMS MO vs MT al hacer roaming, precios específicos de red
  • Soporte para protocolos heredados: CAMEL para roaming 2G/3G (SMS MO-MT, USSD), Diameter para LTE/5G
  • Carga sofisticada: Carga basada en reservas, control de crédito, retroceso de múltiples niveles
  • Enrutamiento dinámico: Enrutamiento basado en costos, selección de proveedores, LCR (Enrutamiento de Menor Costo)

Esta es solo la guía del CRM - se centra en patrones de definición de productos simples que funcionan bien con el sistema de aprovisionamiento de OmniCRM. Para configuraciones avanzadas de CGRateS, consulta la documentación de CGRateS o consulta Acciones de CGRateS y Comportamientos de Recarga para enfoques de saldo y estrategias de calificación.

Flujo de Trabajo Completo para la Definición de Productos

Paso 1: Autenticarse en la API de CRM

import requests
import json

crm_url = 'https://crm.example.com/'
session = requests.Session()

headers = {
"Content-Type": "application/json"
}

# Obtener token de autenticación
response = session.post(crm_url + '/crm/auth/login', json={
"email": "admin@example.com",
"password": "your_password"
}, headers=headers)

assert response.status_code == 200
headers['Authorization'] = 'Bearer ' + response.json()['token']
print("Autenticación en CRM OK")

Paso 2: Definir Plantillas de Inventario (Opcional)

Las plantillas de inventario definen los tipos de artículos físicos (tarjetas SIM, enrutadores, etc.) que se pueden asignar durante el aprovisionamiento.

inventory_list_new = []

# Definir plantilla de inventario de tarjeta SIM
inventory_list_new.append({
"item": "SIM Card",
"itemtext1_label": "ICCID",
"itemtext2_label": "IMSI",
"wholesale_cost": 0.2,
"retail_cost": 1,
"allow_dropdown_staff": True,
"allow_dropdown_customer": True,
"icon": "fa-solid fa-sim-card"
})

# Definir plantilla de inventario de número móvil
inventory_list_new.append({
"item": "Mobile Number",
"itemtext1_label": "E.164 Mobile Number",
"itemtext2_label": "Type",
"wholesale_cost": 0.2,
"retail_cost": 3,
"icon": "fa-solid fa-phone"
})

# Verificar si existe la plantilla de inventario, crear o actualizar
for inventory_template in inventory_list_new:
# Obtener plantillas existentes
inventory_list_existing = session.get(
crm_url + '/crm/inventory/item_template/',
headers=headers
)

# Verificar si la plantilla ya existe
if inventory_template['item'] in [x['item'] for x in inventory_list_existing.json()]:
# Actualizar plantilla existente
inventory_template_id = [
x['inventory_template_id']
for x in inventory_list_existing.json()
if x['item'] == inventory_template['item']
][0]

response = session.patch(
crm_url + '/crm/inventory/item_template/' + str(inventory_template_id),
json=inventory_template,
headers=headers
)
assert response.status_code == 200
print(f"Plantilla de inventario actualizada: {inventory_template['item']}")
else:
# Crear nueva plantilla
response = session.put(
crm_url + '/crm/inventory/item_template',
json=inventory_template,
headers=headers
)
assert response.status_code == 200
print(f"Plantilla de inventario creada: {inventory_template['item']}")

Campos de Plantilla de Inventario:

  • item (requerido) - Nombre de la plantilla
  • itemtext1_label - Etiqueta para el primer campo personalizado
  • itemtext2_label - Etiqueta para el segundo campo personalizado
  • wholesale_cost - Su costo por este artículo
  • retail_cost - Costo para el cliente
  • allow_dropdown_staff - Mostrar en listas desplegables del personal
  • allow_dropdown_customer - Mostrar en listas desplegables del cliente
  • icon - Clase de icono de Font Awesome

Paso 3: Conectar a CGRateS

import cgrateshttpapi
import time

OCS_Obj = cgrateshttpapi.CGRateS("ocs.example.com", "2080")

tenant = "your_tenant_name"
tpid = str(tenant) + "_" + str(int(time.time()))

Paso 4: Definir Destinos en CGRateS

Los destinos definen DÓNDE se pueden usar los saldos. Deben definirse antes de crear Acciones que los referencien.

Hay dos tipos:

  1. Destinos Geográficos - Prefijos de número para voz/SMS A lugares específicos (por ejemplo, Dest_AU_Mobile, Dest_International_UK)
  2. Destinos PLMN - Códigos de red para uso de datos y roaming (por ejemplo, Dest_PLMN_OnNet, Dest_PLMN_US_Verizon)

Regla Crítica:

  • Saldos de Voz/SMS → Usar destinos geográficos (el número que se llama A)
  • Saldos de Datos → Usar destinos PLMN (la red a la que está conectado el cliente A)

Para ejemplos completos de definición de destinos que incluyen:

  • Destinos geográficos (móvil, línea fija, gratuito, internacional)
  • Destinos PLMN (en red, roaming, zonas)
  • Reglas de formato PLMN (mccXXX.mncYYY)
  • Cuándo usar cada enfoque

Ver: Acciones de CGRateS - Definición de Destinos

Paso 5: Definir Acciones de CGRateS

Las Acciones son el mecanismo para agregar saldos a las cuentas de los clientes. Antes de que puedas vincular un producto de CRM a una Acción, la Acción debe estar definida en CGRateS.

Crítico: Las Acciones se definen durante la configuración inicial del sistema (no durante el aprovisionamiento). Especifican qué saldos agregar, tiempos de expiración, comportamiento de rollover, etc.

Consulta Acciones de CGRateS y Comportamientos de Recarga para la documentación completa sobre:

  • Cómo definir Acciones usando Python (OCS_Obj.SendData)
  • Comprender *topup vs *topup_reset (comportamiento de rollover)
  • Cálculos de unidades (bytes para datos, nanosegundos para voz, conteo para SMS)
  • Referencia de campos (BalanceId, BalanceType, DestinationIDs, Units, ExpiryTime, Weight)
  • Ejemplos completos de trabajo (planes de múltiples saldos, complementos de datos, complementos de voz)
  • Reglas y prioridades de consumo de saldo

Referencia Rápida de Rollover:

  • *topup - Agrega al saldo existente (habilita rollover). Para: complementos prepagados, paquetes de datos
  • *topup_reset - Reemplaza el saldo existente (sin rollover). Para: planes mensuales con asignaciones fijas

Paso 6: Crear Productos en CRM

Ahora que las Acciones están definidas en CGRateS, crea los productos correspondientes en CRM.

Ejemplo: Servicio SIM Independiente

product_list_new = []

product_list_new.append({
"category": "standalone",
"provisioning_play": "play_psim_only",
"relies_on_list": "",
"contract_days": 0,
"retail_cost": 0,
"retail_setup_cost": 0,
"product_slug": "Mobile-SIM",
"product_name": "Mobile SIM Only",
"comment": "Tarjeta SIM física para uso con teléfonos móviles",
"provisioning_json_vars": "{\"iccid\" : \"\", \"msisdn\" : \"\"}",
"terms": "Debe activarse dentro de 6 meses. Todo el crédito se pierde si el servicio no se utiliza durante 12 meses.",
"service_type": "mobile",
"residential": True,
"business": True,
"enabled": True,
"inventory_items_list": "['SIM Card', 'Mobile Number']",
"icon": "fa-solid fa-sim-card",
"features_list": "['Número de teléfono australiano (61xxx)', 'Las velocidades más rápidas', 'Mejor cobertura']",
"wholesale_cost": 3,
"wholesale_setup_cost": 1,
"customer_can_purchase": True
})

Ejemplo: Complemento de Plan Mensual

product_list_new.append({
"category": "addon",
"provisioning_play": "play_topup_charge_then_action",
"relies_on_list": "",
"contract_days": 30,
"retail_cost": 59.00,
"retail_setup_cost": 0,
"product_slug": "au-premium-plan-1", # Se vincula a Action_au-premium-plan-1
"product_name": "AU Premium Plan 1",
"comment": "100GB de datos en Australia, 3000 minutos en Australia, 3000 SMS en Australia, 6GB de datos en roaming",
"provisioning_json_vars": "",
"terms": "Plan postpago. Se renueva automáticamente cada 30 días.",
"service_type": "mobile",
"residential": True,
"business": True,
"enabled": True,
"icon": "fa-solid fa-mobile",
"features_list": "['100GB de datos en Australia', '3000 minutos en Australia', '3000 SMS en Australia', '6GB de datos en roaming']",
"wholesale_cost": 45.00,
"wholesale_setup_cost": 0,
"auto_renew": "True",
"customer_can_purchase": True
})

Ejemplo: Complemento de Recarga Única

product_list_new.append({
"category": "addon",
"provisioning_play": "play_topup_charge_then_action",
"relies_on_list": "",
"contract_days": 0,
"retail_cost": 30,
"retail_setup_cost": 0,
"product_slug": "au-data-addon-20gb", # Se vincula a Action_au-data-addon-20gb
"product_name": "AU Data Addon 20GB",
"comment": "20GB de datos en Australia",
"provisioning_json_vars": "",
"terms": "Recarga prepaga. Carga inmediata.",
"service_type": "mobile",
"residential": True,
"business": True,
"enabled": True,
"icon": "fa-solid fa-mobile",
"features_list": "['20GB de datos en Australia']",
"wholesale_cost": 22,
"wholesale_setup_cost": 0,
"auto_renew": "False",
"customer_can_purchase": True
})

Descripciones de Campos del Producto:

  • category (requerido) - Categoría del producto:
    • standalone - Servicio completo (crea un nuevo registro de servicio)
    • addon - Agregado a un servicio existente
    • bundle - Paquete de múltiples servicios
  • provisioning_play (requerido) - Playbook de Ansible a ejecutar (por ejemplo, play_topup_charge_then_action, play_simple_service)
  • relies_on_list - Lista separada por comas de product_slugs de los que depende este producto
  • contract_days - Duración del contrato en días (0 = sin contrato, 30 = mensual)
  • retail_cost (requerido) - Costo mensual/recurrido para el cliente
  • retail_setup_cost - Tarifa de configuración única cobrada al cliente
  • product_slug (requerido) - Identificador único que se vincula a la Acción de CGRateS (convención: Action_{product_slug})
  • product_name (requerido) - Nombre para mostrar
  • comment - Descripción corta
  • provisioning_json_vars - Cadena JSON de variables pasadas al playbook
  • terms - Texto de términos y condiciones
  • service_type - Clasificación del servicio (móvil, dongle, fijo, etc.)
  • residential - Disponible para clientes residenciales
  • business - Disponible para clientes comerciales
  • enabled - El producto está activo y se puede comprar
  • inventory_items_list - Cadena de lista de Python de artículos de inventario requeridos
  • icon - Clase de icono de Font Awesome
  • features_list - Cadena de lista de Python de viñetas de características
  • wholesale_cost - Su costo recurrente
  • wholesale_setup_cost - Su costo único
  • auto_renew - Cadena "True" o "False" para renovación automática
  • customer_can_purchase - El cliente puede comprar a través del portal de autoservicio

Ver también: Ciclo de Vida del Producto

Paso 7: Crear o Actualizar Productos a través de la API

# Obtener productos existentes
product_list_existing = session.get(crm_url + '/crm/product', headers=headers)
existing_products = product_list_existing.json()

# Procesar cada producto
for product in product_list_new:
print(f"Procesando producto: {product['product_slug']}")

# Verificar si el producto ya existe
if product['product_slug'] in [x['product_slug'] for x in existing_products]:
print(f"El producto ya existe: {product['product_slug']}")

# Obtener product_id del producto existente
product_id = [
x['product_id']
for x in existing_products
if x['product_slug'] == product['product_slug']
][0]

product['product_id'] = product_id

# Actualizar producto existente
response = session.patch(
crm_url + '/crm/product/' + str(product_id),
json=product,
headers=headers
)
print(f"Estado: {response.status_code}")
assert response.status_code == 200
print(f"Producto actualizado: {product['product_slug']}")
else:
# Crear nuevo producto
print(f"Creando nuevo producto: {product['product_slug']}")
response = session.put(
crm_url + '/crm/product',
json=product,
headers=headers
)
print(f"Estado: {response.status_code}")
assert response.status_code == 200
print(f"Producto creado: {product['product_slug']}")

Vinculación de Productos a Acciones

El vínculo crítico entre los productos de CRM y las Acciones de CGRateS es la convención de nombres:

# En CGRateS
ActionsId = "Action_au-premium-plan-1"

# En CRM
product_slug = "au-premium-plan-1"

# En el playbook (construido automáticamente)
cgr_action_name = "Action_" + product_slug
# Resultado: "Action_au-premium-plan-1"

Cómo los Playbooks Ejecutan Acciones

Nota: Usar ExecuteAction es solo un patrón para agregar saldos. También podrías llamar directamente a SetBalance u otras APIs de CGRateS dentro de un playbook. Sin embargo, OmniCRM-API/Provisioners/plays/play_topup_charge_then_action.yaml utiliza el patrón ExecuteAction ya que es un enfoque común y reutilizable que separa la lógica de saldo (Acciones) de la lógica de aprovisionamiento (Playbooks).

Cuando un producto se aprovisiona usando este patrón, el playbook construye el nombre de la Acción a partir del product_slug:

# En play_topup_charge_then_action.yaml
- name: Establecer el hecho cgr_action_name
set_fact:
cgr_action_name: "Action_{{ api_response_product.json.product_slug }}"

# Ejecutar la acción
- name: Ejecutar acción de CGRateS
uri:
url: "http://{{ crm_config.ocs.cgrates }}/jsonrpc"
method: POST
body_format: json
body:
{
"method": "APIerSv1.ExecuteAction",
"params": [{
"Tenant": "{{ crm_config.ocs.ocsTenant }}",
"Account": "{{ service_uuid }}",
"ActionsId": "{{ cgr_action_name }}"
}]
}

Al usar este patrón: La Acción debe existir en CGRateS antes de que se ejecute el playbook, de lo contrario, la ejecución fallará con un error de "Acción no encontrada".

Ver también: Guía de Playbooks de Ansible

Ejemplo Completo: Definición de un Nuevo Producto

Vamos a recorrer la creación de un nuevo producto completo "Paquete de Datos de 50GB":

1. Definir la Acción en CGRateS

Consulta el ejemplo de Complemento de Datos Simple en el Paso 5 anterior sobre cómo definir una Acción de complemento de datos. Para nuestro ejemplo de 50GB, la Acción seguiría el mismo patrón pero con diferentes unidades:

  • ActionsId: "Action_50gb-data-pack" (coincide con product_slug a continuación)
  • BalanceType: "*data"
  • DestinationIDs: "Dest_PLMN_OnNet" (para uso de datos en red)
  • Units: 50 * 1024 * 1024 * 1024 (50GB en bytes)
  • Identifier: "*topup" (habilita rollover)

2. Crear el Producto en CRM

product_50gb_data = {
"category": "addon",
"provisioning_play": "play_topup_charge_then_action",
"relies_on_list": "",
"contract_days": 0,
"retail_cost": 25.00,
"retail_setup_cost": 0,
"product_slug": "50gb-data-pack", # Debe coincidir con ActionsId sin "Action_"
"product_name": "Paquete de Datos de 50GB",
"comment": "50GB de datos de alta velocidad válidos por 30 días",
"provisioning_json_vars": "",
"terms": "Los datos expiran después de 30 días. Los datos no utilizados se transfieren si se recarga nuevamente antes de la expiración.",
"service_type": "mobile",
"residential": True,
"business": True,
"enabled": True,
"icon": "fa-solid fa-database",
"features_list": "['50GB de Datos de Alta Velocidad', 'Validez de 30 Días', 'Rollover Habilitado']",
"wholesale_cost": 20.00,
"wholesale_setup_cost": 0,
"auto_renew": "False",
"customer_can_purchase": True
}

# Crear en CRM
response = session.put(
crm_url + '/crm/product',
json=product_50gb_data,
headers=headers
)
assert response.status_code == 200
print("Producto creado: 50gb-data-pack")

3. Verificar el Vínculo

El producto ahora se puede aprovisionar:

  1. El cliente compra "Paquete de Datos de 50GB" (product_slug: 50gb-data-pack)
  2. El playbook play_topup_charge_then_action se ejecuta
  3. El playbook construye el nombre de la Acción: Action_50gb-data-pack
  4. El playbook llama a APIerSv1.ExecuteAction con ActionsId Action_50gb-data-pack
  5. CGRateS encuentra la Acción y la ejecuta
  6. El cliente recibe un saldo de 50GB

Ver también: Cargos y Pagos desde Playbooks

Patrones Comunes de Productos

Estos patrones muestran configuraciones típicas de productos de CRM y cómo se vinculan a Acciones de CGRateS. Para las definiciones de Acción correspondientes, consulta Acciones de CGRateS y Comportamientos de Recarga.

Patrón 1: Plan Mensual de Múltiples Saldos

Caso de Uso: Plan mensual integral con datos, voz, SMS, roaming

Producto CRM:

{
"product_slug": "premium-monthly-plan", # Se vincula a Action_premium-monthly-plan
"product_name": "Plan Mensual Premium",
"category": "addon",
"retail_cost": 59.00,
"auto_renew": "True",
"contract_days": 30,
"provisioning_play": "play_topup_charge_then_action",
"features_list": "['100GB de Datos', '5000 Minutos', '5000 SMS', 'Roaming Incluido']"
}

Acción: Usa *topup_reset con múltiples tipos de saldo. Consulta Ejemplo 1: Plan Mensual de Múltiples Saldos (Python).

Patrón 2: Complemento de Datos Simple (Rollover)

Caso de Uso: Compra de datos única que se transfiere si se recarga nuevamente

Producto CRM:

{
"product_slug": "10gb-addon", # Se vincula a Action_10gb-addon
"product_name": "Complemento de 10GB de Datos",
"category": "addon",
"retail_cost": 15.00,
"auto_renew": "False", # Compra única
"contract_days": 0,
"provisioning_play": "play_topup_charge_then_action",
"features_list": "['10GB de Datos con Rollover', 'Validez de 30 Días']"
}

Acción: Usa *topup para comportamiento de rollover. Consulta Acciones de CGRateS - Rollover.

Patrón 3: Plan Mensual Fijo (Sin Rollover)

Caso de Uso: Plan mensual que siempre se restablece a exactamente la misma cantidad

Producto CRM:

{
"product_slug": "fixed-50gb-monthly", # Se vincula a Action_fixed-50gb-monthly
"product_name": "Mensual Fijo de 50GB",
"category": "addon",
"retail_cost": 35.00,
"auto_renew": "True",
"contract_days": 30,
"provisioning_play": "play_topup_charge_then_action",
"features_list": "['50GB de Datos', 'Se Restablece Mensualmente', 'Sin Rollover']"
}

Acción: Usa *topup_reset para prevenir rollover. Consulta Acciones de CGRateS - Comportamiento de Restablecimiento.

Avanzado: Cargadores y Planes de Calificación

Importante: Esta sección cubre la calificación básica de pago por uso. CGRateS admite escenarios de calificación increíblemente sofisticados, incluyendo:

  • Tarifas de roaming diferenciales: Precios diferentes para llamadas/SMS MO vs MT al hacer roaming
  • Carga específica de protocolo: CAMEL para 2G/3G (SMS MO-MT, USSD), Diameter para 4G/5G
  • Precios conscientes del contexto: Tarifas basadas en tiempo, ubicación, segmento de cliente, calidad de red
  • Calificación multidimensional: Combinando tipo de red, estado de roaming, destino y hora del día

Los ejemplos a continuación muestran configuraciones de PAYG simples y de tarifa plana adecuadas para la mayoría de las implementaciones de OmniCRM.

Para la facturación de pago por uso (donde el uso más allá de los saldos incluidos cuesta dinero), necesitas definir Planes de Calificación que especifiquen montos en dólares a cobrar.

Cómo Funciona la Calificación

Cuando un cliente utiliza un servicio (datos, voz, SMS):

  1. CGRateS verifica los saldos unitarios (por ejemplo, GB de datos incluidos)
  2. Si existe saldo unitario, el uso se deduce de él
  3. Si no hay saldo unitario o el saldo se agota, CGRateS recurre al saldo monetario
  4. El Plan de Calificación determina el precio (por ejemplo, $0.10 por MB)
  5. El costo calculado se deduce del saldo monetario del cliente

Ejemplo: Configuración de Cargos por Uso de Datos

# 1. Definir una Tarifa de Destino (el precio)
OCS_Obj.SendData({
"method": "ApierV2.SetTPDestinationRate",
"params": [{
"TPid": tpid,
"ID": "DR_DATA_PAYG",
"DestinationRates": [{
"DestinationId": "Dest_PLMN_OnNet",
"RateId": "RT_DATA_$0_10_PER_MB",
"RoundingMethod": "*up",
"RoundingDecimals": 4,
"MaxCost": 0,
"MaxCostStrategy": ""
}]
}]
})

# 2. Definir la tarifa real
OCS_Obj.SendData({
"method": "ApierV2.SetTPRate",
"params": [{
"TPid": tpid,
"ID": "RT_DATA_$0_10_PER_MB",
"RateSlots": [{
"ConnectFee": 0, # Sin cargo de conexión
"Rate": 0.10, # $0.10 por unidad
"RateUnit": "1048576", # 1 MB (1024 * 1024 bytes)
"RateIncrement": "1048576", # Facturar por MB
"GroupIntervalStart": "0s"
}]
}]
})

# 3. Definir un Plan de Calificación que use esta tarifa
OCS_Obj.SendData({
"method": "ApierV2.SetTPRatingPlan",
"params": [{
"TPid": tpid,
"ID": "RP_PAYG_DATA",
"RatingPlanBindings": [{
"DestinationRatesId": "DR_DATA_PAYG",
"TimingId": "*any",
"Weight": 10
}]
}]
})

# 4. Vincular el Plan de Calificación a un Perfil de Calificación (para cuentas específicas)
OCS_Obj.SendData({
"method": "ApierV2.SetTPRatingProfile",
"params": [{
"TPid": tpid,
"Tenant": tenant,
"Category": "data",
"Subject": "*any", # O identificador de cuenta específico
"RatingPlanActivations": [{
"ActivationTime": "2024-01-01T00:00:00Z",
"RatingPlanId": "RP_PAYG_DATA",
"FallbackSubjects": ""
}]
}]
})

# 5. Cargar el plan tarifario
OCS_Obj.SendData({
"method": "APIerSv1.LoadTariffPlanFromStorDb",
"params": [{
"TPid": tpid,
"DryRun": False,
"Validate": True,
"APIOpts": {}
}]
})

Qué hace esto:

  • Cuando un cliente no tiene saldo de datos (o se queda sin él), el uso de datos cuesta $0.10 por MB
  • El cargo se deduce de su saldo monetario (*monetary)
  • Los incrementos de facturación son de 1 MB (redondea hacia arriba)

Ejemplo: Tarifas de Llamadas de Voz

# Definir diferentes tarifas para diferentes destinos
OCS_Obj.SendData({
"method": "ApierV2.SetTPRate",
"params": [{
"TPid": tpid,
"ID": "RT_VOICE_DOMESTIC_$0_30_PER_MIN",
"RateSlots": [{
"ConnectFee": 0.15, # $0.15 de cargo de conexión
"Rate": 0.30, # $0.30 por minuto
"RateUnit": "60s", # Facturar por minuto
"RateIncrement": "60s", # Redondear a minutos completos
"GroupIntervalStart": "0s"
}]
}]
})

OCS_Obj.SendData({
"method": "ApierV2.SetTPRate",
"params": [{
"TPid": tpid,
"ID": "RT_VOICE_INTL_$1_50_PER_MIN",
"RateSlots": [{
"ConnectFee": 0.25, # $0.25 de cargo de conexión
"Rate": 1.50, # $1.50 por minuto
"RateUnit": "60s",
"RateIncrement": "1s", # Facturar por segundo (más preciso)
"GroupIntervalStart": "0s"
}]
}]
})

Perfiles de Cargadores (Opcional)

Los cargadores aplican calificación a tipos específicos de eventos. Para la mayoría de los casos de uso, el cargador predeterminado es suficiente:

OCS_Obj.SendData({
"method": "APIerSv1.SetChargerProfile",
"params": [{
"Tenant": tenant,
"ID": "Charger_Default",
"FilterIDs": [],
"AttributeIDs": ["*constant:*req.RequestType:*none"],
"Weight": 999
}]
})

Ver también:

Mejores Prácticas

1. Usar Convenciones de Nombres Consistentes

# Bueno - relación clara
ActionsId = "Action_premium-plan-100gb"
product_slug = "premium-plan-100gb"

# Malo - sin relación clara
ActionsId = "Action_Plan_A"
product_slug = "premium_100"

2. Definir Acciones Antes de Productos

Siempre crea Acciones de CGRateS antes de crear productos de CRM. El playbook de aprovisionamiento fallará si intenta ejecutar una Acción inexistente.

3. Incluir Registro de CDR

Siempre agrega la acción *cdrlog para rastrear adiciones de saldo:

{
"Identifier": "*cdrlog",
"BalanceType": "*generic",
"ExtraParameters": "{\"Category\":\"^activation\",\"Destination\":\"Nombre del Producto\"}",
"Weight": 80
}

4. Usar IDs de Saldo Descriptivos

# Bueno
"BalanceId": "Premium_Data_100GB"
"BalanceId": "AU_Voice_Domestic__" + str(units)

# Malo
"BalanceId": "data1"
"BalanceId": "balance"

5. Documentar Unidades Claramente

# Bueno - muestra el cálculo
Units = 100 * 1024 * 1024 * 1024 # 100GB en bytes
Units = 3000 * 60 * 1000000000 # 3000 minutos en nanosegundos

# Malo - número mágico
Units = 107374182400

6. Usar Peso Estratégicamente

Mayor peso = mayor prioridad tanto para la ejecución como para el consumo:

# Orden de ejecución (peso más alto = se ejecuta primero)
{"Identifier": "*reset_account", "Weight": 700}
{"Identifier": "*topup_reset", "Weight": 90}
{"Identifier": "*cdrlog", "Weight": 80}

# Consumo de saldo (peso más alto = se consume primero)
"BalanceWeight": 1200 # Saldos premium/nacionales
"BalanceWeight": 1100 # Saldos de roaming
"BalanceWeight": 1000 # Saldos internacionales

7. Probar Primero con Valores Pequeños

Al definir nuevos productos, prueba primero con saldos pequeños:

# Pruebas
Units = 100 * 1024 * 1024 # 100MB para pruebas

# Producción
Units = 100 * 1024 * 1024 * 1024 # 100GB

Solución de Problemas

Error: "Acción no encontrada"

Síntoma: El playbook falla con "Acción no encontrada" o "ActionsId no existe"

Causa: Acción no definida en CGRateS, o desajuste de nombres

Solución:

  1. Verifica que la Acción exista: Consulta a CGRateS por la Acción
  2. Verifica el nombre: Asegúrate de que ActionsId = "Action_" + product_slug
  3. Define la Acción si falta

Error: "Destino no encontrado"

Síntoma: La acción se ejecuta pero no se crean saldos

Causa: DestinationIDs hace referencia a un destino inexistente

Solución:

  1. Define el destino en CGRateS primero
  2. Usa *any para destinos universales
  3. Verifica la ortografía de los IDs de destino

Producto Creado Pero No se Agregan Saldos

Síntoma: El producto se aprovisiona con éxito pero el cliente no tiene saldo

Causa: La Acción existe pero no tiene operaciones para agregar saldo

Solución:

  1. Verifica que la Acción tenga operaciones *topup o *topup_reset
  2. Verifica que el valor de Units sea correcto (no 0)
  3. Verifica que ExpiryTime no haya pasado

Saldos No se Transfieren

Síntoma: Usando rollover pero el saldo no utilizado desaparece

Causa: Usando *topup_reset en lugar de *topup

Solución:

  • Cambia Identifier de *topup_reset a *topup
  • Asegúrate de que BalanceId sea consistente entre recargas

Ver también: Acciones de CGRateS y Comportamientos de Recarga

Resumen

Esta guía demuestra un enfoque común para configurar productos en OmniCRM con CGRateS. Los patrones mostrados aquí funcionan bien para casos de uso típicos de operadores móviles virtuales (MVNO) con planes prepagos/postpagos, paquetes de datos y roaming.

Recuerda: CGRateS es capaz de escenarios mucho más sofisticados de los cubiertos aquí. Si necesitas características avanzadas como:

  • Precios diferenciales MO/MT para voz y SMS en roaming
  • Carga basada en CAMEL para dispositivos heredados 2G/3G
  • Variaciones de tarifas por hora del día o estacionales
  • Precios basados en niveles de cliente (bronce/plata/oro)
  • Carga basada en calidad de red o QoS
  • Enrutamiento de menor costo con múltiples proveedores

...consulta la documentación de CGRateS directamente y trabaja con la configuración de tu plan de calificación independientemente de las definiciones de productos de CRM.

Documentación Relacionada