-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Budgeting V1 * Basic UI template * Fully scaffolded budgeting v1 * Basic working budget * Finalize donut chart for budgets * Allow categorization of loan payments for budget * Include loan payments in incomes_and_expenses scope * Add budget allocations progress * Empty states * Clean up budget methods * Category aggregation queries * Handle overage scenarios in form * Finalize budget donut chart controller * Passing tests * Fix allocation naming * Add income category migration * Native support for uncategorized budget category * Formatting * Fix subcategory sort order, padding * Fix calculation for category rollups in budget
- Loading branch information
Showing
61 changed files
with
2,045 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
class BudgetCategoriesController < ApplicationController | ||
def index | ||
@budget = Current.family.budgets.find(params[:budget_id]) | ||
render layout: "wizard" | ||
end | ||
|
||
def show | ||
@budget = Current.family.budgets.find(params[:budget_id]) | ||
|
||
@recent_transactions = @budget.entries | ||
|
||
if params[:id] == BudgetCategory.uncategorized.id | ||
@budget_category = @budget.uncategorized_budget_category | ||
@recent_transactions = @recent_transactions.where(account_transactions: { category_id: nil }) | ||
else | ||
@budget_category = Current.family.budget_categories.find(params[:id]) | ||
@recent_transactions = @recent_transactions.joins("LEFT JOIN categories ON categories.id = account_transactions.category_id") | ||
.where("categories.id = ? OR categories.parent_id = ?", @budget_category.category.id, @budget_category.category.id) | ||
end | ||
|
||
@recent_transactions = @recent_transactions.order("account_entries.date DESC, ABS(account_entries.amount) DESC").take(3) | ||
end | ||
|
||
def update | ||
@budget_category = Current.family.budget_categories.find(params[:id]) | ||
@budget_category.update!(budget_category_params) | ||
|
||
redirect_to budget_budget_categories_path(@budget_category.budget) | ||
end | ||
|
||
private | ||
def budget_category_params | ||
params.require(:budget_category).permit(:budgeted_spending) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
class BudgetsController < ApplicationController | ||
before_action :set_budget, only: %i[show edit update] | ||
|
||
def index | ||
redirect_to_current_month_budget | ||
end | ||
|
||
def show | ||
@next_budget = @budget.next_budget | ||
@previous_budget = @budget.previous_budget | ||
@latest_budget = Budget.find_or_bootstrap(Current.family) | ||
render layout: with_sidebar | ||
end | ||
|
||
def edit | ||
render layout: "wizard" | ||
end | ||
|
||
def update | ||
@budget.update!(budget_params) | ||
redirect_to budget_budget_categories_path(@budget) | ||
end | ||
|
||
def create | ||
start_date = Date.parse(budget_create_params[:start_date]) | ||
@budget = Budget.find_or_bootstrap(Current.family, date: start_date) | ||
redirect_to budget_path(@budget) | ||
end | ||
|
||
def picker | ||
render partial: "budgets/picker", locals: { | ||
family: Current.family, | ||
year: params[:year].to_i || Date.current.year | ||
} | ||
end | ||
|
||
private | ||
def budget_create_params | ||
params.require(:budget).permit(:start_date) | ||
end | ||
|
||
def budget_params | ||
params.require(:budget).permit(:budgeted_spending, :expected_income) | ||
end | ||
|
||
def set_budget | ||
@budget = Current.family.budgets.find(params[:id]) | ||
@budget.sync_budget_categories | ||
end | ||
|
||
def redirect_to_current_month_budget | ||
current_budget = Budget.find_or_bootstrap(Current.family) | ||
redirect_to budget_path(current_budget) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Controller } from "@hotwired/stimulus"; | ||
|
||
// Connects to data-controller="budget-form" | ||
export default class extends Controller { | ||
toggleAutoFill(e) { | ||
const expectedIncome = e.params.income; | ||
const budgetedSpending = e.params.spending; | ||
|
||
if (e.target.checked) { | ||
this.#fillField(expectedIncome.key, expectedIncome.value); | ||
this.#fillField(budgetedSpending.key, budgetedSpending.value); | ||
} else { | ||
this.#clearField(expectedIncome.key); | ||
this.#clearField(budgetedSpending.key); | ||
} | ||
} | ||
|
||
#fillField(id, value) { | ||
this.element.querySelector(`input[id="${id}"]`).value = value; | ||
} | ||
|
||
#clearField(id) { | ||
this.element.querySelector(`input[id="${id}"]`).value = ""; | ||
} | ||
} |
Oops, something went wrong.