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 9 Task Traceability

  • Task 1 → LoanRepaymentSchedule.Table.al (OnModify uses xRec.Paid).
  • Task 2 → LoanRepaymentMgt.Codeunit.al (codeunit 50100 / "Loan Repayment Mgt.").
  • Task 3 → LoanRepaymentMgt.Codeunit.al (MarkInstallmentPaid).
  • Task 4 → LoanRepaymentMgt.Codeunit.al (GenerateSchedule).
  • Task 5 → LoanRepaymentScheduleList.Page.al (MarkPaid action calls MarkInstallmentPaid).
  • Task 6 → LoanRepaymentMgt.Codeunit.al (existing-schedule guard by Loan No.).

Code

LoanRepaymentSchedule.Table.al

table 50100 "Loan Repayment Schedule"
{
    DataClassification = CustomerContent;

    fields
    {
        field(1; "Loan No."; Code[20])
        {
            DataClassification = CustomerContent;
        }
        field(2; "Installment No."; Integer)
        {
            DataClassification = CustomerContent;
        }
        field(3; "Vendor No."; Code[20])
        {
            DataClassification = CustomerContent;
            TableRelation = Vendor."No.";
        }
        field(4; "Due Date"; Date)
        {
            DataClassification = CustomerContent;
        }
        field(5; "Payment Date"; Date)
        {
            DataClassification = CustomerContent;
        }
        field(6; "Principal Amount"; Decimal)
        {
            DataClassification = CustomerContent;
        }
        field(7; "Interest Amount"; Decimal)
        {
            DataClassification = CustomerContent;
        }
        field(8; "Total Amount"; Decimal)
        {
            DataClassification = CustomerContent;
        }
        field(9; Paid; Boolean)
        {
            DataClassification = CustomerContent;
        }
    }

    keys
    {
        key(PK; "Loan No.", "Installment No.")
        {
            Clustered = true;
        }
    }

    trigger OnInsert()
    begin
        "Total Amount" := "Principal Amount" + "Interest Amount";
    end;

    trigger OnModify()
    begin
        if xRec.Paid then
            Error('A paid installment cannot be changed.');
        "Total Amount" := "Principal Amount" + "Interest Amount";
    end;
}

LoanRepaymentMgt.Codeunit.al

codeunit 50100 "Loan Repayment Mgt."
{
    procedure MarkInstallmentPaid(var LoanRepaymentSchedule: Record "Loan Repayment Schedule")
    begin
        LoanRepaymentSchedule."Payment Date" := Today;
        LoanRepaymentSchedule.Paid := true;
        LoanRepaymentSchedule.Modify(true);
    end;

    procedure GenerateSchedule(LoanNo: Code[20]; NumberOfInstallments: Integer; PrincipalPerInstallment: Decimal; InterestPerInstallment: Decimal; FirstDueDate: Date; VendorNo: Code[20])
    var
        LoanRepaymentSchedule: Record "Loan Repayment Schedule";
        i: Integer;
    begin
        LoanRepaymentSchedule.SetRange("Loan No.", LoanNo);
        if LoanRepaymentSchedule.FindFirst() then
            Error('A schedule already exists for loan %1.', LoanNo);

        for i := 1 to NumberOfInstallments do begin
            LoanRepaymentSchedule.Init();
            LoanRepaymentSchedule."Loan No." := LoanNo;
            LoanRepaymentSchedule."Installment No." := i;
            LoanRepaymentSchedule."Vendor No." := VendorNo;
            LoanRepaymentSchedule."Due Date" := CalcDate(StrSubstNo('<+%1M>', i - 1), FirstDueDate);
            LoanRepaymentSchedule."Principal Amount" := PrincipalPerInstallment;
            LoanRepaymentSchedule."Interest Amount" := InterestPerInstallment;
            LoanRepaymentSchedule.Insert(true);
        end;
    end;
}

LoanRepaymentScheduleList.Page.al

page 50100 "Loan Repayment Schedule List"
{
    PageType = List;
    SourceTable = "Loan Repayment Schedule";
    ApplicationArea = All;
    UsageCategory = Lists;
    Caption = 'Loan Repayment Schedule';

    layout
    {
        area(Content)
        {
            repeater(General)
            {
                field("Loan No."; Rec."Loan No.")
                {
                    ApplicationArea = All;
                }
                field("Installment No."; Rec."Installment No.")
                {
                    ApplicationArea = All;
                }
                field("Vendor No."; Rec."Vendor No.")
                {
                    ApplicationArea = All;
                }
                field("Due Date"; Rec."Due Date")
                {
                    ApplicationArea = All;
                }
                field("Payment Date"; Rec."Payment Date")
                {
                    ApplicationArea = All;
                }
                field("Principal Amount"; Rec."Principal Amount")
                {
                    ApplicationArea = All;
                }
                field("Interest Amount"; Rec."Interest Amount")
                {
                    ApplicationArea = All;
                }
                field("Total Amount"; Rec."Total Amount")
                {
                    ApplicationArea = All;
                }
                field(Paid; Rec.Paid)
                {
                    ApplicationArea = All;
                }
            }
        }
    }

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

                trigger OnAction()
                var
                    LoanRepaymentMgt: Codeunit "Loan Repayment Mgt.";
                begin
                    LoanRepaymentMgt.MarkInstallmentPaid(Rec);
                    CurrPage.Update(false);
                end;
            }
        }
    }
}