Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Goals]: Add a long term goal template #3012

Merged
merged 34 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
849ea93
update the parser
youngcw Jul 3, 2024
c7dbdfb
can set goal value, but there are errors and it still needs to look f…
youngcw Jul 3, 2024
2671ec2
fix apply budget
youngcw Jul 8, 2024
e900ba1
un change
youngcw Jul 8, 2024
ef67559
note
youngcw Jul 8, 2024
45dfb1f
lint
youngcw Jul 8, 2024
a0e6be5
working processing, need to set colors based on month somehow
youngcw Jul 8, 2024
2103bec
add long goal option to the gui and db
youngcw Jul 8, 2024
0a0abc2
Merge branch 'master' into youngcw/goal-type-template
youngcw Jul 8, 2024
570d40e
note, lint
youngcw Jul 8, 2024
0295742
fix cleanup
youngcw Jul 8, 2024
cbb3866
fix
youngcw Jul 8, 2024
3880360
make mobile work, lint
youngcw Jul 9, 2024
5895247
fix bindings
youngcw Jul 9, 2024
bda8931
more proper
youngcw Jul 9, 2024
36ea85d
Merge branch 'youngcw/fix-apply-budget' into youngcw/goal-type-template
youngcw Jul 9, 2024
e126281
lint
youngcw Jul 9, 2024
1547a81
fix single category run
youngcw Jul 9, 2024
17a86de
don't unset goal values if they don't have a template too
youngcw Jul 9, 2024
4408b7d
lint
youngcw Jul 9, 2024
b8383f2
Merge branch 'master' into youngcw/goal-type-template
youngcw Jul 9, 2024
7c67dd8
more lint
youngcw Jul 9, 2024
73a2129
Merge branch 'youngcw/goal-type-template' of github.com:actualbudget/…
youngcw Jul 9, 2024
987e574
fix check when no template exists
youngcw Jul 9, 2024
62c5e87
rearrange to get around the issue of inconsistent colors
youngcw Jul 9, 2024
6c46650
lint
youngcw Jul 9, 2024
733014f
typecheck
youngcw Jul 9, 2024
efac158
Merge branch 'master' into youngcw/goal-type-template
youngcw Jul 12, 2024
d2d4b22
add field to aql schema
youngcw Jul 12, 2024
711b3b7
fixes
youngcw Jul 16, 2024
7a7d087
Merge branch 'master' into youngcw/goal-type-template
youngcw Jul 16, 2024
9e972bc
cleanup
youngcw Jul 16, 2024
005a1e4
merge
youngcw Jul 24, 2024
639ed09
migration date
youngcw Jul 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type BalanceWithCarryoverProps = Omit<
balance: Binding;
goal: Binding;
budgeted: Binding;
longGoal: Binding;
disabled?: boolean;
carryoverIndicator?: ({ style }: CarryoverIndicatorProps) => JSX.Element;
};
Expand Down Expand Up @@ -54,6 +55,7 @@ export function BalanceWithCarryover({
balance,
goal,
budgeted,
longGoal,
disabled,
carryoverIndicator = DefaultCarryoverIndicator,
...props
Expand All @@ -62,11 +64,12 @@ export function BalanceWithCarryover({
const balanceValue = useSheetValue(balance);
const goalValue = useSheetValue(goal);
const budgetedValue = useSheetValue(budgeted);
const longGoalValue = useSheetValue(longGoal);
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
const valueStyle = makeBalanceAmountStyle(
balanceValue,
isGoalTemplatesEnabled ? goalValue : null,
budgetedValue,
longGoalValue === 1 ? balanceValue : budgetedValue,
);

return (
Expand All @@ -86,7 +89,7 @@ export function BalanceWithCarryover({
makeBalanceAmountStyle(
value,
isGoalTemplatesEnabled ? goalValue : null,
budgetedValue,
longGoalValue === 1 ? balanceValue : budgetedValue,
)
}
style={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export const CategoryMonth = memo(function CategoryMonth({
balance={reportBudget.catBalance(category.id)}
goal={reportBudget.catGoal(category.id)}
budgeted={reportBudget.catBudgeted(category.id)}
longGoal={reportBudget.catLongGoal(category.id)}
style={{
':hover': { textDecoration: 'underline' },
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
balance={rolloverBudget.catBalance(category.id)}
goal={rolloverBudget.catGoal(category.id)}
budgeted={rolloverBudget.catBudgeted(category.id)}
longGoal={rolloverBudget.catLongGoal(category.id)}
style={{
':hover': { textDecoration: 'underline' },
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
category,
isHidden,
goal,
longGoal,
budgeted,
spent,
balance,
Expand All @@ -336,8 +337,6 @@ const ExpenseCategory = memo(function ExpenseCategory({
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
const goalTemp = useSheetValue(goal);
const goalValue = isGoalTemplatesEnabled ? goalTemp : null;
const budgetedTemp = useSheetValue(budgeted);
const budgetedValue = isGoalTemplatesEnabled ? budgetedTemp : null;

const [budgetType = 'rollover'] = useLocalPref('budgetType');
const dispatch = useDispatch();
Expand All @@ -355,6 +354,14 @@ const ExpenseCategory = memo(function ExpenseCategory({
? rolloverBudget.catBalance(category.id)
: reportBudget.catBalance(category.id),
);
const budgetedtmp = useSheetValue(budgeted);
const balancetmp = useSheetValue(balance);
const isLongGoal = useSheetValue(longGoal) === 1;
const budgetedValue = isGoalTemplatesEnabled
? isLongGoal
? balancetmp
: budgetedtmp
: null;

const onTransfer = () => {
dispatch(
Expand Down Expand Up @@ -566,6 +573,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
balance={balance}
goal={goal}
budgeted={budgeted}
longGoal={longGoal}
formatter={value => (
<Button
type="bare"
Expand Down Expand Up @@ -1344,6 +1352,11 @@ const ExpenseGroup = memo(function ExpenseGroup({
? reportBudget.catGoal(category.id)
: rolloverBudget.catGoal(category.id)
}
longGoal={
type === 'report'
? reportBudget.catLongGoal(category.id)
: rolloverBudget.catLongGoal(category.id)
}
budgeted={
type === 'report'
? reportBudget.catBudgeted(category.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export function ReportBalanceMenuModal({
balance={reportBudget.catBalance(categoryId)}
goal={reportBudget.catGoal(categoryId)}
budgeted={reportBudget.catBudgeted(categoryId)}
longGoal={reportBudget.catLongGoal(categoryId)}
carryoverIndicator={({ style }) =>
DefaultCarryoverIndicator({
style: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export function RolloverBalanceMenuModal({
balance={rolloverBudget.catBalance(categoryId)}
goal={rolloverBudget.catGoal(categoryId)}
budgeted={rolloverBudget.catBudgeted(categoryId)}
longGoal={rolloverBudget.catLongGoal(categoryId)}
carryoverIndicator={({ style }) =>
DefaultCarryoverIndicator({
style: {
Expand Down
6 changes: 6 additions & 0 deletions packages/loot-core/migrations/1720476142000_goal_context.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BEGIN TRANSACTION;

ALTER TABLE zero_budgets ADD COLUMN long_goal INTEGER DEFAULT null;
ALTER TABLE reflect_budgets ADD COLUMN long_goal INTEGER DEFAULT null;

COMMIT;
2 changes: 2 additions & 0 deletions packages/loot-core/src/client/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export const rolloverBudget = {
catBalance: id => `leftover-${id}`,
catCarryover: id => `carryover-${id}`,
catGoal: id => `goal-${id}`,
catLongGoal: id => `long-goal-${id}`,
};

export const reportBudget = {
Expand All @@ -263,4 +264,5 @@ export const reportBudget = {
catBalance: id => `leftover-${id}`,
catCarryover: id => `carryover-${id}`,
catGoal: id => `goal-${id}`,
catLongGoal: id => `long-goal-${id}`,
};
2 changes: 2 additions & 0 deletions packages/loot-core/src/server/aql/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const schema = {
amount: f('integer'),
carryover: f('integer'),
goal: f('integer'),
long_goal: f('integer'),
},
zero_budgets: {
id: f('id'),
Expand All @@ -167,6 +168,7 @@ export const schema = {
amount: f('integer'),
carryover: f('integer'),
goal: f('integer'),
long_foal: f('integer'),
youngcw marked this conversation as resolved.
Show resolved Hide resolved
},
};

Expand Down
4 changes: 3 additions & 1 deletion packages/loot-core/src/server/budget/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function setBudget({
});
}

export function setGoal({ month, category, goal }): Promise<void> {
export function setGoal({ month, category, goal, long_goal }): Promise<void> {
const table = getBudgetTable();
const existing = db.firstSync(
`SELECT id FROM ${table} WHERE month = ? AND category = ?`,
Expand All @@ -124,13 +124,15 @@ export function setGoal({ month, category, goal }): Promise<void> {
return db.update(table, {
id: existing.id,
goal,
long_goal,
});
}
return db.insert(table, {
id: `${dbMonth(month)}-${category}`,
month: dbMonth(month),
category,
goal,
long_goal,
});
}

Expand Down
3 changes: 3 additions & 0 deletions packages/loot-core/src/server/budget/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ function handleBudgetChange(budget) {
budget.carryover === 1 ? true : false,
);
sheet.get().set(`${sheetName}!goal-${budget.category}`, budget.goal);
sheet
.get()
.set(`${sheetName}!long-goal-${budget.category}`, budget.long_goal);
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/loot-core/src/server/budget/cleanup-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ async function processCleanup(month: string): Promise<Notification> {
category: category.id,
month,
goal: budgeted - balance,
long_goal: 0,
});
num_sources += 1;
} else {
Expand Down
37 changes: 20 additions & 17 deletions packages/loot-core/src/server/budget/goal-template.pegjs
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
// https://peggyjs.org

expr
= priority: priority? _? percentOf:percentOf category: name
{ return { type: 'percentage', percent: +percentOf.percent, previous: percentOf.prev, category, priority: +priority }}
/ 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)?
= template: template _ percentOf:percentOf category: name
{ return { type: 'percentage', percent: +percentOf.percent, previous: percentOf.prev, category, priority: template.priority, directive: template.directive }}
/ template: template _ amount: amount _ repeatEvery _ weeks: weekCount _ starting _ starting: date limit: limit?
{ return { type: 'week', amount, weeks, starting, limit, priority: template.priority, directive: template.directive }}
/ template: template _ amount: amount _ by _ month: month from: spendFrom? repeat: (_ repeatEvery _ repeat)?
{ return {
type: from ? 'spend' : 'by',
amount,
month,
...(repeat ? repeat[3] : {}),
from,
priority: +priority
priority: template.priority, directive: template.directive
} }
/ 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 _ full:full? name: name
{ return { type: 'schedule', name, priority: +priority, full } }
/ priority: priority? _? remainder: remainder
{ return { type: 'remainder', priority: null, weight: remainder } }
/ priority: priority? _? 'average'i _ amount: positive _ 'months'i?
{ return { type: 'average', amount: +amount, priority: +priority }}
/ template: template _ monthly: amount limit: limit?
{ return { type: 'simple', monthly, limit, priority: template.priority, directive: template.directive } }
/ template: template _ limit: limit
{ return { type: 'simple', limit , priority: template.priority, directive: template.directive } }
/ template: template _ schedule _ full:full? name: name
{ return { type: 'schedule', name, priority: template.priority, directive: template.directive, full } }
/ template: template _ remainder: remainder limit: limit?
{ return { type: 'remainder', priority: null, directive: template.directive, weight: remainder, limit } }
/ template: template _ 'average'i _ amount: positive _ 'months'i?
{ return { type: 'average', amount: +amount, priority: template.priority, directive: template.directive }}
/ goal: goal amount: amount { return {type: 'simple', amount: amount, priority: null, directive: 'goal' }}


repeat 'repeat interval'
Expand Down Expand Up @@ -53,8 +54,10 @@ starting = 'starting'i
upTo = 'up'i _ 'to'i
schedule = 'schedule'i
full = 'full'i _ {return true}
priority = '-'i number: number _ {return number}
priority = '-'i number: number {return number}
remainder = 'remainder'i _? weight: positive? { return +weight || 1 }
template = '#template' priority: priority? {return {priority: +priority, directive: 'template'}}
goal = '#goal'

_ 'space' = ' '+
d 'digit' = [0-9]
Expand Down
Loading
Loading