You are on page 1of 2

function calculateSchedule(workingInterest, loanAmount, installmentFrequency,

installmentAmount, loanTenure, disbursementDate, actualRepaymentDates,


actualRepaidAmounts) {
// Convert string disbursementDate to Date object
disbursementDate = new Date(disbursementDate);
disbursementDate.setHours(0, 0, 0, 0); // Reset time to start of the day

// Calculate total number of installments based on loan tenure


let totalInstallments;
switch (loanTenure) {
case '6':
totalInstallments = 6;
break;
case '12':
totalInstallments = 12;
break;
case '18':
totalInstallments = 18;
break;
case '24':
totalInstallments = 24;
break;
default:
totalInstallments = 12; // Default to 12 months
}

const masterDays = {
Monthly: 30,
weekly: 7,
['Bi-Weekly']: 14,
};

// Initialize arrays to store the schedule data


let schedule = [];
let currentDate = new Date(disbursementDate);

// Calculate schedule for each installment


for (let i = 1; i <= totalInstallments; i++) {
let days = masterDays[installmentFrequency];
// Calculate interest and principal components
let interest = (loanAmount * workingInterest * days) / (365 * 100);
let principal = installmentAmount - interest;

// Update outstanding principal


let outstandingPrincipal = loanAmount - principal;

// Calculate bi-weekly installment


let biWeeklyInstallment = installmentFrequency === 'Monthly' ?
installmentAmount * 12 / 26 : installmentAmount;

// Calculate the payment date


let paymentDate = new Date(currentDate);
paymentDate.setDate(paymentDate.getDate() + days);
paymentDate.setHours(0, 0, 0, 0); // Reset time to start of the day

// Check if there is an actual repayment date for the current installment


let actualRepaymentDate = actualRepaymentDates[i - 1];
let actualRepaidAmount = actualRepaidAmounts[i - 1];
// Adjust remaining principal and interest if the repaid amount is less
than the installment amount
if (actualRepaidAmount && actualRepaidAmount < installmentAmount) {
// Calculate interest based on the repaid amount
interest = (outstandingPrincipal * workingInterest * days) / (365 *
100);

// Adjust principal based on the repaid amount


principal = actualRepaidAmount;

// Update outstanding principal


outstandingPrincipal = loanAmount - principal;
}

// Adjust interest based on the actual number of days the payment was
delayed or made early
if (actualRepaymentDate && actualRepaymentDate.getTime() !==
paymentDate.getTime()) {
let daysDifference = Math.floor((actualRepaymentDate - paymentDate) /
(1000 * 60 * 60 * 24));
interest = (outstandingPrincipal * workingInterest * daysDifference) /
(365 * 100);
}

// Push schedule data to the array


schedule.push({
"Outstanding": outstandingPrincipal.toFixed(2),
"Principal": principal.toFixed(2),
"Interest": interest.toFixed(2),
"Installment": installmentAmount.toFixed(2),
"Bi-Weekly Instt.": biWeeklyInstallment.toFixed(2),
"# Days": days,
"Actual Repayment Date": actualRepaymentDate ?
actualRepaymentDate.toLocaleDateString('en-US') : "-",
"Actual Repaid Amount": actualRepaidAmount ?
actualRepaidAmount.toFixed(2) : "-",
"Payment Date": paymentDate.toLocaleDateString('en-US') // Format
payment date as a string with only the date
});

// Update loan amount for next iteration


loanAmount = outstandingPrincipal;

// Move currentDate to the next installment date


currentDate.setDate(currentDate.getDate() + days);
}

return schedule;
}

You might also like