- 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.).
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;
}
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;
}
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;
}
}
}
}