support other interest compounding types (#24)

Co-authored-by: Chris Weiss <chrwei@users.noreply.github.com>
This commit is contained in:
Robert Dyer
2025-05-08 14:14:23 -04:00
committed by GitHub
parent 226c8cb5bd
commit e9922e30c1
2 changed files with 32 additions and 5 deletions
+5
View File
@@ -165,6 +165,11 @@ As an example, if your loan is at 4.5% interest and you want to insert an
interest transaction on the 28th of the month, set the account note to
`interestRate:0.045 interestDay:28`.
By default, interest is calculated using the 30/360 method where interest is
computed monthly using 30/360 (or 1/12) of the interest rate. If you need to
compute interest using the ACTUAL/ACTUAL method, set `interest:actual` in the
note. If you need to compute interest daily, set `interest:daily`.
You can optionally change the payee used for the interest transactions by
setting `INTEREST_PAYEE_NAME` in the `.env` file.
+27 -5
View File
@@ -2,6 +2,11 @@ const api = require('@actual-app/api');
const { closeBudget, ensurePayee, getAccountBalance, getAccountNote, getLastTransactionDate, getTagValue, openBudget, showPercent } = require('./utils');
require("dotenv").config();
function daysInYear(year) {
// Check if the year is a leap year
return ((year % 4 === 0 && year % 100 > 0) || year %400 == 0) ? 366 : 365;
}
(async () => {
await openBudget();
@@ -16,9 +21,12 @@ require("dotenv").config();
const note = await getAccountNote(account);
if (note) {
if (note.indexOf('interestRate:') > -1 && note.indexOf('interestDay:') > -1) {
let interestRate = parseFloat(getTagValue(note, 'interestRate'));
const interestDay = parseInt(getTagValue(note, 'interestDay'));
let interestRate = parseFloat(getTagValue(note, 'interestRate', 0.0));
const interestDay = parseInt(getTagValue(note, 'interestDay', 0));
if (interestRate && interestDay) {
const kind = getTagValue(note, 'interest', 'monthly');
const isDaily = kind == 'daily';
const interestTransactionDate = new Date();
if (interestTransactionDate.getDate() < interestDay) {
@@ -35,8 +43,22 @@ require("dotenv").config();
if (!lastDate) continue;
const daysPassed = Math.floor((interestTransactionDate - new Date(lastDate)) / 86400000);
let period = 12;
let numPeriods = 1
switch (kind) {
case 'daily':
period = daysInYear(interestTransactionDate.getFullYear());
numPeriods = daysPassed;
break;
case 'actual':
period = daysInYear(interestTransactionDate.getFullYear()) / daysPassed;
break;
default:
break;
}
const balance = await getAccountBalance(account, interestTransactionDate);
const compoundedInterest = Math.round(balance * (Math.pow(1 + interestRate / 12, 1) - 1));
const compoundedInterest = Math.round(balance * (Math.pow(1 + interestRate / period, numPeriods) - 1));
interestRate = showPercent(interestRate);
@@ -52,7 +74,7 @@ require("dotenv").config();
payee: payeeId,
amount: compoundedInterest,
cleared: true,
notes: `Interest for 1 month at ${interestRate}`,
notes: `Interest for ${daysPassed} days, ${balance / 100.0} at ${interestRate} (${isDaily ? "daily" : "monthly"})`,
}]);
}
}