Browse Source

CLDC-2481: Add ability to disable organisations (#2293)

* CLDC-2481: Add ability to disable organisations.

* CLDC-2481: Add ability to disable organisations

* Tidy up tests

* CLDC-2481: Review markups

* CLDC-2481: Fix location and scheme filters

* Add banners for stock owners and managing agents

* Update view test

---------

Co-authored-by: Kat <katrina@kosiak.co.uk>
pull/2381/head
Robert Sullivan 9 months ago committed by GitHub
parent
commit
d2518d7c38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      app/controllers/organisation_relationships_controller.rb
  2. 31
      app/controllers/organisations_controller.rb
  3. 3
      app/controllers/users_controller.rb
  4. 13
      app/helpers/toggle_active_organisation_helper.rb
  5. 6
      app/models/form/lettings/questions/managing_organisation.rb
  6. 4
      app/models/form/lettings/questions/stock_owner.rb
  7. 6
      app/models/form/sales/questions/managing_organisation.rb
  8. 4
      app/models/form/sales/questions/owning_organisation_id.rb
  9. 20
      app/models/location.rb
  10. 3
      app/models/organisation.rb
  11. 23
      app/models/scheme.rb
  12. 17
      app/models/user.rb
  13. 16
      app/policies/organisation_policy.rb
  14. 2
      app/views/locations/show.html.erb
  15. 18
      app/views/organisation_relationships/managing_agents.html.erb
  16. 18
      app/views/organisation_relationships/stock_owners.html.erb
  17. 9
      app/views/organisations/show.html.erb
  18. 29
      app/views/organisations/toggle_active.html.erb
  19. 2
      app/views/schemes/show.html.erb
  20. 2
      app/views/users/new.html.erb
  21. 2
      app/views/users/show.html.erb
  22. 5
      config/locales/en.yml
  23. 2
      config/routes.rb
  24. 5
      db/migrate/20240304112411_add_reactivate_with_organisation_to_users.rb
  25. 12
      db/migrate/20240305112507_add_default_value_to_organisation_active_field.rb
  26. 3
      db/schema.rb
  27. 15
      spec/models/form/lettings/questions/managing_organisation_spec.rb
  28. 21
      spec/models/form/lettings/questions/stock_owner_spec.rb
  29. 7
      spec/models/form/sales/questions/managing_organisation_spec.rb
  30. 20
      spec/models/form/sales/questions/owning_organisation_id_spec.rb
  31. 13
      spec/models/location_spec.rb
  32. 41
      spec/models/organisation_spec.rb
  33. 10
      spec/models/scheme_spec.rb
  34. 66
      spec/policies/organisation_policy_spec.rb
  35. 60
      spec/requests/organisation_relationships_controller_spec.rb
  36. 120
      spec/requests/organisations_controller_spec.rb
  37. 35
      spec/views/locations/show.html.erb_spec.rb
  38. 14
      spec/views/organisations/show.html.erb_spec.rb
  39. 34
      spec/views/schemes/show.html.erb_spec.rb

10
app/controllers/organisation_relationships_controller.rb

@ -14,7 +14,7 @@ class OrganisationRelationshipsController < ApplicationController
]
def stock_owners
stock_owners = organisation.stock_owners
stock_owners = organisation.stock_owners.filter_by_active
unpaginated_filtered_stock_owners = filtered_collection(stock_owners, search_term)
@pagy, @stock_owners = pagy(unpaginated_filtered_stock_owners)
@ -23,7 +23,7 @@ class OrganisationRelationshipsController < ApplicationController
end
def managing_agents
managing_agents = organisation.managing_agents
managing_agents = organisation.managing_agents.filter_by_active
unpaginated_filtered_managing_agents = filtered_collection(managing_agents, search_term)
@pagy, @managing_agents = pagy(unpaginated_filtered_managing_agents)
@ -48,7 +48,7 @@ class OrganisationRelationshipsController < ApplicationController
flash[:notice] = "#{@organisation_relationship.parent_organisation.name} is now one of #{current_user.data_coordinator? ? 'your' : "this organisation's"} stock owners"
redirect_to stock_owners_organisation_path
else
@organisations = Organisation.where.not(id: organisation.id).pluck(:id, :name)
@organisations = Organisation.filter_by_active.where.not(id: organisation.id).pluck(:id, :name)
render "organisation_relationships/add_stock_owner", status: :unprocessable_entity
end
end
@ -60,7 +60,7 @@ class OrganisationRelationshipsController < ApplicationController
flash[:notice] = "#{@organisation_relationship.child_organisation.name} is now one of #{current_user.data_coordinator? ? 'your' : "this organisation's"} managing agents"
redirect_to managing_agents_organisation_path
else
@organisations = Organisation.where.not(id: organisation.id).pluck(:id, :name)
@organisations = Organisation.filter_by_active.where.not(id: organisation.id).pluck(:id, :name)
render "organisation_relationships/add_managing_agent", status: :unprocessable_entity
end
end
@ -110,7 +110,7 @@ private
end
def organisations
@organisations ||= Organisation.where.not(id: organisation.id).pluck(:id, :name)
@organisations ||= Organisation.filter_by_active.where.not(id: organisation.id).pluck(:id, :name)
end
def parent_organisation

31
app/controllers/organisations_controller.rb

@ -94,10 +94,37 @@ class OrganisationsController < ApplicationController
end
end
def deactivate
authorize @organisation
render "toggle_active", locals: { action: "deactivate" }
end
def reactivate
authorize @organisation
render "toggle_active", locals: { action: "reactivate" }
end
def update
if current_user.data_coordinator? || current_user.support?
if (current_user.data_coordinator? && org_params[:active].nil?) || current_user.support?
if @organisation.update(org_params)
case org_params[:active]
when "false"
@organisation.users.filter_by_active.each do |user|
user.deactivate!(reactivate_with_organisation: true)
end
flash[:notice] = I18n.t("organisation.deactivated", organisation: @organisation.name)
when "true"
users_to_reactivate = @organisation.users.where(reactivate_with_organisation: true)
users_to_reactivate.each do |user|
user.reactivate!
user.send_confirmation_instructions
end
flash[:notice] = I18n.t("organisation.reactivated", organisation: @organisation.name)
else
flash[:notice] = I18n.t("organisation.updated")
end
redirect_to details_organisation_path(@organisation)
end
else
@ -239,7 +266,7 @@ private
end
def org_params
params.require(:organisation).permit(:name, :address_line1, :address_line2, :postcode, :phone, :holds_own_stock, :provider_type, :housing_registration_no)
params.require(:organisation).permit(:name, :address_line1, :address_line2, :postcode, :phone, :holds_own_stock, :provider_type, :housing_registration_no, :active)
end
def codes_only_export?

3
app/controllers/users_controller.rb

@ -62,9 +62,10 @@ class UsersController < ApplicationController
else
user_name = @user.name&.possessive || @user.email.possessive
if user_params[:active] == "false"
@user.update!(confirmed_at: nil, sign_in_count: 0, initial_confirmation_sent: false)
@user.deactivate!
flash[:notice] = I18n.t("devise.activation.deactivated", user_name:)
elsif user_params[:active] == "true"
@user.reactivate!
@user.send_confirmation_instructions
flash[:notice] = I18n.t("devise.activation.reactivated", user_name:)
elsif user_params.key?("email")

13
app/helpers/toggle_active_organisation_helper.rb

@ -0,0 +1,13 @@
module ToggleActiveOrganisationHelper
def toggle_organisation_form_path(action, organisation)
if action == "deactivate"
organisation_new_deactivation_path(organisation)
else
organisation_reactivate_path(organisation)
end
end
def date_type_question(action)
action == "deactivate" ? :deactivation_date_type : :reactivation_date_type
end
end

6
app/models/form/lettings/questions/managing_organisation.rb

@ -31,11 +31,11 @@ class Form::Lettings::Questions::ManagingOrganisation < ::Form::Question
end
orgs = if user.support?
log.owning_organisation.managing_agents
log.owning_organisation.managing_agents.filter_by_active
elsif user.organisation.absorbed_organisations.include?(log.owning_organisation)
user.organisation.managing_agents + log.owning_organisation.managing_agents
user.organisation.managing_agents.filter_by_active + log.owning_organisation.managing_agents.filter_by_active
else
user.organisation.managing_agents
user.organisation.managing_agents.filter_by_active
end
user.organisation.absorbed_organisations.each do |absorbed_org|

4
app/models/form/lettings/questions/stock_owner.rb

@ -30,7 +30,7 @@ class Form::Lettings::Questions::StockOwner < ::Form::Question
end
if user.support?
Organisation.where(holds_own_stock: true).find_each do |org|
Organisation.filter_by_active.where(holds_own_stock: true).find_each do |org|
if org.merge_date.present?
answer_opts[org.id] = "#{org.name} (inactive as of #{org.merge_date.to_fs(:govuk_date)})" if org.merge_date >= FormHandler.instance.start_date_of_earliest_open_for_editing_collection_period
elsif org.absorbed_organisations.merged_during_open_collection_period.exists? && org.available_from.present?
@ -40,7 +40,7 @@ class Form::Lettings::Questions::StockOwner < ::Form::Question
end
end
else
user.organisation.stock_owners.each do |stock_owner|
user.organisation.stock_owners.filter_by_active.each do |stock_owner|
answer_opts[stock_owner.id] = stock_owner.name
end
recently_absorbed_organisations.each do |absorbed_org|

6
app/models/form/sales/questions/managing_organisation.rb

@ -31,11 +31,11 @@ class Form::Sales::Questions::ManagingOrganisation < ::Form::Question
end
orgs = if user.support?
log.owning_organisation.managing_agents
log.owning_organisation.managing_agents.filter_by_active
elsif user.organisation.absorbed_organisations.include?(log.owning_organisation)
user.organisation.managing_agents + log.owning_organisation.managing_agents
user.organisation.managing_agents.filter_by_active + log.owning_organisation.managing_agents.filter_by_active
else
user.organisation.managing_agents
user.organisation.managing_agents.filter_by_active
end.pluck(:id, :name).to_h
user.organisation.absorbed_organisations.each do |absorbed_org|

4
app/models/form/sales/questions/owning_organisation_id.rb

@ -25,7 +25,7 @@ class Form::Sales::Questions::OwningOrganisationId < ::Form::Question
answer_opts[user.organisation.id] = "#{user.organisation.name} (Your organisation)"
end
user.organisation.stock_owners.where(holds_own_stock: true).find_each do |org|
user.organisation.stock_owners.filter_by_active.where(holds_own_stock: true).find_each do |org|
answer_opts[org.id] = org.name
end
end
@ -44,7 +44,7 @@ class Form::Sales::Questions::OwningOrganisationId < ::Form::Question
end
if user.support?
Organisation.where(holds_own_stock: true).find_each do |org|
Organisation.filter_by_active.where(holds_own_stock: true).find_each do |org|
if org.merge_date.present?
answer_opts[org.id] = "#{org.name} (inactive as of #{org.merge_date.to_fs(:govuk_date)})" if org.merge_date >= FormHandler.instance.start_date_of_earliest_open_for_editing_collection_period
elsif org.absorbed_organisations.merged_during_open_collection_period.exists? && org.available_from.present?

20
app/models/location.rb

@ -40,6 +40,7 @@ class Location < ApplicationRecord
if scopes.any?
filtered_records = filtered_records
.left_outer_joins(:location_deactivation_periods)
.joins(scheme: [:owning_organisation])
.order("location_deactivation_periods.created_at DESC")
.merge(scopes.reduce(&:or))
end
@ -53,6 +54,15 @@ class Location < ApplicationRecord
}
scope :deactivated, lambda {
deactivated_by_organisation
.or(deactivated_directly)
}
scope :deactivated_by_organisation, lambda {
merge(Organisation.filter_by_inactive)
}
scope :deactivated_directly, lambda {
merge(LocationDeactivationPeriod.deactivations_without_reactivation)
.where("location_deactivation_periods.deactivation_date <= ?", Time.zone.now)
}
@ -60,20 +70,23 @@ class Location < ApplicationRecord
scope :deactivating_soon, lambda {
merge(LocationDeactivationPeriod.deactivations_without_reactivation)
.where("location_deactivation_periods.deactivation_date > ?", Time.zone.now)
.where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id))
}
scope :reactivating_soon, lambda {
where.not("location_deactivation_periods.reactivation_date IS NULL")
.where("location_deactivation_periods.reactivation_date > ?", Time.zone.now)
.where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id))
}
scope :activating_soon, lambda {
where("startdate > ?", Time.zone.now)
where("locations.startdate > ?", Time.zone.now)
}
scope :active_status, lambda {
where.not(id: joins(:location_deactivation_periods).reactivating_soon.pluck(:id))
.where.not(id: joins(:location_deactivation_periods).deactivated.pluck(:id))
.where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id))
.where.not(id: joins(:location_deactivation_periods).deactivated_directly.pluck(:id))
.where.not(id: incomplete.pluck(:id))
.where.not(id: joins(:location_deactivation_periods).deactivating_soon.pluck(:id))
.where.not(id: activating_soon.pluck(:id))
@ -142,7 +155,8 @@ class Location < ApplicationRecord
def status_at(date)
return :deleted if discarded_at.present?
return :incomplete unless confirmed
return :deactivated if open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date
return :deactivated if scheme.owning_organisation.status_at(date) == :deactivated ||
open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date
return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date
return :reactivating_soon if last_deactivation_before(date)&.reactivation_date.present? && date < last_deactivation_before(date).reactivation_date
return :activating_soon if startdate.present? && date < startdate

3
app/models/organisation.rb

@ -37,6 +37,8 @@ class Organisation < ApplicationRecord
scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") }
scope :search_by, ->(param) { search_by_name(param) }
scope :filter_by_active, -> { where(active: true) }
scope :filter_by_inactive, -> { where(active: false) }
scope :merged_during_open_collection_period, -> { where("merge_date >= ?", FormHandler.instance.start_date_of_earliest_open_for_editing_collection_period) }
has_paper_trail
@ -138,6 +140,7 @@ class Organisation < ApplicationRecord
def status_at(date)
return :merged if merge_date.present? && merge_date < date
return :deactivated unless active
:active
end

23
app/models/scheme.rb

@ -35,6 +35,7 @@ class Scheme < ApplicationRecord
if scopes.any?
filtered_records = filtered_records
.left_outer_joins(:scheme_deactivation_periods)
.joins(:owning_organisation)
.merge(scopes.reduce(&:or))
end
@ -45,12 +46,22 @@ class Scheme < ApplicationRecord
where.not(confirmed: true)
.or(where(confirmed: nil))
.or(where.not(id: Location.select(:scheme_id).where(confirmed: true).distinct))
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
.where.not(id: joins(:scheme_deactivation_periods).deactivated_directly.pluck(:id))
.where.not(id: joins(:scheme_deactivation_periods).reactivating_soon.pluck(:id))
.where.not(id: joins(:scheme_deactivation_periods).deactivated.pluck(:id))
.where.not(id: joins(:scheme_deactivation_periods).deactivating_soon.pluck(:id))
}
scope :deactivated, lambda {
deactivated_by_organisation
.or(deactivated_directly)
}
scope :deactivated_by_organisation, lambda {
merge(Organisation.filter_by_inactive)
}
scope :deactivated_directly, lambda {
merge(SchemeDeactivationPeriod.deactivations_without_reactivation)
.where("scheme_deactivation_periods.deactivation_date <= ?", Time.zone.now)
}
@ -58,22 +69,25 @@ class Scheme < ApplicationRecord
scope :deactivating_soon, lambda {
merge(SchemeDeactivationPeriod.deactivations_without_reactivation)
.where("scheme_deactivation_periods.deactivation_date > ? AND scheme_deactivation_periods.deactivation_date < ? ", Time.zone.now, 6.months.from_now)
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
}
scope :reactivating_soon, lambda {
where.not("scheme_deactivation_periods.reactivation_date IS NULL")
.where("scheme_deactivation_periods.reactivation_date > ?", Time.zone.now)
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
}
scope :activating_soon, lambda {
where("startdate > ?", Time.zone.now)
where("schemes.startdate > ?", Time.zone.now)
}
scope :active_status, lambda {
where.not(id: joins(:scheme_deactivation_periods).reactivating_soon.pluck(:id))
.where.not(id: joins(:scheme_deactivation_periods).deactivated.pluck(:id))
.where.not(id: incomplete.pluck(:id))
.where.not(id: joins(:scheme_deactivation_periods).deactivating_soon.pluck(:id))
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
.where.not(id: joins(:owning_organisation).joins(:scheme_deactivation_periods).deactivated_directly.pluck(:id))
.where.not(id: activating_soon.pluck(:id))
}
@ -268,7 +282,8 @@ class Scheme < ApplicationRecord
def status_at(date)
return :deleted if discarded_at.present?
return :incomplete unless confirmed && locations.confirmed.any?
return :deactivated if open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date
return :deactivated if owning_organisation.status_at(date) == :deactivated ||
(open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date)
return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date
return :reactivating_soon if last_deactivation_before(date)&.reactivation_date.present? && date < last_deactivation_before(date).reactivation_date
return :activating_soon if startdate.present? && date < startdate

17
app/models/user.rb

@ -134,6 +134,23 @@ class User < ApplicationRecord
update!(is_dpo: true)
end
def deactivate!(reactivate_with_organisation: false)
update!(
active: false,
confirmed_at: nil,
sign_in_count: 0,
initial_confirmation_sent: false,
reactivate_with_organisation:,
)
end
def reactivate!
update!(
active: true,
reactivate_with_organisation: false,
)
end
MFA_TEMPLATE_ID = "6bdf5ee1-8e01-4be1-b1f9-747061d8a24c".freeze
RESET_PASSWORD_TEMPLATE_ID = "2c410c19-80a7-481c-a531-2bcb3264f8e6".freeze
CONFIRMABLE_TEMPLATE_ID = "3fc2e3a7-0835-4b84-ab7a-ce51629eb614".freeze

16
app/policies/organisation_policy.rb

@ -0,0 +1,16 @@
class OrganisationPolicy
attr_reader :user, :organisation
def initialize(user, organisation)
@user = user
@organisation = organisation
end
def deactivate?
user.support? && organisation.status == :active
end
def reactivate?
user.support? && organisation.status == :deactivated
end
end

2
app/views/locations/show.html.erb

@ -47,7 +47,7 @@
</div>
</div>
<% if LocationPolicy.new(current_user, @location).deactivate? %>
<% if @location.scheme.owning_organisation.active? && LocationPolicy.new(current_user, @location).deactivate? %>
<%= toggle_location_link(@location) %>
<% end %>

18
app/views/organisation_relationships/managing_agents.html.erb

@ -5,19 +5,35 @@
<%= render SubNavigationComponent.new(
items: secondary_items(request.path, @organisation.id),
) %>
<% if !@organisation.active? %>
<%= govuk_notification_banner(title_text: "Important") do %>
<p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content">
This organisation is deactivated.
<p>
You cannot add any new managing agents.
<% end %>
<% end %>
<h2 class="govuk-visually-hidden">Managing Agents</h2>
<p class="govuk-body">A managing agent can submit logs for this organisation.</p>
<% if @total_count == 0 %>
<p class="govuk-body">This organisation does not currently have any managing agents.</p>
<% end %>
<% else %>
<% if !@organisation.active? %>
<%= govuk_notification_banner(title_text: "Important") do %>
<p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content">
This organisation is deactivated.
<p>
You cannot add any new managing agents.
<% end %>
<% end %>
<%= render partial: "organisations/headings", locals: { main: "Your managing agents", sub: current_user.organisation.name } %>
<p class="govuk-body">A managing agent can submit logs for this organisation.</p>
<% if @total_count == 0 %>
<p class="govuk-body">This organisation does not currently have any managing agents.</p>
<% end %>
<% end %>
<% if current_user.support? || current_user.data_coordinator? %>
<% if (current_user.support? || current_user.data_coordinator?) && @organisation.active? %>
<%= govuk_button_link_to "Add a managing agent", managing_agents_add_organisation_path, html: { method: :get } %>
<% end %>
<% if @total_count != 0 %>

18
app/views/organisation_relationships/stock_owners.html.erb

@ -2,19 +2,35 @@
<% if current_user.support? %>
<%= render partial: "organisations/headings", locals: { main: @organisation.name, sub: nil } %>
<%= render SubNavigationComponent.new(items: secondary_items(request.path, @organisation.id)) %>
<% if !@organisation.active? %>
<%= govuk_notification_banner(title_text: "Important") do %>
<p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content">
This organisation is deactivated.
<p>
You cannot add any new stock owners.
<% end %>
<% end %>
<h2 class="govuk-visually-hidden">Stock Owners</h2>
<p class="govuk-body">This organisation can submit logs for its stock owners.</p>
<% if @total_count == 0 %>
<p class="govuk-body">This organisation does not currently have any stock owners.</p>
<% end %>
<% else %>
<% if !@organisation.active? %>
<%= govuk_notification_banner(title_text: "Important") do %>
<p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content">
This organisation is deactivated.
<p>
You cannot add any new stock owners.
<% end %>
<% end %>
<%= render partial: "organisations/headings", locals: { main: "Your stock owners", sub: current_user.organisation.name } %>
<p class="govuk-body">Your organisation can submit logs for its stock owners.</p>
<% if @total_count == 0 %>
<p class="govuk-body">You do not currently have any stock owners.</p>
<% end %>
<% end %>
<% if current_user.support? || current_user.data_coordinator? %>
<% if (current_user.support? || current_user.data_coordinator?) && @organisation.active? %>
<%= govuk_button_link_to "Add a stock owner", stock_owners_add_organisation_path, html: { method: :get } %>
<% end %>
<% if @total_count != 0 %>

9
app/views/organisations/show.html.erb

@ -40,3 +40,12 @@
<%= render partial: "organisations/merged_organisation_details" %>
</div>
</div>
<% if OrganisationPolicy.new(current_user, @organisation).deactivate? %>
<%= govuk_button_link_to "Deactivate this organisation", deactivate_organisation_path(@organisation), warning: true %>
<% end %>
<% if OrganisationPolicy.new(current_user, @organisation).reactivate? %>
<span class="app-!-colour-muted govuk-!-margin-right-2">
<%= govuk_button_link_to "Reactivate this organisation", reactivate_organisation_path(@organisation) %>
</span>
<% end %>

29
app/views/organisations/toggle_active.html.erb

@ -0,0 +1,29 @@
<% title = "#{action.humanize} #{@organisation.name}" %>
<% content_for :title, title %>
<% content_for :before_content do %>
<%= govuk_back_link(
href: organisation_path(@organisation),
) %>
<% end %>
<%= form_for(@organisation, as: :organisation, html: { method: :patch }) do |f| %>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="govuk-heading-l">
<span class="govuk-caption-l"><%= @organisation.name %></span>
Are you sure you want to <%= action %> this organisation?
</h1>
<%= govuk_warning_text text: I18n.t("warnings.organisation.#{action}") %>
<% active_value = action != "deactivate" %>
<%= f.hidden_field :active, value: active_value %>
<%= f.govuk_submit "#{action.capitalize} this organisation" %>
<p class="govuk-body">
<%= govuk_link_to("Cancel", organisation_path(@organisation)) %>
</p>
</div>
</div>
<% end %>

2
app/views/schemes/show.html.erb

@ -49,7 +49,7 @@
</div>
</div>
<% if SchemePolicy.new(current_user, @scheme).deactivate? %>
<% if @scheme.owning_organisation.active? && SchemePolicy.new(current_user, @scheme).deactivate? %>
<%= toggle_scheme_link(@scheme) %>
<% end %>

2
app/views/users/new.html.erb

@ -31,7 +31,7 @@
<% if current_user.support? %>
<% null_option = [OpenStruct.new(id: "", name: "Select an option")] %>
<% organisations = Organisation.all.map { |org| OpenStruct.new(id: org.id, name: org.name) } %>
<% organisations = Organisation.filter_by_active.map { |org| OpenStruct.new(id: org.id, name: org.name) } %>
<% answer_options = null_option + organisations %>
<% if @organisation_id %>

2
app/views/users/show.html.erb

@ -127,8 +127,8 @@
end %>
<% end %>
<% if @user.organisation.active? && current_user.can_toggle_active?(@user) %>
<div class="govuk-button-group">
<% if current_user.can_toggle_active?(@user) %>
<% if @user.active? %>
<%= govuk_button_link_to "Deactivate user", deactivate_user_path(@user), warning: true %>
<% if current_user.support? && @user.last_sign_in_at.nil? %>

5
config/locales/en.yml

@ -34,6 +34,8 @@ en:
feedback_form: "https://forms.office.com/Pages/ResponsePage.aspx?id=EGg0v32c3kOociSi7zmVqC4YDsCJ3llAvEZelBFBLUBURFVUTzFDTUJPQlM4M0laTE5DTlNFSjJBQi4u"
organisation:
updated: "Organisation details updated"
reactivated: "%{organisation} has been reactivated."
deactivated: "%{organisation} has been deactivated."
user:
create_password: "Create a password to finish setting up your account"
reset_password: "Reset your password"
@ -860,6 +862,9 @@ Make sure these answers are correct."
offered: "Times previously offered since becoming available"
warnings:
organisation:
deactivate: "All schemes and users at this organisation will be deactivated. All the organisation's relationships will be removed. It will no longer be possible to create logs for this organisation."
reactivate: "All schemes, users, and relationships that were active when this organisation was deactivated will be reactivated."
location:
deactivate:
existing_logs: "It will not be possible to add logs with this location if their tenancy start date is on or after the date you enter. Any existing logs may be affected."

2
config/routes.rb

@ -179,6 +179,8 @@ Rails.application.routes.draw do
post "managing-agents", to: "organisation_relationships#create_managing_agent"
delete "managing-agents", to: "organisation_relationships#delete_managing_agent"
get "merge-request", to: "organisations#merge_request"
get "deactivate", to: "organisations#deactivate"
get "reactivate", to: "organisations#reactivate"
end
end

5
db/migrate/20240304112411_add_reactivate_with_organisation_to_users.rb

@ -0,0 +1,5 @@
class AddReactivateWithOrganisationToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :reactivate_with_organisation, :boolean
end
end

12
db/migrate/20240305112507_add_default_value_to_organisation_active_field.rb

@ -0,0 +1,12 @@
class AddDefaultValueToOrganisationActiveField < ActiveRecord::Migration[7.0]
def up
change_column :organisations, :active, :boolean, default: true
execute "UPDATE organisations
SET active = true;"
end
def down
change_column :organisations, :active, :boolean
end
end

3
db/schema.rb

@ -453,7 +453,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_03_19_122706) do
t.string "managing_agents_label"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "active"
t.boolean "active", default: true
t.integer "old_association_type"
t.string "software_supplier_id"
t.string "housing_management_system"
@ -764,6 +764,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_03_19_122706) do
t.string "unconfirmed_email"
t.boolean "initial_confirmation_sent"
t.datetime "discarded_at"
t.boolean "reactivate_with_organisation"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true

15
spec/models/form/lettings/questions/managing_organisation_spec.rb

@ -57,6 +57,7 @@ RSpec.describe Form::Lettings::Questions::ManagingOrganisation, type: :model do
let(:managing_org1) { create(:organisation, name: "Managing org 1") }
let(:managing_org2) { create(:organisation, name: "Managing org 2") }
let(:managing_org3) { create(:organisation, name: "Managing org 3") }
let(:inactive_managing_org) { create(:organisation, name: "Inactive managing org", active: false) }
let(:log) { create(:lettings_log, managing_organisation: managing_org1) }
let!(:org_rel1) do
@ -76,7 +77,9 @@ RSpec.describe Form::Lettings::Questions::ManagingOrganisation, type: :model do
}
end
it "shows current managing agent at top, followed by user's org (with hint), followed by the managing agents of the user's org" do
it "shows current managing agent at top, followed by user's org (with hint), followed by the active managing agents of the user's org" do
create(:organisation_relationship, parent_organisation: user.organisation, child_organisation: inactive_managing_org)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
end
@ -100,6 +103,10 @@ RSpec.describe Form::Lettings::Questions::ManagingOrganisation, type: :model do
create(:organisation_relationship, parent_organisation: log_owning_org, child_organisation: managing_org3)
end
before do
create(:organisation, name: "Inactive managing org", active: false)
end
context "when org owns stock" do
let(:options) do
{
@ -111,7 +118,7 @@ RSpec.describe Form::Lettings::Questions::ManagingOrganisation, type: :model do
}
end
it "shows current managing agent at top, followed by the current owning organisation (with hint), followed by the managing agents of the current owning organisation" do
it "shows current managing agent at top, followed by the current owning organisation (with hint), followed by the active managing agents of the current owning organisation" do
log_owning_org.update!(holds_own_stock: true)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -133,7 +140,7 @@ RSpec.describe Form::Lettings::Questions::ManagingOrganisation, type: :model do
org_rel2.child_organisation.update!(merge_date: Time.zone.local(2023, 8, 2), absorbing_organisation_id: log_owning_org.id)
end
it "shows current managing agent at top, followed by the current owning organisation (with hint), followed by the managing agents of the current owning organisation" do
it "shows current managing agent at top, followed by the current owning organisation (with hint), followed by the active managing agents of the current owning organisation" do
log_owning_org.update!(holds_own_stock: true)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -149,7 +156,7 @@ RSpec.describe Form::Lettings::Questions::ManagingOrganisation, type: :model do
}
end
it "shows current managing agent at top, followed by the managing agents of the current owning organisation" do
it "shows current managing agent at top, followed by the active managing agents of the current owning organisation" do
log_owning_org.update!(holds_own_stock: false)
expect(question.displayed_answer_options(log, user)).to eq(options)
end

21
spec/models/form/lettings/questions/stock_owner_spec.rb

@ -46,6 +46,7 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
let(:owning_org_1) { create(:organisation, name: "Owning org 1") }
let(:owning_org_2) { create(:organisation, name: "Owning org 2") }
let(:inactive_owning_org) { create(:organisation, name: "Inactive owning org", active: false) }
let!(:org_rel) do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: owning_org_2)
end
@ -61,7 +62,8 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
}
end
it "shows current stock owner at top, followed by user's org (with hint), followed by the stock owners of the user's org" do
it "shows current stock owner at top, followed by user's org (with hint), followed by the active stock owners of the user's org" do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: inactive_owning_org)
user.organisation.update!(holds_own_stock: true)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -93,7 +95,8 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
}
end
it "shows current stock owner at top, followed by the stock owners of the user's org" do
it "shows current stock owner at top, followed by the active stock active owners of the user's org" do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: inactive_owning_org)
user.organisation.update!(holds_own_stock: false)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -203,21 +206,21 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
end
context "when user is support" do
let(:user) { create(:user, :support) }
let!(:user) { create(:user, :support) }
let!(:log) { create(:lettings_log) }
let(:log) { create(:lettings_log) }
it "shows active orgs where organisation holds own stock" do
non_stock_organisation = create(:organisation, name: "Non-stockholding org", holds_own_stock: false)
inactive_organisation = create(:organisation, name: "Inactive org", active: false)
let(:non_stock_organisation) { create(:organisation, holds_own_stock: false) }
let(:expected_opts) do
Organisation.where(holds_own_stock: true).each_with_object(options) do |organisation, hsh|
expected_opts = Organisation.filter_by_active.where(holds_own_stock: true).each_with_object(options) do |organisation, hsh|
hsh[organisation.id] = organisation.name
hsh
end
end
it "shows orgs where organisation holds own stock" do
expect(question.displayed_answer_options(log, user)).to eq(expected_opts)
expect(question.displayed_answer_options(log, user)).not_to include(non_stock_organisation.id)
expect(question.displayed_answer_options(log, user)).not_to include(inactive_organisation.id)
end
context "and org has recently absorbed other orgs and does not have available from date" do

7
spec/models/form/sales/questions/managing_organisation_spec.rb

@ -57,6 +57,7 @@ RSpec.describe Form::Sales::Questions::ManagingOrganisation, type: :model do
let(:managing_org1) { create(:organisation, name: "Managing org 1") }
let(:managing_org2) { create(:organisation, name: "Managing org 2") }
let(:managing_org3) { create(:organisation, name: "Managing org 3") }
let(:inactive_org) { create(:organisation, name: "Inactive org", active: false) }
let(:log) do
create(:lettings_log, owning_organisation: log_owning_org, managing_organisation: managing_org1,
@ -80,7 +81,8 @@ RSpec.describe Form::Sales::Questions::ManagingOrganisation, type: :model do
}
end
it "shows current managing agent at top, followed by the current owning organisation (with hint), followed by the managing agents of the current owning organisation" do
it "shows current managing agent at top, followed by the current owning organisation (with hint), followed by the active managing agents of the current owning organisation" do
create(:organisation_relationship, parent_organisation: log_owning_org, child_organisation: inactive_org)
log_owning_org.update!(holds_own_stock: true)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -96,7 +98,8 @@ RSpec.describe Form::Sales::Questions::ManagingOrganisation, type: :model do
}
end
it "shows current managing agent at top, followed by the managing agents of the current owning organisation" do
it "shows current managing agent at top, followed by the active managing agents of the current owning organisation" do
create(:organisation_relationship, parent_organisation: log_owning_org, child_organisation: inactive_org)
log_owning_org.update!(holds_own_stock: false)
expect(question.displayed_answer_options(log, user)).to eq(options)
end

20
spec/models/form/sales/questions/owning_organisation_id_spec.rb

@ -57,6 +57,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
let(:owning_org_1) { create(:organisation, name: "Owning org 1") }
let(:owning_org_2) { create(:organisation, name: "Owning org 2") }
let(:inactive_owning_org) { create(:organisation, name: "Inactive owning org", active: false) }
let(:non_stock_owner) { create(:organisation, name: "Non stock owner", holds_own_stock: false) }
let(:log) { create(:lettings_log, owning_organisation: owning_org_1) }
@ -75,7 +76,8 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
}
end
it "shows user organisation, current owning organisation and the stock owners that hold their stock" do
it "shows user organisation, current owning organisation and the activestock owners that hold their stock" do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: inactive_owning_org)
user.organisation.update!(holds_own_stock: true)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -95,7 +97,8 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: non_stock_owner)
end
it "shows current owning organisation and the stock owners that hold their stock" do
it "shows current owning organisation and the active stock owners that hold their stock" do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: inactive_owning_org)
user.organisation.update!(holds_own_stock: false)
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -204,20 +207,21 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
context "when user is support" do
let(:user) { create(:user, :support, organisation: organisation_1) }
let(:log) { create(:lettings_log, created_by: user) }
let(:non_stock_organisation) { create(:organisation, holds_own_stock: false) }
let(:expected_opts) do
Organisation.where(holds_own_stock: true).each_with_object(options) do |organisation, hsh|
it "shows active orgs where organisation holds own stock" do
non_stock_organisation = create(:organisation, holds_own_stock: false)
inactive_org = create(:organisation, active: false)
expected_opts = Organisation.filter_by_active.where(holds_own_stock: true).each_with_object(options) do |organisation, hsh|
hsh[organisation.id] = organisation.name
hsh
end
end
it "shows orgs where organisation holds own stock" do
expect(question.displayed_answer_options(log, user)).to eq(expected_opts)
expect(question.displayed_answer_options(log, user)).not_to include(non_stock_organisation.id)
expect(question.displayed_answer_options(log, user)).not_to include(inactive_org.id)
expect(question.displayed_answer_options(log, user)).to include(organisation_1.id)
end
context "when an org has recently absorbed other orgs" do

13
spec/models/location_spec.rb

@ -870,6 +870,11 @@ RSpec.describe Location, type: :model do
expect(location.status).to eq(:deactivating_soon)
end
it "returns deactivated if the owning organisation is deactivated" do
location.scheme.owning_organisation.active = false
expect(location.status).to eq(:deactivated)
end
it "returns deactivated if deactivation_date is in the past" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), location:)
location.save!
@ -969,6 +974,9 @@ RSpec.describe Location, type: :model do
end
describe "filter by status" do
let!(:deactivated_organisation) { FactoryBot.create(:organisation, active: false) }
let!(:deactivated_by_organisation_scheme) { FactoryBot.create(:scheme, owning_organisation: deactivated_organisation) }
let!(:deactivated_by_organisation_location) { FactoryBot.create(:location, scheme: deactivated_by_organisation_scheme) }
let!(:incomplete_location) { FactoryBot.create(:location, :incomplete, startdate: Time.zone.local(2022, 4, 1)) }
let!(:incomplete_location_with_nil_confirmed) { FactoryBot.create(:location, :incomplete, startdate: Time.zone.local(2022, 4, 1), confirmed: nil) }
let!(:active_location) { FactoryBot.create(:location, startdate: Time.zone.local(2022, 4, 1)) }
@ -1015,8 +1023,9 @@ RSpec.describe Location, type: :model do
context "when filtering by deactivated status" do
it "returns only deactivated locations" do
expect(described_class.filter_by_status(%w[deactivated]).count).to eq(1)
expect(described_class.filter_by_status(%w[deactivated]).first).to eq(deactivated_location)
expect(described_class.filter_by_status(%w[deactivated]).count).to eq(2)
expect(described_class.filter_by_status(%w[deactivated])).to include(deactivated_location)
expect(described_class.filter_by_status(%w[deactivated])).to include(deactivated_by_organisation_location)
end
end

41
spec/models/organisation_spec.rb

@ -212,8 +212,8 @@ RSpec.describe Organisation, type: :model do
describe "scopes" do
before do
create(:organisation, name: "Joe Bloggs")
create(:organisation, name: "Tom Smith")
create(:organisation, name: "Joe Bloggs", active: false)
create(:organisation, name: "Tom Smith", active: true)
end
context "when searching by name" do
@ -229,5 +229,42 @@ RSpec.describe Organisation, type: :model do
expect(described_class.search_by("joe").count).to eq(1)
end
end
context "when searching by active" do
it "returns only active records" do
results = described_class.filter_by_active
expect(results.count).to eq(1)
expect(results[0].name).to eq("Tom Smith")
end
end
end
describe "status" do
let!(:organisation) { create(:organisation) }
it "returns inactive when organisation inactive" do
organisation.active = false
expect(organisation.status).to be(:deactivated)
end
it "returns active when organisation active" do
organisation.active = true
expect(organisation.status).to be(:active)
end
it "returns merged when organisation merged in the past" do
organisation.merge_date = 1.month.ago
expect(organisation.status).to be(:merged)
end
it "does not return merged when organisation merges in the future" do
organisation.active = true
organisation.merge_date = Time.zone.now + 1.month
expect(organisation.status).to be(:active)
end
end
end

10
spec/models/scheme_spec.rb

@ -112,11 +112,13 @@ RSpec.describe Scheme, type: :model do
end
context "when filtering by status" do
let!(:deactivated_organisation) { FactoryBot.create(:organisation, active: false) }
let!(:incomplete_scheme) { FactoryBot.create(:scheme, :incomplete, service_name: "name") }
let!(:incomplete_scheme_2) { FactoryBot.create(:scheme, :incomplete, service_name: "name") }
let!(:incomplete_scheme_with_nil_confirmed) { FactoryBot.create(:scheme, :incomplete, service_name: "name", confirmed: nil) }
let(:active_scheme) { FactoryBot.create(:scheme) }
let(:active_scheme_2) { FactoryBot.create(:scheme) }
let!(:deactivated_by_organisation_scheme) { FactoryBot.create(:scheme, owning_organisation: deactivated_organisation) }
let(:deactivating_soon_scheme) { FactoryBot.create(:scheme) }
let(:deactivating_soon_scheme_2) { FactoryBot.create(:scheme) }
let(:deactivated_scheme) { FactoryBot.create(:scheme) }
@ -181,9 +183,10 @@ RSpec.describe Scheme, type: :model do
context "when filtering by deactivated status" do
it "returns only deactivated schemes" do
expect(described_class.filter_by_status(%w[deactivated]).count).to eq(2)
expect(described_class.filter_by_status(%w[deactivated]).count).to eq(3)
expect(described_class.filter_by_status(%w[deactivated])).to include(deactivated_scheme)
expect(described_class.filter_by_status(%w[deactivated])).to include(deactivated_scheme_2)
expect(described_class.filter_by_status(%w[deactivated])).to include(deactivated_by_organisation_scheme)
end
end
@ -231,6 +234,11 @@ RSpec.describe Scheme, type: :model do
expect(scheme.status).to eq(:deactivating_soon)
end
it "returns deactivated if the owning organisation is deactivated" do
scheme.owning_organisation.active = false
expect(scheme.status).to eq(:deactivated)
end
it "returns deactivated if deactivation_date is in the past" do
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:)
scheme.reload

66
spec/policies/organisation_policy_spec.rb

@ -0,0 +1,66 @@
require "rails_helper"
RSpec.describe OrganisationPolicy do
subject(:policy) { described_class }
let(:organisation) { FactoryBot.create(:organisation) }
let(:data_provider) { FactoryBot.create(:user, :data_provider) }
let(:data_coordinator) { FactoryBot.create(:user, :data_coordinator) }
let(:support) { FactoryBot.create(:user, :support) }
permissions :deactivate? do
it "does not permit data providers to deactivate an organisation" do
organisation.active = true
expect(policy).not_to permit(data_provider, organisation)
end
it "does not permit data coordinators to deactivate an organisation" do
organisation.active = true
expect(policy).not_to permit(data_coordinator, organisation)
end
it "permits support users to deactivate an active organisation" do
organisation.active = true
expect(policy).to permit(support, organisation)
end
it "does not permit support users to deactivate an inactive organisation" do
organisation.active = false
expect(policy).not_to permit(support, organisation)
end
it "does not permit support users to deactivate a merged organisation" do
organisation.active = true
organisation.merge_date = Time.zone.local(2023, 8, 2)
expect(policy).not_to permit(support, organisation)
end
end
permissions :reactivate? do
it "does not permit data providers to reactivate an organisation" do
organisation.active = false
expect(policy).not_to permit(data_provider, organisation)
end
it "does not permit data coordinators to reactivate an organisation" do
organisation.active = false
expect(policy).not_to permit(data_coordinator, organisation)
end
it "permits support users to reactivate an inactive organisation" do
organisation.active = false
expect(policy).to permit(support, organisation)
end
it "does not permit support users to reactivate an active organisation" do
organisation.active = true
expect(policy).not_to permit(support, organisation)
end
it "does not permit support users to reactivate a merged organisation" do
organisation.active = false
organisation.merge_date = Time.zone.local(2023, 8, 2)
expect(policy).not_to permit(support, organisation)
end
end
end

60
spec/requests/organisation_relationships_controller_spec.rb

@ -18,11 +18,13 @@ RSpec.describe OrganisationRelationshipsController, type: :request do
context "with an organisation that the user belongs to" do
let!(:stock_owner) { FactoryBot.create(:organisation) }
let!(:other_org_stock_owner) { FactoryBot.create(:organisation, name: "Foobar LTD") }
let!(:inactive_stock_owner) { FactoryBot.create(:organisation, name: "Inactive LTD", active: false) }
let!(:other_organisation) { FactoryBot.create(:organisation, name: "Foobar LTD 2") }
before do
FactoryBot.create(:organisation_relationship, child_organisation: organisation, parent_organisation: stock_owner)
FactoryBot.create(:organisation_relationship, child_organisation: other_organisation, parent_organisation: other_org_stock_owner)
FactoryBot.create(:organisation_relationship, child_organisation: organisation, parent_organisation: inactive_stock_owner)
get "/organisations/#{organisation.id}/stock-owners", headers:, params: {}
end
@ -46,11 +48,18 @@ RSpec.describe OrganisationRelationshipsController, type: :request do
expect(page).not_to have_content(other_org_stock_owner.name)
end
it "does not show inactive stock owners" do
expect(page).not_to have_content(inactive_stock_owner.name)
end
it "shows the pagination count" do
expect(page).to have_content("1 total stock owners")
end
context "when adding a stock owner" do
let!(:active_organisation) { FactoryBot.create(:organisation, name: "Active Org", active: true) }
let!(:inactive_organisation) { FactoryBot.create(:organisation, name: "Inactive LTD", active: false) }
before do
get "/organisations/#{organisation.id}/stock-owners/add", headers:, params: {}
end
@ -66,6 +75,27 @@ RSpec.describe OrganisationRelationshipsController, type: :request do
it "shows a cancel button" do
expect(page).to have_link("Cancel", href: "/organisations/#{organisation.id}/stock-owners")
end
it "includes only active organisations as options" do
expect(response.body).to include(active_organisation.name)
expect(response.body).not_to include(inactive_organisation.name)
end
end
context "and current organisation is deactivated" do
before do
organisation.update!(active: false)
get "/organisations/#{organisation.id}/stock-owners", headers:, params: {}
end
it "does not show the add stock owner button" do
expect(page).not_to have_link("Add a stock owner")
end
it "shows a banner" do
expect(page).to have_content("This organisation is deactivated.")
expect(page).to have_content("You cannot add any new stock owners.")
end
end
end
@ -84,11 +114,13 @@ RSpec.describe OrganisationRelationshipsController, type: :request do
context "with an organisation that the user belongs to" do
let!(:managing_agent) { FactoryBot.create(:organisation) }
let!(:other_org_managing_agent) { FactoryBot.create(:organisation, name: "Foobar LTD") }
let!(:inactive_managing_agent) { FactoryBot.create(:organisation, name: "Inactive LTD", active: false) }
let!(:other_organisation) { FactoryBot.create(:organisation, name: "Foobar LTD") }
before do
FactoryBot.create(:organisation_relationship, parent_organisation: organisation, child_organisation: managing_agent)
FactoryBot.create(:organisation_relationship, parent_organisation: other_organisation, child_organisation: other_org_managing_agent)
FactoryBot.create(:organisation_relationship, parent_organisation: organisation, child_organisation: inactive_managing_agent)
get "/organisations/#{organisation.id}/managing-agents", headers:, params: {}
end
@ -112,12 +144,35 @@ RSpec.describe OrganisationRelationshipsController, type: :request do
expect(page).not_to have_content(other_org_managing_agent.name)
end
it "does not show inactive managing-agents" do
expect(page).not_to have_content(inactive_managing_agent.name)
end
it "shows the pagination count" do
expect(page).to have_content("1 total managing agents")
end
context "and current organisation is deactivated" do
before do
organisation.update!(active: false)
get "/organisations/#{organisation.id}/managing-agents", headers:, params: {}
end
it "does not show the add managing agent button" do
expect(page).not_to have_link("Add a managing agent")
end
it "shows a banner" do
expect(page).to have_content("This organisation is deactivated.")
expect(page).to have_content("You cannot add any new managing agents.")
end
end
end
context "when adding a managing agent" do
let!(:active_organisation) { FactoryBot.create(:organisation, name: "Active Org", active: true) }
let!(:inactive_organisation) { FactoryBot.create(:organisation, name: "Inactive LTD", active: false) }
before do
get "/organisations/#{organisation.id}/managing-agents/add", headers:, params: {}
end
@ -125,6 +180,11 @@ RSpec.describe OrganisationRelationshipsController, type: :request do
it "has the correct header" do
expect(response.body).to include("What is the name of your managing agent?")
end
it "includes only active organisations as options" do
expect(response.body).to include(active_organisation.name)
expect(response.body).not_to include(inactive_organisation.name)
end
end
context "with an organisation that are not in scope for the user, i.e. that they do not belong to" do

120
spec/requests/organisations_controller_spec.rb

