EJERCICIO 06 · FLOWFILTERS

FlowFilters

Dificultad: 7/10
Ejercicios anteriores

¿Qué tienes construido hasta ahora?

  • Enum "Rental Status" con los estados de maquinaria, extensible.
  • Tabla "Maquinaria" (50100): FlowFields "No. Alquileres" (count), "Tiene Historial" (exist) y "Ultimo Cambio Estado" (max).
  • Tabla "Cabecera Alquiler" (50103): FlowFields "No. Lineas" (count) y "Descripcion Maquina" (lookup).
  • Tabla "Linea Alquiler" (50101): PK compuesta, TableRelation hacia ambas tablas superiores.
  • Tabla "Historial Estado Maquina" (50102): AutoIncrement, campo "Fecha Cambio" (DateTime), TableRelation condicional.
  • Pages "Maquinaria List", "Maquinaria Card" y "Cabecera Alquiler Card".

Los FlowFields que creaste en el ejercicio anterior siempre calculan el total global: todos los alquileres de una máquina desde el principio de los tiempos. Pero el responsable de flota quiere poder preguntar: "¿Cuántos alquileres tuvo esta máquina en el primer trimestre?" o "¿Cuántos cambios de estado ocurrieron este mes?". Para eso necesitas FlowFilters.

En este ejercicio vas a añadir un "Date Filter" a las tablas clave del proyecto y conectarlo con los FlowFields existentes, de modo que los totales respondan al rango de fechas que el usuario introduzca en pantalla.

Ejercicio 01
FlowFilter · Definición

Añade un Date Filter a Maquinaria

Objetivo: Declarar el campo FlowFilter "Date Filter" en la tabla "Maquinaria" y conectarlo al FlowField "No. Alquileres" para que el contador solo tenga en cuenta las líneas cuya "Fecha Inicio" caiga dentro del rango indicado.

Lo que cambia

