Guía Avanzada de Fórmulas para Centralización Contable
Introducción
Este documento proporciona una guía técnica completa sobre el motor de fórmulas utilizado en el sistema de reportes de Centralización Contable. El objetivo es capacitar a los implementadores para construir y personalizar reportes complejos, garantizando la precisión y la integridad de los datos contables generados.
1. Conceptos Fundamentales del Motor de Fórmulas
Antes de construir fórmulas, es crucial comprender los siguientes principios:
Contexto de Operación: Fila Única
Una fórmula siempre opera dentro del contexto de una única fila de datos. Esto significa que solo puede acceder a los valores de las columnas presentes en esa misma fila. No es posible referenciar datos de filas anteriores o posteriores directamente.
Acceso a Campos y Columnas
- Campos Disponibles (field): Se puede utilizar cualquier campo de tipo field dentro de una fórmula, siempre que la columna esté definida explícitamente en la estructura del reporte.
- Campos No Visibles: Si necesitas un dato que no está definido como una columna visible, debes primero crear una columna de tipo Hidden (oculta). Esta columna contendrá el dato requerido y podrá ser referenciada por su código en otras fórmulas, actuando como una variable interna.
Manejo de Columnas con Códigos Duplicados
Es un escenario común tener múltiples columnas que apuntan al mismo campo (por ejemplo, una para el "Debe" y otra para el "Haber" que usan el mismo bind_field). Para evitar la sobrescritura de datos:
- La primera vez que se define una columna con un código, se invoca el dato original.
- En las definiciones posteriores de columnas con el mismo código, no se debe volver a invocar el dato. En su lugar, se debe referenciar el valor ya procesado por la primera columna.
- Advertencia: Si no se sigue esta regla, el valor de la primera columna será sobrescrito por la última definición, lo que puede llevar a la pérdida de información.
2. Métodos y Funciones Disponibles
A continuación se detalla el catálogo completo de métodos predefinidos para la construcción de fórmulas.
Métodos para Cadenas de Texto (String)
Método | Descripción y Parámetros | Ejemplo |
|---|---|---|
FORMAT_DATE(fecha, formato) | Formatea un valor de tipo fecha según un patrón de Ruby (strftime). | FORMAT_DATE(fecha_inicio, 'ac') → "2025-04-23" |
REPLACE(cadena, buscar, reemplazar) | Reemplaza todas las ocurrencias de una subcadena por otra. | REPLACE(nombre_completo, ' ', '_') → "Juan_Perez" |
SUBSTR(cadena, inicio, fin) | Extrae una subcadena especificando la posición inicial y final (base 0). | SUBSTR(codigo_producto, 0, 5) → Extrae los 6 primeros caracteres. |
MERGE_STR(separador, str1, str2, ...) | Concatena múltiples cadenas con un separador definido. | MERGE_STR('-', centro_costo, cuenta) → "CC-101-41100" |
SPLIT_PART(cadena, delimitador, indice) | Divide una cadena por un delimitador y devuelve la parte en el índice especificado (base 1). | SPLIT_PART('A;B;C', ';', 2) → "B" |
CONCAT(str1, str2, ...) | Concatena dos o más cadenas de texto sin un separador. | CONCAT('E', SPLIT_PART(rut, '-', 0)) → "E12345678" |
UNACCENT(cadena) | Elimina o quita acentos y diacríticos de una cadena de texto. | UNACCENT('Nómina') → "Nomina" |
UPPERCASE(cadena) | Convierte una cadena de texto a mayúsculas. | UPPERCASE(' hola') → "HOLA" |
LOWERCASE(cadena) | Convierte una cadena de texto a minúsculas. | LOWERCASE('Reporte') → "reporte" |
Métodos Condicionales y de Valor
Método | Descripción y Parámetros | Ejemplo |
|---|---|---|
IF(condicion, valor_si_verdadero, valor_si_falso) | Evalúa una condición lógica y retorna un valor según el resultado. | IF(operation_type == 'debit', value, value * -1) |
VALUE(valor_comp, campo_eval, v_coincide, v_no_coincide) | Compara un valor con un campo y retorna un resultado basado en la coincidencia. | VALUE('debit', operation_type, ROUND(value), '') |
Métodos Numéricos
Método | Descripción y Parámetros | Ejemplo |
|---|---|---|
ROUND(valor, decimales) | Redondea un número a la cantidad de decimales especificada (por defecto 0). | ROUND(monto_imponible, 0) |
ABS(numero) | Devuelve el valor absoluto de un número. | ABS(descuento) |
3. Ejemplos de Fórmulas Complejas (Análisis)
Ejemplo 1: Lógica Condicional Anidada
IF(operation_type == 'debit', CONCAT(center, '-', IF(SUBSTR(center, 3, 3) == '5', CONCAT('5', SUBSTR(account, 1, LEN(account))), account)), CONCAT(balance, account))
- Análisis:
- Condición Principal: Si operation_type es 'debit'.
- Ruta Verdadera: Concatena center con un guion (-) y el resultado de una segunda condición.
- Condición Anidada: Revisa si el cuarto carácter de center es '5'.
- Si es '5', concatena '5' con la cuenta contable (account).
- Si no es '5', usa el valor de account directamente.
- Ruta Falsa: Si operation_type no es 'debit', concatena balance con account.
Ejemplo 2: Limpieza y Formateo de RUT
REPLACE(CONCAT('E', rut), '-', '')
- Análisis:
- CONCAT('E', rut): Agrega el prefijo 'E' al RUT del empleado. (Ej: "E12345678-9").
- REPLACE(...): Toma el resultado anterior y reemplaza el guion (-) con una cadena vacía, eliminándolo. (Ej: "E123456789").
4. Anexo: Formatos de Fecha (FORMAT_DATE)
Utiliza los siguientes especificadores de formato basados en strftime de Ruby.
Categoría | Formato | Descripción | Ejemplo |
|---|---|---|---|
Año | %Y | Año con siglo | 2025 |
%y | Año sin siglo (00-99) | 25 | |
Mes | %m | Mes del año (01-12) | 09 |
%-m | Mes del año sin cero inicial (1-12) | 9 | |
%B | Nombre completo del mes | September | |
%b | Nombre abreviado del mes | Sep | |
Día | %d | Día del mes (01-31) | 02 |
%-d | Día del mes sin cero inicial (1-31) | 2 | |
%j | Día del año (001-366) | 245 | |
Hora | %H | Hora (24h, 00-23) | 14 |
%I | Hora (12h, 01-12) | 02 | |
%p | AM/PM en mayúsculas | PM | |
%M | Minuto (00-59) | 30 | |
%S | Segundo (00-59) | 55 | |
Combinados | %F | Formato AAAA-MM-DD | 2025-09-02 |
%T | Formato HH:MM:SS | 14:30:55 |
5. Preguntas Frecuentes (FAQ) para Implementadores
P1: ¿Qué hago si mi fórmula no produce ningún resultado o da error? R:
- Verifica la Sintaxis: Revisa que los nombres de los métodos, los paréntesis y las comas estén correctos.
- Revisa los Nombres de las Columnas: Asegúrate de que los códigos de las columnas que referencias en la fórmula existan y estén escritos exactamente igual.
- Aísla el Problema: Simplifica la fórmula. Empieza con una parte pequeña y funcional (ej: solo el código de una columna) y ve añadiendo complejidad gradualmente hasta encontrar el punto de fallo.
- Tipos de Datos: Confirma que estás aplicando los métodos correctos al tipo de dato adecuado (ej: no usar SUBSTR en un campo numérico sin convertirlo primero).
P2: ¿Es posible realizar cálculos entre diferentes filas, como un total acumulado? R: No directamente dentro de una fórmula. El motor opera exclusivamente en el contexto de la fila actual. Los totales acumulados o cálculos inter-filas deben ser manejados por la lógica de agregación del reporte de Odoo, no por las fórmulas a nivel de línea.
P3: ¿Cómo referencio el valor de una columna que acabo de crear con otra fórmula? R: Simplemente usa el código (ID) que le asignaste a esa columna en la nueva fórmula. El motor procesa las columnas en un orden determinado, por lo que para cuando se evalúe tu nueva fórmula, el valor de la columna referenciada ya debería haber sido calculado.
P4: ¿Cuál es la diferencia principal entre CONCAT y MERGE_STR? R: MERGE_STR está diseñado para unir múltiples elementos con un separador común definido en el primer parámetro. CONCAT simplemente une las cadenas una tras otra, sin ningún separador automático entre ellas. Usa MERGE_STR para listas (ej: codigo-cuenta-centro_costo) y CONCAT para uniones directas (ej: prefijo-valor).
P5: Mi fórmula con IF no se comporta como espero. ¿Qué debo revisar? R:
- La Condición: Asegúrate de usar == para la comparación de igualdad.
- Valores de Texto: Las cadenas de texto deben ir entre comillas simples ('). Ejemplo: IF(tipo == 'debit', ...).
- Valores Verdadero/Falso: Verifica que lo que has puesto en valor_si_verdadero y valor_si_falso sea correcto. Puedes poner el código de otra columna, un valor fijo, o incluso otra fórmula anidada.