Lógica y Eventos

FlowFields

Dificultad: 6/10

En 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:

AL
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.

AL
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.

AL
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?

AL
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.

AL
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.

AL
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.

AL
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:

AL
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 CalcFields antes 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.
← Volver a Teoría