Antes — sin FlowFilter field(10; "No. Alquileres"; Integer) { FieldClass = FlowField; CalcFormula = count("Linea Alquiler" where ("No. Maquina" = field("No."))); // cuenta TODOS los alquileres }
Después — con FlowFilter field(10; "No. Alquileres"; Integer) { FieldClass = FlowField; CalcFormula = count("Linea Alquiler" where ("No. Maquina" = field("No."), "Fecha Inicio" = field("Date Filter"))); // solo el rango elegido }

Instrucciones

  • Abre Maquinaria.Table.al y añade el campo "Date Filter" (Date) con FieldClass = FlowFilter y un Caption descriptivo.
  • Modifica la CalcFormula del FlowField "No. Alquileres" para añadir una segunda condición en el where: "Fecha Inicio" = field("Date Filter").
  • Haz lo mismo con el FlowField "Tiene Historial": añade la condición "Fecha Cambio" = field("Date Filter") para que la comprobación de existencia también respete el periodo.

Pista de Código

AL — Maquinaria.Table.al (campos nuevos y modificados)
        // ── FlowFilter ──────────────────────────────────────────────
        field(20; "Date Filter"; Date)
        {
            FieldClass = FlowFilter;
            Caption    = 'Rango de Fechas';
        }

        // ── FlowField actualizado: count filtrando por fecha ────────
        field(10; "No. Alquileres"; Integer)
        {
            FieldClass  = FlowField;
            CalcFormula = count("Linea Alquiler"
                                where ("No. Maquina"  = field("No."),
                                       "Fecha Inicio" = field("Date Filter")));
            Editable    = false;
        }

        // ── FlowField actualizado: exist filtrando por fecha ────────
        field(11; "Tiene Historial"; Boolean)
        {
            FieldClass  = FlowField;
            CalcFormula = exist("Historial Estado Maquina"
                                where ("No. Maquina"  = field("No."),
                                       "Fecha Cambio" = field("Date Filter")));
            Editable    = false;
        }
💡 Recuerda: Cuando el usuario deja el "Date Filter" vacío, BC lo ignora por completo y el FlowField devuelve el total global. El filtro solo restringe el cálculo cuando tiene un valor asignado.
Ejercicio 02
FlowFilter · Page

Muestra el Date Filter en Maquinaria Card

Objetivo: Exponer el FlowFilter "Date Filter" en la ficha de maquinaria para que el usuario pueda introducir un rango de fechas directamente en pantalla y ver cómo cambian los FlowFields al instante.

Instrucciones

  • Abre MaquinariaCard.Page.al y añade un nuevo group llamado Estadisticas después del grupo General.
  • Dentro de Estadisticas, añade primero el campo "Date Filter" para que el usuario pueda introducir el rango. Los campos FlowFilter son editables por defecto en las pages: no necesitas ninguna propiedad especial.
  • Debajo del filtro, añade los campos "No. Alquileres", "Tiene Historial" y "Ultimo Cambio Estado".
  • En el trigger OnAfterGetRecord que ya tienes, añade también Rec.CalcFields("No. Alquileres", "Tiene Historial") para que se calculen al abrir la ficha.

Pista de Código

AL — MaquinariaCard.Page.al (fragmento layout)
            group(Estadisticas)
            {
                Caption = 'Estadísticas';

                field("Date Filter";        Rec."Date Filter")        { ApplicationArea = All; }
                field("No. Alquileres";    Rec."No. Alquileres")    { ApplicationArea = All; }
                field("Tiene Historial";   Rec."Tiene Historial")   { ApplicationArea = All; }
                field("Ultimo Cambio Estado"; Rec."Ultimo Cambio Estado") { ApplicationArea = All; }
            }
AL — trigger OnAfterGetRecord actualizado
    trigger OnAfterGetRecord()
    begin
        Rec.CalcFields(
            "Ultimo Cambio Estado",
            "No. Alquileres",
            "Tiene Historial"
        );
    end;
⚠️ Ojo: Cuando el usuario cambia el "Date Filter" en pantalla, BC recalcula automáticamente los FlowFields vinculados. El CalcFields manual solo es necesario en el OnAfterGetRecord para la carga inicial del registro.
Ejercicio 03
FlowFilter · SetRange en código

Comparativa trimestral de alquileres por máquina

Objetivo: Escribir un procedimiento en un codeunit que, para una máquina concreta, compare el número de alquileres del primer y segundo trimestre del año en curso usando SetRange sobre el FlowFilter antes de cada CalcFields.

Instrucciones

  • Crea un codeunit con ID 50100 y nombre "Maquinaria Stats".
  • Añade el procedimiento ComparativaTrimestral(MaquinaNo: Code[20]).
  • Dentro del procedimiento, declara un Record "Maquinaria" y llama a Get con MaquinaNo.
  • Aplica SetRange("Date Filter", ...) con el rango del primer trimestre (01/01 al 31/03 del año actual), llama a CalcFields("No. Alquileres") y guarda el valor en una variable.
  • Repite el proceso para el segundo trimestre (01/04 al 30/06) usando un nuevo SetRange sobre el mismo registro.
  • Muestra ambos valores con un Message.

Pista de Código

AL — MaquinariaStats.Codeunit.al
codeunit 50100 "Maquinaria Stats"
{
    procedure ComparativaTrimestral(MaquinaNo: Code[20])
    var
        Maquina : Record "Maquinaria";
        Q1      : Integer;
        Q2      : Integer;
        Hoy     : Date;
        AnoActual: Integer;
    begin
        Maquina.Get(MaquinaNo);
        Hoy       := Today();
        AnoActual := Date2DMY(Hoy, 3); // extrae el año

        // ── Primer trimestre ────────────────────────────────────────
        Maquina.SetRange("Date Filter",
            DMY2Date(1, 1, AnoActual),   // 01/01/AAAA
            DMY2Date(31, 3, AnoActual));  // 31/03/AAAA
        Maquina.CalcFields("No. Alquileres");
        Q1 := Maquina."No. Alquileres";

        // ── Segundo trimestre ───────────────────────────────────────
        Maquina.SetRange("Date Filter",
            DMY2Date(1, 4, AnoActual),   // 01/04/AAAA
            DMY2Date(30, 6, AnoActual));  // 30/06/AAAA
        Maquina.CalcFields("No. Alquileres");
        Q2 := Maquina."No. Alquileres";

        Message('Máquina %1 — Alquileres Q1: %2 | Q2: %3', MaquinaNo, Q1, Q2);
    end;
}
⚠️ Recuerda: El SetRange del FlowFilter debe ir siempre antes del CalcFields. Si los intercambias, BC ya habrá calculado el valor sin el filtro y el resultado será incorrecto.
💡 Bonus: Ahora que tienes el codeunit "Maquinaria Stats", puedes añadir una acción VerComparativa en MaquinariaCard.Page.al que llame a "Maquinaria Stats".ComparativaTrimestral(Rec."No.") desde su trigger OnAction. Así el usuario puede ejecutar el análisis con un solo clic desde la ficha de cualquier máquina.
← Volver a Ejercicios