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

Remove OpenStruct from fixed expense #17

Merged
merged 6 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
@apply rounded-lg px-4 bg-red-600 inline-block font-medium text-white;
}

.btn-secondary {
@apply rounded-lg px-4 bg-blue-600 inline-block font-medium text-white;
}

h1 {
@apply text-3xl font-bold tracking-tight text-gray-800
}
Expand Down
13 changes: 13 additions & 0 deletions app/controllers/concerns/dashboard_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module DashboardBuilder
include TaxedIncome
include TotalCost

def build_dashboard_variables!
@incomes = Income.order_by_type
@fixed_expenses = FixedExpense.get_ordered
build_taxed_income_vars!
build_total_cost_vars!
end
end
19 changes: 19 additions & 0 deletions app/controllers/concerns/taxed_income.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module TaxedIncome
def tax_on_salary
income = Income.find_by(income_type: "Salary")
Rails.logger.debug "**** Tax Salary: #{income.inspect}"
IncomeTaxCalculatorService.new(income: income)
end

def tax_on_hourly
income = Income.find_by(income_type: "Hourly")
IncomeTaxCalculatorService.new(income: income)
end

def build_taxed_income_vars!
@salary_taxed = tax_on_salary
@hourly_taxed = tax_on_hourly
end
end
27 changes: 27 additions & 0 deletions app/controllers/concerns/total_cost.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module TotalCost
def total_annual_cost
Money.new(get_sum(:annual_cost_cents))
end

def total_monthly_cost
Money.new(get_sum(:monthly_cost_cents))
end

def total_bi_weekly_cost
Money.new(get_sum(:bi_weekly_cost_cents))
end

def build_total_cost_vars!
@total_annual_cost = total_annual_cost
@total_monthly_cost = total_monthly_cost
@total_bi_weekly_cost = total_bi_weekly_cost
end

private

def get_sum(time_period)
FixedExpense.sum(&time_period)
end
end
9 changes: 3 additions & 6 deletions app/controllers/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
class DashboardController < ApplicationController
include DashboardBuilder

def index
@incomes = Income.order_by_type
@fixed_expenses = FixedExpense.get_ordered
@totals = FixedExpense.total_costs
@federal_tax_brackets = FederalTaxBracket.order_by_range
@salary_taxed = Income.tax_on_income(income_type: "Salary")
@hourly_taxed = Income.tax_on_income(income_type: "Hourly")
build_dashboard_variables!
end
end
15 changes: 5 additions & 10 deletions app/controllers/fixed_expenses_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class FixedExpensesController < ApplicationController
include DashboardBuilder

before_action :set_fixed_expense, only: %i[show edit update destroy]

# GET /fixed_expenses or /fixed_expenses.json
Expand All @@ -25,10 +27,7 @@ def create

respond_to do |format|
if @fixed_expense.save
@totals = FixedExpense.total_costs
@fixed_expenses = FixedExpense.get_ordered
@salary_taxed = Income.tax_on_income(income_type: "Salary")
@hourly_taxed = Income.tax_on_income(income_type: "Hourly")
build_dashboard_variables!
format.html { redirect_to root_path, notice: "Fixed expense was successfully created." }
format.turbo_stream
else
Expand All @@ -42,9 +41,7 @@ def create
def update
respond_to do |format|
if @fixed_expense.update_from_dashboard(params: params[:fixed_expense])
@totals = FixedExpense.total_costs
@salary_taxed = Income.tax_on_income(income_type: "Salary")
@hourly_taxed = Income.tax_on_income(income_type: "Hourly")
build_dashboard_variables!
format.html { redirect_to root_path, notice: "Fixed expense was successfully updated." }
format.turbo_stream
else
Expand All @@ -57,10 +54,8 @@ def update
# DELETE /fixed_expenses/1 or /fixed_expenses/1.json
def destroy
@fixed_expense.destroy
@totals = FixedExpense.total_costs
build_dashboard_variables!
@fixed_expenses = FixedExpense.get_ordered
@salary_taxed = Income.tax_on_income(income_type: "Salary")
@hourly_taxed = Income.tax_on_income(income_type: "Hourly")
respond_to do |format|
format.html { redirect_to fixed_expenses_path, notice: "Fixed expense was successfully destroyed." }
format.turbo_stream
Expand Down
32 changes: 16 additions & 16 deletions app/controllers/incomes_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
class IncomesController < ApplicationController
include DashboardBuilder
include TotalCost

