diff --git a/packages/loot-core/src/server/budget/goals/goalsSchedule.ts b/packages/loot-core/src/server/budget/goals/goalsSchedule.ts index f75bd7506e..b11e583539 100644 --- a/packages/loot-core/src/server/budget/goals/goalsSchedule.ts +++ b/packages/loot-core/src/server/budget/goals/goalsSchedule.ts @@ -74,11 +74,23 @@ export async function goalsSchedule( ); while (next_date < next_month) { monthlyTarget += -target; + let current_date = next_date; next_date = monthUtils.addDays(next_date, 1); next_date = getNextDate( dateConditions, monthUtils._parse(next_date), ); + let diffDays = monthUtils.differenceInCalendarDays( + next_date, + current_date, + ); + if (!diffDays) { + next_date = monthUtils.addDays(next_date, 3); + next_date = getNextDate( + dateConditions, + monthUtils._parse(next_date), + ); + } } t[ll].target = -monthlyTarget; totalScheduledGoal += target; diff --git a/packages/loot-core/src/shared/months.ts b/packages/loot-core/src/shared/months.ts index 4ea2221359..651333707f 100644 --- a/packages/loot-core/src/shared/months.ts +++ b/packages/loot-core/src/shared/months.ts @@ -137,6 +137,13 @@ export function differenceInCalendarMonths( return d.differenceInCalendarMonths(_parse(month1), _parse(month2)); } +export function differenceInCalendarDays( + month1: DateLike, + month2: DateLike, +): number { + return d.differenceInCalendarDays(_parse(month1), _parse(month2)); +} + export function subMonths(month: string | Date, n: number) { return d.format(d.subMonths(_parse(month), n), 'yyyy-MM'); } diff --git a/upcoming-release-notes/1917.md b/upcoming-release-notes/1917.md new file mode 100644 index 0000000000..a61ec5f59b --- /dev/null +++ b/upcoming-release-notes/1917.md @@ -0,0 +1,6 @@ +--- +category: Bugfix +authors: [shall0pass] +--- + +Goals: Fix infinite loop situation with Schedule keyword