diff --git a/app/controllers/concerns/dashboard_builder.rb b/app/controllers/concerns/dashboard_builder.rb index eaa0644..6b7358a 100644 --- a/app/controllers/concerns/dashboard_builder.rb +++ b/app/controllers/concerns/dashboard_builder.rb @@ -12,8 +12,8 @@ def build_dashboard_variables! @fixed_expenses = FixedExpense.get_ordered @savings_rate = SavingsRate.savings @investing_rate = SavingsRate.investing - build_taxed_income_vars! - build_savings_vars! + build_income_tax_variables! + build_savings_vars!(salary_income: @salary_taxed.net_income, hourly_income: @hourly_taxed.net_income) build_guilt_free_vars! build_total_cost_vars! end diff --git a/app/controllers/concerns/guilt_free.rb b/app/controllers/concerns/guilt_free.rb index 8b2432d..b632a5b 100644 --- a/app/controllers/concerns/guilt_free.rb +++ b/app/controllers/concerns/guilt_free.rb @@ -2,8 +2,8 @@ module GuiltFree def build_guilt_free_vars! - @guilt_free_salary = GuiltFreeCalculator.new(@salary_taxed.total_net_income, salary_savings_totalizer) - @guilt_free_hourly = GuiltFreeCalculator.new(@hourly_taxed.total_net_income, hourly_savings_totalizer) + @guilt_free_salary = GuiltFreeCalculator.new(@salary_taxed.net_income, salary_savings_totalizer) + @guilt_free_hourly = GuiltFreeCalculator.new(@hourly_taxed.net_income, hourly_savings_totalizer) end def salary_savings_totalizer diff --git a/app/controllers/concerns/save_income.rb b/app/controllers/concerns/save_income.rb index 4e0ffb7..a1e69b1 100644 --- a/app/controllers/concerns/save_income.rb +++ b/app/controllers/concerns/save_income.rb @@ -2,38 +2,29 @@ module SaveIncome extend ActiveSupport::Concern - include TaxedIncome - def build_savings_vars! - @hourly_saving = hourly_saving - @hourly_invest = hourly_investing - @salary_saving = salary_saving - @salary_invest = salary_investing + def build_savings_vars!(salary_income:, hourly_income:) + @salary_saving = savings(income: salary_income) + @salary_invest = investing(income: salary_income) + @hourly_saving = savings(income: hourly_income) + @hourly_invest = investing(income: hourly_income) end - def salary_investing - SavingsCalculator.new(tax_on_salary, set_invest_rate) - end - - def salary_saving - SavingsCalculator.new(tax_on_salary, set_save_rate) - end + private - def hourly_investing - SavingsCalculator.new(tax_on_hourly, set_invest_rate) + def savings(income:) + SavingsCalculator.new(income, savings_rate) end - def hourly_saving - SavingsCalculator.new(tax_on_hourly, set_save_rate) + def investing(income:) + SavingsCalculator.new(income, investing_rate) end - private - - def set_save_rate - SavingsRate.savings.rate + def savings_rate + @savings_rate ||= SavingsRate.savings_rate end - def set_invest_rate - SavingsRate.investing.rate + def investing_rate + @investing_rate ||= SavingsRate.investing_rate end end diff --git a/app/controllers/concerns/taxed_income.rb b/app/controllers/concerns/taxed_income.rb index 09ff25c..a1e59cc 100644 --- a/app/controllers/concerns/taxed_income.rb +++ b/app/controllers/concerns/taxed_income.rb @@ -1,18 +1,28 @@ # frozen_string_literal: true module TaxedIncome - def tax_on_salary - income = Income.find_by(income_type: "Salary") - IncomeTaxCalculatorService.new(income: income) + extend ActiveSupport::Concern + + def build_income_tax_variables! + @salary_taxed = build_income_tax_object(income: salary_income) + @hourly_taxed = build_income_tax_object(income: hourly_income) + end + + private + + def salary_income + @salary_income = Income.find_by(income_type: "Salary").weekly_income * 52 end - def tax_on_hourly - income = Income.find_by(income_type: "Hourly") - IncomeTaxCalculatorService.new(income: income) + def hourly_income + @hourly_income = Income.find_by(income_type: "Hourly").weekly_income * 52 end - def build_taxed_income_vars! - @salary_taxed = tax_on_salary - @hourly_taxed = tax_on_hourly + def build_income_tax_object(income:) + federal_tax = FederalTaxCalculator.call(income: income) + fica_tax = FicaTaxCalculator.call(income: income) + state_tax = StateTaxCalculator.call(income: income) + net_income = income - (fica_tax + federal_tax + state_tax) + OpenStruct.new(federal_tax: federal_tax, fica_tax: fica_tax, state_tax: state_tax, net_income: net_income) end end diff --git a/app/services/federal_tax_calculator.rb b/app/services/federal_tax_calculator.rb new file mode 100644 index 0000000..0ff5c4e --- /dev/null +++ b/app/services/federal_tax_calculator.rb @@ -0,0 +1,27 @@ +class FederalTaxCalculator + include Callable + + def initialize(income:) + self.income = income + end + + def call + calculate + end + + private + + attr_accessor :income + + def calculate + bracket = FederalTaxBracket.where("bottom_range_cents <= ?", taxable_income.fractional).order(:bottom_range_cents).last + taxable_at_bracket_rate = Money.new(taxable_income - bracket.bottom_range) + rated = bracket.rate * taxable_at_bracket_rate + rated + bracket.cumulative + end + + def taxable_income + # 2024 standard deduction = 13,850 + @taxable_income ||= income - Money.new(13_850_00) + end +end diff --git a/app/services/fica_tax_calculator.rb b/app/services/fica_tax_calculator.rb new file mode 100644 index 0000000..abe190f --- /dev/null +++ b/app/services/fica_tax_calculator.rb @@ -0,0 +1,15 @@ +class FicaTaxCalculator + include Callable + + def initialize(income:) + self.income = income + end + + def call + income * 0.0765 + end + + private + + attr_accessor :income +end diff --git a/app/services/net_income_calculator.rb b/app/services/net_income_calculator.rb new file mode 100644 index 0000000..c7a845c --- /dev/null +++ b/app/services/net_income_calculator.rb @@ -0,0 +1,32 @@ +class NetIncomeCalculator + attr_reader :annual_income, :daily_income, :weekly_income, :monthly_income, :quarterly_income, :biannual_income + + def initialize(annual_income:) + @annual_income = annual_income + @biannual_income = calculate_biannual_income + @quarterly_income = calculate_quarterly_income + @monthly_income = calculate_monthly_income + @weekly_income = calculate_weekly_income + @daily_income = calculate_daily_income + end + + def calculate_biannual_income + @annual_income / 2 + end + + def calculate_quarterly_income + @annual_income / 4 + end + + def calculate_monthly_income + @annual_income / 12 + end + + def calculate_weekly_income + @annual_income / 52 + end + + def calculate_daily_income + @annual_income / 365 + end +end diff --git a/app/services/savings_calculator.rb b/app/services/savings_calculator.rb index 7cfe974..9a943f6 100644 --- a/app/services/savings_calculator.rb +++ b/app/services/savings_calculator.rb @@ -11,8 +11,8 @@ class SavingsCalculator :daily_saving def initialize(income_type, saving_rate) - @annual_income = income_type.annual_income - @saving_rate = saving_rate + @annual_income = income_type + @saving_rate = saving_rate.rate @annual_saving = calculate_savings @bi_weekly_saving = calculate_bi_weekly_saving @daily_saving = calculate_daily_saving diff --git a/app/services/state_tax_calculator.rb b/app/services/state_tax_calculator.rb new file mode 100644 index 0000000..d50a3b6 --- /dev/null +++ b/app/services/state_tax_calculator.rb @@ -0,0 +1,16 @@ +class StateTaxCalculator + include Callable + + def initialize(income:) + self.income = income + end + + # Colorado state tax rate is 4.4% + def call + income * 0.044 + end + + private + + attr_accessor :income +end diff --git a/app/views/shared/_taxed_income.html.erb b/app/views/shared/_taxed_income.html.erb index 97bf581..da19282 100644 --- a/app/views/shared/_taxed_income.html.erb +++ b/app/views/shared/_taxed_income.html.erb @@ -1,4 +1,4 @@ -<% paid_taxes = [ taxed_income.federal_income_tax, taxed_income.fica_tax, taxed_income.state_tax, taxed_income.total_net_income ] %> +<% paid_taxes = [ taxed_income.federal_tax, taxed_income.fica_tax, taxed_income.state_tax, taxed_income.net_income ] %> <% paid_taxes.each do |tax| %> <% if annual %> @@ -6,4 +6,4 @@ <% else %>