before_action :set_income, only: %i[show edit update destroy]

# GET /incomes or /incomes.json
Expand Down Expand Up @@ -38,9 +41,7 @@ def create
def update
respond_to do |format|
if @income.update_from_dashboard(params: params)
@salary_taxed = Income.tax_on_income(income_type: "Salary")
@hourly_taxed = Income.tax_on_income(income_type: "Hourly")
@totals = FixedExpense.total_costs
build_dashboard_variables!
format.html { redirect_to root_path, notice: "Income was successfully updated." }
format.turbo_stream
else
Expand All @@ -61,31 +62,20 @@ def destroy
end

def income_switch
totals = FixedExpense.total_costs
if params[:enabled] == "0"
salary = Income.tax_on_income(income_type: "Salary")

respond_to do |format|
format.turbo_stream {
render turbo_stream: turbo_stream.replace("hourly_budget",
partial: "budget/salary_budget",
locals: {
totals: totals,
income: salary
})
locals: build_locals(tax_on_salary))
}
end
else
hourly = Income.tax_on_income(income_type: "Hourly")

respond_to do |format|
format.turbo_stream {
render turbo_stream: turbo_stream.replace("salary_budget",
partial: "budget/hourly_budget",
locals: {
totals: totals,
income: hourly
})
locals: build_locals(tax_on_hourly))
}
end
end
Expand All @@ -102,4 +92,14 @@ def set_income
def income_params
params.require(:income).permit(:income_type, :rate, :hours, :weekly_income)
end

def build_locals(income)
build_total_cost_vars!
{
total_annual_cost: @total_annual_cost,
total_monthly_cost: @total_monthly_cost,
total_bi_weekly_cost: @total_bi_weekly_cost,
income: income
}
end
end
14 changes: 2 additions & 12 deletions app/models/fixed_expense.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class FixedExpense < ApplicationRecord
monetize :monthly_cost_cents
monetize :bi_weekly_cost_cents

scope :get_ordered, -> { order(annual_cost_cents: :desc) }

def self.new_from_dashboard(params:)
expense = params[:fixed_expense]
amount = (expense[:amount].to_f * 100).to_i
Expand Down Expand Up @@ -63,16 +65,4 @@ def update_from_dashboard(params:)
false
end
end

def self.total_costs
OpenStruct.new(
total_annual_cost: sum(&:annual_cost_cents).to_f / 100,
total_monthly_cost: sum(&:monthly_cost_cents).to_f / 100,
total_bi_weekly_cost: sum(&:bi_weekly_cost_cents).to_f / 100
)
end

def self.get_ordered
all.order(annual_cost_cents: :desc)
end
end
13 changes: 2 additions & 11 deletions app/models/income.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class Income < ApplicationRecord
monetize :rate_cents
monetize :weekly_income_cents

scope :order_by_type, -> { order(income_type: :desc) }

def update_from_dashboard(params:)
income = params[:income]
income_type_passed = income[:income_type]
Expand All @@ -40,22 +42,11 @@ def update_from_dashboard(params:)
end
end

def self.order_by_type
Income.all.order(income_type: :desc)
end

def is_hourly?
income_type == "Hourly"
end

def is_salary?
income_type == "Salary"
end

def self.tax_on_income(income_type:)
income = Income.find_by(income_type: income_type)
taxable_income = IncomeTaxCalculator.new(income: income)
taxable_income.calculate_taxes
taxable_income
end
end
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class IncomeTaxCalculator
class IncomeTaxCalculatorService
attr_reader :income,
:annual_income,
:federal_tax,
Expand All @@ -14,20 +14,7 @@ class IncomeTaxCalculator

def initialize(income:)
@income = income
@annual_income = income.weekly_income_cents * 52
@federal_tax = nil
@net_after_fed_tax = nil
@state_tax = nil
@total_net_income = nil
@bi_weekly_net_income = nil
@daily_income = nil
@weekly_income = nil
@monthly_income = nil
@quarterly_income = nil
@biannual_income = nil
end

