Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
9 changes: 9 additions & 0 deletions app/controllers/reports/annual_reports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ def index
@years = (foundation_year...@actual_year).to_a

@month_remaining_to_report = 12 - Time.current.month

respond_to do |format|
format.html
format.csv do
yearly_reports = Reports.reports_across_the_year(organization: current_organization)
send_data Exports::ExportYearlyReportCSVService.new(yearly_reports:).generate_csv,
filename: "NdbnYearlyReports-#{Time.zone.today}.csv"
end
end
end

def show
Expand Down
39 changes: 39 additions & 0 deletions app/services/exports/export_yearly_report_csv_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Exports yearly reports to csv
# expects a report with a report method returns a hash with keys corresponding to columns and values corresponding to the reported value
# It should also have a columns_for_csv method to determine the order of the columns
module Exports
class ExportYearlyReportCSVService
def initialize(yearly_reports:)
@yearly_reports = yearly_reports
end

def generate_csv
csv_data = generate_csv_data

::CSV.generate(headers: true) do |csv|
csv_data.each { |row| csv << row }
end
end

def generate_csv_data
csv_data = []

@yearly_reports.each do |yearly_report|
headers = []
data = []
yearly_report.each do |report|
headers.concat(report["entries"].keys)
data.concat(report["entries"].values)
end

if csv_data.empty?
csv_data << headers
end

csv_data << data
end

csv_data
end
end
end
29 changes: 29 additions & 0 deletions app/services/reports.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,34 @@ def retrieve_report(year:, organization:, recalculate: false)
end
report
end

# @param organization [Organization]
# @return [Array<Reports::Report>]
def reports_across_the_year(organization:)
foundation_year = organization.earliest_reporting_year
last_completed_year = 1.year.ago.year
years = (foundation_year..last_completed_year).to_a
reports_across_the_year = []
years.each do |year|
report = retrieve_report(year: year, organization: organization)
unless report.all_reports.blank?
reports_across_the_year << report.all_reports.unshift(year_hash(year))
end
end
reports_across_the_year
end

private

# @param year [Integer]
# @return [Hash]
def year_hash(year)
{
"name" => "Report Year",
"entries" => {
"Year" => year.to_s
}
}
end
end
end
8 changes: 8 additions & 0 deletions app/views/reports/annual_reports/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
<h5 class="mb-1">Reports are available at the end of every year.</h5>
<span class="text-muted"> <%= "#{@actual_year} (available in #{pluralize(@month_remaining_to_report, 'month')})" %> </span>
</div>
<div class="col-md-12 mb-2">
<%=
download_button_to(
reports_annual_reports_path(format: :csv),
text: "Export Yearly Reports"
)
%>
</div>
<div class="col-md-12">
<div class="card card-primary">
<div class="card-header">
Expand Down
78 changes: 78 additions & 0 deletions spec/services/exports/export_yearly_report_csv_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
RSpec.describe Exports::ExportYearlyReportCSVService do
describe ".generate_csv_data" do
it "creates CSV data including headers" do
yearly_reports = [
[
{
"entries" => {
"Year" => 2023
}
},
{
"entries" => {
"First" => 1,
"Second" => 2
}
}
],
[
{
"entries" => {
"Year" => 2024
}
},
{
"entries" => {
"First" => 5,
"Second" => 10
}
}
]
]

result = described_class.new(yearly_reports:).generate_csv_data

expect(result.first).to eq(%w[Year First Second])
expect(result.last).to eq([2024, 5, 10])
end

it "creates a CSV string" do
yearly_reports = [
[
{
"entries" => {
"Year" => 2023
}
},
{
"entries" => {
"First" => 1,
"Second" => 2
}
}
],
[
{
"entries" => {
"Year" => 2024
}
},
{
"entries" => {
"First" => 5,
"Second" => 10
}
}
]
]

result = described_class.new(yearly_reports:).generate_csv
expected_result = <<~CSV
Year,First,Second
2023,1,2
2024,5,10
CSV
expect(result).to eq(expected_result)
end
end
end