@ -579,6 +579,32 @@ RSpec.describe OrganisationsController, type: :request do
expect(whodunnit_actor).to be_a(User)
expect(whodunnit_actor.id).to eq(user.id)
end
context "with active parameter true" do
let(:params) do
{
id: organisation.id,
organisation: { active: "true" },
}
end
it "redirects" do
expect(response).to have_http_status(:unauthorized)
end
end
context "with active parameter false" do
let(:params) do
{
id: organisation.id,
organisation: { active: "false" },
}
end
it "redirects" do
expect(response).to have_http_status(:unauthorized)
end
end
end
context "with an organisation that the user does not belong to" do
@ -1407,6 +1433,100 @@ RSpec.describe OrganisationsController, type: :request do
end
end
describe "#update" do
context "with active parameter false" do
let(:params) { { id: organisation.id, organisation: { active: "false" } } }
user_to_update = nil
before do
user_to_update = create(:user, :data_coordinator, organisation:)
patch "/organisations/#{organisation.id}", headers:, params:
end
it "deactivates associated users" do
user_to_update.reload
expect(user_to_update.active).to eq(false)
expect(user_to_update.reactivate_with_organisation).to eq(true)
end
end
context "with active parameter true" do
user_to_reactivate = nil
user_not_to_reactivate = nil
let(:params) do
{
id: organisation.id,
organisation: { active: "true" },
}
end
let(:notify_client) { instance_double(Notifications::Client) }
let(:devise_notify_mailer) { DeviseNotifyMailer.new }
let(:expected_personalisation) do
{
name: user_to_reactivate.name,
email: user_to_reactivate.email,
organisation: organisation.name,
link: include("/account/confirmation?confirmation_token="),
}
end
before do
allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer)
allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client)
allow(notify_client).to receive(:send_email).and_return(true)
user_to_reactivate = create(:user, :data_coordinator, organisation:, active: false, reactivate_with_organisation: true)
user_not_to_reactivate = create(:user, :data_coordinator, organisation:, active: false, reactivate_with_organisation: false)
patch "/organisations/#{organisation.id}", headers:, params:
end
it "reactivates users deactivated with organisation" do
user_to_reactivate.reload
user_not_to_reactivate.reload
expect(user_to_reactivate.active).to eq(true)
expect(user_to_reactivate.reactivate_with_organisation).to eq(false)
expect(user_not_to_reactivate.active).to eq(false)
end
it "sends invitation emails" do
expect(notify_client).to have_received(:send_email).with(email_address: user_to_reactivate.email, template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation: expected_personalisation).once
end
end
end
describe "#deactivate" do
before do
get "/organisations/#{organisation.id}/deactivate", headers:, params: {}
end
it "shows deactivation page with deactivate and cancel buttons for the organisation" do
expect(path).to include("/organisations/#{organisation.id}/deactivate")
expect(page).to have_content(organisation.name)
expect(page).to have_content("Are you sure you want to deactivate this organisation?")
expect(page).to have_button("Deactivate this organisation")
expect(page).to have_link("Cancel", href: "/organisations/#{organisation.id}")
end
end
describe "#reactivate" do
let(:inactive_organisation) { create(:organisation, name: "Inactive org", active: false) }
before do
get "/organisations/#{inactive_organisation.id}/reactivate", headers:, params: {}
end
it "shows reactivation page with reactivate and cancel buttons for the organisation" do
expect(path).to include("/organisations/#{inactive_organisation.id}/reactivate")
expect(page).to have_content(inactive_organisation.name)
expect(page).to have_content("Are you sure you want to reactivate this organisation?")
expect(page).to have_button("Reactivate this organisation")
expect(page).to have_link("Cancel", href: "/organisations/#{inactive_organisation.id}")
end
end
describe "#create" do
let(:name) { " Unique new org name" }
let(:address_line1) { "12 Random Street" }

35
spec/views/locations/show.html.erb_spec.rb

@ -1,9 +1,6 @@
require "rails_helper"
RSpec.describe "locations/show.html.erb" do
context "when a data provider" do
let(:user) { create(:user) }
let(:scheme) do
instance_double(
Scheme,
@ -43,9 +40,13 @@ RSpec.describe "locations/show.html.erb" do
scheme:,
deactivates_in_a_long_time?: false,
is_la_inferred: nil,
deactivated?: false,
)
end
context "when a data provider" do
let(:user) { create(:user) }
it "does not see add a location button" do
assign(:scheme, scheme)
assign(:location, location)
@ -70,4 +71,32 @@ RSpec.describe "locations/show.html.erb" do
expect(rendered).not_to have_content("Change")
end
end
context "when a support user" do
let(:user) { create(:user, role: "support") }
it "sees deactivate scheme location button" do
assign(:scheme, scheme)
assign(:location, location)
allow(view).to receive(:current_user).and_return(user)
render
expect(rendered).to have_content("Deactivate this location")
end
it "does not see deactivate scheme location button when organisation is deactivated" do
user.organisation.active = false
assign(:scheme, scheme)
assign(:location, location)
allow(view).to receive(:current_user).and_return(user)
render
expect(rendered).not_to have_content("Deactivate this location")
end
end
end

14
spec/views/organisations/show.html.erb_spec.rb

@ -113,6 +113,20 @@ RSpec.describe "organisations/show.html.erb" do
expect(fragment).to have_link(text: "View agreement", href: "/organisations/#{organisation_with_dsa.id}/data-sharing-agreement")
end
end
it "shows deactivate button when organisation is active" do
user.organisation.active = true
render
expect(fragment).to have_content("Deactivate this organisation")
expect(fragment).not_to have_content("Reactivate this organisation")
end
it "shows reactivate button when organisation is inactive" do
user.organisation.active = false
render
expect(fragment).not_to have_content("Deactivate this organisation")
expect(fragment).to have_content("Reactivate this organisation")
end
end
context "when not dpo" do

34
spec/views/schemes/show.html.erb_spec.rb

@ -1,10 +1,15 @@
require "rails_helper"
RSpec.describe "schemes/show.html.erb" do
context "when data provider" do
let(:organisation) { create(:organisation, holds_own_stock: true) }
let(:scheme) { create(:scheme, owning_organisation: organisation, confirmed: true) }
before do
create(:location, scheme:, confirmed: true)
end
context "when data provider" do
let(:user) { build(:user, organisation:) }
let(:scheme) { create(:scheme, owning_organisation: user.organisation) }
it "does not render button to deactivate schemes" do
assign(:scheme, scheme)
@ -26,4 +31,29 @@ RSpec.describe "schemes/show.html.erb" do
expect(rendered).not_to have_content("Change")
end
end
context "when support" do
let(:user) { build(:user, organisation:, role: "support") }
it "renders button to deactivate scheme" do
assign(:scheme, scheme)
allow(view).to receive(:current_user).and_return(user)
render
expect(rendered).to have_content("Deactivate this scheme")
end
it "does not render button to deactivate scheme if organisation is deactivated" do
organisation.active = false
assign(:scheme, scheme)
allow(view).to receive(:current_user).and_return(user)
render
expect(rendered).not_to have_content("Deactivate this scheme")
end
end
end

Loading…
Cancel
Save