def calculate_taxes
@annual_income = income.weekly_income * 52
@federal_tax = calculate_fed_tax
@net_after_fed_tax = calculate_net_after_fed_tax
@state_tax = calculate_state_tax
Expand All @@ -43,45 +30,44 @@ def calculate_taxes
private

def calculate_fed_tax
bracket = FederalTaxBracket.where("bottom_range_cents <= ?", @annual_income).order(:bottom_range_cents).last
bracket = FederalTaxBracket.where("bottom_range_cents <= ?", @annual_income.cents).order(:bottom_range_cents).last
rated = bracket.rate * @annual_income
Money.new(rated + bracket.cumulative_cents, "USD")
rated + bracket.cumulative
end

def calculate_state_tax
state_tax = (@net_after_fed_tax.fractional * 0.0463).to_i
Money.new(state_tax, "USD")
@net_after_fed_tax * 0.0463
end

def calculate_net_after_fed_tax
Money.new(@annual_income - @federal_tax.fractional, "USD")
@annual_income - @federal_tax
end

def calculate_total_net_income
Money.new(@net_after_fed_tax.fractional - @state_tax.fractional, "USD")
@net_after_fed_tax - @state_tax
end

def calculate_bi_weekly_income
Money.new(@total_net_income.fractional / 26)
@total_net_income / 26
end

def calculate_daily_income
Money.new(@total_net_income.fractional / 365)
@total_net_income / 365
end

def calculate_weekly_income
Money.new(@total_net_income.fractional / 52)
@total_net_income / 52
end

def calculate_monthly_income
Money.new(@total_net_income.fractional / 12)
@total_net_income / 12
end

def calculate_quarterly_income
Money.new(@total_net_income.fractional / 4)
@total_net_income / 4
end

def calculate_biannual_income
Money.new(@total_net_income.fractional / 2)
@total_net_income / 2
end
end
2 changes: 1 addition & 1 deletion app/views/budget/_hourly_budget.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<div id="hourly_budget" class="py-4">
<strong>Hourly</strong>
<%= render partial: "budget/budget_headings" %>
<%= render partial: "shared/budget", locals: {totals: totals, income: income} %>
<%= render partial: "shared/budget", locals: { total_annual_cost: total_annual_cost, total_monthly_cost: total_monthly_cost, total_bi_weekly_cost: total_bi_weekly_cost, income: income } %>
</div>
<% end %>
2 changes: 1 addition & 1 deletion app/views/budget/_salary_budget.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<div id="salary_budget" class="py-4">
<strong>Salary</strong>
<%= render partial: "budget/budget_headings" %>
<%= render partial: "shared/budget", locals: {totals: totals, income: income} %>
<%= render partial: "shared/budget", locals: { total_annual_cost: total_annual_cost, total_monthly_cost: total_monthly_cost, total_bi_weekly_cost: total_bi_weekly_cost, income: income } %>
</div>
<% end %>
4 changes: 2 additions & 2 deletions app/views/dashboard/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<%= render partial: "components/income_switch" %>
</div>
<div id="final_income">
<%= render partial: "budget/salary_budget", locals: {totals: @totals, income: @salary_taxed} %>
<%= render partial: "budget/salary_budget", locals: { total_annual_cost: @total_annual_cost, total_monthly_cost: @total_monthly_cost, total_bi_weekly_cost: @total_bi_weekly_cost, income: @salary_taxed } %>
</div>
</div>
</div>
Expand Down Expand Up @@ -50,7 +50,7 @@
<% end %>

<%= turbo_frame_tag "total_costs" do %>
<%= render partial: "shared/total_costs", locals: { totals: @totals } %>
<%= render partial: "shared/total_costs", locals: { total_annual_cost: @total_annual_cost, total_monthly_cost: @total_monthly_cost, total_bi_weekly_cost: @total_bi_weekly_cost } %>
<% end %>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/views/federal_tax_brackets/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
</div>

<div class="inline">
<%= form.submit class: "rounded-lg py-1 px-4 bg-gray-100 inline-block font-medium" %>
<%= form.submit class: "btn btn-primary" %>
</div>
<div>
<%= link_to "Cancel", fixed_expenses_path, class: "rounded-lg py-1 px-4 bg-gray-100 inline-block font-medium" %>
<%= link_to "Cancel", fixed_expenses_path, class: "btn btn-secondary" %>
</div>
</div>
<% end %>
Loading