Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CPDNPQ-2346] Cohort + schedule management #2068

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module NpqSeparation
module NavigationStructures
class AdminNavigationStructure < NpqSeparation::NavigationStructure
include Rails.application.routes.url_helpers
include AdminHelper

private

Expand All @@ -19,6 +20,11 @@ def structure
href: npq_separation_admin_applications_path,
prefix: "/npq-separation/admin/applications",
) => [],
Node.new(
name: "Cohorts",
href: npq_separation_admin_cohorts_path,
prefix: "/npq-separation/admin/cohorts",
) => cohort_nodes,
Node.new(
name: "Courses",
href: npq_separation_admin_courses_path,
Expand Down Expand Up @@ -63,6 +69,22 @@ def structure
) => [],
}
end

def cohort_nodes
[
Node.new(
name: "All cohorts",
href: npq_separation_admin_cohorts_path,
prefix: /\/npq-separation\/admin\/cohorts$/,
),
] + Cohort.order(start_year: :desc).map do |cohort|
Node.new(
name: "Cohort #{format_cohort(cohort)}",
href: npq_separation_admin_cohort_path(cohort),
prefix: "/npq-separation/admin/cohorts/#{cohort.id}",
)
end
end
end
end
end
78 changes: 78 additions & 0 deletions app/controllers/npq_separation/admin/cohorts_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
class NpqSeparation::Admin::CohortsController < NpqSeparation::AdminController
before_action :ensure_super_admin, except: %i[index show]
before_action :ensure_editable, only: %i[edit update destroy]

def index
@pagy, @cohorts = pagy(Cohort.all.order(start_year: :desc))
end

def show
@cohort = cohort
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
end

def new
@cohort = Cohort.new
render :form
end

def create
@cohort = Cohort.new(cohort_params)

if @cohort.save
flash[:success] = "Cohort created"
redirect_to action: :index
else
render :form, status: :unprocessable_entity
end
end

def edit
@cohort = cohort
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
render :form
end

def update
if cohort.update(cohort_params)
flash[:success] = "Cohort updated"
redirect_to npq_separation_admin_cohort_path(cohort)
else
@cohort = cohort
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
render :form, status: :unprocessable_entity
end
end

def destroy
if params[:confirm].present?
cohort.destroy!
flash[:success] = "Cohort deleted"
redirect_to action: :index
else
@cohort = cohort
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
render :destroy
end
end

private

def cohort_params
params.require(:cohort).permit(:start_year, :registration_start_date, :funding_cap)
end

def cohort
@cohort ||= Cohort.find(params[:id])
end

def ensure_super_admin
unless current_admin.super_admin?
flash[:error] = "You must be a super admin to change cohorts"
redirect_to action: :index
end
end

def ensure_editable
unless cohort.editable?
flash[:error] = "This cohort is not editable"
redirect_to npq_separation_admin_cohort_path(cohort)
end
end
end
78 changes: 78 additions & 0 deletions app/controllers/npq_separation/admin/schedules_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
class NpqSeparation::Admin::SchedulesController < NpqSeparation::AdminController
before_action :ensure_super_admin, except: :show
before_action :ensure_editable, only: %i[edit update destroy]

def show
@schedule = schedule
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
end

def new
@schedule = cohort.schedules.new
render :form
end

def create
@schedule = cohort.schedules.new(schedule_params)

if @schedule.save
flash[:success] = "Schedule created"
redirect_to npq_separation_admin_cohort_path(cohort)
else
render :form, status: :unprocessable_entity
end
end

def edit
@schedule = schedule
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
render :form
end

def update
if schedule.update(schedule_params)
flash[:success] = "Schedule updated"
redirect_to npq_separation_admin_cohort_path(cohort)
else
@schedule = schedule
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
render :form, status: :unprocessable_entity
end
end

def destroy
if params[:confirm].present?
schedule.destroy!
flash[:success] = "Schedule deleted"
redirect_to npq_separation_admin_cohort_path(schedule.cohort)
else
@schedule = schedule
rwrrll marked this conversation as resolved.
Show resolved Hide resolved
render :destroy
end
end

private

def schedule_params
params.require(:schedule).permit(:course_group_id, :name, :identifier, :applies_from, :applies_to, allowed_declaration_types: [])
end

def schedule
@schedule ||= cohort.schedules.find(params[:id])
end

def cohort
@cohort ||= Cohort.find(params[:cohort_id])
end

def ensure_super_admin
unless current_admin.super_admin?
flash[:error] = "You must be a super admin to change schedules"
redirect_to npq_separation_admin_cohort_path(cohort)
end
end

def ensure_editable
unless schedule.editable?
flash[:error] = "This schedule is not editable"
redirect_to npq_separation_admin_cohort_schedule_path(cohort, schedule)
end
end
end
16 changes: 12 additions & 4 deletions app/models/cohort.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
class Cohort < ApplicationRecord
has_many :declarations, dependent: :restrict_with_exception
has_many :schedules, dependent: :destroy
has_many :statements, dependent: :restrict_with_exception

validates :start_year,
presence: true,
numericality: {
Expand All @@ -16,15 +20,19 @@ class Cohort < ApplicationRecord
}
validates :ecf_id, uniqueness: { case_sensitive: false }, allow_nil: true

def self.current(timestamp = Time.zone.today)
where(registration_start_date: ..timestamp)
.order(start_year: :desc)
.first!
end

def registration_start_date_matches_start_year
return if registration_start_date.blank?

errors.add(:registration_start_date, "year must match the start year") if registration_start_date.year != start_year
end

def self.current(timestamp = Time.zone.today)
where(registration_start_date: ..timestamp)
.order(start_year: :desc)
.first!
def editable?
registration_start_date.future? && statements.none? && declarations.none?
end
end
8 changes: 8 additions & 0 deletions app/models/schedule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,17 @@ class Schedule < ApplicationRecord
belongs_to :cohort
has_many :courses, through: :course_group

delegate :editable?, to: :cohort

normalizes :allowed_declaration_types, with: ->(value) { value.reject(&:blank?) }

validates :name, presence: true
validates :identifier, presence: true, uniqueness: { scope: :cohort_id }
validates :ecf_id, uniqueness: { case_sensitive: false }, allow_nil: true
validates :applies_from, presence: true
validates :applies_to, presence: true

def self.allowed_declaration_types
connection.execute("SELECT unnest(enum_range(NULL::declaration_types))").values.flatten
end
Comment on lines +30 to +32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit unusual or I'm not following? Whats the advantage of normalizing the list in a separate method, why not normalize it here? Though I'm also not understanding why postgres would return a blank enum type?

end
9 changes: 9 additions & 0 deletions app/views/npq_separation/admin/cohorts/destroy.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<h1 class="govuk-heading-l">Delete cohort <%= format_cohort @cohort %></h1>

<p class="govuk-body">Are you sure you want to delete this cohort and <%= pluralize @cohort.schedules.count, 'associated schedule' %>? There is no way to undo this action.</p>

<%= form_with model: [:npq_separation, :admin, @cohort], method: 'delete' do |f| %>
<%= hidden_field_tag :confirm, 1 %>
<%= f.govuk_submit 'Confirm delete cohort', warning: true %>
<%= govuk_button_link_to('Cancel', npq_separation_admin_cohort_path(@cohort), secondary: true) %>
<% end %>
26 changes: 26 additions & 0 deletions app/views/npq_separation/admin/cohorts/form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<h1 class="govuk-heading-l">
<% if @cohort.new_record? %>
New cohort
<% else %>
Edit cohort
<% end %>
</h1>

<%= form_with model: [:npq_separation, :admin, @cohort] do |f| %>
<%= f.govuk_number_field :start_year,
label: { text: "Start year" },
class: 'govuk-input--width-4' %>

<%= f.govuk_check_box :funding_cap,
1,
0,
multiple: false,
link_errors: true,
label: { text: "Funding cap" } %>

<%= f.govuk_date_field :registration_start_date,
legend: { text: 'Registration start date' },
class: 'govuk-!-margin-top-5' %>

<%= f.govuk_submit @cohort.new_record? ? 'Create cohort' : 'Update cohort' %>
<% end %>
27 changes: 27 additions & 0 deletions app/views/npq_separation/admin/cohorts/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<h1 class="govuk-heading-l">All cohorts</h1>

<%= govuk_button_link_to('New cohort', new_npq_separation_admin_cohort_path) if current_admin.super_admin? %>

<%=
govuk_table do |table|
table.with_head do |header|
header.with_row do |row|
row.with_cell(text: "Start year")
row.with_cell(text: "Registration start date")
row.with_cell(text: "Funding cap")
end
end

table.with_body do |body|
@cohorts.each do |cohort|
body.with_row do |row|
row.with_cell(text: govuk_link_to(format_cohort(cohort), npq_separation_admin_cohort_path(cohort)))
row.with_cell(text: cohort.registration_start_date.to_date.to_fs(:govuk))
row.with_cell(text: boolean_red_green_tag(cohort.funding_cap))
end
end
end
end
%>

<%= govuk_pagination(pagy: @pagy) %>
57 changes: 57 additions & 0 deletions app/views/npq_separation/admin/cohorts/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<h1 class="govuk-heading-l">Cohort <%= format_cohort @cohort %></h1>

<%=
govuk_summary_list do |sl|
sl.with_row do |row|
row.with_key(text: "Start year")
row.with_value(text: @cohort.start_year)
end

sl.with_row do |row|
row.with_key(text: "Registration start date")
row.with_value(text: @cohort.registration_start_date.to_date.to_fs(:govuk))
end

sl.with_row do |row|
row.with_key(text: "Funding cap")
row.with_value(text: boolean_red_green_tag(@cohort.funding_cap))
end
end
%>

<% if current_admin.super_admin? && @cohort.editable? %>
<%= govuk_button_link_to('Edit cohort details', edit_npq_separation_admin_cohort_path(@cohort)) %>
<%= govuk_button_link_to('Delete cohort', npq_separation_admin_cohort_path(@cohort), method: :delete, warning: true) %>
<% end %>

<hr class="govuk-section-break govuk-section-break--l">

<h2 class="govuk-heading-m">Schedules</h1>

<% if current_admin.super_admin? && @cohort.editable? %>
<%= govuk_button_link_to('New schedule', new_npq_separation_admin_cohort_schedule_path(@cohort)) %>
<% end %>

<%=
govuk_table do |table|
table.with_head do |head|
head.with_row do |row|
row.with_cell(text: 'Name')
row.with_cell(text: 'Applies from')
row.with_cell(text: 'Applies to')
row.with_cell(text: 'Declaration types')
end
end

table.with_body do |body|
@cohort.schedules.order(:name).each do |schedule|
body.with_row do |row|
row.with_cell(text: govuk_link_to(schedule.name, npq_separation_admin_cohort_schedule_path(@cohort, schedule)))
row.with_cell(text: schedule.applies_from.to_fs(:govuk_short))
row.with_cell(text: schedule.applies_to.to_fs(:govuk_short))
row.with_cell(text: schedule.allowed_declaration_types.count)
end
end
end
end
%>
9 changes: 9 additions & 0 deletions app/views/npq_separation/admin/schedules/destroy.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<h1 class="govuk-heading-l">Delete schedule <%= @schedule.name %></h1>

<p class="govuk-body">Are you sure you want to delete this schedule? There is no way to undo this action.</p>

<%= form_with model: [:npq_separation, :admin, @schedule.cohort, @schedule], method: 'delete' do |f| %>
<%= hidden_field_tag :confirm, 1 %>
<%= f.govuk_submit 'Confirm delete schedule', warning: true %>
<%= govuk_button_link_to('Cancel', npq_separation_admin_cohort_schedule_path(@schedule.cohort, @schedule), secondary: true) %>
<% end %>
Loading
Loading