EJERCICIO 06 · FLOWFILTERS
FlowFilters
Dificultad: 7/10Ejercicios 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,TableRelationhacia ambas tablas superiores. - Tabla
"Historial Estado Maquina"(50102):AutoIncrement, campo"Fecha Cambio"(DateTime),TableRelationcondicional. - 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.aly añade el campo"Date Filter"(Date) conFieldClass = FlowFiltery unCaptiondescriptivo. - Modifica la
CalcFormuladel FlowField"No. Alquileres"para añadir una segunda condición en elwhere:"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.aly añade un nuevogroupllamadoEstadisticasdespués del grupoGeneral. - 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
OnAfterGetRecordque ya tienes, añade tambiénRec.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
50100y nombre"Maquinaria Stats". - Añade el procedimiento
ComparativaTrimestral(MaquinaNo: Code[20]). - Dentro del procedimiento, declara un
Record "Maquinaria"y llama aGetconMaquinaNo. - Aplica
SetRange("Date Filter", ...)con el rango del primer trimestre (01/01 al 31/03 del año actual), llama aCalcFields("No. Alquileres")y guarda el valor en una variable. - Repite el proceso para el segundo trimestre (01/04 al 30/06) usando un nuevo
SetRangesobre 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.