94 lines
3.2 KiB
JavaScript
94 lines
3.2 KiB
JavaScript
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();
|
|
|
|
const payeeId = await ensurePayee(process.env.INTEREST_PAYEE_NAME || 'Loan Interest');
|
|
|
|
const accounts = await api.getAccounts();
|
|
for (const account of accounts) {
|
|
if (account.closed) {
|
|
continue;
|
|
}
|
|
|
|
const note = await getAccountNote(account);
|
|
|
|
if (note) {
|
|
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) {
|
|
interestTransactionDate.setMonth(interestTransactionDate.getMonth() - 1);
|
|
}
|
|
interestTransactionDate.setDate(interestDay);
|
|
interestTransactionDate.setHours(5, 0, 0, 0);
|
|
|
|
const cutoff = new Date(interestTransactionDate);
|
|
cutoff.setMonth(cutoff.getMonth() - 1);
|
|
cutoff.setDate(cutoff.getDate() + 1);
|
|
|
|
const lastDate = await getLastTransactionDate(account, cutoff);
|
|
if (!lastDate) continue;
|
|
const daysPassed = Math.round(
|
|
(interestTransactionDate.setHours(0, 0, 0, 0) - new Date(lastDate).setHours(0, 0, 0, 0)) / 86400000
|
|
);
|
|
|
|
let period = 12;
|
|
let numPeriods = 1
|
|
switch (kind) {
|
|
case 'daily':
|
|
case 'daily-simple':
|
|
period = daysInYear(interestTransactionDate.getFullYear());
|
|
numPeriods = daysPassed;
|
|
break;
|
|
case 'actual':
|
|
period = daysInYear(interestTransactionDate.getFullYear()) / daysPassed;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
const balance = await getAccountBalance(account, interestTransactionDate);
|
|
|
|
let compoundedInterest;
|
|
if (kind == 'daily-simple')
|
|
compoundedInterest = Math.round(balance * (interestRate / 365) * numPeriods);
|
|
else
|
|
compoundedInterest = Math.round(balance * (Math.pow(1 + interestRate / period, numPeriods) - 1));
|
|
|
|
interestRate = showPercent(interestRate);
|
|
|
|
console.log(`== ${account.name} ==`);
|
|
console.log(` -> Balance: ${balance}`);
|
|
console.log(` as of ${lastDate}`);
|
|
console.log(` -> # days: ${daysPassed}`);
|
|
console.log(` -> Interest: ${compoundedInterest} (${interestRate})`)
|
|
|
|
if (compoundedInterest) {
|
|
await api.importTransactions(account.id, [{
|
|
date: interestTransactionDate,
|
|
payee: payeeId,
|
|
amount: compoundedInterest,
|
|
cleared: true,
|
|
notes: `Interest for ${daysPassed} days, ${balance / 100.0} at ${interestRate} (${isDaily ? "daily" : "monthly"})`,
|
|
}]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
await closeBudget();
|
|
})();
|