Skip to content

Commit

Permalink
feat(fworks): download frameworks register csv
Browse files Browse the repository at this point in the history
  • Loading branch information
serenaabbott11 committed Apr 24, 2024
1 parent 7492361 commit a6a9dcc
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 12 deletions.
9 changes: 8 additions & 1 deletion app/controllers/frameworks/dashboards_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
class Frameworks::DashboardsController < Frameworks::ApplicationController
before_action { @back_url = nil }

def index; end
def index
respond_to do |format|
format.html
format.csv do
send_data Frameworks::FrameworkDatum.to_csv, filename: "frameworks_data.csv", type: "text/csv"
end
end
end
end
26 changes: 26 additions & 0 deletions app/models/frameworks/framework_datum.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require "csv"

module Frameworks
class FrameworkDatum < ApplicationRecord
self.primary_key = :framework_id

# Since these are all coming from other records, there is a risk of method collision
# To avoid this, prefixes are used
enum source: Framework.sources, _prefix: :framework
enum status: Framework.statuses, _prefix: :framework
enum lot: Framework.lots, _prefix: :framework

def readonly?
true
end

# @return [String]
def self.to_csv
CSV.generate(headers: true) do |csv|
csv << column_names

find_each { |record| csv << record.attributes.values }
end
end
end
end
2 changes: 1 addition & 1 deletion app/views/frameworks/evaluations/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="case-list govuk-grid-row">
<div class="govuk-grid-column-one-quarter">
<% unless params[:viewing_from_entity] == "true" %>
<%= link_to "Add Evalutaion", new_frameworks_evaluation_path(back_to: current_url_b64(:evaluations)), class: "govuk-button", "data-turbo" => false %>
<%= link_to "Add Evaluation", new_frameworks_evaluation_path(back_to: current_url_b64(:evaluations)), class: "govuk-button", "data-turbo" => false %>
<% end %>
<%= render "index_filters" %>
Expand Down
2 changes: 2 additions & 0 deletions app/views/frameworks/frameworks/_index_filters.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@
<% end %>
<% end %>
<% end %>
<%= link_to I18n.t("frameworks.register.download_csv"), frameworks_root_path(format: :csv), class: "govuk-button", role: "button" %>
</div>
4 changes: 3 additions & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,8 @@ en:
quick_edit:
header: Quick edit evaluation %{reference}
add_note: Add a note
register:
download_csv: Download Frameworks CSV
generic:
button:
back: Back
Expand Down Expand Up @@ -1528,7 +1530,7 @@ en:
triage: Triage
unspecified: Unspecified
download:
csv: Download CSV
csv: Download Cases CSV
header: Case statistics
header_link: Case Statistics
missing_data:
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20240415143752_create_frameworks_framework_data.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class CreateFrameworksFrameworkData < ActiveRecord::Migration[7.1]
def change
create_view :frameworks_framework_data
end
end
61 changes: 55 additions & 6 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2024_03_28_151344) do
ActiveRecord::Schema[7.1].define(version: 2024_04_15_143752) do
create_sequence "evaluation_refs"
create_sequence "framework_refs"

