Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 16 Task Traceability

  • Task 1 → Extension flow (text diagram):
    1. User opens page (PettyCashLogList.Page.al).
    2. Table enforces data rules and edit restrictions (PettyCashLog.Table.al).
    3. Page action calls business logic (MarkReconciled in PettyCashMgt.Codeunit.al).
    4. Test protects behavior (PettyCashMgtTests.Codeunit.al).
    5. Permission sets control access (PettyCashView.PermissionSet.al, PettyCashFull.PermissionSet.al).
    6. Field classification supports compliance (PettyCashLog.Table.al data classifications).
  • Task 2 → Implemented in:
    • PettyCashLog.Table.al
    • PettyCashLogList.Page.al
    • PettyCashMgt.Codeunit.al
    • PettyCashView.PermissionSet.al
    • PettyCashFull.PermissionSet.al
    • PettyCashMgtTests.Codeunit.al
  • Task 3 → A composite key is unnecessary because entries are independent transactions and do not belong to a natural grouped sequence like installments within one loan.

Code

PettyCashLog.Table.al

table 50110 "Petty Cash Log"
{
    DataClassification = CustomerContent;

    fields
    {
        field(1; "Entry No."; Integer)
        {
            DataClassification = SystemMetadata;
            AutoIncrement = true;
        }
        field(2; "Received By"; Code[20])
        {
            DataClassification = EndUserIdentifiableInformation;
            TableRelation = Employee."No.";
        }
        field(3; Amount; Decimal)
        {
            DataClassification = CustomerContent;
            MinValue = 0.01;
        }
        field(4; Purpose; Text[100])
        {
            DataClassification = CustomerContent;
            NotBlank = true;
        }
        field(5; "Entry Date"; Date)
        {
            DataClassification = CustomerContent;
        }
        field(6; Reconciled; Boolean)
        {
            DataClassification = CustomerContent;
        }
    }

    keys
    {
        key(PK; "Entry No.")
        {
            Clustered = true;
        }
    }

    trigger OnModify()
    begin
        if xRec.Reconciled then
            Error('A reconciled petty cash entry cannot be changed.');
    end;
}

PettyCashLogList.Page.al

page 50110 "Petty Cash Log List"
{
    PageType = List;
    SourceTable = "Petty Cash Log";
    ApplicationArea = All;
    UsageCategory = Lists;
    Caption = 'Petty Cash Log';

    layout
    {
        area(Content)
        {
            repeater(General)
            {
                field("Entry No."; Rec."Entry No.")
                {
                    ApplicationArea = All;
                }
                field("Received By"; Rec."Received By")
                {
                    ApplicationArea = All;
                }
                field(Amount; Rec.Amount)
                {
                    ApplicationArea = All;
                }
                field(Purpose; Rec.Purpose)
                {
                    ApplicationArea = All;
                }
                field("Entry Date"; Rec."Entry Date")
                {
                    ApplicationArea = All;
                }
                field(Reconciled; Rec.Reconciled)
                {
                    ApplicationArea = All;
                }
            }
        }
    }

    actions
    {
        area(Processing)
        {
            action(MarkReconciled)
            {
                ApplicationArea = All;
                Caption = 'Mark Reconciled';
                Image = Approve;

                trigger OnAction()
                var
                    PettyCashMgt: Codeunit "Petty Cash Mgt.";
                begin
                    PettyCashMgt.MarkReconciled(Rec);
                    CurrPage.Update(false);
                end;
            }
        }
    }
}

PettyCashMgt.Codeunit.al

codeunit 50111 "Petty Cash Mgt."
{
    procedure MarkReconciled(var PettyCashLog: Record "Petty Cash Log")
    begin
        PettyCashLog.Reconciled := true;
        PettyCashLog.Modify(true);
    end;
}

PettyCashView.PermissionSet.al

permissionset 50112 "Petty Cash - View"
{
    Assignable = true;
    Caption = 'Petty Cash (View Only)';

    Permissions =
        table "Petty Cash Log" = X,
        tabledata "Petty Cash Log" = R,
        page "Petty Cash Log List" = X;
}

PettyCashFull.PermissionSet.al

permissionset 50113 "Petty Cash - Full"
{
    Assignable = true;
    Caption = 'Petty Cash (Full Access)';
    IncludedPermissionSets = "Petty Cash - View";

    Permissions =
        tabledata "Petty Cash Log" = IMD,
        codeunit "Petty Cash Mgt." = X;
}

PettyCashMgtTests.Codeunit.al

codeunit 50114 "Petty Cash Mgt. Tests"
{
    Subtype = Test;

    [Test]
    procedure MarkReconciledSetsFlag()
    var
        PettyCashLog: Record "Petty Cash Log";
        PettyCashMgt: Codeunit "Petty Cash Mgt.";
        Assert: Codeunit Assert;
    begin
        PettyCashLog.Init();
        PettyCashLog."Received By" := 'E0001';
        PettyCashLog.Amount := 20;
        PettyCashLog.Purpose := 'Office supplies';
        PettyCashLog."Entry Date" := Today;
        PettyCashLog.Insert(true);

        PettyCashMgt.MarkReconciled(PettyCashLog);

        Assert.IsTrue(PettyCashLog.Reconciled, 'Entry should be marked reconciled.');
    end;
}