diff --git a/lib/container.rb b/lib/container.rb index c1a0e617..848f1f60 100644 --- a/lib/container.rb +++ b/lib/container.rb @@ -39,7 +39,7 @@ def initialize fetch_dec_summary_use_case = UseCase::FetchDecSummary.new(certificates_gateway) fetch_statistics_use_case = UseCase::FetchStatistics.new(statistics_gateway: Gateway::StatisticsGateway.new(internal_api_client), co2_gateway: Gateway::AverageCo2EmissionsGateway.new(internal_data_warehouse_api_client)) - fetch_statistics_csv_use_case = UseCase::FetchStatisticsCsv.new(Gateway::StatisticsGateway.new(internal_api_client)) + fetch_statistics_csv_use_case = UseCase::FetchStatisticsCsv.new(statistics_gateway: Gateway::StatisticsGateway.new(internal_api_client), co2_gateway: Gateway::AverageCo2EmissionsGateway.new(internal_data_warehouse_api_client)) @objects = { internal_api_client:, diff --git a/lib/domain/statistics_results.rb b/lib/domain/statistics_results.rb index 9a033120..d84b0281 100644 --- a/lib/domain/statistics_results.rb +++ b/lib/domain/statistics_results.rb @@ -46,5 +46,32 @@ def get_results results[:assessments][:grouped] = grouped_by_assessment_type_and_country results end + + def get_country_results(country:) + country_key = country == "northern-ireland" ? :northernIreland : country.to_sym + @results.key?(country_key.to_sym) ? @results[country_key.to_sym] : @results[:all] + end + + def to_csv_hash(country:) + results = get_country_results(country:) + return_array = [] + months = results.group_by { |h| h[:month] }.keys + types = %w[SAP RdSAP CEPC DEC DEC-RR AC-CERT] + months.each do |month| + hash = { "Month" => Date.parse("#{month}-01").strftime("%b-%Y") } + types.each do |type| + stats_item = results.select { |item| item[:month] == month && item[:assessmentType] == type }.first + hash["#{type}s Lodged"] = !stats_item.nil? && stats_item.key?(:numAssessments) && !stats_item[:numAssessments].nil? ? stats_item[:numAssessments] : nil + if %w[SAP RdSAP CEPC].include?(type) && !stats_item.nil? + hash["Average #{type} Energy Rating"] = stats_item.key?(:ratingAverage) && !stats_item[:ratingAverage].nil? ? stats_item[:ratingAverage].round(2) : nil + end + if %w[SAP RdSAP].include?(type) && !stats_item.nil? + hash["Average #{type} CO2/sqm emissions"] = stats_item.key?(:avgCo2Emission) && !stats_item[:avgCo2Emission].nil? ? stats_item[:avgCo2Emission].round(2) : nil + end + end + return_array << hash + end + return_array + end end end diff --git a/lib/frontend_service.rb b/lib/frontend_service.rb index 688fe8d7..75f2d1d2 100644 --- a/lib/frontend_service.rb +++ b/lib/frontend_service.rb @@ -1072,9 +1072,6 @@ def initialize attachment params["country"] ? "service-performance-#{params['country']}.csv" : "service-performance-all-regions.csv" to_csv(data) - rescue StandardError => e - content_type "text/html" - return server_error(e) end get "/help", host_name: /#{FIND_ENERGY_CERTIFICATE_HOST_NAME}/ do diff --git a/lib/use_case/fetch_statistics.rb b/lib/use_case/fetch_statistics.rb index 9753831e..585cf4c1 100644 --- a/lib/use_case/fetch_statistics.rb +++ b/lib/use_case/fetch_statistics.rb @@ -1,12 +1,7 @@ # frozen_string_literal: true module UseCase - class FetchStatistics - def initialize(statistics_gateway:, co2_gateway:) - @statistics_gateway = statistics_gateway - @co2_gateway = co2_gateway - end - + class FetchStatistics < UseCase::FetchStatisticsBase def execute register_data = @statistics_gateway.fetch[:data] warehouse_data = @co2_gateway.fetch[:data] @@ -14,28 +9,5 @@ def execute @domain.set_results unless warehouse_data.empty? @domain.get_results end - - private - - def raise_errors_if_exists(response) - return unless response.include?(:errors) - - response[:errors].each do |error| - if error[:code] == "Auth::Errors::TokenMissing" - raise Errors::AuthTokenMissing - end - if error[:code] == "PAYLOAD_TOO_LARGE" - raise Errors::TooManyResults - end - - yield(error) if block_given? - end - - raise Errors::UnknownErrorResponseError, - sprintf( - "Unknown error response from internal API; errors sent were: %s", - response[:errors].to_s, - ) - end end end diff --git a/lib/use_case/fetch_statistics_base.rb b/lib/use_case/fetch_statistics_base.rb new file mode 100644 index 00000000..4a46bb4a --- /dev/null +++ b/lib/use_case/fetch_statistics_base.rb @@ -0,0 +1,31 @@ +module UseCase + class FetchStatisticsBase + def initialize(statistics_gateway:, co2_gateway:) + @statistics_gateway = statistics_gateway + @co2_gateway = co2_gateway + end + + private + + def raise_errors_if_exists(response) + return unless response.include?(:errors) + + response[:errors].each do |error| + if error[:code] == "Auth::Errors::TokenMissing" + raise Errors::AuthTokenMissing + end + if error[:code] == "PAYLOAD_TOO_LARGE" + raise Errors::TooManyResults + end + + yield(error) if block_given? + end + + raise Errors::UnknownErrorResponseError, + sprintf( + "Unknown error response from internal API; errors sent were: %s", + response[:errors].to_s, + ) + end + end +end diff --git a/lib/use_case/fetch_statistics_csv.rb b/lib/use_case/fetch_statistics_csv.rb index abd9af8f..a64cd737 100644 --- a/lib/use_case/fetch_statistics_csv.rb +++ b/lib/use_case/fetch_statistics_csv.rb @@ -1,27 +1,13 @@ # frozen_string_literal: true module UseCase - class FetchStatisticsCsv < UseCase::Base + class FetchStatisticsCsv < UseCase::FetchStatisticsBase def execute(country = "all") - data = @gateway.fetch[:data][:assessments] - country_key = country == "northern-ireland" ? :northernIreland : country.to_sym - results = data.key?(country_key.to_sym) ? data[country_key.to_sym] : data[:all] - - return_array = [] - months = results.group_by { |h| h[:month] }.keys - types = %w[SAP RdSAP CEPC DEC DEC-RR AC-CERT] - months.each do |month| - hash = { "Month" => Date.parse("#{month}-01").strftime("%b-%Y") } - types.each do |type| - stats_item = results.select { |item| item[:month] == month && item[:assessmentType] == type }.first - hash["#{type}s Lodged"] = !stats_item.nil? && stats_item.key?(:numAssessments) && !stats_item[:numAssessments].nil? ? stats_item[:numAssessments] : nil - if %w[SAP RdSAP CEPC].include?(type) && !stats_item.nil? - hash["Average #{type} Energy Rating"] = stats_item.key?(:ratingAverage) && !stats_item[:ratingAverage].nil? ? stats_item[:ratingAverage].round(2) : nil - end - end - return_array << hash - end - return_array + register_data = @statistics_gateway.fetch[:data] + warehouse_data = @co2_gateway.fetch[:data] + @domain = Domain::StatisticsResults.new(register_data: register_data[:assessments], warehouse_data:) + @domain.set_results unless warehouse_data.empty? + @domain.to_csv_hash(country:) end end end diff --git a/spec/acceptance/service_performance_csv_spec.rb b/spec/acceptance/service_performance_csv_spec.rb index deac266b..cd4c1526 100644 --- a/spec/acceptance/service_performance_csv_spec.rb +++ b/spec/acceptance/service_performance_csv_spec.rb @@ -1,6 +1,4 @@ -describe "Acceptance::ServicePerformanceCSV", type: :feature do - include RSpecFrontendServiceMixin - +shared_context "when request service performance csv" do def stats_web_mock(body) WebMock .stub_request( @@ -14,6 +12,20 @@ def file_name_from_header response.original_headers["Content-Disposition"].match(/filename=("?)(.+)\1/)[2] end + def expected_header + ["Month", "SAPs Lodged", "Average SAP Energy Rating", "Average SAP CO2/sqm emissions", "RdSAPs Lodged", "Average RdSAP Energy Rating", "Average RdSAP CO2/sqm emissions", "CEPCs Lodged", "Average CEPC Energy Rating", "DECs Lodged", "DEC-RRs Lodged", "AC-CERTs Lodged"] + end + + def response_csv_header(body) + header = body.split("\n").first + header.split(",") + end +end + +describe "Acceptance::ServicePerformanceCSV", type: :feature do + include RSpecFrontendServiceMixin + include_context "when request service performance csv" + describe "get . find-energy-certificate/service-performance/download-csv" do let(:response) do get "http://find-energy-certificate.epb-frontend/service-performance/download-csv" @@ -25,9 +37,11 @@ def file_name_from_header before do stats_web_mock(ServicePerformance::MonthsStatsDataStub.get_data) + ServicePerformance::AverageCo2EmissionsStub.statistics end it "return a response 200 response" do + save_response_to_file(file: "test", content: response.body) expect(response.status).to eq(200) end @@ -40,11 +54,11 @@ def file_name_from_header end it "has a csv with the correct headers" do - expect(response.body).to match(/Month,SAPs Lodged,Average SAP Energy Rating,RdSAPs Lodged,Average RdSAP Energy Rating,CEPCs Lodged,Average CEPC Energy Rating,DECs Lodged,DEC-RRs Lodged,AC-CERTs Lodged/) + expect(response_csv_header(response.body)).to eq expected_header end it "has a csv with the correct body" do - expect(response.body).to match(/Oct-2021,21163,78.41,122394,61.71,8208,67.36,2189,470,1251/) + expect(response.body).to match(/Oct-2021,21163,78.41,,122394,61.71,,8208,67.36,2189,470,1251/) end it "produces a data set with correct number of rows" do @@ -59,7 +73,7 @@ def file_name_from_header end it "has a csv with the headers in the expected order" do - expect(response.body).to match(/Month,SAPs Lodged,Average SAP Energy Rating,RdSAPs Lodged,Average RdSAP Energy Rating,CEPCs Lodged,Average CEPC Energy Rating,DECs Lodged,DEC-RRs Lodged,AC-CERTs Lodged/) + expect(response_csv_header(response.body)).to eq expected_header end end @@ -96,6 +110,7 @@ def file_name_from_header before do stats_web_mock(ServicePerformance::MonthsStatsDataStub.get_data) + ServicePerformance::AverageCo2EmissionsStub.statistics end it "return a response 200 response" do @@ -111,11 +126,11 @@ def file_name_from_header end it "has a csv with the correct headers" do - expect(response.body).to match(/Month,SAPs Lodged,Average SAP Energy Rating,RdSAPs Lodged,Average RdSAP Energy Rating,CEPCs Lodged,Average CEPC Energy Rating,DECs Lodged,DEC-RRs Lodged,AC-CERTs Lodged/) + expect(response_csv_header(response.body)).to eq expected_header end it "has a csv with the correct body" do - expect(response.body).to match(/Oct-2021,20489,78.4,120045,61.73,8074,67.33,2781,462,1206/) + expect(response.body).to match(/Sep-2021,23834,77.82,15.74,119033,61.74,10.88,7572,68.18,3298,402,861/) end it "produces a data set with correct number of rows" do @@ -134,9 +149,11 @@ def file_name_from_header before do stats_web_mock(ServicePerformance::MonthsStatsDataStub.get_data) + ServicePerformance::AverageCo2EmissionsStub.statistics end it "return a response 200 response" do + File.write("test.html", response.body) expect(response.status).to eq(200) end @@ -149,11 +166,11 @@ def file_name_from_header end it "has a csv with the correct headers" do - expect(response.body).to match(/Month,SAPs Lodged,Average SAP Energy Rating,RdSAPs Lodged,Average RdSAP Energy Rating,CEPCs Lodged,Average CEPC Energy Rating,DECs Lodged,DEC-RRs Lodged,AC-CERTs Lodged/) + expect(response_csv_header(response.body)).to eq expected_header end it "has a csv with the correct body" do - expect(response.body).to match(/Oct-2021,674,81.7,2349,61.11,134,90.5,38,8,45/) + expect(response.body).to match(/Oct-2021,674,81.7,,2349,61.11,,134,90.5,38,8,45/) end it "produces a data set with correct number of rows" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f7d37714..1b2aebf3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -14,6 +14,7 @@ require "active_support/cache" require "active_support/notifications" require "rake" +require "timecop" AUTH_URL = "http://test-auth-server.gov.uk" @@ -68,6 +69,10 @@ def get_task(name) loader_enable_override "helper/toggles" +def save_response_to_file(file:, content:) + File.write("#{file}.html", content) +end + module RSpecUnitMixin def get_api_client(api_url = nil) url = api_url.nil? ? ENV["EPB_API_URL"] : api_url diff --git a/spec/unit/domain/shared_statistics.rb b/spec/unit/domain/shared_statistics.rb new file mode 100644 index 00000000..ab4afe87 --- /dev/null +++ b/spec/unit/domain/shared_statistics.rb @@ -0,0 +1,82 @@ +shared_examples "Domain::Statistics" do + def england + [{ "Month" => "Oct-2021", + "SAPs Lodged" => 20_489, + "Average SAP Energy Rating" => 78.40, + "Average SAP CO2/sqm emissions" => nil, + "RdSAPs Lodged" => 120_045, + "Average RdSAP Energy Rating" => 61.73, + "Average RdSAP CO2/sqm emissions" => nil, + "CEPCs Lodged" => 8074, + "Average CEPC Energy Rating" => 67.33, + "DECs Lodged" => 2781, + "DEC-RRs Lodged" => 462, + "AC-CERTs Lodged" => 1206 }, + { "Month" => "Sep-2021", + "SAPs Lodged" => 23_834, + "Average SAP Energy Rating" => 77.82, + "Average SAP CO2/sqm emissions" => 15.74, + "RdSAPs Lodged" => 119_033, + "Average RdSAP Energy Rating" => 61.74, + "Average RdSAP CO2/sqm emissions" => 10.88, + "CEPCs Lodged" => 7572, + "Average CEPC Energy Rating" => 68.18, + "DECs Lodged" => 3298, + "DEC-RRs Lodged" => 402, + "AC-CERTs Lodged" => 861 }] + end + + def northern_ireland + [{ "Month" => "Oct-2021", + "SAPs Lodged" => 674, + "Average SAP Energy Rating" => 81.70, + "Average SAP CO2/sqm emissions" => nil, + "RdSAPs Lodged" => 2349, + "Average RdSAP Energy Rating" => 61.11, + "Average RdSAP CO2/sqm emissions" => nil, + "CEPCs Lodged" => 134, + "Average CEPC Energy Rating" => 90.5, + "DECs Lodged" => 38, + "DEC-RRs Lodged" => 8, + "AC-CERTs Lodged" => 45 }, + { "Month" => "Sep-2021", + "SAPs Lodged" => 643, + "Average SAP Energy Rating" => 82.56, + "Average SAP CO2/sqm emissions" => nil, + "RdSAPs Lodged" => 2466, + "Average RdSAP Energy Rating" => 58.59, + "Average RdSAP CO2/sqm emissions" => nil, + "CEPCs Lodged" => 146, + "Average CEPC Energy Rating" => 79.33, + "DECs Lodged" => 202, + "DEC-RRs Lodged" => 26, + "AC-CERTs Lodged" => 57 }] + end + + def all_countries + [{ "Month" => "Oct-2021", + "SAPs Lodged" => 21_163, + "Average SAP Energy Rating" => 78.41, + "Average SAP CO2/sqm emissions" => nil, + "RdSAPs Lodged" => 122_394, + "Average RdSAP Energy Rating" => 61.71, + "Average RdSAP CO2/sqm emissions" => nil, + "CEPCs Lodged" => 8208, + "Average CEPC Energy Rating" => 67.36, + "DECs Lodged" => 2189, + "DEC-RRs Lodged" => 470, + "AC-CERTs Lodged" => 1251 }, + { "Month" => "Sep-2021", + "SAPs Lodged" => 24_477, + "Average SAP Energy Rating" => 77.83, + "Average SAP CO2/sqm emissions" => 16.24, + "RdSAPs Lodged" => 121_499, + "Average RdSAP Energy Rating" => 61.71, + "Average RdSAP CO2/sqm emissions" => 10.88, + "CEPCs Lodged" => 7718, + "Average CEPC Energy Rating" => 68.27, + "DECs Lodged" => 3500, + "DEC-RRs Lodged" => 428, + "AC-CERTs Lodged" => 918 }] + end +end diff --git a/spec/unit/domain/statistics_results_spec.rb b/spec/unit/domain/statistics_results_spec.rb index 78506a90..281e70fe 100644 --- a/spec/unit/domain/statistics_results_spec.rb +++ b/spec/unit/domain/statistics_results_spec.rb @@ -1,3 +1,5 @@ +require_relative "./shared_statistics" + describe Domain::StatisticsResults do subject(:domain) { described_class.new(register_data:, warehouse_data:) } @@ -118,4 +120,73 @@ expect(result[:assessments][:grouped]).not_to eq [] end end + + describe "#get_country_results" do + before do + domain.set_results + end + + context "when passing northern-ireland as the country" do + it "returns the items for that the country key" do + result = domain.get_country_results(country: "northern-ireland") + grouped = result.group_by { |i| i[:country] }.flatten + expect(grouped.first).to eq "Northern Ireland" + expect(grouped.length).to eq 2 + expect(grouped.last.length).to eq 6 + end + end + + context "when passing England as the country" do + it "returns the items for that the country key" do + result = domain.get_country_results(country: "england") + grouped = result.group_by { |i| i[:country] }.flatten + expect(grouped.first).to eq "England" + expect(grouped.length).to eq 2 + expect(grouped.last.length).to eq 6 + end + end + end + + describe "#to_csv_hash" do + subject(:domain) do + described_class.new(register_data: ServicePerformance::MonthsStatsDataStub.get_data[:data][:assessments], + warehouse_data: ServicePerformance::AverageCo2EmissionsStub.body[:data]) + end + + before do + domain.set_results + end + + include_examples "Domain::Statistics" + + context "when filtering for England" do + let!(:result) do + domain.to_csv_hash(country: "england") + end + + it "returns an array of hashes that matches" do + expect(result).to eq england + end + end + + context "when filtering for Northern Ireland" do + let!(:result) do + domain.to_csv_hash(country: "northern-ireland") + end + + it "returns an array of hashes that matches" do + expect(result).to eq northern_ireland + end + end + + context "when filtering all items/countries" do + let!(:result) do + domain.to_csv_hash(country: "all") + end + + it "returns an array of hashes that matches" do + expect(result).to eq all_countries + end + end + end end diff --git a/spec/unit/use_case/fetch_statistics_csv_spec.rb b/spec/unit/use_case/fetch_statistics_csv_spec.rb index 4d3133c9..8a3ddbee 100644 --- a/spec/unit/use_case/fetch_statistics_csv_spec.rb +++ b/spec/unit/use_case/fetch_statistics_csv_spec.rb @@ -1,110 +1,35 @@ describe UseCase::FetchStatisticsCsv do include RSpecUnitMixin - let(:statistics_gateway) { instance_double(Gateway::StatisticsGateway) } + let(:statistics_gateway) { Gateway::StatisticsGateway.new(get_api_client) } + let(:co2_gateway) { Gateway::AverageCo2EmissionsGateway.new(get_warehouse_api_client) } + let(:fetch_statistics) { described_class.new(statistics_gateway:, co2_gateway:) } let(:api_data) { ServicePerformance::MonthsStatsDataStub.get_data } - let(:fetch_statistics) { described_class.new(statistics_gateway) } - context "when converting statistics data from the API to format for the csv" do - let(:expectation) do - [{ "Month" => "Oct-2021", - "SAPs Lodged" => 21_163, - "Average SAP Energy Rating" => 78.41, - "RdSAPs Lodged" => 122_394, - "Average RdSAP Energy Rating" => 61.71, - "CEPCs Lodged" => 8208, - "Average CEPC Energy Rating" => 67.36, - "DECs Lodged" => 2189, - "DEC-RRs Lodged" => 470, - "AC-CERTs Lodged" => 1251 }, - { "Month" => "Sep-2021", - "SAPs Lodged" => 24_477, - "Average SAP Energy Rating" => 77.83, - "RdSAPs Lodged" => 121_499, - "Average RdSAP Energy Rating" => 61.71, - "CEPCs Lodged" => 7718, - "Average CEPC Energy Rating" => 68.27, - "DECs Lodged" => 3500, - "DEC-RRs Lodged" => 428, - "AC-CERTs Lodged" => 918 }] - end - - let(:results) { fetch_statistics.execute } - - before do - allow(statistics_gateway).to receive(:fetch).and_return(api_data) - end - - it "groups the data by months" do - expect(results).to eq(expectation) - end + before do + allow(statistics_gateway).to receive(:fetch).and_return(api_data) + allow(co2_gateway).to receive(:fetch).and_return(ServicePerformance::AverageCo2EmissionsStub.body) end - context "when converting stats data for England into a csv" do - let(:results) { fetch_statistics.execute("england") } - let(:expectation) do - [{ "Month" => "Oct-2021", - "SAPs Lodged" => 20_489, - "Average SAP Energy Rating" => 78.40, - "RdSAPs Lodged" => 120_045, - "Average RdSAP Energy Rating" => 61.73, - "CEPCs Lodged" => 8074, - "Average CEPC Energy Rating" => 67.33, - "DECs Lodged" => 2781, - "DEC-RRs Lodged" => 462, - "AC-CERTs Lodged" => 1206 }, - { "Month" => "Sep-2021", - "SAPs Lodged" => 23_834, - "Average SAP Energy Rating" => 77.82, - "RdSAPs Lodged" => 119_033, - "Average RdSAP Energy Rating" => 61.74, - "CEPCs Lodged" => 7572, - "Average CEPC Energy Rating" => 68.18, - "DECs Lodged" => 3298, - "DEC-RRs Lodged" => 402, - "AC-CERTs Lodged" => 861 }] - end - - before do - allow(statistics_gateway).to receive(:fetch).and_return(api_data) - end - - it "groups the data by months" do - expect(results).to eq(expectation) - end - end + context "when converting statistics data from the API to format for the csv" do + context "when no filter is passed" do + let(:results) { fetch_statistics.execute } - context "when converting stats data for Nothern Ireland into a csv" do - let(:results) { fetch_statistics.execute("northern-ireland") } - let(:expectation) do - [{ "Month" => "Oct-2021", - "SAPs Lodged" => 674, - "Average SAP Energy Rating" => 81.70, - "RdSAPs Lodged" => 2349, - "Average RdSAP Energy Rating" => 61.11, - "CEPCs Lodged" => 134, - "Average CEPC Energy Rating" => 90.5, - "DECs Lodged" => 38, - "DEC-RRs Lodged" => 8, - "AC-CERTs Lodged" => 45 }, - { "Month" => "Sep-2021", - "SAPs Lodged" => 643, - "Average SAP Energy Rating" => 82.56, - "RdSAPs Lodged" => 2466, - "Average RdSAP Energy Rating" => 58.59, - "CEPCs Lodged" => 146, - "Average CEPC Energy Rating" => 79.33, - "DECs Lodged" => 202, - "DEC-RRs Lodged" => 26, - "AC-CERTs Lodged" => 57 }] + it "groups the data by months into an array of 2 hashes for all month" do + expect(results.length).to eq(2) + expect(results.first).to be_a(Hash) + expect(results.first["SAPs Lodged"]).to eq 21_163 + end end - before do - allow(statistics_gateway).to receive(:fetch).and_return(api_data) - end + context "when filtering for England" do + let(:results) { fetch_statistics.execute("england") } - it "groups the data by months" do - expect(results).to eq(expectation) + it "groups the data by months into an array of 2 hashes" do + expect(results.length).to eq(2) + expect(results.first).to be_a(Hash) + expect(results.first["SAPs Lodged"]).to eq 20_489 + end end end end