mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-28 18:40:34 -05:00
Goals: Compounding changes for By and Schedules (#1028)
This commit is contained in:
@@ -2,7 +2,6 @@ import {
|
||||
differenceInCalendarMonths,
|
||||
addMonths,
|
||||
addWeeks,
|
||||
addDays,
|
||||
format,
|
||||
} from 'date-fns';
|
||||
|
||||
@@ -305,9 +304,7 @@ async function applyCategoryTemplate(
|
||||
let limit;
|
||||
let hold;
|
||||
let last_month_balance = balance - spent - budgeted;
|
||||
let totalTarget = 0;
|
||||
let totalMonths = 0;
|
||||
let skipMonths = 0;
|
||||
let remainder = 0;
|
||||
for (let l = 0; l < template_lines.length; l++) {
|
||||
let template = template_lines[l];
|
||||
switch (template.type) {
|
||||
@@ -339,7 +336,7 @@ async function applyCategoryTemplate(
|
||||
}
|
||||
case 'by': {
|
||||
// by has 'amount' and 'month' params
|
||||
let N = template_lines.length;
|
||||
let target = 0;
|
||||
let target_month = new Date(`${template_lines[l].month}-01`);
|
||||
let num_months = differenceInCalendarMonths(
|
||||
target_month,
|
||||
@@ -356,21 +353,19 @@ async function applyCategoryTemplate(
|
||||
current_month,
|
||||
);
|
||||
}
|
||||
if (num_months < 0) {
|
||||
skipMonths++;
|
||||
if (l === 0) remainder = last_month_balance;
|
||||
remainder = amountToInteger(template_lines[l].amount) - remainder;
|
||||
if (remainder >= 0) {
|
||||
target = remainder;
|
||||
remainder = 0;
|
||||
} else {
|
||||
totalTarget += amountToInteger(template_lines[l].amount);
|
||||
totalMonths += num_months + 1;
|
||||
target = 0;
|
||||
remainder = Math.abs(remainder);
|
||||
}
|
||||
|
||||
let diff = totalTarget - last_month_balance;
|
||||
if (diff >= 0 && totalMonths > 0 && l === N - 1) {
|
||||
let increment = Math.round(
|
||||
((totalTarget - last_month_balance) / totalMonths) *
|
||||
(N - skipMonths),
|
||||
);
|
||||
if (to_budget + increment < budgetAvailable || !priority) {
|
||||
to_budget += increment;
|
||||
let diff = num_months > -1 ? Math.round(target / (num_months + 1)) : 0;
|
||||
if (diff >= 0) {
|
||||
if (to_budget + diff < budgetAvailable || !priority) {
|
||||
to_budget += diff;
|
||||
} else {
|
||||
if (budgetAvailable > 0) to_budget += budgetAvailable;
|
||||
errors.push(`Insufficient funds.`);
|
||||
@@ -506,44 +501,35 @@ async function applyCategoryTemplate(
|
||||
let conditions = rule.serialize().conditions;
|
||||
let { date: dateCond, amount: amountCond } =
|
||||
extractScheduleConds(conditions);
|
||||
let isRepeating =
|
||||
Object(dateCond.value) === dateCond.value &&
|
||||
'frequency' in dateCond.value;
|
||||
let next_date_string = getNextDate(dateCond, current_month);
|
||||
let num_months = differenceInCalendarMonths(
|
||||
new Date(next_date_string),
|
||||
current_month,
|
||||
);
|
||||
let target = -getScheduledAmount(amountCond.value);
|
||||
let diff = target - balance + budgeted;
|
||||
if (l === 0) remainder = last_month_balance;
|
||||
remainder = -getScheduledAmount(amountCond.value) - remainder;
|
||||
let target = 0;
|
||||
if (remainder >= 0) {
|
||||
target = remainder;
|
||||
remainder = 0;
|
||||
} else {
|
||||
target = 0;
|
||||
remainder = Math.abs(remainder);
|
||||
}
|
||||
let diff = num_months > 0 ? Math.round(target / num_months) : 0;
|
||||
if (num_months < 0) {
|
||||
errors.push(
|
||||
`Non-repeating schedule ${template.name} was due on ${next_date_string}, which is in the past.`,
|
||||
);
|
||||
return { errors };
|
||||
} else if (num_months > 0) {
|
||||
if (diff >= 0 && num_months > -1) {
|
||||
to_budget += Math.round(diff / num_months);
|
||||
}
|
||||
} else {
|
||||
let monthly_target = 0;
|
||||
let next_month = addMonths(current_month, 1);
|
||||
let next_date = new Date(next_date_string);
|
||||
if (isRepeating) {
|
||||
while (next_date.getTime() < next_month.getTime()) {
|
||||
if (next_date.getTime() >= current_month.getTime()) {
|
||||
monthly_target += target;
|
||||
}
|
||||
next_date = addDays(next_date, 1);
|
||||
next_date_string = getNextDate(dateCond, next_date);
|
||||
next_date = new Date(next_date_string);
|
||||
}
|
||||
} else {
|
||||
monthly_target = target;
|
||||
}
|
||||
let increment = monthly_target - balance + budgeted;
|
||||
if (to_budget + increment < budgetAvailable || !priority) {
|
||||
to_budget += increment;
|
||||
if (
|
||||
(diff >= 0 &&
|
||||
num_months > -1 &&
|
||||
to_budget + diff < budgetAvailable) ||
|
||||
!priority
|
||||
) {
|
||||
to_budget += diff;
|
||||
} else {
|
||||
if (budgetAvailable > 0) to_budget = budgetAvailable;
|
||||
errors.push(`Insufficient funds.`);
|
||||
|
||||
6
upcoming-release-notes/1028.md
Normal file
6
upcoming-release-notes/1028.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Bugfix
|
||||
authors: [shall0pass]
|
||||
---
|
||||
|
||||
Bugfix: Goals template compounding - Large target differences resulted in not enough funding
|
||||
Reference in New Issue
Block a user