mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-09 03:32:54 -05:00
🐛 fix template priorities in the tracking budget when templating income (#5316)
This commit is contained in:
@@ -100,7 +100,7 @@ export class CategoryTemplateContext {
|
||||
);
|
||||
}
|
||||
getPriorities(): number[] {
|
||||
return this.priorities;
|
||||
return Array.from(this.priorities);
|
||||
}
|
||||
hasRemainder(): boolean {
|
||||
return this.remainderWeight > 0 && !this.limitMet;
|
||||
@@ -115,11 +115,11 @@ export class CategoryTemplateContext {
|
||||
// what is the full requested amount this month
|
||||
async runAll(available: number) {
|
||||
let toBudget: number = 0;
|
||||
for (let i = 0; i < this.priorities.length; i++) {
|
||||
const p = this.priorities[i];
|
||||
const prioritiesSorted = this.getPriorities().sort();
|
||||
for (let i = 0; i < prioritiesSorted.length; i++) {
|
||||
const p = prioritiesSorted[i];
|
||||
toBudget += await this.runTemplatesForPriority(p, available, available);
|
||||
}
|
||||
//TODO does this need to run limits? maybe pass in option to ignore previous balance?
|
||||
return toBudget;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ export class CategoryTemplateContext {
|
||||
budgetAvail: number,
|
||||
availStart: number,
|
||||
): Promise<number> {
|
||||
if (!this.priorities.includes(priority)) return 0;
|
||||
if (!this.priorities.has(priority)) return 0;
|
||||
if (this.limitMet) return 0;
|
||||
|
||||
const t = this.templates.filter(t => t.priority === priority);
|
||||
@@ -227,8 +227,8 @@ export class CategoryTemplateContext {
|
||||
//round all budget values if needed
|
||||
if (this.hideDecimal) toBudget = this.removeFraction(toBudget);
|
||||
|
||||
// don't overbudget when using a priority
|
||||
if (priority > 0 && available < 0) {
|
||||
// don't overbudget when using a priority unless income category
|
||||
if (priority > 0 && available < 0 && !this.category.is_income) {
|
||||
this.fullAmount += toBudget;
|
||||
toBudget = Math.max(0, toBudget + available);
|
||||
this.toBudgetAmount += toBudget;
|
||||
@@ -236,7 +236,7 @@ export class CategoryTemplateContext {
|
||||
this.fullAmount += toBudget;
|
||||
this.toBudgetAmount += toBudget;
|
||||
}
|
||||
return toBudget;
|
||||
return this.category.is_income ? -toBudget : toBudget;
|
||||
}
|
||||
|
||||
runRemainder(budgetAvail: number, perWeight: number) {
|
||||
@@ -285,7 +285,7 @@ export class CategoryTemplateContext {
|
||||
private templates: Template[] = [];
|
||||
private remainder: RemainderTemplate[] = [];
|
||||
private goals: GoalTemplate[] = [];
|
||||
private priorities: number[] = [];
|
||||
private priorities: Set<number> = new Set();
|
||||
readonly hideDecimal: boolean = false;
|
||||
private remainderWeight: number = 0;
|
||||
private toBudgetAmount: number = 0; // amount that will be budgeted by the templates
|
||||
@@ -318,42 +318,19 @@ export class CategoryTemplateContext {
|
||||
templates.forEach(t => {
|
||||
if (t.directive === 'template' && t.type !== 'remainder') {
|
||||
this.templates.push(t);
|
||||
}
|
||||
});
|
||||
templates.forEach(t => {
|
||||
if (t.directive === 'template' && t.type === 'remainder') {
|
||||
if (t.priority !== null) this.priorities.add(t.priority);
|
||||
} else if (t.directive === 'template' && t.type === 'remainder') {
|
||||
this.remainder.push(t);
|
||||
this.remainderWeight += t.weight;
|
||||
} else if (t.directive === 'goal' && t.type === 'goal') {
|
||||
this.goals.push(t);
|
||||
}
|
||||
});
|
||||
templates.forEach(t => {
|
||||
if (t.directive === 'goal' && t.type === 'goal') this.goals.push(t);
|
||||
});
|
||||
}
|
||||
|
||||
this.checkLimit(templates);
|
||||
this.checkSpend();
|
||||
this.checkGoal();
|
||||
|
||||
//find priorities
|
||||
const p = [];
|
||||
this.templates.forEach(t => {
|
||||
if (t.priority != null) {
|
||||
p.push(t.priority);
|
||||
}
|
||||
});
|
||||
//sort and reduce to unique items
|
||||
this.priorities = p
|
||||
.sort(function (a, b) {
|
||||
return a - b;
|
||||
})
|
||||
.filter((item, idx, curr) => curr.indexOf(item) === idx);
|
||||
|
||||
//find remainder weight
|
||||
let weight = 0;
|
||||
this.remainder.forEach(r => {
|
||||
weight += r.weight;
|
||||
});
|
||||
this.remainderWeight = weight;
|
||||
}
|
||||
|
||||
private runGoal() {
|
||||
|
||||
@@ -158,8 +158,8 @@ async function processTemplate(
|
||||
categories: CategoryEntity[] = [],
|
||||
): Promise<Notification> {
|
||||
// setup categories
|
||||
const isReflect = isReflectBudget();
|
||||
if (!categories.length) {
|
||||
const isReflect = isReflectBudget();
|
||||
categories = (await getCategories()).filter(c => isReflect || !c.is_income);
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ async function processTemplate(
|
||||
monthUtils.sheetForMonth(month),
|
||||
`to-budget`,
|
||||
);
|
||||
let priorities: number[] = [];
|
||||
const prioritiesSet = new Set<number>();
|
||||
const errors: string[] = [];
|
||||
const budgetList: TemplateBudget[] = [];
|
||||
const goalList: TemplateGoal[] = [];
|
||||
@@ -182,9 +182,6 @@ async function processTemplate(
|
||||
|
||||
// only run categories that are unbudgeted or if we are forcing it
|
||||
if ((budgeted === 0 || force) && templates) {
|
||||
// add to available budget
|
||||
// gather needed priorities
|
||||
// gather remainder weights
|
||||
try {
|
||||
const templateContext = await CategoryTemplateContext.init(
|
||||
templates,
|
||||
@@ -197,7 +194,7 @@ async function processTemplate(
|
||||
availBudget += budgeted;
|
||||
}
|
||||
availBudget += templateContext.getLimitExcess();
|
||||
priorities = [...priorities, ...templateContext.getPriorities()];
|
||||
templateContext.getPriorities().forEach(p => prioritiesSet.add(p));
|
||||
templateContexts.push(templateContext);
|
||||
} catch (e) {
|
||||
errors.push(`${category.name}: ${e.message}`);
|
||||
@@ -231,13 +228,7 @@ async function processTemplate(
|
||||
};
|
||||
}
|
||||
|
||||
//compress to needed, sorted priorities
|
||||
priorities = priorities
|
||||
.sort((a, b) => {
|
||||
return a - b;
|
||||
})
|
||||
.filter((item, idx, curr) => curr.indexOf(item) === idx);
|
||||
|
||||
const priorities = [...prioritiesSet].sort();
|
||||
// run each priority level
|
||||
for (const priority of priorities) {
|
||||
const availStart = availBudget;
|
||||
|
||||
6
upcoming-release-notes/5316.md
Normal file
6
upcoming-release-notes/5316.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Enhancements
|
||||
authors: [youngcw]
|
||||
---
|
||||
|
||||
Fix templates in tracking budget when using priorities, and templated income.
|
||||
Reference in New Issue
Block a user