mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-22 00:13:45 -05:00
🐛 improve budgeting of schedules templates (#5319)
* fix * fix * didn't need that * prevent div by 0
This commit is contained in:
@@ -159,7 +159,7 @@ async function createScheduleList(
|
||||
return { t: t.filter(c => c.completed === 0), errors };
|
||||
}
|
||||
|
||||
async function getPayMonthOfTotal(t: ScheduleTemplateTarget[]) {
|
||||
function getPayMonthOfTotal(t: ScheduleTemplateTarget[]) {
|
||||
//return the contribution amounts of full or every month type schedules
|
||||
let total = 0;
|
||||
const schedules = t.filter(c => c.num_months === 0);
|
||||
@@ -194,20 +194,53 @@ async function getSinkingContributionTotal(
|
||||
return total;
|
||||
}
|
||||
|
||||
async function getSinkingBaseContributionTotal(t: ScheduleTemplateTarget[]) {
|
||||
function getSinkingBaseContributionTotal(t: ScheduleTemplateTarget[]) {
|
||||
//return only the base contribution of each schedule
|
||||
let total = 0;
|
||||
for (const schedule of t) {
|
||||
let monthlyAmount = schedule.target / schedule.target_interval;
|
||||
if (schedule.target_frequency === 'yearly') {
|
||||
monthlyAmount /= 12;
|
||||
let monthlyAmount = 0;
|
||||
let prevDate;
|
||||
let intervalMonths;
|
||||
switch (schedule.target_frequency) {
|
||||
case 'yearly':
|
||||
monthlyAmount = schedule.target / schedule.target_interval / 12;
|
||||
break;
|
||||
case 'monthly':
|
||||
monthlyAmount = schedule.target / schedule.target_interval;
|
||||
break;
|
||||
case 'weekly':
|
||||
prevDate = monthUtils.subWeeks(
|
||||
schedule.next_date_string,
|
||||
schedule.target_interval,
|
||||
);
|
||||
intervalMonths = monthUtils.differenceInCalendarMonths(
|
||||
schedule.next_date_string,
|
||||
prevDate,
|
||||
);
|
||||
// shouldn't be possible, but better check
|
||||
if (intervalMonths === 0) intervalMonths = 1;
|
||||
monthlyAmount = schedule.target / intervalMonths;
|
||||
break;
|
||||
case 'daily':
|
||||
prevDate = monthUtils.subDays(
|
||||
schedule.next_date_string,
|
||||
schedule.target_interval,
|
||||
);
|
||||
intervalMonths = monthUtils.differenceInCalendarMonths(
|
||||
schedule.next_date_string,
|
||||
prevDate,
|
||||
);
|
||||
// shouldn't be possible, but better check
|
||||
if (intervalMonths === 0) intervalMonths = 1;
|
||||
monthlyAmount = schedule.target / intervalMonths;
|
||||
break;
|
||||
}
|
||||
total += monthlyAmount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
async function getSinkingTotal(t: ScheduleTemplateTarget[]) {
|
||||
function getSinkingTotal(t: ScheduleTemplateTarget[]) {
|
||||
//sum the total of all upcoming schedules
|
||||
let total = 0;
|
||||
for (const schedule of t) {
|
||||
@@ -227,7 +260,6 @@ export async function runSchedule(
|
||||
category: CategoryEntity,
|
||||
) {
|
||||
const scheduleTemplates = template_lines.filter(t => t.type === 'schedule');
|
||||
//in the case of multiple templates per category, schedules may have wrong priority level
|
||||
|
||||
const t = await createScheduleList(
|
||||
scheduleTemplates,
|
||||
@@ -241,20 +273,18 @@ export async function runSchedule(
|
||||
(c.target_frequency === 'monthly' &&
|
||||
c.target_interval === 1 &&
|
||||
c.num_months === 0) ||
|
||||
(c.target_frequency === 'weekly' &&
|
||||
c.target_interval >= 0 &&
|
||||
c.num_months === 0) ||
|
||||
c.target_frequency === 'daily' ||
|
||||
(c.target_frequency === 'weekly' && c.target_interval <= 4) ||
|
||||
(c.target_frequency === 'daily' && c.target_interval <= 31) ||
|
||||
isReflectBudget();
|
||||
|
||||
const t_payMonthOf = t.t.filter(isPayMonthOf);
|
||||
const t_sinking = t.t
|
||||
.filter(c => !isPayMonthOf(c))
|
||||
.sort((a, b) => a.next_date_string.localeCompare(b.next_date_string));
|
||||
const totalPayMonthOf = await getPayMonthOfTotal(t_payMonthOf);
|
||||
const totalSinking = await getSinkingTotal(t_sinking);
|
||||
const totalPayMonthOf = getPayMonthOfTotal(t_payMonthOf);
|
||||
const totalSinking = getSinkingTotal(t_sinking);
|
||||
const totalSinkingBaseContribution =
|
||||
await getSinkingBaseContributionTotal(t_sinking);
|
||||
getSinkingBaseContributionTotal(t_sinking);
|
||||
|
||||
if (balance >= totalSinking + totalPayMonthOf) {
|
||||
to_budget += Math.round(totalPayMonthOf + totalSinkingBaseContribution);
|
||||
|
||||
Reference in New Issue
Block a user