EJERCICIO 09 · PARTS Y FACTBOXES

Parts y FactBoxes

Dificultad: 6/10
Ejercicios anteriores

¿Qué tienes construido hasta ahora?

  • Modelo de datos completo: "Maquinaria", "Cabecera Alquiler", "Linea Alquiler" y "Historial Estado Maquina" con triggers, FlowFields, FlowFilters y TableRelations.
  • Pages completas: "Maquinaria List" y "Maquinaria Card" (con grupos, Importance, CardPageId y OnAfterGetRecord).
  • "Cabecera Alquiler List", "Alquileres Activos List" y "Cabecera Alquiler Card".
  • "Historial Maquina Part" (ListPart) y "Maquinaria Stats Part" (CardPart) ya creadas en el ejercicio anterior y embebidas en "Maquinaria Card".

Ya tienes las Parts básicas en pie. En este ejercicio vas a profundizar en SubPageLink, añadir Parts donde aún faltan y conectar el lado de Cabecera Alquiler con toda su información relacionada. El resultado final será una interfaz completa donde el usuario puede ver las líneas de un alquiler y el resumen de la máquina sin salir de la pantalla actual.

Este es el wireframe de la pantalla que construirás en el ejercicio:

Cabecera Alquiler Card — grupo General
No. Descripcion No. Maquina Principal Fecha Inicio Fecha Fin Estado Creado Por Modificado Por
ListPart — "Lineas Alquiler Part" (nueva)
No. Linea | No. Maquina | Fecha Inicio | Fecha Fin | Dias Alquiler
No. Linea | No. Maquina | Fecha Inicio | Fecha Fin | Dias Alquiler
No. Linea | No. Maquina | Fecha Inicio | Fecha Fin | Dias Alquiler
CardPart — "Maquinaria Stats Part" (ya existe)
No. Alquileres: 12
Tiene Historial: Sí
Último Cambio: 01/03/2026
ListPart — "Historial Maquina Part" (ya existe)
Disponible → Alquilado
Alquilado → En Reparación
En Reparación → Disponible
ListPart (zona principal) FactBoxes (columna lateral)
Ejercicio 01
ListPart · SubPageLink

Crea el ListPart de líneas de alquiler

Objetivo: Construir el subformulario de líneas y embebarlo directamente en el layout principal de "Cabecera Alquiler Card" (no en FactBoxes), para reproducir el patrón clásico de cabecera → líneas que tienen los documentos de BC.

Instrucciones

  • Crea LineasAlquilerPart.Page.al (ID 50109): PageType = ListPart, SourceTable = "Linea Alquiler". Muestra los campos "No. Linea", "No. Maquina", "Fecha Inicio", "Fecha Fin" y "Dias Alquiler". Recuerda: en un ListPart no se usa repeater.
  • Abre CabeceraAlquilerCard.Page.al y añade un part dentro del area(Content), después del grupo General, apuntando a "Lineas Alquiler Part".
  • Configura el SubPageLink: el campo "No. Alquiler" de "Linea Alquiler" debe enlazarse con el campo "No." de "Cabecera Alquiler".

Pista de Código

AL — LineasAlquilerPart.Page.al
page 50109 "Lineas Alquiler Part"
{
    PageType        = ListPart;
    ApplicationArea = All;
    SourceTable     = "Linea Alquiler";

    layout
    {
        area(Content)
        {
            // ⚠️ Sin repeater — el ListPart ya lo implica
            field("No. Linea";    Rec."No. Linea")    { ApplicationArea = All; }
            field("No. Maquina";  Rec."No. Maquina")  { ApplicationArea = All; }
            field("Fecha Inicio"; Rec."Fecha Inicio") { ApplicationArea = All; }
            field("Fecha Fin";    Rec."Fecha Fin")    { ApplicationArea = All; }
            field("Dias Alquiler"; Rec."Dias Alquiler") { ApplicationArea = All; }
        }
    }
}
AL — CabeceraAlquilerCard.Page.al (layout con part)
    layout
    {
        area(Content)
        {
            group(General)
            {
                // ... campos existentes
            }

            // Part embebido en el cuerpo principal (no en FactBoxes)
            part(LineasAlquiler; "Lineas Alquiler Part")
            {
                ApplicationArea = All;
                Caption         = 'Líneas de Alquiler';
                SubPageLink     = "No. Alquiler" = field("No.");
            }
        }
    }
💡 Recuerda: La diferencia entre poner el part en area(Content) y en area(FactBoxes) es visual. En Content aparece integrado en el cuerpo principal de la ficha (patrón cabecera/líneas); en FactBoxes aparece en la columna lateral derecha. Para un subformulario de líneas, siempre va en Content.
Ejercicio 02
FactBoxes · CardPart · SubPageLink

Añade FactBoxes a Cabecera Alquiler Card

Objetivo: Reutilizar las Parts ya construidas en ejercicios anteriores para enriquecer "Cabecera Alquiler Card" con dos FactBoxes laterales: el resumen estadístico de la máquina y su historial de estados, conectados a través del campo "No. Maquina Principal".

