From 5f38b579fe24df94e5915be931391b04d0729500 Mon Sep 17 00:00:00 2001
From: youngcw <calebyoung94@gmail.com>
Date: Wed, 24 May 2023 07:57:25 -0700
Subject: [PATCH] Template: Apply schedule template only on needed month
 (#1052)

Add option to schedule templates to budget the full amount only in the
needed month. Default behavior stays the same of spreading the expense
out over the available range.

To use the option, use a template like `#template schedule full
SCHEDULE_NAME`


Also some minor cleanup.
---
 .../src/server/budget/goal-template.pegjs     | 23 ++++++++++---------
 .../src/server/budget/goaltemplates.ts        | 14 ++++++++---
 upcoming-release-notes/1052.md                |  6 +++++
 3 files changed, 29 insertions(+), 14 deletions(-)
 create mode 100644 upcoming-release-notes/1052.md

diff --git a/packages/loot-core/src/server/budget/goal-template.pegjs b/packages/loot-core/src/server/budget/goal-template.pegjs
index 26b7ac630..2efb87f54 100644
--- a/packages/loot-core/src/server/budget/goal-template.pegjs
+++ b/packages/loot-core/src/server/budget/goal-template.pegjs
@@ -1,11 +1,9 @@
-// https://peggyjs.org
-
 expr
-  = priority: priority? _? percent: percent _ of _ category: name
+  = priority: priority? percent: percent _ of _ category: name
     { return { type: 'percentage', percent: +percent, category, priority: +priority }}
-  / priority: priority? _? amount: amount _ repeatEvery _ weeks: weekCount _ starting _ starting: date limit: limit?
+  / priority: priority? amount: amount _ repeatEvery _ weeks: weekCount _ starting _ starting: date limit: limit?
     { return { type: 'week', amount, weeks, starting, limit, priority: +priority }}
-  / priority: priority? _? amount: amount _ by _ month: month from: spendFrom? repeat: (_ repeatEvery _ repeat)?
+  / priority: priority? amount: amount _ by _ month: month from: spendFrom? repeat: (_ repeatEvery _ repeat)?
     { return {
       type: from ? 'spend' : 'by',
       amount,
@@ -14,12 +12,13 @@ expr
       from,
       priority: +priority
     } }
-  / priority: priority? _? monthly: amount limit: limit?
-    { return { type: 'simple', monthly, limit, priority: +priority  } }
-  / priority: priority? _? limit: limit
+  / priority: priority? monthly: amount limit: limit?
+    { return { type: 'simple', monthly, limit, priority: +priority  } } 
+  / priority: priority? limit: limit
     { return { type: 'simple', limit , priority: +priority } }
-  / priority: priority? _? schedule _ name: name
-    { return { type: 'schedule', name, priority: +priority } }
+  / priority: priority? schedule _ full:full? name: name
+  	{ return { type: 'schedule', name, priority: +priority, full } }
+  
 
 repeat 'repeat interval'
   = 'month'i { return { annual: false } }
@@ -28,7 +27,7 @@ repeat 'repeat interval'
   / years: d _ 'years'i { return { annual: true, repeat: +years } }
 
 limit =  _? upTo _ amount: amount _ 'hold'i { return {amount: amount, hold: true } }
-		/ _? upTo _ amount: amount { return {amount: amount, hold: false } }
+        / _? upTo _ amount: amount { return {amount: amount, hold: false } }
 
 
 weekCount
@@ -45,6 +44,7 @@ repeatEvery = 'repeat'i _ 'every'i
 starting = 'starting'i
 upTo = 'up'i _ 'to'i
 schedule = 'schedule'i
+full = 'full'i _ {return true}
 priority = '-'i number: number _ {return number}
 
 _ 'space' = ' '+
@@ -59,3 +59,4 @@ date = $(month '-' day)
 currencySymbol 'currency symbol' = symbol: . & { return /\p{Sc}/u.test(symbol) }
 
 name 'Name' = $([^\r\n\t]+)
+
diff --git a/packages/loot-core/src/server/budget/goaltemplates.ts b/packages/loot-core/src/server/budget/goaltemplates.ts
index 992acae7a..9cad8ffb7 100644
--- a/packages/loot-core/src/server/budget/goaltemplates.ts
+++ b/packages/loot-core/src/server/budget/goaltemplates.ts
@@ -489,9 +489,6 @@ async function applyCategoryTemplate(
         }
         break;
       }
-      case 'error':
-        return { errors };
-      default:
       case 'schedule': {
         let { id: schedule_id } = await db.first(
           'SELECT id FROM schedules WHERE name = ?',
@@ -506,6 +503,14 @@ async function applyCategoryTemplate(
           new Date(next_date_string),
           current_month,
         );
+
+        if (template.full === true) {
+          if (num_months === 1) {
+            to_budget = -getScheduledAmount(amountCond.value);
+          }
+          break;
+        }
+
         if (l === 0) remainder = last_month_balance;
         remainder = -getScheduledAmount(amountCond.value) - remainder;
         let target = 0;
@@ -537,6 +542,9 @@ async function applyCategoryTemplate(
         }
         break;
       }
+      case 'error':
+        return { errors };
+      default:
     }
   }
 
diff --git a/upcoming-release-notes/1052.md b/upcoming-release-notes/1052.md
new file mode 100644
index 000000000..9568abde8
--- /dev/null
+++ b/upcoming-release-notes/1052.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [youngcw]
+---
+
+Templates: Add option to only apply schedule template to the month of the schedule instead of spreading out the charge.
-- 
GitLab