Skip to content
Snippets Groups Projects
Unverified Commit 0bcf6ea6 authored by shall0pass's avatar shall0pass Committed by GitHub
Browse files

Change method of calculating 'by' matches to use averaging (#879)

I've changed the method of calculating the budgeted amount. There may be
a more efficient way of writing the loop, so I'm looking forward to the
review.

This change implements the mathematics of
(Target1+Target2+TargetN-Last_months_category_balance) / (MonthsRemaing1
+ MonthsRemaining2 + MonthsRemaingN) * N. This is an averaged approach
for multiple templates in the same category. It will appear to
overbudget or underbudget some months compared to multiple single
targets in different categories, yet there should always be enough saved
in the category to satisfy the target due.

Setting a target, it's assumed that money will be spent in the
appropriate month, When a target reaches maturity, the money in the
category associated with that target should be spent or moved so the
remaining targets continue to be funded. I don't see an easy way of
fixing that, but I hope this change will be of some help.

Current method:
Notice how the Bills (flexible) category reduces each month, resulting
in larger budgeted amounts later in the goal cycle.


![Templates-now](https://user-images.githubusercontent.com/20625555/230964939-d20ca72b-1055-471a-9044-7cd640f19875.gif)

Proposed method:
**Note: The fact that the initial fill in this example equals the
expected fill is a coincidence based on the template values I chose. The
initial fills can be different from expected fill.


![Templates-proposed](https://user-images.githubusercontent.com/20625555/230965265-669f996c-3112-437b-ab83-9715ea5dfc7f.gif)
parent f8b73355
No related branches found
No related tags found
No related merge requests found
...@@ -207,6 +207,9 @@ async function applyCategoryTemplate(category, template_lines, month, force) { ...@@ -207,6 +207,9 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
let spent = await getSheetValue(sheetName, `sum-amount-${category.id}`); let spent = await getSheetValue(sheetName, `sum-amount-${category.id}`);
let balance = await getSheetValue(sheetName, `leftover-${category.id}`); let balance = await getSheetValue(sheetName, `leftover-${category.id}`);
let last_month_balance = balance - spent - budgeted; let last_month_balance = balance - spent - budgeted;
let totalTarget = 0;
let totalMonths = 0;
let skipMonths = 0;
for (let l = 0; l < template_lines.length; l++) { for (let l = 0; l < template_lines.length; l++) {
let template = template_lines[l]; let template = template_lines[l];
switch (template.type) { switch (template.type) {
...@@ -230,8 +233,8 @@ async function applyCategoryTemplate(category, template_lines, month, force) { ...@@ -230,8 +233,8 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
} }
case 'by': { case 'by': {
// by has 'amount' and 'month' params // by has 'amount' and 'month' params
let target_month = new Date(`${template.month}-01`); let N = template_lines.length;
let target = amountToInteger(template.amount); let target_month = new Date(`${template_lines[l].month}-01`);
let num_months = differenceInCalendarMonths( let num_months = differenceInCalendarMonths(
target_month, target_month,
current_month, current_month,
...@@ -242,11 +245,24 @@ async function applyCategoryTemplate(category, template_lines, month, force) { ...@@ -242,11 +245,24 @@ async function applyCategoryTemplate(category, template_lines, month, force) {
: (template.repeat || 1) * 12; : (template.repeat || 1) * 12;
while (num_months < 0 && repeat) { while (num_months < 0 && repeat) {
target_month = addMonths(target_month, repeat); target_month = addMonths(target_month, repeat);
num_months = differenceInCalendarMonths(target_month, current_month); num_months = differenceInCalendarMonths(
template_lines[l],
current_month,
);
} }
let diff = target - last_month_balance; if (num_months < 0) {
if (diff >= 0 && num_months > -1) { skipMonths++;
to_budget += Math.round(diff / (num_months + 1)); } else {
totalTarget += amountToInteger(template_lines[l].amount);
totalMonths += num_months + 1;
}
let diff = totalTarget - last_month_balance;
if (diff >= 0 && totalMonths > 0 && l === N - 1) {
to_budget += Math.round(
((totalTarget - last_month_balance) / totalMonths) *
(N - skipMonths),
);
} }
break; break;
} }
......
---
category: Enhancements
authors: [shall0pass]
---
Goal templates: Changed how compounding 'by' matches are filled. Now uses an average across templates.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment