Skip to content

Commit

Permalink
Remove OpenStruct from fixed expense (#17)
Browse files Browse the repository at this point in the history
* Refactor to rid of OpenStruct

* Refactor user of services

* Find and replace all @totals

* Extract methods to concerns

* Style buttons

* Refactor building variables
  • Loading branch information
neb417 authored Nov 17, 2023
1 parent 80b114b commit 57db6ff
Show file tree
Hide file tree
Showing 22 changed files with 142 additions and 120 deletions.
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

0 comments on commit 57db6ff

Please sign in to comment.