Instrucciones

  • En CabeceraAlquilerCard.Page.al, añade un area(FactBoxes) después del area(Content).
  • Añade el part que apunte a "Maquinaria Stats Part" (ya existe del ejercicio anterior). El SubPageLink debe conectar el campo "No." de "Maquinaria" con el campo "No. Maquina Principal" de "Cabecera Alquiler".
  • Añade un segundo part que apunte a "Historial Maquina Part" (también ya existe). El SubPageLink debe conectar "No. Maquina" de "Historial Estado Maquina" con "No. Maquina Principal" de "Cabecera Alquiler".

Pista de Código

AL — CabeceraAlquilerCard.Page.al (area FactBoxes)
        area(FactBoxes)
        {
            // Reutilizamos "Maquinaria Stats Part" del ejercicio anterior
            part(EstadisticasMaquina; "Maquinaria Stats Part")
            {
                ApplicationArea = All;
                Caption         = 'Estadísticas de la Máquina';
                // "No." en tabla Maquinaria = "No. Maquina Principal" en Cabecera Alquiler
                SubPageLink     = "No." = field("No. Maquina Principal");
            }

            // Reutilizamos "Historial Maquina Part" del ejercicio anterior
            part(HistorialMaquina; "Historial Maquina Part")
            {
                ApplicationArea = All;
                Caption         = 'Historial de Estado';
                // "No. Maquina" en Historial = "No. Maquina Principal" en Cabecera Alquiler
                SubPageLink     = "No. Maquina" = field("No. Maquina Principal");
            }
        }
⚠️ Ojo con el SubPageLink: El campo de la izquierda siempre pertenece a la tabla de la Part (tabla hija). El campo de la derecha, dentro de field(), pertenece a la tabla de la page padre. Si los intercambias, BC no lanzará error de compilación pero el filtro no funcionará y el panel mostrará todos los registros.
Ejercicio 03
SubPageLink compuesto

SubPageLink con clave primaria compuesta

Objetivo: Practicar el SubPageLink con más de un campo, necesario cuando la tabla hija tiene una clave primaria compuesta. Añadirás una page de tipo ListPart al historial que filtre simultáneamente por máquina y por tipo de origen.

Instrucciones

  • Crea HistorialAlquilerPart.Page.al (ID 50110): PageType = ListPart, SourceTable = "Historial Estado Maquina". Muestra "Entry No.", "Estado Anterior", "Estado Nuevo", "Fecha Cambio" y "No. Origen".
  • Añade este ListPart como segunda Part en el area(FactBoxes) de "Cabecera Alquiler Card", reemplazando al "Historial Maquina Part" que ya estaba. Configura un SubPageLink compuesto con dos condiciones:
    • "No. Maquina" = field("No. Maquina Principal")
    • "Tipo Origen" = const(Alquiler)
  • De este modo el panel lateral mostrará solo los cambios de estado que ocurrieron durante un alquiler, no los manuales.

Pista de Código

AL — HistorialAlquilerPart.Page.al
page 50110 "Historial Alquiler Part"
{
    PageType        = ListPart;
    ApplicationArea = All;
    SourceTable     = "Historial Estado Maquina";
    Editable        = false;

    layout
    {
        area(Content)
        {
            field("Entry No.";       Rec."Entry No.")       { ApplicationArea = All; }
            field("Estado Anterior"; Rec."Estado Anterior") { ApplicationArea = All; }
            field("Estado Nuevo";    Rec."Estado Nuevo")    { ApplicationArea = All; }
            field("Fecha Cambio";    Rec."Fecha Cambio")    { ApplicationArea = All; }
            field("No. Origen";     Rec."No. Origen")     { ApplicationArea = All; }
        }
    }
}
AL — SubPageLink compuesto en CabeceraAlquilerCard
            part(HistorialAlquiler; "Historial Alquiler Part")
            {
                ApplicationArea = All;
                Caption         = 'Historial de Estados (Alquiler)';
                SubPageLink     = "No. Maquina"  = field("No. Maquina Principal"),
                                  "Tipo Origen"  = const(Alquiler);
                // const(Alquiler) filtra directamente por el valor del Option
                // sin necesidad de que sea un campo de la tabla padre
            }
💡 Recuerda: En un SubPageLink puedes mezclar field() (valor del registro padre) con const() (valor fijo hardcodeado). Esto permite filtrar la Part por una combinación de contexto dinámico y condición estática, sin necesidad de crear una page separada para cada caso.
💡 Bonus: Ahora tienes "Historial Maquina Part" (todos los cambios) y "Historial Alquiler Part" (solo los de alquiler). Podrías añadir ambas en "Maquinaria Card" como dos FactBoxes independientes: una con todos los cambios y otra filtrada solo por const(Manual) para ver las revisiones manuales. El usuario tendría una vista completa del ciclo de vida de cada máquina sin salir de su ficha.
← Volver a Ejercicios