Skip to content
Open
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
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