-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
76b3f59
commit 4875ea5
Showing
10 changed files
with
290 additions
and
0 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,4 @@ | ||
class FinancialReportsController < ApplicationController | ||
layout "wide" | ||
expose(:financial_report) { FinancialReport.new(params[:year].to_i) } | ||
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,62 @@ | ||
class FinancialReport | ||
def self.months_for_year(year) | ||
start_on = Date.parse("#{year}-01-01") | ||
end_on = Date.parse("#{year}-12-01") | ||
(start_on..end_on).uniq(&:month) | ||
end | ||
|
||
attr_reader :year | ||
|
||
def initialize(year = Time.now.year) | ||
@year = year | ||
end | ||
|
||
def prev_year | ||
@year - 1 | ||
end | ||
|
||
def next_year | ||
@year + 1 | ||
end | ||
|
||
def checking_data | ||
AccountData.new(FinancialAccount.wf_checking, @year) | ||
end | ||
|
||
def savings_data | ||
AccountData.new(FinancialAccount.wf_savings, @year) | ||
end | ||
|
||
class AccountData | ||
def initialize(account, year) | ||
@account = account | ||
@year = year | ||
end | ||
|
||
def starting_amounts | ||
statements.map(&:starting_amount_cents) | ||
end | ||
|
||
def ending_amounts | ||
statements.map(&:ending_amount_cents) | ||
end | ||
|
||
def net_amounts | ||
statements.map(&:net_amount_cents) | ||
end | ||
|
||
private | ||
|
||
def compute_statements | ||
account_statements = @account.financial_statements.for_year(@year) | ||
FinancialReport.months_for_year(@year).map do |date| | ||
statement_for_period = account_statements.find { |statement| statement.period_start_on == date } | ||
statement_for_period || NullStatement.instance | ||
end | ||
end | ||
|
||
def statements | ||
@statements ||= compute_statements | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
class NullStatement | ||
include Singleton | ||
|
||
def starting_amount_cents | ||
end | ||
|
||
def ending_amount_cents | ||
end | ||
|
||
def net_amount_cents | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
- if amount_cents | ||
%td.text-right{class: "#{amount_cents < 0 && 'text-purple'}"} | ||
= number_to_currency(amount_cents / 100.0, negative_format: "(%u%n)") | ||
- else | ||
%td.text-right - |
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,66 @@ | ||
- content_for :header do | ||
%nav.flex.justify-between.items-center.py-6.border-b-8.border-dark-gray | ||
%p.m-0= link_to "prev", financial_report_path(financial_report.prev_year) | ||
%h1.m-0= financial_report.year | ||
%p.m-0= link_to "next", financial_report_path(financial_report.next_year) | ||
|
||
- checking_data = financial_report.checking_data | ||
- savings_data = financial_report.savings_data | ||
|
||
%h2 Checking | ||
|
||
%table.text-sm.table-fixed | ||
%thead | ||
%tr | ||
%th.text-left(class="w-[70px]") Month | ||
%th.text-right(class="w-[120px]") Jan | ||
%th.text-right(class="w-[120px]") Feb | ||
%th.text-right(class="w-[120px]") Mar | ||
%th.text-right(class="w-[120px]") Apr | ||
%th.text-right(class="w-[120px]") May | ||
%th.text-right(class="w-[120px]") Jun | ||
%th.text-right(class="w-[120px]") Jul | ||
%th.text-right(class="w-[120px]") Aug | ||
%th.text-right(class="w-[120px]") Sep | ||
%th.text-right(class="w-[120px]") Oct | ||
%th.text-right(class="w-[120px]") Nov | ||
%th.text-right(class="w-[120px]") Dec | ||
%tbody | ||
%tr | ||
%td.text-left Starting | ||
= render partial: "amount_cents", collection: checking_data.starting_amounts | ||
%tr | ||
%td.text-left Ending | ||
= render partial: "amount_cents", collection: checking_data.ending_amounts | ||
%tr | ||
%td.text-left Net | ||
= render partial: "amount_cents", collection: checking_data.net_amounts | ||
|
||
%h2 Savings | ||
|
||
%table.text-sm.table-fixed | ||
%thead | ||
%tr | ||
%th.text-left(class="w-[70px]") Month | ||
%th.text-right(class="w-[120px]") Jan | ||
%th.text-right(class="w-[120px]") Feb | ||
%th.text-right(class="w-[120px]") Mar | ||
%th.text-right(class="w-[120px]") Apr | ||
%th.text-right(class="w-[120px]") May | ||
%th.text-right(class="w-[120px]") Jun | ||
%th.text-right(class="w-[120px]") Jul | ||
%th.text-right(class="w-[120px]") Aug | ||
%th.text-right(class="w-[120px]") Sep | ||
%th.text-right(class="w-[120px]") Oct | ||
%th.text-right(class="w-[120px]") Nov | ||
%th.text-right(class="w-[120px]") Dec | ||
%tbody | ||
%tr | ||
%td.text-left Starting | ||
= render partial: "amount_cents", collection: savings_data.starting_amounts | ||
%tr | ||
%td.text-left Ending | ||
= render partial: "amount_cents", collection: savings_data.ending_amounts | ||
%tr | ||
%td.text-left Net | ||
= render partial: "amount_cents", collection: savings_data.net_amounts |
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,7 @@ | ||
!!! | ||
%html | ||
%head | ||
= render partial: "layouts/shared_head" | ||
= yield :head | ||
%body.bg-off-black.text-off-white.selection:bg-pink.p-4.md:p-0.mx-8 | ||
= render partial: "layouts/shared_main" |
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
128 changes: 128 additions & 0 deletions
128
spec/system/financial_reports/admin_views_financial_report_spec.rb
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,128 @@ | ||
require "rails_helper" | ||
|
||
describe "Admin views financial reports" do | ||
include_context "admin password matches" | ||
|
||
before do | ||
FactoryBot.create(:usb_checking) | ||
FactoryBot.create(:wf_checking) | ||
FactoryBot.create(:wf_savings) | ||
end | ||
|
||
let!(:last_year) { Date.today - 1.year } | ||
|
||
scenario "with no statements for that year" do | ||
visit "/financial_reports/#{last_year}" | ||
|
||
header = page.find("header nav h1") | ||
expect(header.text).to eq last_year.year.to_s | ||
|
||
prev_link, next_link = page.all("header nav a").to_a | ||
|
||
expect(prev_link.text).to eq "prev" | ||
expect(prev_link["href"]).to end_with((last_year.year - 1).to_s) | ||
|
||
expect(next_link.text).to eq "next" | ||
expect(next_link["href"]).to end_with((last_year.year + 1).to_s) | ||
|
||
page.all("table").to_a.each do |table| | ||
month_row, starting_row, ending_row, net_row = table.all("tr").to_a | ||
|
||
expect(month_row.all("th").map(&:text)).to eq %w[ | ||
Month Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec | ||
] | ||
|
||
expect(starting_row.all("td").map(&:text)).to eq %w[ | ||
Starting - - - - - - - - - - - - | ||
] | ||
|
||
expect(ending_row.all("td").map(&:text)).to eq %w[ | ||
Ending - - - - - - - - - - - - | ||
] | ||
|
||
expect(net_row.all("td").map(&:text)).to eq %w[ | ||
Net - - - - - - - - - - - - | ||
] | ||
end | ||
end | ||
|
||
scenario "with one statement in the middle of that year" do | ||
FactoryBot.create( | ||
:financial_statement, | ||
financial_account: FinancialAccount.wf_checking, | ||
period_start_on: Date.parse("#{last_year.year}-05-01"), | ||
starting_amount_cents: 1_034_89, | ||
ending_amount_cents: 99_00 | ||
) | ||
|
||
visit "/financial_reports/#{last_year}" | ||
|
||
checking_table = page.all("table").to_a.first | ||
_month_tr, starting_tr, ending_tr, net_tr = checking_table.all("tr").to_a | ||
|
||
may_starting_td = starting_tr.all("td").to_a[5] | ||
expect(may_starting_td.text).to eq "$1,034.89" | ||
|
||
may_ending_td = ending_tr.all("td").to_a[5] | ||
expect(may_ending_td.text).to eq "$99.00" | ||
|
||
may_net_td = net_tr.all("td").to_a[5] | ||
expect(may_net_td.text).to eq "($935.89)" | ||
end | ||
|
||
scenario "with statements for every month of that year" do | ||
FinancialReport.months_for_year(last_year.year).each do |date| | ||
FactoryBot.create( | ||
:financial_statement, | ||
financial_account: FinancialAccount.wf_checking, | ||
period_start_on: date, | ||
starting_amount_cents: 1_034_89, | ||
ending_amount_cents: 99_00 | ||
) | ||
|
||
FactoryBot.create( | ||
:financial_statement, | ||
financial_account: FinancialAccount.wf_savings, | ||
period_start_on: date, | ||
starting_amount_cents: 99_00, | ||
ending_amount_cents: 1_034_89 | ||
) | ||
end | ||
|
||
visit "/financial_reports/#{last_year}" | ||
|
||
checking_table, savings_table = page.all("table").to_a | ||
|
||
within checking_table do | ||
_month_tr, starting_tr, ending_tr, net_tr = checking_table.all("tr").to_a | ||
|
||
_starting_label, *starting_tds = starting_tr.all("td").to_a | ||
expect(starting_tds.count).to eq 12 | ||
expect(starting_tds.map(&:text).uniq).to eq ["$1,034.89"] | ||
|
||
_ending_label, *ending_tds = ending_tr.all("td").to_a | ||
expect(ending_tds.count).to eq 12 | ||
expect(ending_tds.map(&:text).uniq).to eq ["$99.00"] | ||
|
||
_net_label, *net_tds = net_tr.all("td").to_a | ||
expect(net_tds.count).to eq 12 | ||
expect(net_tds.map(&:text).uniq).to eq ["($935.89)"] | ||
end | ||
|
||
within savings_table do | ||
_month_tr, starting_tr, ending_tr, net_tr = savings_table.all("tr").to_a | ||
|
||
_starting_label, *starting_tds = starting_tr.all("td").to_a | ||
expect(starting_tds.count).to eq 12 | ||
expect(starting_tds.map(&:text).uniq).to eq ["$99.00"] | ||
|
||
_ending_label, *ending_tds = ending_tr.all("td").to_a | ||
expect(ending_tds.count).to eq 12 | ||
expect(ending_tds.map(&:text).uniq).to eq ["$1,034.89"] | ||
|
||
_net_label, *net_tds = net_tr.all("td").to_a | ||
expect(net_tds.count).to eq 12 | ||
expect(net_tds.map(&:text).uniq).to eq ["$935.89"] | ||
end | ||
end | ||
end |