Lógica y Eventos
FlowFields
Dificultad: 6/10En las bases de datos normales, si entras en un albarán y quieres mostrar siempre la "Suma Total de Euros" a pagar, creas un campo y programas triggers para que se actualice sumando cada vez que añadan, editen o borren una línea. Un FlowField te libera de todo ese trabajo sucio.
¿Qué es un FlowField?
Los FlowFields son campos virtuales que representan una consulta configurada que se ejecuta bajo demanda. No ocupan espacio en la base de datos SQL y garantizan que la información esté siempre actualizada.
Un FlowField no existe físicamente en la base de datos como un número estático guardado en su cajita.
Actúa como un embudo vivo: su valor está siempre vacío hasta que una pieza de interfaz (una
pantalla) o un código lo calcula pidiendo su refresco explícito con CalcFields.
¿Qué logra? Ahorra espacio de almacenamiento masivo y evita errores fatales si un trigger se salta la actualización.
⚠️ Aviso importante
Un FlowField nunca se actualiza solo en código. Siempre hay que llamar a
Rec.CalcFields("NombreCampo") antes de leer su valor desde AL.
Estructura base
Un FlowField requiere siempre FieldClass = FlowField y una fórmula matemática expresada con
CalcFormula:
field(<id>; "<NombreCampo>"; <TipoDato>)
{
FieldClass = FlowField;
CalcFormula = <funcion>("<Tabla>"."<Campo>" where ("<CampoFiltro>" = field("<CampoOrigen>")));
}
Las 6 funciones de CalcFormula
| Función | Tipo resultado | Descripción |
|---|---|---|
Sum |
Decimal |
Suma los valores de una columna numérica en una tabla relacionada |
Average |
Decimal |
Calcula la media aritmética de un conjunto de valores |
Exist |
Boolean |
Devuelve true si existe al menos un registro que cumpla el filtro |
Count |
Integer |
Cuenta la cantidad exacta de registros que coinciden con la relación |
Min / Max |
Decimal / Date |
Localiza el valor más bajo o más alto (numérico o de fecha) |
Lookup |
Cualquiera | Recupera un valor de una tabla externa sin duplicar la información físicamente |
Sum — Suma acumulada
Suma los valores de una columna numérica en una tabla relacionada. Ejemplo: saldo acumulado del cliente desde los movimientos detallados.
field(50100; "Balance (LCY)"; Decimal)
{
FieldClass = FlowField;
CalcFormula = sum("Detailed Cust. Ledg. Entry"."Amount (LCY)"
where ("Customer No." = field("No.")));
}
Average — Precio medio
Calcula la media aritmética de un conjunto de valores. Ejemplo: precio medio de compra de un producto.
field(50101; "Avg. Cost"; Decimal)
{
FieldClass = FlowField;
CalcFormula = average("Item Ledger Entry"."Cost Amount (Actual)"
where ("Item No." = field("No.")));
}
Exist — Comprobación de existencia
Devuelve un booleano (true/false) indicando si existen registros que cumplan el
filtro. Ejemplo: ¿tiene el cliente movimientos registrados?
field(50102; "Has Entries"; Boolean)
{
FieldClass = FlowField;
CalcFormula = exist("Item Ledger Entry"
where ("Item No." = field("No.")));
}
Count — Contador de registros
Cuenta la cantidad exacta de registros que coinciden con la relación. Ejemplo: número de líneas de venta en un documento.
field(50103; "No. of Lines"; Integer)
{
FieldClass = FlowField;
CalcFormula = count("Sales Line"
where ("Document No." = field("No.")));
}
Min / Max — Valores extremos
Localiza el valor más bajo o más alto (numérico o de fecha). Ejemplo: fecha de la primera contabilización en una cuenta contable.
field(50104; "First Posting Date"; Date)
{
FieldClass = FlowField;
CalcFormula = min("G/L Entry"."Posting Date"
where ("G/L Account No." = field("No.")));
}
Lookup — Búsqueda de valor
Recupera un valor (texto, código, etc.) de una tabla externa sin duplicar la información físicamente. Ejemplo: obtener el nombre del vendedor desde su tabla maestra.
field(50105; "Salesperson Name"; Text[100])
{
FieldClass = FlowField;
CalcFormula = lookup(Salesperson.Name
where (Code = field("Salesperson Code")));
}
Usar un FlowField desde código: CalcFields
Cuando lees un FlowField desde código AL, su valor no se calcula automáticamente. Debes llamar
explícitamente a CalcFields antes de usarlo:
var
Socio : Record "Socio";
begin
Socio.Get('S001');
Socio.CalcFields("Total Prestamos"); // forzamos el cálculo
Message('Total préstamos: %1', Socio."Total Prestamos");
end;
💡 Tips
- Los FlowFields no ocupan espacio en SQL: son consultas virtuales que se ejecutan bajo demanda.
- Siempre llama a
CalcFieldsantes de leer un FlowField desde código. En las páginas, BC lo hace automáticamente al mostrar el campo. - Un FlowField es de solo lectura: no puedes asignarle un valor directamente.
- Úsalos para totales, contadores y búsquedas que deben estar siempre actualizados sin programar triggers de actualización.