Expand Down Expand Up @@ -423,8 +423,8 @@
t.string "title"
t.text "body"
t.string "slug"
t.datetime "created_at", precision: nil, default: -> { "CURRENT_TIMESTAMP" }, null: false
t.datetime "updated_at", precision: nil, default: -> { "CURRENT_TIMESTAMP" }, null: false
t.datetime "created_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
t.datetime "updated_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
t.string "contentful_id"
t.text "sidebar"
t.string "breadcrumbs", default: [], array: true
Expand Down Expand Up @@ -848,7 +848,7 @@
t.string "ukprn"
t.string "telephone_number"
t.jsonb "local_authority_legacy"
t.datetime "opened_date", precision: nil
t.datetime "opened_date"
t.string "number"
t.string "rsc_region"
t.string "trust_name"
Expand Down Expand Up @@ -1215,9 +1215,9 @@
se.egroup_status AS establishment_group_status,
se.establishment_type,
array_length(fr.school_urns, 1) AS request_num_schools,
replace(TRIM(BOTH '{}"'::text FROM (fr.school_urns)::text), ','::text, ', '::text) AS request_school_urns,
replace(btrim((fr.school_urns)::text, '{}"'::text), ','::text, ', '::text) AS request_school_urns,
array_length(cr.school_urns, 1) AS case_num_schools,
replace(TRIM(BOTH '{}"'::text FROM (cr.school_urns)::text), ','::text, ', '::text) AS case_school_urns,
replace(btrim((cr.school_urns)::text, '{}"'::text), ','::text, ', '::text) AS case_school_urns,
sf.name AS framework_name,
sp.reason_for_route_to_market,
sp.required_agreement_type,
Expand Down Expand Up @@ -1325,4 +1325,53 @@
FROM support_interactions si_1
WHERE (si_1.event_type = 8)) sir ON ((si.case_id = sir.case_id)));
SQL
create_view "frameworks_framework_data", sql_definition: <<-SQL
SELECT ff.id AS framework_id,
ff.source,
ff.status,
ff.name,
ff.short_name,
ff.url,
ff.reference,
fp.name AS provider_name,
fp.short_name AS provider_short_name,
fpc.name AS provider_contact_name,
fpc.email AS provider_contact_email,
ff.provider_start_date,
ff.provider_end_date,
ff.dfe_start_date,
ff.dfe_review_date,
ff.sct_framework_owner,
ff.sct_framework_provider_lead,
(((sap.first_name)::text || ' '::text) || (sap.last_name)::text) AS procops_lead_name,
sap.email AS procops_lead_email,
(((saeo.first_name)::text || ' '::text) || (saeo.last_name)::text) AS e_and_o_lead_name,
saeo.email AS e_and_o_lead_email,
(ff.created_at)::date AS created_at,
(ff.updated_at)::date AS updated_at,
ff.dps,
ff.lot,
ff.provider_reference,
(ff.faf_added_date)::date AS faf_added_date,
(ff.faf_end_date)::date AS faf_end_date,
cats.categories,
CASE
WHEN (evals.has_evaluation IS NOT NULL) THEN 'Yes'::text
ELSE 'No'::text
END AS has_evaluation
FROM ((((((frameworks_frameworks ff
LEFT JOIN frameworks_providers fp ON ((ff.provider_id = fp.id)))
LEFT JOIN frameworks_provider_contacts fpc ON ((ff.provider_contact_id = fpc.id)))
LEFT JOIN support_agents sap ON ((ff.proc_ops_lead_id = sap.id)))
LEFT JOIN support_agents saeo ON ((ff.e_and_o_lead_id = saeo.id)))
LEFT JOIN ( SELECT ffc.framework_id,
jsonb_agg(sc.title) AS categories
FROM (frameworks_framework_categories ffc
LEFT JOIN support_categories sc ON ((sc.id = ffc.support_category_id)))
GROUP BY ffc.framework_id) cats ON ((cats.framework_id = ff.id)))
LEFT JOIN ( SELECT ffe.framework_id,
count(ffe.id) AS has_evaluation
FROM frameworks_evaluations ffe
GROUP BY ffe.framework_id) evals ON ((evals.framework_id = ff.id)));
SQL
end
51 changes: 51 additions & 0 deletions db/views/frameworks_framework_data_v01.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
SELECT ff.id AS "framework_id",
ff.source,
ff.status,
ff.name,
ff.short_name,
ff.url,
ff.reference,
fp.name AS "provider_name",
fp.short_name AS "provider_short_name",
fpc.name AS "provider_contact_name",
fpc.email AS "provider_contact_email",
ff.provider_start_date::DATE,
ff.provider_end_date::DATE,
ff.dfe_start_date::DATE,
ff.dfe_review_date::DATE,
ff.sct_framework_owner,
ff.sct_framework_provider_lead,
sap.first_name || ' ' || sap.last_name AS "procops_lead_name",
sap.email AS "procops_lead_email",
saeo.first_name || ' ' || saeo.last_name AS "e_and_o_lead_name",
saeo.email AS "e_and_o_lead_email",
ff.created_at::DATE,
ff.updated_at::DATE,
ff.dps,
ff.lot,
ff.provider_reference,
ff.faf_added_date::DATE,
ff.faf_end_date::DATE,
cats.categories,
(CASE
WHEN evals.has_evaluation IS NOT NULL THEN 'Yes'
ELSE 'No'
END) AS "has_evaluation"
FROM frameworks_frameworks AS ff
LEFT JOIN frameworks_providers AS fp ON ff.provider_id = fp.id
LEFT JOIN frameworks_provider_contacts AS fpc ON ff.provider_contact_id = fpc.id
LEFT JOIN support_agents AS sap ON ff.proc_ops_lead_id = sap.id
LEFT JOIN support_agents AS saeo ON ff.e_and_o_lead_id = saeo.id
LEFT JOIN (
SELECT ffc.framework_id,
jsonb_agg(sc.title) AS "categories"
FROM frameworks_framework_categories AS ffc
LEFT JOIN support_categories AS sc ON sc.id = ffc.support_category_id
GROUP BY ffc.framework_id
) AS cats ON cats.framework_id = ff.id
LEFT JOIN (
SELECT ffe.framework_id,
COUNT(ffe.id) AS "has_evaluation"
FROM frameworks_evaluations AS ffe
GROUP BY ffe.framework_id
) AS evals ON evals.framework_id = ff.id
2 changes: 1 addition & 1 deletion doc/roles-and-portals.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Access to portals is dictated by the agents roles. The roles are checked on page
|Portal|Endpoint|Roles required (either)|
|-|-|-|
|Support / ProcOps CMS|`/support`|`internal procops_admin procops`|
|Frameworks Evalutaion|`/frameworks`|`framework_evaluator_admin framework_evaluator`|
|Frameworks Evaluation|`/frameworks`|`framework_evaluator_admin framework_evaluator`|
|Engagement & Outreach|`/engagement`|`internal e_and_o_admin e_and_o`|

- See `app/models/support/agent.rb` for full list of roles.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require "rails_helper"

describe "Agent can download frameworks register csv", js: true do
include_context "with a framework evaluation agent"

before do
visit frameworks_root_path
end

it "has a link to download the CSV of the frameworks data" do
within "#frameworks-register" do
expect(page).to have_link "Download Frameworks CSV", class: "govuk-button", href: frameworks_root_path(format: :csv)
end
end
end
4 changes: 2 additions & 2 deletions spec/features/support/case_statistics_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,11 @@

describe "case statistics downloads" do
it "has a link to download the CSV of the case data" do
expect(page).to have_link "Download CSV", class: "govuk-button", href: support_case_statistics_path(format: :csv)
expect(page).to have_link "Download Cases CSV", class: "govuk-button", href: support_case_statistics_path(format: :csv)
end

it "provides a case data CSV download" do
click_on "Download CSV"
click_on "Download Cases CSV"
expect(page.response_headers["Content-Type"]).to eq "text/csv"
expect(page.response_headers["Content-Disposition"]).to match(/^attachment/)
expect(page.response_headers["Content-Disposition"]).to match(/filename="case_data.csv"/)
Expand Down
9 changes: 9 additions & 0 deletions spec/models/frameworks/framework_datum_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RSpec.describe Frameworks::FrameworkDatum, type: :model do
describe "#to_csv" do
it "includes headers" do
expect(described_class.to_csv).to eql(
"framework_id,source,status,name,short_name,url,reference,provider_name,provider_short_name,provider_contact_name,provider_contact_email,provider_start_date,provider_end_date,dfe_start_date,dfe_review_date,sct_framework_owner,sct_framework_provider_lead,procops_lead_name,procops_lead_email,e_and_o_lead_name,e_and_o_lead_email,created_at,updated_at,dps,lot,provider_reference,faf_added_date,faf_end_date,categories,has_evaluation\n",
)
end
end
end
14 changes: 14 additions & 0 deletions spec/requests/frameworks/download_frameworks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require "rails_helper"

describe "Agent can download frameworks register csv" do
before do
agent_is_signed_in(roles: %w[procops framework_evaluator])
end

it "provides a framework register CSV download" do
get "/frameworks.csv"
expect(response.headers["Content-Type"]).to eq "text/csv"
expect(response.headers["Content-Disposition"]).to match(/^attachment/)
expect(response.headers["Content-Disposition"]).to match(/filename="frameworks_data.csv"/)
end
end

0 comments on commit a6a9dcc

Please sign in to comment.