Browse Source

Merge remote-tracking branch 'origin/CLDC-3740-Replace-you-didnt-answer-with-link' into CLDC-3740-Replace-you-didnt-answer-with-link

CLDC-3740-Replace-you-didnt-answer-with-link
Manny Dinssa 1 month ago
parent
commit
6ebfffe175
  1. 1
      app/controllers/merge_requests_controller.rb
  2. 2
      app/controllers/organisations_controller.rb
  3. 6
      app/controllers/schemes_controller.rb
  4. 1
      app/controllers/users_controller.rb
  5. 8
      app/helpers/filters_helper.rb
  6. 4
      app/helpers/merge_requests_helper.rb
  7. 20
      app/helpers/schemes_helper.rb
  8. 5
      app/models/derived_variables/lettings_log_variables.rb
  9. 5
      app/models/derived_variables/sales_log_variables.rb
  10. 1
      app/models/form/lettings/subsections/household_needs.rb
  11. 8
      app/models/location.rb
  12. 1
      app/models/log.rb
  13. 7
      app/models/merge_request_organisation.rb
  14. 8
      app/models/scheme.rb
  15. 15
      app/policies/location_policy.rb
  16. 15
      app/policies/scheme_policy.rb
  17. 15
      app/views/locations/index.html.erb
  18. 2
      app/views/locations/show.html.erb
  19. 8
      app/views/merge_requests/_notification_banners.html.erb
  20. 2
      app/views/merge_requests/show.html.erb
  21. 6
      app/views/schemes/details.html.erb
  22. 2
      app/views/schemes/show.html.erb
  23. 2
      config/environments/development.rb
  24. 2
      config/environments/review.rb
  25. 4
      config/locales/en.yml
  26. 524
      db/seeds.rb
  27. 2
      spec/components/check_answers_summary_list_card_component_spec.rb
  28. 4
      spec/components/lettings_log_summary_component_spec.rb
  29. 2
      spec/components/sales_log_summary_component_spec.rb
  30. 10
      spec/factories/lettings_log.rb
  31. 20
      spec/factories/organisation.rb
  32. 44
      spec/factories/sales_log.rb
  33. 3
      spec/factories/scheme.rb
  34. 6
      spec/factories/user.rb
  35. 4
      spec/features/lettings_log_spec.rb
  36. 4
      spec/features/sales_log_spec.rb
  37. 11
      spec/features/schemes_spec.rb
  38. 2
      spec/helpers/organisations_helper_spec.rb
  39. 2
      spec/helpers/tab_nav_helper_spec.rb
  40. 2
      spec/models/form_spec.rb
  41. 27
      spec/models/lettings_log_spec.rb
  42. 5
      spec/models/location_spec.rb
  43. 2
      spec/models/organisation_spec.rb
  44. 29
      spec/models/sales_log_spec.rb
  45. 5
      spec/models/scheme_spec.rb
  46. 2
      spec/models/user_spec.rb
  47. 46
      spec/requests/merge_requests_controller_spec.rb
  48. 11
      spec/requests/organisations_controller_spec.rb
  49. 86
      spec/requests/schemes_controller_spec.rb
  50. 25
      spec/requests/users_controller_spec.rb
  51. 4
      spec/services/csv/lettings_log_csv_service_spec.rb
  52. 10
      spec/services/csv/sales_log_csv_service_spec.rb
  53. 2
      spec/services/csv/scheme_csv_service_spec.rb
  54. 17
      spec/services/exports/lettings_log_export_service_spec.rb
  55. 2
      spec/services/exports/organisation_export_service_spec.rb
  56. 4
      spec/services/exports/user_export_service_spec.rb
  57. 28
      spec/services/merge/merge_organisations_service_spec.rb

1
app/controllers/merge_requests_controller.rb

@ -143,6 +143,7 @@ private
if [day, month, year].none?(&:blank?) && Date.valid_date?(year.to_i, month.to_i, day.to_i) if [day, month, year].none?(&:blank?) && Date.valid_date?(year.to_i, month.to_i, day.to_i)
merge_request_params["merge_date"] = Time.zone.local(year.to_i, month.to_i, day.to_i) merge_request_params["merge_date"] = Time.zone.local(year.to_i, month.to_i, day.to_i)
@merge_request.errors.add(:merge_date, :more_than_year_from_today) if Time.zone.local(year.to_i, month.to_i, day.to_i) - 1.year > Time.zone.today
else else
@merge_request.errors.add(:merge_date, :invalid) @merge_request.errors.add(:merge_date, :invalid)
end end

2
app/controllers/organisations_controller.rb

@ -24,7 +24,7 @@ class OrganisationsController < ApplicationController
end end
def schemes def schemes
organisation_schemes = Scheme.visible.where(owning_organisation: [@organisation] + @organisation.parent_organisations) organisation_schemes = Scheme.visible.where(owning_organisation: [@organisation] + @organisation.parent_organisations + @organisation.absorbed_organisations.visible.merged_during_open_collection_period)
@pagy, @schemes = pagy(filter_manager.filtered_schemes(organisation_schemes, search_term, session_filters)) @pagy, @schemes = pagy(filter_manager.filtered_schemes(organisation_schemes, search_term, session_filters))
@searched = search_term.presence @searched = search_term.presence

6
app/controllers/schemes_controller.rb

@ -118,6 +118,10 @@ class SchemesController < ApplicationController
validation_errors scheme_params validation_errors scheme_params
if @scheme.errors.empty? && @scheme.save if @scheme.errors.empty? && @scheme.save
if @scheme.owning_organisation.merge_date.present?
deactivation = SchemeDeactivationPeriod.new(scheme: @scheme, deactivation_date: @scheme.owning_organisation.merge_date)
deactivation.save!(validate: false)
end
redirect_to scheme_primary_client_group_path(@scheme) redirect_to scheme_primary_client_group_path(@scheme)
else else
if @scheme.errors.any? { |error| error.attribute == :owning_organisation } if @scheme.errors.any? { |error| error.attribute == :owning_organisation }
@ -152,7 +156,7 @@ class SchemesController < ApplicationController
flash[:notice] = if scheme_previously_confirmed flash[:notice] = if scheme_previously_confirmed
"#{@scheme.service_name} has been updated." "#{@scheme.service_name} has been updated."
else else
"#{@scheme.service_name} has been created. It does not require helpdesk approval." "#{@scheme.service_name} has been created."
end end
redirect_to scheme_path(@scheme) redirect_to scheme_path(@scheme)
end end

1
app/controllers/users_controller.rb

@ -114,6 +114,7 @@ class UsersController < ApplicationController
validate_attributes validate_attributes
if @user.errors.empty? && @user.save if @user.errors.empty? && @user.save
flash[:notice] = "Invitation sent to #{@user.email}"
redirect_to created_user_redirect_path redirect_to created_user_redirect_path
else else
unless @user.errors[:organisation].empty? unless @user.errors[:organisation].empty?

8
app/helpers/filters_helper.rb

@ -192,9 +192,15 @@ module FiltersHelper
end end
def show_scheme_managing_org_filter?(user) def show_scheme_managing_org_filter?(user)
return true if user.support?
org = user.organisation org = user.organisation
stock_owners = org.stock_owners.count
recently_absorbed_with_stock = org.absorbed_organisations.visible.merged_during_open_collection_period.where(holds_own_stock: true).count
relevant_orgs_count = stock_owners + recently_absorbed_with_stock + (org.holds_own_stock? ? 1 : 0)
user.support? || org.stock_owners.count > 1 || (org.holds_own_stock? && org.stock_owners.count.positive?) relevant_orgs_count > 1
end end
def logs_for_both_needstypes_present?(organisation) def logs_for_both_needstypes_present?(organisation)

4
app/helpers/merge_requests_helper.rb

@ -293,4 +293,8 @@ module MergeRequestsHelper
def any_organisations_share_logs?(organisations, type) def any_organisations_share_logs?(organisations, type)
organisations.any? { |organisation| organisation.send("#{type}_logs").filter_by_managing_organisation(organisations.where.not(id: organisation.id)).exists? } organisations.any? { |organisation| organisation.send("#{type}_logs").filter_by_managing_organisation(organisations.where.not(id: organisation.id)).exists? }
end end
def begin_merge_disabled?(merge_request)
merge_request.status != "ready_to_merge" || merge_request.merge_date.future?
end
end end

20
app/helpers/schemes_helper.rb

@ -20,11 +20,14 @@ module SchemesHelper
end end
def owning_organisation_options(current_user) def owning_organisation_options(current_user)
all_orgs = Organisation.visible.map { |org| OpenStruct.new(id: org.id, name: org.name) } if current_user.support?
user_org = [OpenStruct.new(id: current_user.organisation_id, name: current_user.organisation.name)] Organisation.visible.map { |org| OpenStruct.new(id: org.id, name: org.name) }
stock_owners = current_user.organisation.stock_owners.visible.map { |org| OpenStruct.new(id: org.id, name: org.name) } else
merged_organisations = current_user.organisation.absorbed_organisations.visible.merged_during_open_collection_period.map { |org| OpenStruct.new(id: org.id, name: org.name) } user_org = [current_user.organisation]
current_user.support? ? all_orgs : user_org + stock_owners + merged_organisations stock_owners = current_user.organisation.stock_owners.visible.filter { |org| org.status == :active || (org.status == :merged && org.merge_date >= FormHandler.instance.start_date_of_earliest_open_for_editing_collection_period) }
merged_organisations = current_user.organisation.absorbed_organisations.visible.merged_during_open_collection_period
(user_org + stock_owners + merged_organisations).map { |org| OpenStruct.new(id: org.id, name: org.name) }
end
end end
def null_option def null_option
@ -86,7 +89,12 @@ module SchemesHelper
when :deactivating_soon when :deactivating_soon
"This scheme deactivates on #{scheme.last_deactivation_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Reactivate the scheme to add locations active after this date." "This scheme deactivates on #{scheme.last_deactivation_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Reactivate the scheme to add locations active after this date."
when :deactivated when :deactivated
"This scheme deactivated on #{scheme.last_deactivation_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Reactivate the scheme to add locations active after this date." case scheme.owning_organisation.status
when :active
"This scheme deactivated on #{scheme.last_deactivation_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Reactivate the scheme to add locations active after this date."
when :merged
"This scheme has been deactivated due to #{scheme.owning_organisation.name} merging into #{scheme.owning_organisation.absorbing_organisation.name} on #{scheme.owning_organisation.merge_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Use the after merge organisation for schemes and locations active after this date."
end
end end
end end

5
app/models/derived_variables/lettings_log_variables.rb

@ -124,6 +124,11 @@ module DerivedVariables::LettingsLogVariables
self.nationality_all = nationality_all_group if nationality_uk_or_prefers_not_to_say? self.nationality_all = nationality_all_group if nationality_uk_or_prefers_not_to_say?
if startdate_changed? && !LocalAuthority.active(startdate).where(code: la).exists?
self.la = nil
self.is_la_inferred = false
end
reset_address_fields! if is_supported_housing? reset_address_fields! if is_supported_housing?
end end

5
app/models/derived_variables/sales_log_variables.rb

@ -75,6 +75,11 @@ module DerivedVariables::SalesLogVariables
self.nationality_all = nationality_all_group if nationality_uk_or_prefers_not_to_say? self.nationality_all = nationality_all_group if nationality_uk_or_prefers_not_to_say?
self.nationality_all_buyer2 = nationality_all_buyer2_group if nationality2_uk_or_prefers_not_to_say? self.nationality_all_buyer2 = nationality_all_buyer2_group if nationality2_uk_or_prefers_not_to_say?
if saledate_changed? && !LocalAuthority.active(saledate).where(code: la).exists?
self.la = nil
self.is_la_inferred = false
end
set_encoded_derived_values!(DEPENDENCIES) set_encoded_derived_values!(DEPENDENCIES)
end end

1
app/models/form/lettings/subsections/household_needs.rb

@ -2,7 +2,6 @@ class Form::Lettings::Subsections::HouseholdNeeds < ::Form::Subsection
def initialize(id, hsh, section) def initialize(id, hsh, section)
super super
@id = "household_needs" @id = "household_needs"
@copy_key = "lettings.household_needs.housingneeds_type"
@label = "Household needs" @label = "Household needs"
@depends_on = [{ "non_location_setup_questions_completed?" => true }] @depends_on = [{ "non_location_setup_questions_completed?" => true }]
end end

8
app/models/location.rb

@ -54,13 +54,13 @@ class Location < ApplicationRecord
} }
scope :deactivated, lambda { |date = Time.zone.now| scope :deactivated, lambda { |date = Time.zone.now|
deactivated_by_organisation deactivated_by_organisation(date)
.or(deactivated_directly(date)) .or(deactivated_directly(date))
.or(deactivated_by_scheme(date)) .or(deactivated_by_scheme(date))
} }
scope :deactivated_by_organisation, lambda { scope :deactivated_by_organisation, lambda { |date = Time.zone.now|
merge(Organisation.filter_by_inactive) merge(Organisation.filter_by_inactive.or(Organisation.where("merge_date <= ?", date)))
} }
scope :deactivated_by_scheme, lambda { |date = Time.zone.now| scope :deactivated_by_scheme, lambda { |date = Time.zone.now|
@ -206,7 +206,7 @@ class Location < ApplicationRecord
def status_at(date) def status_at(date)
return :deleted if discarded_at.present? return :deleted if discarded_at.present?
return :incomplete unless confirmed return :incomplete unless confirmed
return :deactivated if scheme.owning_organisation.status_at(date) == :deactivated || return :deactivated if scheme.owning_organisation.status_at(date) == :deactivated || scheme.owning_organisation.status_at(date) == :merged ||
open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date || scheme.status_at(date) == :deactivated open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date || scheme.status_at(date) == :deactivated
return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date || scheme.status_at(date) == :deactivating_soon return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date || scheme.status_at(date) == :deactivating_soon
return :activating_soon if startdate.present? && date < startdate return :activating_soon if startdate.present? && date < startdate

1
app/models/log.rb

@ -111,6 +111,7 @@ class Log < ApplicationRecord
self.town_or_city = nil self.town_or_city = nil
self.county = nil self.county = nil
self.postcode_full = postcode_full_input self.postcode_full = postcode_full_input
process_postcode_changes!
else else
self.uprn = uprn_selection self.uprn = uprn_selection
self.uprn_confirmed = 1 self.uprn_confirmed = 1

7
app/models/merge_request_organisation.rb

@ -29,5 +29,12 @@ private
if merging_organisation_id.blank? || !Organisation.where(id: merging_organisation_id).exists? if merging_organisation_id.blank? || !Organisation.where(id: merging_organisation_id).exists?
merge_request.errors.add(:merging_organisation, I18n.t("validations.merge_request.organisation_not_selected")) merge_request.errors.add(:merging_organisation, I18n.t("validations.merge_request.organisation_not_selected"))
end end
existing_merges = MergeRequestOrganisation.with_merging_organisation(merging_organisation)
if existing_merges.count.positive?
existing_merge_request = existing_merges.first.merge_request
errors.add(:merging_organisation, I18n.t("validations.merge_request.organisation_part_of_another_merge"))
merge_request.errors.add(:merging_organisation, I18n.t("validations.merge_request.organisation_part_of_another_incomplete_merge", organisation: merging_organisation.name, absorbing_organisation: existing_merge_request.absorbing_organisation&.name, merge_date: existing_merge_request.merge_date&.to_fs(:govuk_date)))
end
end end
end end

8
app/models/scheme.rb

@ -57,8 +57,8 @@ class Scheme < ApplicationRecord
.or(deactivated_directly) .or(deactivated_directly)
} }
scope :deactivated_by_organisation, lambda { scope :deactivated_by_organisation, lambda { |date = Time.zone.now|
merge(Organisation.filter_by_inactive) merge(Organisation.filter_by_inactive.or(Organisation.where("merge_date <= ?", date)))
} }
scope :deactivated_directly, lambda { |date = Time.zone.now| scope :deactivated_directly, lambda { |date = Time.zone.now|
@ -96,7 +96,7 @@ class Scheme < ApplicationRecord
scope :active, lambda { |date = Time.zone.now| scope :active, lambda { |date = Time.zone.now|
where.not(id: joins(:scheme_deactivation_periods).reactivating_soon(date).pluck(:id)) where.not(id: joins(:scheme_deactivation_periods).reactivating_soon(date).pluck(:id))
.where.not(id: incomplete.pluck(:id)) .where.not(id: incomplete.pluck(:id))
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id)) .where.not(id: joins(:owning_organisation).deactivated_by_organisation(date).pluck(:id))
.where.not(id: joins(:owning_organisation).joins(:scheme_deactivation_periods).deactivated_directly(date).pluck(:id)) .where.not(id: joins(:owning_organisation).joins(:scheme_deactivation_periods).deactivated_directly(date).pluck(:id))
.where.not(id: activating_soon(date).pluck(:id)) .where.not(id: activating_soon(date).pluck(:id))
} }
@ -314,7 +314,7 @@ class Scheme < ApplicationRecord
def status_at(date) def status_at(date)
return :deleted if discarded_at.present? return :deleted if discarded_at.present?
return :incomplete unless confirmed && locations.confirmed.any? return :incomplete unless confirmed && locations.confirmed.any?
return :deactivated if owning_organisation.status_at(date) == :deactivated || return :deactivated if owning_organisation.status_at(date) == :deactivated || owning_organisation.status_at(date) == :merged ||
(open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date) (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 :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 :reactivating_soon if last_deactivation_before(date)&.reactivation_date.present? && date < last_deactivation_before(date).reactivation_date

15
app/policies/location_policy.rb

@ -16,14 +16,14 @@ class LocationPolicy
if location == Location if location == Location
user.data_coordinator? user.data_coordinator?
else else
user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
end end
def update? def update?
return true if user.support? return true if user.support?
user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
def delete_confirmation? def delete_confirmation?
@ -62,7 +62,7 @@ class LocationPolicy
define_method method_name do define_method method_name do
return true if user.support? return true if user.support?
user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
end end
@ -73,7 +73,7 @@ class LocationPolicy
define_method method_name do define_method method_name do
return true if user.support? return true if user.support?
scheme_owned_by_user_org_or_stock_owner scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
end end
@ -83,8 +83,11 @@ private
location.scheme location.scheme
end end
def scheme_owned_by_user_org_or_stock_owner def scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
scheme&.owning_organisation == user.organisation || user.organisation.stock_owners.exists?(scheme&.owning_organisation_id) scheme_owned_by_user_org = scheme&.owning_organisation == user.organisation
scheme_owned_by_stock_owner = user.organisation.stock_owners.exists?(scheme&.owning_organisation_id)
scheme_owned_by_recently_absorbed_org = user.organisation.absorbed_organisations.visible.merged_during_open_collection_period.exists?(scheme&.owning_organisation_id)
scheme_owned_by_user_org || scheme_owned_by_stock_owner || scheme_owned_by_recently_absorbed_org
end end
def has_any_logs_in_editable_collection_period def has_any_logs_in_editable_collection_period

15
app/policies/scheme_policy.rb

@ -12,7 +12,7 @@ class SchemePolicy
if scheme == Scheme if scheme == Scheme
true true
else else
scheme_owned_by_user_org_or_stock_owner scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
end end
@ -27,7 +27,7 @@ class SchemePolicy
def update? def update?
return true if user.support? return true if user.support?
user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
def changes? def changes?
@ -41,7 +41,7 @@ class SchemePolicy
define_method method_name do define_method method_name do
return true if user.support? return true if user.support?
scheme_owned_by_user_org_or_stock_owner scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
end end
@ -61,7 +61,7 @@ class SchemePolicy
define_method method_name do define_method method_name do
return true if user.support? return true if user.support?
user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner user.data_coordinator? && scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
end end
end end
@ -78,8 +78,11 @@ class SchemePolicy
private private
def scheme_owned_by_user_org_or_stock_owner def scheme_owned_by_user_org_or_stock_owner_or_recently_absorbed_org
scheme&.owning_organisation == user.organisation || user.organisation.stock_owners.exists?(scheme&.owning_organisation_id) scheme_owned_by_user_org = scheme&.owning_organisation == user.organisation
scheme_owned_by_stock_owner = user.organisation.stock_owners.exists?(scheme&.owning_organisation_id)
scheme_owned_by_recently_absorbed_org = user.organisation.absorbed_organisations.visible.merged_during_open_collection_period.exists?(scheme&.owning_organisation_id)
scheme_owned_by_user_org || scheme_owned_by_stock_owner || scheme_owned_by_recently_absorbed_org
end end
def has_any_logs_in_editable_collection_period def has_any_logs_in_editable_collection_period

15
app/views/locations/index.html.erb

@ -56,14 +56,13 @@
<% end %> <% end %>
<% end %> <% end %>
<% if status_hint_message = scheme_status_hint(@scheme) %> <% if LocationPolicy.new(current_user, @scheme.locations.new).create? && [:active, :merged].include?(@scheme.owning_organisation.status) %>
<div class="govuk-hint"> <% if status_hint_message = scheme_status_hint(@scheme) %>
<%= status_hint_message %> <div class="govuk-hint">
</div> <%= status_hint_message %>
<br> </div>
<% end %> <br>
<% end %>
<% if LocationPolicy.new(current_user, @scheme.locations.new).create? %>
<%= govuk_button_to "Add a location", scheme_locations_path(@scheme), method: "post" %> <%= govuk_button_to "Add a location", scheme_locations_path(@scheme), method: "post" %>
<% end %> <% end %>
<br> <br>

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

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

8
app/views/merge_requests/_notification_banners.html.erb

@ -19,3 +19,11 @@
No changes have been made. Try beginning the merge again. No changes have been made. Try beginning the merge again.
<% end %> <% end %>
<% end %> <% end %>
<% if @merge_request.merge_date&.future? %>
<%= govuk_notification_banner(title_text: "Important") do %>
<p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content">
This merge is happening in the future. Wait until the merge date to begin this merge.
</p>
<% end %>
<% end %>

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

@ -12,7 +12,7 @@
</h1> </h1>
<% unless @merge_request.status == "request_merged" || @merge_request.status == "processing" %> <% unless @merge_request.status == "request_merged" || @merge_request.status == "processing" %>
<div class="govuk-button-group"> <div class="govuk-button-group">
<%= govuk_button_link_to "Begin merge", merge_start_confirmation_merge_request_path(@merge_request), disabled: @merge_request.status != "ready_to_merge" %> <%= govuk_button_link_to "Begin merge", merge_start_confirmation_merge_request_path(@merge_request), disabled: begin_merge_disabled?(@merge_request) %>
<%= govuk_button_link_to "Delete merge request", delete_confirmation_merge_request_path(@merge_request), warning: true %> <%= govuk_button_link_to "Delete merge request", delete_confirmation_merge_request_path(@merge_request), warning: true %>
</div> </div>
<% end %> <% end %>

6
app/views/schemes/details.html.erb

@ -49,11 +49,13 @@
:description, :description,
legend: { text: "Is this scheme registered under the Care Standards Act 2000?", size: "m" } %> legend: { text: "Is this scheme registered under the Care Standards Act 2000?", size: "m" } %>
<% if current_user.data_coordinator? && current_user.organisation.stock_owners.count.zero? && !current_user.organisation.has_recent_absorbed_organisations? %> <% scheme_owning_organisation_options = owning_organisation_options(current_user) %>
<% if scheme_owning_organisation_options.count == 1 %>
<%= f.hidden_field :owning_organisation_id, value: current_user.organisation.id %> <%= f.hidden_field :owning_organisation_id, value: current_user.organisation.id %>
<% else %> <% else %>
<%= f.govuk_collection_select :owning_organisation_id, <%= f.govuk_collection_select :owning_organisation_id,
owning_organisation_options(current_user), scheme_owning_organisation_options,
:id, :id,
:name, :name,
label: { text: "Which organisation owns the housing stock for this scheme?", size: "m" }, label: { text: "Which organisation owns the housing stock for this scheme?", size: "m" },

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

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

2
config/environments/development.rb

@ -81,6 +81,8 @@ Rails.application.configure do
# Uncomment if you wish to allow Action Cable access from any origin. # Uncomment if you wish to allow Action Cable access from any origin.
# config.action_cable.disable_request_forgery_protection = true # config.action_cable.disable_request_forgery_protection = true
Faker::Config.locale = "en-GB"
# see https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 # see https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017
config.active_record.yaml_column_permitted_classes = [Time, BigDecimal] config.active_record.yaml_column_permitted_classes = [Time, BigDecimal]

2
config/environments/review.rb

@ -125,6 +125,8 @@ Rails.application.configure do
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
Faker::Config.locale = "en-GB"
# see https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 # see https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017
config.active_record.yaml_column_permitted_classes = [Time, BigDecimal] config.active_record.yaml_column_permitted_classes = [Time, BigDecimal]
end end

4
config/locales/en.yml

@ -183,8 +183,11 @@ en:
merge_date: merge_date:
blank: "Enter a merge date." blank: "Enter a merge date."
invalid: "Enter a valid merge date." invalid: "Enter a valid merge date."
more_than_year_from_today: "The merge date must not be later than a year from today’s date."
existing_absorbing_organisation: existing_absorbing_organisation:
blank: "You must answer absorbing organisation already active?" blank: "You must answer absorbing organisation already active?"
merging_organisation_id:
part_of_another_merge: "Another merge request records %{organisation} as merging into %{absorbing_organisation} on %{merge_date}. Select another organisation or remove this organisation from the other merge request."
notification: notification:
attributes: attributes:
title: title:
@ -370,6 +373,7 @@ en:
during_deactivated_period: "The location is already deactivated during this date, please enter a different date." during_deactivated_period: "The location is already deactivated during this date, please enter a different date."
merge_request: merge_request:
organisation_part_of_another_merge: "This organisation is part of another merge - select a different one." organisation_part_of_another_merge: "This organisation is part of another merge - select a different one."
organisation_part_of_another_incomplete_merge: "Another merge request records %{organisation} as merging into %{absorbing_organisation} on %{merge_date}. Select another organisation or remove this organisation from the other merge request."
organisation_not_selected: "Select an organisation from the search list." organisation_not_selected: "Select an organisation from the search list."
soft_validations: soft_validations:

524
db/seeds.rb

@ -1,434 +1,175 @@
# This file should contain all the record creation needed to seed the database with its default values. # This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
#
# Examples:
#
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
# Character.create(name: 'Luke', movie: movies.first)
# rubocop:disable Rails/Output def find_or_create_user(organisation, email, name, role)
def create_data_protection_confirmation(user) case role
DataProtectionConfirmation.find_or_create_by!( when :data_provider
organisation: user.organisation, FactoryBot.create(:user, :if_unique, :data_provider, organisation:, email:, name:, password: ENV["REVIEW_APP_USER_PASSWORD"])
confirmed: true, when :data_coordinator
data_protection_officer: user, FactoryBot.create(:user, :if_unique, :data_coordinator, organisation:, email:, name:, password: ENV["REVIEW_APP_USER_PASSWORD"])
signed_at: Time.zone.local(2019, 1, 1), when :support
data_protection_officer_email: user.email, FactoryBot.create(:user, :if_unique, :support, organisation:, email:, name:, password: ENV["REVIEW_APP_USER_PASSWORD"])
data_protection_officer_name: user.name, end
)
end end
unless Rails.env.test? unless Rails.env.test?
stock_owner1 = Organisation.find_or_create_by!( if LocalAuthority.count.zero?
name: "Stock Owner 1", la_path = "config/local_authorities_data/initial_local_authorities.csv"
address_line1: "2 Marsham Street", service = Imports::LocalAuthoritiesService.new(path: la_path)
address_line2: "London", service.call
postcode: "SW1P 4DF", end
holds_own_stock: true,
other_stock_owners: "None",
managing_agents_label: "None",
provider_type: "LA",
)
stock_owner2 = Organisation.find_or_create_by!(
name: "Stock Owner 2",
address_line1: "2 Marsham Street",
address_line2: "London",
postcode: "SW1P 4DF",
holds_own_stock: true,
other_stock_owners: "None",
managing_agents_label: "None",
provider_type: "LA",
)
managing_agent1 = Organisation.find_or_create_by!(
name: "Managing Agent 1 (PRP)",
address_line1: "2 Marsham Street",
address_line2: "London",
postcode: "SW1P 4DF",
holds_own_stock: true,
other_stock_owners: "None",
managing_agents_label: "None",
provider_type: "PRP",
)
managing_agent2 = Organisation.find_or_create_by!(
name: "Managing Agent 2",
address_line1: "2 Marsham Street",
address_line2: "London",
postcode: "SW1P 4DF",
holds_own_stock: true,
other_stock_owners: "None",
managing_agents_label: "None",
provider_type: "LA",
)
org = Organisation.find_or_create_by!( if LaRentRange.count.zero?
name: "MHCLG", Dir.glob("config/rent_range_data/*.csv").each do |path|
address_line1: "2 Marsham Street", start_year = File.basename(path, ".csv")
address_line2: "London", service = Imports::RentRangesService.new(start_year:, path:)
postcode: "SW1P 4DF", service.call
holds_own_stock: true,
other_stock_owners: "None",
managing_agents_label: "None",
provider_type: "LA",
) do
info = "Seeded MHCLG Organisation"
if Rails.env.development?
pp info
else
Rails.logger.info info
end end
end end
standalone_owns_stock = Organisation.find_or_create_by!( if LaSaleRange.count.zero?
name: "Standalone Owns Stock 1 Ltd", Dir.glob("config/sale_range_data/*.csv").each do |path|
address_line1: "2 Marsham Street", start_year = File.basename(path, ".csv")
address_line2: "London", service = Imports::SaleRangesService.new(start_year:, path:)
postcode: "SW1P 4DF", service.call
holds_own_stock: true, end
other_stock_owners: "None", end
managing_agents_label: "None",
provider_type: "LA", first_run = Organisation.count.zero?
)
all_rent_periods = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
standalone_no_stock = Organisation.find_or_create_by!( mhclg = FactoryBot.create(
name: "Standalone No Stock 1 Ltd", :organisation,
:if_unique,
name: "MHCLG",
address_line1: "2 Marsham Street", address_line1: "2 Marsham Street",
address_line2: "London", address_line2: "London",
postcode: "SW1P 4DF", postcode: "SW1P 4DF",
holds_own_stock: false, holds_own_stock: true,
other_stock_owners: "None", other_stock_owners: "None",
managing_agents_label: "None", managing_agents_label: "None",
provider_type: "LA", provider_type: "LA",
) housing_registration_no: nil,
rent_periods: all_rent_periods,
User.find_or_create_by!(
name: "Provider Owns Stock",
email: "provider.owner1@example.com",
organisation: standalone_owns_stock,
role: "data_provider",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
User.find_or_create_by!(
name: "Coordinator Owns Stock",
email: "coordinator.owner1@example.com",
organisation: standalone_owns_stock,
role: "data_coordinator",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
User.find_or_create_by!(
name: "Provider No Stock",
email: "provider.nostock@example.com",
organisation: standalone_no_stock,
role: "data_provider",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
User.find_or_create_by!(
name: "Coordinator No Stock",
email: "coordinator.nostock@example.com",
organisation: standalone_no_stock,
role: "data_coordinator",
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
end
User.find_or_create_by!(
name: "Stock owner 1",
email: "stock_owner1_dpo@example.com",
organisation: stock_owner1,
role: "data_coordinator",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
User.find_or_create_by!(
name: "Stock owner 2",
email: "stock_owner2_dpo@example.com",
organisation: stock_owner2,
role: "data_coordinator",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
User.find_or_create_by!(
name: "Managing agent 1",
email: "managing_agent1_dpo@example.com",
organisation: managing_agent1,
role: "data_coordinator",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
User.find_or_create_by!(
name: "Managing agent 2",
email: "managing_agent2_dpo@example.com",
organisation: managing_agent2,
role: "data_coordinator",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
OrganisationRelationship.find_or_create_by!(
parent_organisation: stock_owner1,
child_organisation: org,
)
OrganisationRelationship.find_or_create_by!(
parent_organisation: stock_owner2,
child_organisation: org,
)
OrganisationRelationship.find_or_create_by!(
parent_organisation: org,
child_organisation: managing_agent1,
)
OrganisationRelationship.find_or_create_by!(
parent_organisation: org,
child_organisation: managing_agent2,
) )
if Rails.env.development? || Rails.env.review? if Rails.env.development? || Rails.env.review?
User.find_or_create_by!( stock_owner1 = FactoryBot.create(:organisation, :if_unique, :la, :holds_own_stock, name: "Stock Owner 1", rent_periods: all_rent_periods)
name: "Provider", stock_owner2 = FactoryBot.create(:organisation, :if_unique, :la, :holds_own_stock, name: "Stock Owner 2", rent_periods: all_rent_periods.sample(5))
email: "provider@example.com", managing_agent1 = FactoryBot.create(:organisation, :if_unique, :prp, :holds_own_stock, name: "Managing Agent 1 (PRP)", rent_periods: all_rent_periods)
organisation: org, managing_agent2 = FactoryBot.create(:organisation, :if_unique, :la, :holds_own_stock, name: "Managing Agent 2", rent_periods: all_rent_periods.sample(5))
role: "data_provider", standalone_owns_stock = FactoryBot.create(:organisation, :if_unique, :la, :holds_own_stock, name: "Standalone Owns Stock 1 Ltd", rent_periods: all_rent_periods)
) do |user| standalone_no_stock = FactoryBot.create(:organisation, :if_unique, :la, :does_not_own_stock, name: "Standalone No Stock 1 Ltd", rent_periods: all_rent_periods)
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now other_orgs = FactoryBot.create_list(:organisation, 5, :prp, rent_periods: all_rent_periods.sample(3)) if first_run
end
OrganisationRelationship.find_or_create_by!(
parent_organisation: stock_owner1,
child_organisation: mhclg,
)
OrganisationRelationship.find_or_create_by!(
parent_organisation: stock_owner2,
child_organisation: mhclg,
)
OrganisationRelationship.find_or_create_by!(
parent_organisation: mhclg,
child_organisation: managing_agent1,
)
OrganisationRelationship.find_or_create_by!(
parent_organisation: mhclg,
child_organisation: managing_agent2,
)
User.find_or_create_by!( provider = find_or_create_user(mhclg, "provider@example.com", "Provider", :data_provider)
name: "Coordinator", coordinator = find_or_create_user(mhclg, "coordinator@example.com", "Coordinator", :data_coordinator)
email: "coordinator@example.com", support = find_or_create_user(mhclg, "support@example.com", "Support", :support)
organisation: org,
role: "data_coordinator",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
user.is_dpo = true
create_data_protection_confirmation(user)
end
support_user = User.find_or_create_by!( stock_owner1_user = find_or_create_user(stock_owner1, "stock_owner1_dpo@example.com", "Stock owner 1", :data_coordinator)
name: "Support", stock_owner2_user = find_or_create_user(stock_owner2, "stock_owner2_dpo@example.com", "Stock owner 2", :data_coordinator)
email: "support@example.com",
organisation: org,
role: "support",
is_dpo: true,
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end
pp "Seeded dummy users" managing_agent1_user = find_or_create_user(managing_agent1, "managing_agent1_dpo@example.com", "Managing agent 1", :data_coordinator)
end managing_agent2_user = find_or_create_user(managing_agent2, "managing_agent2_dpo@example.com", "Managing agent 2", :data_coordinator)
if (Rails.env.development? || Rails.env.review?) && SalesLog.count.zero? provider_owner1 = find_or_create_user(standalone_owns_stock, "provider.owner1@example.com", "Provider Owns Stock", :data_provider)
SalesLog.find_or_create_by!( coordinator_owner1 = find_or_create_user(standalone_owns_stock, "coordinator.owner1@example.com", "Coordinator Owns Stock", :data_coordinator)
assigned_to: support_user,
owning_organisation: org,
managing_organisation: org,
saledate: Time.zone.today,
purchid: "1",
ownershipsch: 1,
type: 2,
jointpur: 1,
jointmore: 1,
)
SalesLog.find_or_create_by!( find_or_create_user(standalone_no_stock, "provider.nostock@example.com", "Provider No Stock", :data_provider)
assigned_to: support_user, find_or_create_user(standalone_no_stock, "coordinator.nostock@example.com", "Coordinator No Stock", :data_coordinator)
owning_organisation: org,
managing_organisation: org,
saledate: Time.zone.today,
purchid: "1",
ownershipsch: 2,
type: 9,
jointpur: 1,
jointmore: 1,
)
SalesLog.find_or_create_by!( if Scheme.count.zero?
assigned_to: support_user, beulahside = FactoryBot.create(:scheme, service_name: "Beulahside Care", owning_organisation: mhclg)
owning_organisation: org, abdullah = FactoryBot.create(:scheme, service_name: "Abdullahview Point", owning_organisation: mhclg)
managing_organisation: org,
saledate: Time.zone.today,
purchid: "1",
ownershipsch: 3,
type: 10,
companybuy: 1,
)
pp "Seeded a sales log of each type" FactoryBot.create(:location, scheme: beulahside, name: "Rectory Road", postcode: "CU193AA", location_code: "E09000033", location_admin_district: "Westminster", type_of_unit: 4, mobility_type: "N")
end FactoryBot.create(:location, scheme: beulahside, name: "Smithy Lane", postcode: "DM25ODC", location_code: "E09000033", location_admin_district: "Westminster", type_of_unit: 1, mobility_type: "W")
FactoryBot.create(:location, scheme: abdullah, name: "Smithy Lane", postcode: "YX130WP", location_code: "E09000033", location_admin_district: "Westminster", type_of_unit: 2, mobility_type: "W")
if Rails.env.development? || Rails.env.review? mhclg_scheme = FactoryBot.create(:scheme, :created_now, owning_organisation: mhclg)
dummy_org = Organisation.find_or_create_by!( stock_owner_scheme = FactoryBot.create(:scheme, owning_organisation: stock_owner1)
name: "FooBar LTD",
address_line1: "Higher Kingston",
address_line2: "Yeovil",
postcode: "BA21 4AT",
holds_own_stock: true,
other_stock_owners: "None",
managing_agents_label: "None",
provider_type: "LA",
)
pp "Seeded dummy FooBar LTD organisation" other_schemes = first_run ? other_orgs.sample(3).map { |org| FactoryBot.create(:scheme, owning_organisation: org) } : []
User.find_or_create_by!( [mhclg_scheme, stock_owner_scheme, *other_schemes].each do |scheme|
name: "Dummy user", FactoryBot.create(:location, scheme:)
email: "dummy_org@example.com", end
organisation: dummy_org, [beulahside, mhclg_scheme, *other_schemes].each do |scheme|
role: "data_provider", FactoryBot.create_list(:location, 3, scheme:)
is_dpo: true, end
) do |user|
user.password = ENV["REVIEW_APP_USER_PASSWORD"]
user.confirmed_at = Time.zone.now
create_data_protection_confirmation(user)
end end
end
if (Rails.env.development? || Rails.env.review?) && Scheme.count.zero? other_org_users = first_run ? other_orgs.map { |org| org.users.first } : []
scheme1 = Scheme.create!( users_with_logs = [provider, coordinator, support, stock_owner1_user, stock_owner2_user, managing_agent1_user, managing_agent2_user, provider_owner1, coordinator_owner1, *other_org_users]
service_name: "Beulahside Care",
sensitive: 0,
registered_under_care_act: 1,
support_type: 2,
scheme_type: 4,
intended_stay: "M",
primary_client_group: "O",
has_other_client_group: 1,
secondary_client_group: "H",
owning_organisation: org,
arrangement_type: "D",
confirmed: true,
created_at: Time.zone.now,
)
scheme2 = Scheme.create!( if SalesLog.count.zero?
service_name: "Abdullahview Point", users_with_logs.each do |user|
sensitive: 0, FactoryBot.create(:sales_log, :shared_ownership_setup_complete, assigned_to: user)
registered_under_care_act: 1, FactoryBot.create(:sales_log, :discounted_ownership_setup_complete, assigned_to: user)
support_type: 2, FactoryBot.create(:sales_log, :outright_sale_setup_complete, assigned_to: user) if Time.zone.today < Time.zone.local(2025, 4, 1)
scheme_type: 5, FactoryBot.create(:sales_log, :completed, assigned_to: user)
intended_stay: "S", FactoryBot.create_list(:sales_log, 2, :completed, :ignore_validation_errors, saledate: Time.zone.today - 1.year, assigned_to: user)
primary_client_group: "D",
secondary_client_group: "E",
has_other_client_group: 1,
owning_organisation: org,
arrangement_type: "D",
confirmed: true,
created_at: Time.zone.now,
)
Scheme.create!( next unless FeatureToggle.allow_future_form_use?
service_name: "Caspermouth Center",
sensitive: 1,
registered_under_care_act: 1,
support_type: 4,
scheme_type: 7,
intended_stay: "X",
primary_client_group: "G",
has_other_client_group: 1,
secondary_client_group: "R",
owning_organisation: dummy_org,
arrangement_type: "D",
confirmed: true,
created_at: Time.zone.now,
)
Location.create!( FactoryBot.create(:sales_log, :shared_ownership_setup_complete, saledate: Time.zone.today + 1.year, assigned_to: user)
scheme: scheme1, FactoryBot.create(:sales_log, :discounted_ownership_setup_complete, saledate: Time.zone.today + 1.year, assigned_to: user)
location_code: "E09000033", FactoryBot.create(:sales_log, :completed, saledate: Time.zone.today + 1.year, assigned_to: user)
location_admin_district: "Westminster", end
postcode: "CU193AA",
name: "Rectory Road",
type_of_unit: 4,
units: 1,
mobility_type: "N",
)
Location.create!( FactoryBot.create(:sales_log, :completed, assigned_to: managing_agent1_user, owning_organisation: mhclg)
scheme: scheme1, FactoryBot.create(:sales_log, :completed, assigned_to: provider, owning_organisation: stock_owner1)
location_code: "E09000033",
location_admin_district: "Westminster",
postcode: "DM250DC",
name: "Smithy Lane",
type_of_unit: 1,
units: 1,
mobility_type: "W",
)
Location.create!(
scheme: scheme2,
location_code: "E09000033",
location_admin_district: "Westminster",
postcode: "YX130WP",
name: "Smithy Lane",
type_of_unit: 2,
units: 1,
mobility_type: "W",
)
pp "Seeded dummy schemes"
end
if LocalAuthority.count.zero?
la_path = "config/local_authorities_data/initial_local_authorities.csv"
service = Imports::LocalAuthoritiesService.new(path: la_path)
service.call
end
if (Rails.env.development? || Rails.env.review?) && LocalAuthorityLink.count.zero?
links_data_paths = ["config/local_authorities_data/local_authority_links_2023.csv", "config/local_authorities_data/local_authority_links_2022.csv"]
links_data_paths.each do |path|
service = Imports::LocalAuthorityLinksService.new(path:)
service.call
end end
pp "Seeded local authority links" if LettingsLog.count.zero?
end users_with_logs.each do |user|
FactoryBot.create(:lettings_log, :setup_completed, assigned_to: user)
if LaRentRange.count.zero? FactoryBot.create(:lettings_log, :completed, assigned_to: user)
Dir.glob("config/rent_range_data/*.csv").each do |path| if user.organisation.owned_schemes.any?
start_year = File.basename(path, ".csv") scheme = user.organisation.owned_schemes.first
service = Imports::RentRangesService.new(start_year:, path:) FactoryBot.create(:lettings_log, :setup_completed, :sh, scheme:, location: scheme.locations.first, assigned_to: user)
service.call end
FactoryBot.create_list(:lettings_log, 2, :completed, :ignore_validation_errors, startdate: Time.zone.today - 1.year, assigned_to: user)
next unless FeatureToggle.allow_future_form_use?
FactoryBot.create(:lettings_log, :setup_completed, startdate: Time.zone.today + 1.year, assigned_to: user)
FactoryBot.create(:lettings_log, :completed, startdate: Time.zone.today + 1.year, assigned_to: user)
if user.organisation.owned_schemes.any?
scheme = user.organisation.owned_schemes.first
FactoryBot.create(:lettings_log, :setup_completed, :sh, scheme:, location: scheme.locations.first, startdate: Time.zone.today + 1.year, assigned_to: user)
end
end
FactoryBot.create(:lettings_log, :completed, assigned_to: managing_agent1_user, owning_organisation: mhclg)
FactoryBot.create(:lettings_log, :completed, assigned_to: provider, owning_organisation: stock_owner1)
end end
end
if LaSaleRange.count.zero? if LocalAuthorityLink.count.zero?
Dir.glob("config/sale_range_data/*.csv").each do |path| links_data_paths = ["config/local_authorities_data/local_authority_links_2023.csv", "config/local_authorities_data/local_authority_links_2022.csv"]
start_year = File.basename(path, ".csv") links_data_paths.each do |path|
service = Imports::SaleRangesService.new(start_year:, path:) service = Imports::LocalAuthorityLinksService.new(path:)
service.call service.call
end
end end
end end
end end
@ -438,4 +179,3 @@ if LocalAuthority.count.zero?
service = Imports::LocalAuthoritiesService.new(path:) service = Imports::LocalAuthoritiesService.new(path:)
service.call service.call
end end
# rubocop:enable Rails/Output

2
spec/components/check_answers_summary_list_card_component_spec.rb

@ -6,7 +6,7 @@ RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
let(:rendered) { render_inline(component) } let(:rendered) { render_inline(component) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:log) { create(:lettings_log, :completed, age2: 99, retirement_value_check: 1) } let(:log) { create(:lettings_log, :completed, sex1: "F", age2: 99, retirement_value_check: 1) }
let(:subsection_id) { "household_characteristics" } let(:subsection_id) { "household_characteristics" }
let(:subsection) { log.form.get_subsection(subsection_id) } let(:subsection) { log.form.get_subsection(subsection_id) }
let(:questions) { subsection.applicable_questions(log) } let(:questions) { subsection.applicable_questions(log) }

4
spec/components/lettings_log_summary_component_spec.rb

@ -3,9 +3,11 @@ require "rails_helper"
RSpec.describe LettingsLogSummaryComponent, type: :component do RSpec.describe LettingsLogSummaryComponent, type: :component do
let(:support_user) { FactoryBot.create(:user, :support) } let(:support_user) { FactoryBot.create(:user, :support) }
let(:coordinator_user) { FactoryBot.create(:user) } let(:coordinator_user) { FactoryBot.create(:user) }
let(:organisation) { create(:organisation, name: "MHCLG") }
let(:log_user) { create(:user, name: "Danny Rojas", organisation:) }
let(:propcode) { "P3647" } let(:propcode) { "P3647" }
let(:tenancycode) { "T62863" } let(:tenancycode) { "T62863" }
let(:lettings_log) { FactoryBot.create(:lettings_log, needstype: 1, tenancycode:, propcode:, startdate: Time.zone.today) } let(:lettings_log) { FactoryBot.create(:lettings_log, assigned_to: log_user, needstype: 1, tenancycode:, propcode:, startdate: Time.zone.today) }
context "when rendering lettings log for a support user" do context "when rendering lettings log for a support user" do
it "shows the log summary with organisational relationships" do it "shows the log summary with organisational relationships" do

2
spec/components/sales_log_summary_component_spec.rb

@ -16,7 +16,7 @@ RSpec.describe SalesLogSummaryComponent, type: :component do
it "shows the log summary with organisational relationships" do it "shows the log summary with organisational relationships" do
result = render_inline(described_class.new(current_user: support_user, log: sales_log)) result = render_inline(described_class.new(current_user: support_user, log: sales_log))
expect(result).to have_content("Owned by\n MHCLG") expect(result).to have_content("Owned by\n #{sales_log.owning_organisation.name}")
expect(result).not_to have_content("Managed by") expect(result).not_to have_content("Managed by")
end end
end end

10
spec/factories/lettings_log.rb

@ -56,8 +56,8 @@ FactoryBot.define do
status { 2 } status { 2 }
tenancycode { Faker::Name.initials(number: 10) } tenancycode { Faker::Name.initials(number: 10) }
age1_known { 0 } age1_known { 0 }
age1 { 35 } age1 { Faker::Number.within(range: 25..45) }
sex1 { "F" } sex1 { %w[F M X R].sample }
ethnic_group { 0 } ethnic_group { 0 }
ethnic { 2 } ethnic { 2 }
national { 13 } national { 13 }
@ -67,8 +67,8 @@ FactoryBot.define do
relat2 { "P" } relat2 { "P" }
age2_known { 0 } age2_known { 0 }
details_known_2 { 0 } details_known_2 { 0 }
age2 { 32 } age2 { Faker::Number.within(range: 25..45) }
sex2 { "M" } sex2 { %w[F M X R].sample }
ecstat2 { 6 } ecstat2 { 6 }
homeless { 1 } homeless { 1 }
underoccupation_benefitcap { 0 } underoccupation_benefitcap { 0 }
@ -163,7 +163,7 @@ FactoryBot.define do
uprn_known { 0 } uprn_known { 0 }
joint { 3 } joint { 3 }
address_line1 { "Address line 1" } address_line1 { "Address line 1" }
town_or_city { "London" } town_or_city { Faker::Address.city }
ppcodenk { 1 } ppcodenk { 1 }
tshortfall_known { 1 } tshortfall_known { 1 }
after(:build) do |log, _evaluator| after(:build) do |log, _evaluator|

20
spec/factories/organisation.rb

@ -1,11 +1,11 @@
FactoryBot.define do FactoryBot.define do
factory :organisation do factory :organisation do
name { "MHCLG" } name { Faker::Company.name }
address_line1 { "2 Marsham Street" } address_line1 { Faker::Address.street_address }
address_line2 { "London" } address_line2 { Faker::Address.city }
provider_type { "LA" } provider_type { "LA" }
housing_registration_no { "1234" } housing_registration_no { rand(99_999).to_s }
postcode { "SW1P 4DF" } postcode { Faker::Address.postcode }
created_at { Time.zone.now } created_at { Time.zone.now }
updated_at { Time.zone.now } updated_at { Time.zone.now }
holds_own_stock { true } holds_own_stock { true }
@ -41,7 +41,13 @@ FactoryBot.define do
trait :prp do trait :prp do
provider_type { "PRP" } provider_type { "PRP" }
end end
trait :la do
provider_type { "LA" }
end
trait :holds_own_stock do
holds_own_stock { true }
end
trait :does_not_own_stock do trait :does_not_own_stock do
holds_own_stock { false } holds_own_stock { false }
end end
@ -53,6 +59,10 @@ FactoryBot.define do
data_protection_confirmation { nil } data_protection_confirmation { nil }
end end
trait :if_unique do
initialize_with { Organisation.find_or_create_by(name:) }
end
end end
factory :organisation_rent_period do factory :organisation_rent_period do

44
spec/factories/sales_log.rb

@ -5,7 +5,7 @@ FactoryBot.define do
created_by { assigned_to } created_by { assigned_to }
owning_organisation { assigned_to.organisation } owning_organisation { assigned_to.organisation }
managing_organisation { owning_organisation } managing_organisation { assigned_to.organisation }
created_at { Time.zone.now } created_at { Time.zone.now }
updated_at { Time.zone.now } updated_at { Time.zone.now }
trait :in_progress do trait :in_progress do
@ -32,6 +32,17 @@ FactoryBot.define do
jointpur { 2 } jointpur { 2 }
noint { 2 } noint { 2 }
privacynotice { 1 } privacynotice { 1 }
purchid { rand(999_999_999).to_s }
end
trait :discounted_ownership_setup_complete do
saledate_today
ownershipsch { 2 }
type { 9 }
jointpur { 1 }
jointmore { 1 }
noint { 2 }
privacynotice { 1 }
purchid { rand(999_999_999).to_s }
end end
trait :outright_sale_setup_complete do trait :outright_sale_setup_complete do
saledate_today saledate_today
@ -67,14 +78,14 @@ FactoryBot.define do
noint { 2 } noint { 2 }
privacynotice { 1 } privacynotice { 1 }
age1_known { 0 } age1_known { 0 }
age1 { 30 } age1 { Faker::Number.within(range: 27..45) }
sex1 { "X" } sex1 { %w[F M X R].sample }
national { 18 } national { 18 }
buy1livein { 1 } buy1livein { 1 }
relat2 { "P" } relat2 { "P" }
proptype { 1 } proptype { 1 }
age2_known { 0 } age2_known { 0 }
age2 { 35 } age2 { Faker::Number.within(range: 25..45) }
builtype { 1 } builtype { 1 }
ethnic { 3 } ethnic { 3 }
ethnic_group { 17 } ethnic_group { 17 }
@ -104,16 +115,16 @@ FactoryBot.define do
inc2mort { 1 } inc2mort { 1 }
uprn_known { 0 } uprn_known { 0 }
address_line1 { "Address line 1" } address_line1 { "Address line 1" }
town_or_city { "Town or city" } town_or_city { Faker::Address.city }
la_known { 1 } la_known { 1 }
la { "E09000003" } la { "E09000003" }
savingsnk { 1 } savingsnk { 1 }
prevown { 1 } prevown { 1 }
prevshared { 2 } prevshared { 2 }
sex3 { "X" } sex3 { %w[F M X R].sample }
sex4 { "X" } sex4 { %w[F M X R].sample }
sex5 { "X" } sex5 { %w[F M X R].sample }
sex6 { "X" } sex6 { %w[F M X R].sample }
mortgage { 20_000 } mortgage { 20_000 }
ecstat3 { 9 } ecstat3 { 9 }
ecstat4 { 3 } ecstat4 { 3 }
@ -122,6 +133,7 @@ FactoryBot.define do
disabled { 1 } disabled { 1 }
deposit { 80_000 } deposit { 80_000 }
value { 110_000 } value { 110_000 }
value_value_check { 0 }
grant { 10_000 } grant { 10_000 }
proplen { 10 } proplen { 10 }
pregyrha { 1 } pregyrha { 1 }
@ -161,6 +173,13 @@ FactoryBot.define do
log.uprn = "10033558653" log.uprn = "10033558653"
log.uprn_selection = 1 log.uprn_selection = 1
end end
if log.saledate >= Time.zone.local(2025, 4, 1)
log.relat2 = "X" if log.relat2 == "C"
log.relat3 = "X" if log.relat3 == "C"
log.relat4 = "X" if log.relat4 == "C"
log.relat5 = "X" if log.relat5 == "C"
log.relat6 = "X" if log.relat6 == "C"
end
end end
end end
trait :with_uprn do trait :with_uprn do
@ -174,5 +193,12 @@ FactoryBot.define do
trait :imported do trait :imported do
old_id { Random.hex } old_id { Random.hex }
end end
trait :ignore_validation_errors do
to_create do |instance|
instance.valid?
instance.errors.clear
instance.save!(validate: false)
end
end
end end
end end

3
spec/factories/scheme.rb

@ -41,5 +41,8 @@ FactoryBot.define do
support_type { 2 } support_type { 2 }
intended_stay { "M" } intended_stay { "M" }
end end
trait :created_now do
created_at { Time.zone.now }
end
end end
end end

6
spec/factories/user.rb

@ -1,7 +1,7 @@
FactoryBot.define do FactoryBot.define do
factory :user do factory :user do
sequence(:email) { "test#{SecureRandom.hex}@example.com" } sequence(:email) { "test#{SecureRandom.hex}@example.com" }
name { "Danny Rojas" } name { Faker::Name.name }
password { "pAssword1" } password { "pAssword1" }
organisation { association :organisation, with_dsa: is_dpo ? false : true } organisation { association :organisation, with_dsa: is_dpo ? false : true }
role { "data_provider" } role { "data_provider" }
@ -40,5 +40,9 @@ FactoryBot.define do
) )
end end
end end
trait :if_unique do
initialize_with { User.find_or_create_by(email:) }
end
end end
end end

4
spec/features/lettings_log_spec.rb

@ -276,7 +276,7 @@ RSpec.describe "Lettings Log Features" do
expect(breadcrumbs.length).to eq 3 expect(breadcrumbs.length).to eq 3
expect(breadcrumbs[0].text).to eq "Home" expect(breadcrumbs[0].text).to eq "Home"
expect(breadcrumbs[0][:href]).to eq root_path expect(breadcrumbs[0][:href]).to eq root_path
expect(breadcrumbs[1].text).to eq "Lettings logs (MHCLG)" expect(breadcrumbs[1].text).to eq "Lettings logs (#{lettings_log.owning_organisation.name})"
expect(breadcrumbs[1][:href]).to eq lettings_logs_organisation_path(lettings_log.owning_organisation) expect(breadcrumbs[1][:href]).to eq lettings_logs_organisation_path(lettings_log.owning_organisation)
expect(breadcrumbs[2].text).to eq "Log #{lettings_log.id}" expect(breadcrumbs[2].text).to eq "Log #{lettings_log.id}"
expect(breadcrumbs[2][:href]).to eq lettings_log_path(lettings_log) expect(breadcrumbs[2][:href]).to eq lettings_log_path(lettings_log)
@ -292,7 +292,7 @@ RSpec.describe "Lettings Log Features" do
expect(breadcrumbs.length).to eq 3 expect(breadcrumbs.length).to eq 3
expect(breadcrumbs[0].text).to eq "Home" expect(breadcrumbs[0].text).to eq "Home"
expect(breadcrumbs[0][:href]).to eq root_path expect(breadcrumbs[0][:href]).to eq root_path
expect(breadcrumbs[1].text).to eq "Lettings logs (MHCLG)" expect(breadcrumbs[1].text).to eq "Lettings logs (#{lettings_log.owning_organisation.name})"
expect(breadcrumbs[1][:href]).to eq lettings_logs_organisation_path(lettings_log.owning_organisation) expect(breadcrumbs[1][:href]).to eq lettings_logs_organisation_path(lettings_log.owning_organisation)
expect(breadcrumbs[2].text).to eq "Log #{lettings_log.id}" expect(breadcrumbs[2].text).to eq "Log #{lettings_log.id}"
expect(breadcrumbs[2][:href]).to eq lettings_log_path(lettings_log) expect(breadcrumbs[2][:href]).to eq lettings_log_path(lettings_log)

4
spec/features/sales_log_spec.rb

@ -259,7 +259,7 @@ RSpec.describe "Sales Log Features" do
expect(breadcrumbs.length).to eq 3 expect(breadcrumbs.length).to eq 3
expect(breadcrumbs[0].text).to eq "Home" expect(breadcrumbs[0].text).to eq "Home"
expect(breadcrumbs[0][:href]).to eq root_path expect(breadcrumbs[0][:href]).to eq root_path
expect(breadcrumbs[1].text).to eq "Sales logs (MHCLG)" expect(breadcrumbs[1].text).to eq "Sales logs (#{sales_log.owning_organisation.name})"
expect(breadcrumbs[1][:href]).to eq sales_logs_organisation_path(sales_log.owning_organisation) expect(breadcrumbs[1][:href]).to eq sales_logs_organisation_path(sales_log.owning_organisation)
expect(breadcrumbs[2].text).to eq "Log #{sales_log.id}" expect(breadcrumbs[2].text).to eq "Log #{sales_log.id}"
expect(breadcrumbs[2][:href]).to eq sales_log_path(sales_log.id) expect(breadcrumbs[2][:href]).to eq sales_log_path(sales_log.id)
@ -273,7 +273,7 @@ RSpec.describe "Sales Log Features" do
expect(breadcrumbs.length).to eq 3 expect(breadcrumbs.length).to eq 3
expect(breadcrumbs[0].text).to eq "Home" expect(breadcrumbs[0].text).to eq "Home"
expect(breadcrumbs[0][:href]).to eq root_path expect(breadcrumbs[0][:href]).to eq root_path
expect(breadcrumbs[1].text).to eq "Sales logs (MHCLG)" expect(breadcrumbs[1].text).to eq "Sales logs (#{sales_log.owning_organisation.name})"
expect(breadcrumbs[1][:href]).to eq sales_logs_organisation_path(sales_log.owning_organisation) expect(breadcrumbs[1][:href]).to eq sales_logs_organisation_path(sales_log.owning_organisation)
expect(breadcrumbs[2].text).to eq "Log #{sales_log.id}" expect(breadcrumbs[2].text).to eq "Log #{sales_log.id}"
expect(breadcrumbs[2][:href]).to eq sales_log_path(sales_log.id) expect(breadcrumbs[2][:href]).to eq sales_log_path(sales_log.id)

11
spec/features/schemes_spec.rb

@ -5,9 +5,10 @@ RSpec.describe "Schemes scheme Features" do
include SchemesHelpers include SchemesHelpers
context "when viewing list of schemes" do context "when viewing list of schemes" do
context "when I am signed as a coordinator user and there are schemes in the database" do context "when I am signed as a coordinator user and there are schemes in the database" do
let!(:user) { FactoryBot.create(:user, :data_coordinator, last_sign_in_at: Time.zone.now) } let(:organisation) { FactoryBot.create(:organisation, name: "MHCLG") }
let!(:schemes) { FactoryBot.create_list(:scheme, 5, owning_organisation: user.organisation) } let!(:user) { FactoryBot.create(:user, :data_coordinator, organisation:, last_sign_in_at: Time.zone.now) }
let!(:scheme_to_search) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } let!(:schemes) { FactoryBot.create_list(:scheme, 5, owning_organisation: organisation) }
let!(:scheme_to_search) { FactoryBot.create(:scheme, owning_organisation: organisation) }
before do before do
Timecop.freeze(Time.zone.local(2024, 3, 1)) Timecop.freeze(Time.zone.local(2024, 3, 1))
@ -225,7 +226,7 @@ RSpec.describe "Schemes scheme Features" do
end end
it "shows list of links to the organisation's schemes" do it "shows list of links to the organisation's schemes" do
click_on("Schemes (MHCLG)") click_on("Schemes (#{user.organisation.name})")
same_organisation_schemes.each do |scheme| same_organisation_schemes.each do |scheme|
expect(page).to have_link(scheme.service_name) expect(page).to have_link(scheme.service_name)
expect(page).to have_content(scheme.id_to_display) expect(page).to have_content(scheme.id_to_display)
@ -677,7 +678,7 @@ RSpec.describe "Schemes scheme Features" do
end end
it "adds scheme to the list of schemes" do it "adds scheme to the list of schemes" do
expect(page).to have_content "#{scheme.service_name} has been created. It does not require helpdesk approval." expect(page).to have_content "#{scheme.service_name} has been created."
click_link "Schemes" click_link "Schemes"
expect(page).to have_content "Supported housing schemes" expect(page).to have_content "Supported housing schemes"
expect(page).to have_content scheme.id_to_display expect(page).to have_content scheme.id_to_display

2
spec/helpers/organisations_helper_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe OrganisationsHelper do RSpec.describe OrganisationsHelper do
include TagHelper include TagHelper
describe "display_organisation_attributes" do describe "display_organisation_attributes" do
let(:organisation) { create(:organisation) } let(:organisation) { create(:organisation, :la, :holds_own_stock, address_line1: "2 Marsham Street", address_line2: "London", postcode: "SW1P 4DF", housing_registration_no: 1234, organisation_rent_periods: []) }
it "has the correct values" do it "has the correct values" do
expect(display_organisation_attributes(organisation)).to eq( expect(display_organisation_attributes(organisation)).to eq(

2
spec/helpers/tab_nav_helper_spec.rb

@ -15,7 +15,7 @@ RSpec.describe TabNavHelper do
describe "#org_cell" do describe "#org_cell" do
it "returns the users org name and role separated by a newline character" do it "returns the users org name and role separated by a newline character" do
expected_html = "MHCLG\n<span class=\"app-!-colour-muted\">Data provider</span>" expected_html = "#{organisation.name}\n<span class=\"app-!-colour-muted\">Data provider</span>"
expect(org_cell(current_user)).to match(expected_html) expect(org_cell(current_user)).to match(expected_html)
end end
end end

2
spec/models/form_spec.rb

@ -329,7 +329,7 @@ RSpec.describe Form, type: :model do
end end
context "when a value is changed such that a radio and free input questions are no longer routed to" do context "when a value is changed such that a radio and free input questions are no longer routed to" do
let(:log) { FactoryBot.create(:lettings_log, :completed, startdate: now) } let(:log) { FactoryBot.create(:lettings_log, :completed, startdate: now, hhmemb: 2, details_known_2: 0, sex2: "M", relat2: "P", age2_known: 0, age2: 32, ecstat2: 6) }
it "all attributes relating to that checkbox question are cleared" do it "all attributes relating to that checkbox question are cleared" do
expect(log.hhmemb).to be 2 expect(log.hhmemb).to be 2

27
spec/models/lettings_log_spec.rb

@ -809,6 +809,21 @@ RSpec.describe LettingsLog do
expect { lettings_log.update!(nationality_all_group: nil, declaration: 1) }.not_to change(lettings_log, :nationality_all) expect { lettings_log.update!(nationality_all_group: nil, declaration: 1) }.not_to change(lettings_log, :nationality_all)
end end
end end
context "when form year changes and LA is no longer active" do
before do
LocalAuthority.find_by(code: "E08000003").update!(end_date: Time.zone.today)
end
it "removes the LA" do
lettings_log.update!(startdate: Time.zone.yesterday, la: "E08000003")
expect(lettings_log.reload.la).to eq("E08000003")
lettings_log.update!(startdate: Time.zone.tomorrow)
expect(lettings_log.reload.la).to eq(nil)
expect(lettings_log.reload.is_la_inferred).to eq(false)
end
end
end end
describe "optional fields" do describe "optional fields" do
@ -2006,5 +2021,17 @@ RSpec.describe LettingsLog do
end end
end end
end end
describe "#process_address_change!" do
context "when uprn_selection is uprn_not_listed" do
let(:log) { build(:lettings_log, uprn_selection: "uprn_not_listed", address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "sets log address fields, including postcode known" do
expect { log.process_address_change! }.to change(log, :address_line1).from(nil).to("Address line 1")
.and change(log, :postcode_full).from(nil).to("AA1 1AA")
.and change(log, :postcode_known).from(nil).to(1)
end
end
end
end end
# rubocop:enable RSpec/MessageChain # rubocop:enable RSpec/MessageChain

5
spec/models/location_spec.rb

@ -929,6 +929,11 @@ RSpec.describe Location, type: :model do
expect(location.status).to eq(:deactivated) expect(location.status).to eq(:deactivated)
end end
it "returns deactivated if the owning organisation has been merged" do
location.scheme.owning_organisation.merge_date = 2.days.ago
expect(location.status).to eq(:deactivated)
end
it "returns deactivated if deactivation_date is in the past" do it "returns deactivated if deactivation_date is in the past" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.yesterday, location:) FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.yesterday, location:)
location.save! location.save!

2
spec/models/organisation_spec.rb

@ -207,7 +207,7 @@ RSpec.describe Organisation, type: :model do
end end
describe "paper trail" do describe "paper trail" do
let(:organisation) { create(:organisation) } let(:organisation) { create(:organisation, name: "MHCLG") }
it "creates a record of changes to a log" do it "creates a record of changes to a log" do
expect { organisation.update!(name: "new test name") }.to change(organisation.versions, :count).by(1) expect { organisation.update!(name: "new test name") }.to change(organisation.versions, :count).by(1)

29
spec/models/sales_log_spec.rb

@ -978,5 +978,34 @@ RSpec.describe SalesLog, type: :model do
end end
end end
end end
context "when form year changes and LA is no longer active" do
let!(:sales_log) { create(:sales_log) }
before do
LocalAuthority.find_by(code: "E08000003").update!(end_date: Time.zone.today)
end
it "removes the LA" do
sales_log.update!(saledate: Time.zone.yesterday, la: "E08000003")
expect(sales_log.reload.la).to eq("E08000003")
sales_log.update!(saledate: Time.zone.tomorrow)
expect(sales_log.reload.la).to eq(nil)
expect(sales_log.reload.is_la_inferred).to eq(false)
end
end
describe "#process_address_change!" do
context "when uprn_selection is uprn_not_listed" do
let(:log) { build(:sales_log, uprn_selection: "uprn_not_listed", address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "sets log address fields, including postcode known" do
expect { log.process_address_change! }.to change(log, :address_line1).from(nil).to("Address line 1")
.and change(log, :postcode_full).from(nil).to("AA1 1AA")
.and change(log, :pcodenk).from(nil).to(0)
end
end
end
end end
# rubocop:enable RSpec/MessageChain # rubocop:enable RSpec/MessageChain

5
spec/models/scheme_spec.rb

@ -363,6 +363,11 @@ RSpec.describe Scheme, type: :model do
expect(scheme.status).to eq(:deactivated) expect(scheme.status).to eq(:deactivated)
end end
it "returns deactivated if the owning organisation has been merged" do
scheme.owning_organisation.merge_date = 2.days.ago
expect(scheme.status).to eq(:deactivated)
end
it "returns deactivated if deactivation_date is in the past" do it "returns deactivated if deactivation_date is in the past" do
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.yesterday, scheme:) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.yesterday, scheme:)
scheme.reload scheme.reload

2
spec/models/user_spec.rb

@ -380,7 +380,7 @@ RSpec.describe User, type: :model do
end end
describe "paper trail" do describe "paper trail" do
let(:user) { create(:user) } let(:user) { create(:user, name: "Danny Rojas") }
it "creates a record of changes to a log" do it "creates a record of changes to a log" do
expect { user.update!(name: "new test name") }.to change(user.versions, :count).by(1) expect { user.update!(name: "new test name") }.to change(user.versions, :count).by(1)

46
spec/requests/merge_requests_controller_spec.rb

@ -49,7 +49,7 @@ RSpec.describe MergeRequestsController, type: :request do
end end
it "shows the correct content" do it "shows the correct content" do
expect(page).to have_content("Which organisations are merging into MHCLG?") expect(page).to have_content("Which organisations are merging into #{organisation.name}?")
end end
end end
end end
@ -64,7 +64,7 @@ RSpec.describe MergeRequestsController, type: :request do
it "adds merging organisation to the page" do it "adds merging organisation to the page" do
merge_request.reload merge_request.reload
expect(page).to have_content("MHCLG") expect(page).to have_content(organisation.name)
expect(page).to have_content("Other Test Org") expect(page).to have_content("Other Test Org")
expect(page).to have_link("Remove") expect(page).to have_link("Remove")
end end
@ -84,6 +84,22 @@ RSpec.describe MergeRequestsController, type: :request do
end end
end end
context "when the user updates merge request with organisation that is already part of another merge" do
let(:another_organisation) { create(:organisation) }
let(:other_merge_request) { create(:merge_request, merge_date: Time.zone.local(2022, 5, 4)) }
let(:params) { { merge_request: { merging_organisation: another_organisation.id, new_merging_org_ids: [] } } }
before do
MergeRequestOrganisation.create!(merge_request_id: other_merge_request.id, merging_organisation_id: another_organisation.id)
patch "/merge-request/#{merge_request.id}/merging-organisations", headers:, params:
end
it "displays the page with an error message" do
expect(response).to have_http_status(:unprocessable_entity)
expect(page).to have_content("Another merge request records #{another_organisation.name} as merging into #{other_merge_request.absorbing_organisation&.name} on 4 May 2022. Select another organisation or remove this organisation from the other merge request.")
end
end
context "when the user selects an organisation that is a part of another merge" do context "when the user selects an organisation that is a part of another merge" do
let(:another_organisation) { create(:organisation) } let(:another_organisation) { create(:organisation) }
let(:params) { { merge_request: { merging_organisation: another_organisation.id, new_merging_org_ids: [] } } } let(:params) { { merge_request: { merging_organisation: another_organisation.id, new_merging_org_ids: [] } } }
@ -396,6 +412,24 @@ RSpec.describe MergeRequestsController, type: :request do
}.from(nil).to(Time.zone.local(2022, 4, 10)) }.from(nil).to(Time.zone.local(2022, 4, 10))
end end
end end
context "when merge date set to a date more than 1 year in the future" do
let(:merge_request) { MergeRequest.create!(requesting_organisation: organisation) }
let(:params) do
{ merge_request: { page: "merge_date", "merge_date(3i)": (Time.zone.now.day + 1).to_s, "merge_date(2i)": Time.zone.now.month.to_s, "merge_date(1i)": (Time.zone.now.year + 1).to_s } }
end
let(:request) do
patch "/merge-request/#{merge_request.id}", headers:, params:
end
it "displays the page with an error message" do
request
expect(response).to have_http_status(:unprocessable_entity)
expect(page).to have_content("The merge date must not be later than a year from today’s date.")
end
end
end end
describe "from merging_organisations page" do describe "from merging_organisations page" do
@ -623,7 +657,7 @@ RSpec.describe MergeRequestsController, type: :request do
it "shows user outcomes after merge" do it "shows user outcomes after merge" do
expect(page).to have_link("View all 4 Organisation with some users users (opens in a new tab)", href: users_organisation_path(organisation_with_some_users)) expect(page).to have_link("View all 4 Organisation with some users users (opens in a new tab)", href: users_organisation_path(organisation_with_some_users))
expect(page).to have_link("View all 12 Organisation with many users users (opens in a new tab)", href: users_organisation_path(organisation_with_some_more_users)) expect(page).to have_link("View all 12 Organisation with many users users (opens in a new tab)", href: users_organisation_path(organisation_with_some_more_users))
expect(page).to have_link("View all 3 MHCLG users (opens in a new tab)", href: users_organisation_path(organisation)) expect(page).to have_link("View all 3 #{organisation.name} users (opens in a new tab)", href: users_organisation_path(organisation))
expect(page).to have_content("Organisation with no users and Organisation with no users too have no users.") expect(page).to have_content("Organisation with no users and Organisation with no users too have no users.")
expect(page).to have_content("19 users after merge") expect(page).to have_content("19 users after merge")
end end
@ -650,7 +684,7 @@ RSpec.describe MergeRequestsController, type: :request do
it "shows scheme outcomes after merge" do it "shows scheme outcomes after merge" do
expect(page).to have_link("View all 4 Organisation with some schemes schemes (opens in a new tab)", href: schemes_organisation_path(organisation_with_some_schemes)) expect(page).to have_link("View all 4 Organisation with some schemes schemes (opens in a new tab)", href: schemes_organisation_path(organisation_with_some_schemes))
expect(page).to have_link("View all 6 Organisation with many schemes schemes (opens in a new tab)", href: schemes_organisation_path(organisation_with_some_more_schemes)) expect(page).to have_link("View all 6 Organisation with many schemes schemes (opens in a new tab)", href: schemes_organisation_path(organisation_with_some_more_schemes))
expect(page).to have_link("View all 3 MHCLG schemes (opens in a new tab)", href: schemes_organisation_path(organisation)) expect(page).to have_link("View all 3 #{organisation.name} schemes (opens in a new tab)", href: schemes_organisation_path(organisation))
expect(page).to have_content("Organisation with no schemes and Organisation with no schemes too have no schemes.") expect(page).to have_content("Organisation with no schemes and Organisation with no schemes too have no schemes.")
expect(page).to have_content("13 schemes after merge") expect(page).to have_content("13 schemes after merge")
end end
@ -676,8 +710,8 @@ RSpec.describe MergeRequestsController, type: :request do
it "shows logs outcomes after merge" do it "shows logs outcomes after merge" do
expect(page).to have_link("View all 4 Organisation with some logs lettings logs (opens in a new tab)", href: lettings_logs_organisation_path(organisation_with_some_logs)) expect(page).to have_link("View all 4 Organisation with some logs lettings logs (opens in a new tab)", href: lettings_logs_organisation_path(organisation_with_some_logs))
expect(page).to have_link("View all 2 Organisation with some logs sales logs (opens in a new tab)", href: sales_logs_organisation_path(organisation_with_some_logs)) expect(page).to have_link("View all 2 Organisation with some logs sales logs (opens in a new tab)", href: sales_logs_organisation_path(organisation_with_some_logs))
expect(page).to have_link("View all 2 MHCLG lettings logs (opens in a new tab)", href: lettings_logs_organisation_path(organisation)) expect(page).to have_link("View all 2 #{organisation.name} lettings logs (opens in a new tab)", href: lettings_logs_organisation_path(organisation))
expect(page).to have_link("View all 3 MHCLG sales logs (opens in a new tab)", href: sales_logs_organisation_path(organisation)) expect(page).to have_link("View all 3 #{organisation.name} sales logs (opens in a new tab)", href: sales_logs_organisation_path(organisation))
expect(page).to have_content("Organisation with no logs and Organisation with no logs too have no lettings logs.") expect(page).to have_content("Organisation with no logs and Organisation with no logs too have no lettings logs.")
expect(page).to have_content("Organisation with no logs and Organisation with no logs too have no sales logs.") expect(page).to have_content("Organisation with no logs and Organisation with no logs too have no sales logs.")
expect(page).to have_content("6 lettings logs after merge") expect(page).to have_content("6 lettings logs after merge")

11
spec/requests/organisations_controller_spec.rb

@ -1431,7 +1431,7 @@ RSpec.describe OrganisationsController, type: :request do
end end
context "when a search parameter is passed" do context "when a search parameter is passed" do
let!(:matching_user) { create(:user, organisation:, name: "joe", email: "matching@example.com") } let!(:matching_user) { create(:user, organisation:, name: "abcdefghijklmnopqrstuvwxyz", email: "matching@example.com") }
let(:org_user_count) { User.where(organisation:).count } let(:org_user_count) { User.where(organisation:).count }
before do before do
@ -1439,7 +1439,7 @@ RSpec.describe OrganisationsController, type: :request do
end end
context "when our search string matches case" do context "when our search string matches case" do
let(:search_param) { "joe" } let(:search_param) { "abcdefghijklmnopqrstuvwxyz" }
it "returns only matching results" do it "returns only matching results" do
expect(page).to have_content(matching_user.name) expect(page).to have_content(matching_user.name)
@ -1459,7 +1459,7 @@ RSpec.describe OrganisationsController, type: :request do
end end
context "when we need case insensitive search" do context "when we need case insensitive search" do
let(:search_param) { "Joe" } let(:search_param) { "Abcdefghijklmnopqrstuvwxyz" }
it "returns only matching results" do it "returns only matching results" do
expect(page).to have_content(matching_user.name) expect(page).to have_content(matching_user.name)
@ -1643,6 +1643,11 @@ RSpec.describe OrganisationsController, type: :request do
context "when search results require pagination" do context "when search results require pagination" do
let(:search_param) { "MHCLG" } let(:search_param) { "MHCLG" }
before do
create_list(:organisation, 27, name: "MHCLG")
get "/organisations?search=#{search_param}"
end
it "has search and pagination in the title" do it "has search and pagination in the title" do
expect(page).to have_title("Organisations (27 organisations matching ‘#{search_param}’) (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") expect(page).to have_title("Organisations (27 organisations matching ‘#{search_param}’) (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK")
end end

86
spec/requests/schemes_controller_spec.rb

@ -89,9 +89,47 @@ RSpec.describe SchemesController, type: :request do
end end
end end
context "when a recently absorbed organisation has schemes" do
let(:absorbed_org) { create(:organisation) }
let!(:absorbed_org_schemes) { create_list(:scheme, 2, owning_organisation: absorbed_org) }
before do
absorbed_org.merge_date = 2.days.ago
absorbed_org.absorbing_organisation = user.organisation
absorbed_org.save!
end
it "shows absorbed organisation schemes" do
get "/schemes"
follow_redirect!
absorbed_org_schemes.each do |scheme|
expect(page).to have_content(scheme.id_to_display)
end
end
end
context "when a non-recently absorbed organisation has schemes" do
let(:absorbed_org) { create(:organisation) }
let!(:absorbed_org_schemes) { create_list(:scheme, 2, owning_organisation: absorbed_org) }
before do
absorbed_org.merge_date = 2.years.ago
absorbed_org.absorbing_organisation = user.organisation
absorbed_org.save!
end
it "shows absorbed organisation schemes" do
get "/schemes"
follow_redirect!
absorbed_org_schemes.each do |scheme|
expect(page).not_to have_content(scheme.id_to_display)
end
end
end
context "when filtering" do context "when filtering" do
context "with owning organisation filter" do context "with owning organisation filter" do
context "when user org does not have owning orgs" do context "when user org does not have owning orgs or recently absorbed orgs" do
it "does not show filter" do it "does not show filter" do
expect(page).not_to have_content("Owned by") expect(page).not_to have_content("Owned by")
end end
@ -700,6 +738,27 @@ RSpec.describe SchemesController, type: :request do
end end
end end
context "when coordinator attempts to see scheme belonging to a recently absorbed organisation" do
let(:absorbed_organisation) { create(:organisation) }
let!(:specific_scheme) { create(:scheme, owning_organisation: absorbed_organisation) }
before do
absorbed_organisation.merge_date = 2.days.ago
absorbed_organisation.absorbing_organisation = user.organisation
absorbed_organisation.save!
get "/schemes/#{specific_scheme.id}"
end
it "shows the scheme" do
expect(page).to have_content(specific_scheme.id_to_display)
end
it "allows editing" do
expect(page).to have_link("Change")
end
end
context "when the scheme has all details but no confirmed locations" do context "when the scheme has all details but no confirmed locations" do
it "shows the scheme as incomplete with text to explain" do it "shows the scheme as incomplete with text to explain" do
get scheme_path(specific_scheme) get scheme_path(specific_scheme)
@ -1146,6 +1205,31 @@ RSpec.describe SchemesController, type: :request do
end end
end end
end end
context "when making a scheme in an organisation recently absorbed by the users organisation" do
let(:absorbed_organisation) { create(:organisation) }
let(:params) do
{ scheme: { service_name: " testy ",
sensitive: "1",
scheme_type: "Foyer",
registered_under_care_act: "No",
owning_organisation_id: absorbed_organisation.id,
arrangement_type: "D" } }
end
before do
absorbed_organisation.merge_date = 2.days.ago
absorbed_organisation.absorbing_organisation = user.organisation
absorbed_organisation.save!
end
it "creates a new scheme for this organisation and renders correct page" do
expect { post "/schemes", params: }.to change(Scheme, :count).by(1)
follow_redirect!
expect(response).to have_http_status(:ok)
expect(page).to have_content("What client group is this scheme intended for?")
end
end
end end
context "when signed in as a support user" do context "when signed in as a support user" do

25
spec/requests/users_controller_spec.rb

@ -1043,6 +1043,9 @@ RSpec.describe UsersController, type: :request do
it "invites a new user" do it "invites a new user" do
expect { request }.to change(User, :count).by(1) expect { request }.to change(User, :count).by(1)
follow_redirect!
expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
expect(page).to have_content("Invitation sent to new_user@example.com")
end end
it "sends an invitation email" do it "sends an invitation email" do
@ -1261,8 +1264,8 @@ RSpec.describe UsersController, type: :request do
end end
context "when user is signed in as a support user" do context "when user is signed in as a support user" do
let(:user) { create(:user, :support, organisation: create(:organisation, :without_dpc)) } let(:user) { create(:user, :support, name: "Danny Rojas", organisation: create(:organisation, :without_dpc)) }
let(:other_user) { create(:user, organisation: user.organisation, last_sign_in_at: Time.zone.now) } let(:other_user) { create(:user, name: "Danny Rojas", organisation: user.organisation, last_sign_in_at: Time.zone.now) }
before do before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false) allow(user).to receive(:need_two_factor_authentication?).and_return(false)
@ -1999,7 +2002,7 @@ RSpec.describe UsersController, type: :request do
end end
context "when the user is not part of the same organisation as the current user" do context "when the user is not part of the same organisation as the current user" do
let(:other_user) { create(:user) } let(:other_user) { create(:user, organisation: create(:organisation, name: "Another org")) }
let(:params) { { id: other_user.id, user: { name: new_name } } } let(:params) { { id: other_user.id, user: { name: new_name } } }
it "updates the user" do it "updates the user" do
@ -2188,9 +2191,9 @@ RSpec.describe UsersController, type: :request do
context "when different organisations manage the logs" do context "when different organisations manage the logs" do
before do before do
create(:lettings_log, managing_organisation: other_user.organisation, assigned_to: other_user) create(:lettings_log, owning_organisation: other_user.organisation, managing_organisation: other_user.organisation, assigned_to: other_user)
create(:lettings_log, managing_organisation: new_organisation_2, assigned_to: other_user) create(:lettings_log, owning_organisation: other_user.organisation, managing_organisation: new_organisation_2, assigned_to: other_user)
create(:sales_log, managing_organisation: new_organisation_3, assigned_to: other_user) create(:sales_log, owning_organisation: other_user.organisation, managing_organisation: new_organisation_3, assigned_to: other_user)
patch "/users/#{other_user.id}/log-reassignment", headers:, params: patch "/users/#{other_user.id}/log-reassignment", headers:, params:
end end
@ -2206,8 +2209,8 @@ RSpec.describe UsersController, type: :request do
context "when users organisation manages the logs" do context "when users organisation manages the logs" do
before do before do
create(:lettings_log, owning_organisation: other_user.organisation, assigned_to: other_user) create(:lettings_log, owning_organisation: other_user.organisation, managing_organisation: other_user.organisation, assigned_to: other_user)
create(:sales_log, owning_organisation: other_user.organisation, assigned_to: other_user) create(:sales_log, owning_organisation: other_user.organisation, managing_organisation: other_user.organisation, assigned_to: other_user)
patch "/users/#{other_user.id}/log-reassignment", headers:, params: patch "/users/#{other_user.id}/log-reassignment", headers:, params:
end end
@ -2219,15 +2222,15 @@ RSpec.describe UsersController, type: :request do
context "when different organisations manage the logs" do context "when different organisations manage the logs" do
before do before do
create(:lettings_log, owning_organisation: other_user.organisation, assigned_to: other_user) create(:lettings_log, owning_organisation: other_user.organisation, managing_organisation: other_user.organisation, assigned_to: other_user)
create(:lettings_log, owning_organisation: new_organisation_2, assigned_to: other_user) create(:lettings_log, owning_organisation: new_organisation_2, managing_organisation: other_user.organisation, assigned_to: other_user)
create(:sales_log, owning_organisation: new_organisation_3, managing_organisation: other_user.organisation, assigned_to: other_user) create(:sales_log, owning_organisation: new_organisation_3, managing_organisation: other_user.organisation, assigned_to: other_user)
patch "/users/#{other_user.id}/log-reassignment", headers:, params: patch "/users/#{other_user.id}/log-reassignment", headers:, params:
end end
it "required the new org to have managing agent relationship with owning organisations" do it "required the new org to have managing agent relationship with owning organisations" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
expect(page).to have_content("New org must be a managing agent of #{other_user.organisation_name}, #{new_organisation_2.name}, and #{new_organisation_3.name} to make this change.") expect(page).to have_content("New org must be a managing agent of #{other_user.organisation.name}, #{new_organisation_2.name}, and #{new_organisation_3.name} to make this change.")
end end
end end
end end

4
spec/services/csv/lettings_log_csv_service_spec.rb

@ -196,7 +196,7 @@ RSpec.describe Csv::LettingsLogCsvService do
describe "the full CSV output" do describe "the full CSV output" do
context "when the requested log year is 2024" do context "when the requested log year is 2024" do
let(:year) { 2024 } let(:year) { 2024 }
let(:organisation) { create(:organisation, provider_type: "LA") } let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") }
let(:log) do let(:log) do
create( create(
:lettings_log, :lettings_log,
@ -389,7 +389,7 @@ RSpec.describe Csv::LettingsLogCsvService do
context "when the requested log year is 2023" do context "when the requested log year is 2023" do
let(:year) { 2023 } let(:year) { 2023 }
let(:organisation) { create(:organisation, provider_type: "LA") } let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") }
let(:log) do let(:log) do
create( create(
:lettings_log, :lettings_log,

10
spec/services/csv/sales_log_csv_service_spec.rb

@ -4,7 +4,7 @@ RSpec.describe Csv::SalesLogCsvService do
subject(:task) { Rake::Task["data_import:add_variable_definitions"] } subject(:task) { Rake::Task["data_import:add_variable_definitions"] }
let(:form_handler_mock) { instance_double(FormHandler) } let(:form_handler_mock) { instance_double(FormHandler) }
let(:organisation) { create(:organisation) } let(:organisation) { create(:organisation, name: "MHCLG") }
let(:fixed_time) { now } let(:fixed_time) { now }
let(:now) { Time.zone.now } let(:now) { Time.zone.now }
let(:user) { create(:user, :support, email: "billyboy@eyeKLAUD.com") } let(:user) { create(:user, :support, email: "billyboy@eyeKLAUD.com") }
@ -17,15 +17,23 @@ RSpec.describe Csv::SalesLogCsvService do
created_at: fixed_time, created_at: fixed_time,
updated_at: now, updated_at: now,
owning_organisation: organisation, owning_organisation: organisation,
managing_organisation: organisation,
purchid: nil, purchid: nil,
hholdcount: 3, hholdcount: 3,
age1: 30,
sex1: "X",
age2: 35,
sex2: "X",
sex3: "X",
age4_known: 1, age4_known: 1,
sex4: "X",
details_known_5: 2, details_known_5: 2,
age6_known: nil, age6_known: nil,
age6: nil, age6: nil,
ecstat6: nil, ecstat6: nil,
relat6: nil, relat6: nil,
sex6: nil, sex6: nil,
town_or_city: "Town or city",
address_line1_as_entered: "address line 1 as entered", address_line1_as_entered: "address line 1 as entered",
address_line2_as_entered: "address line 2 as entered", address_line2_as_entered: "address line 2 as entered",
town_or_city_as_entered: "town or city as entered", town_or_city_as_entered: "town or city as entered",

2
spec/services/csv/scheme_csv_service_spec.rb

@ -1,7 +1,7 @@
require "rails_helper" require "rails_helper"
RSpec.describe Csv::SchemeCsvService do RSpec.describe Csv::SchemeCsvService do
let(:organisation) { create(:organisation) } let(:organisation) { create(:organisation, name: "MHCLG") }
let(:fixed_time) { Time.zone.local(2023, 6, 26) } let(:fixed_time) { Time.zone.local(2023, 6, 26) }
let(:scheme) { create(:scheme, :export, owning_organisation: organisation, service_name: "Test name") } let(:scheme) { create(:scheme, :export, owning_organisation: organisation, service_name: "Test name") }
let(:location) { create(:location, :export, scheme:) } let(:location) { create(:location, :export, scheme:) }

17
spec/services/exports/lettings_log_export_service_spec.rb

@ -15,7 +15,8 @@ RSpec.describe Exports::LettingsLogExportService do
let(:expected_data_filename) { "core_2021_2022_apr_mar_f0001_inc0001_pt001.xml" } let(:expected_data_filename) { "core_2021_2022_apr_mar_f0001_inc0001_pt001.xml" }
let(:expected_manifest_filename) { "manifest.xml" } let(:expected_manifest_filename) { "manifest.xml" }
let(:start_time) { Time.zone.local(2022, 5, 1) } let(:start_time) { Time.zone.local(2022, 5, 1) }
let(:user) { FactoryBot.create(:user, email: "test1@example.com") } let(:organisation) { create(:organisation, name: "MHCLG", housing_registration_no: 1234) }
let(:user) { FactoryBot.create(:user, email: "test1@example.com", organisation:) }
def replace_entity_ids(lettings_log, export_template) def replace_entity_ids(lettings_log, export_template)
export_template.sub!(/\{id\}/, (lettings_log["id"] + Exports::LettingsLogExportService::LOG_ID_OFFSET).to_s) export_template.sub!(/\{id\}/, (lettings_log["id"] + Exports::LettingsLogExportService::LOG_ID_OFFSET).to_s)
@ -79,7 +80,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log is available for export" do context "and one lettings log is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", town_or_city: "London", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
it "generates a ZIP export file with the expected filename" do it "generates a ZIP export file with the expected filename" do
expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args)
@ -123,7 +124,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log with unknown user details is available for export" do context "and one lettings log with unknown user details is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, details_known_2: 1, assigned_to: user, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, details_known_2: 1, assigned_to: user, age1: 35, sex1: "F", propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", town_or_city: "London", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
def replace_person_details(export_file) def replace_person_details(export_file)
export_file.sub!("<age2>32</age2>", "<age2>-9</age2>") export_file.sub!("<age2>32</age2>", "<age2>-9</age2>")
@ -176,7 +177,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log is available for export" do context "and one lettings log is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, uprn_known: 1, uprn: "100023336956", propcode: "123", postcode_full: "SE2 6RT", ppostcode_full: "SE2 6RT", tenancycode: "BZ737", startdate: Time.zone.local(2023, 4, 2, 10, 36, 49), voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", uprn_known: 1, uprn: "100023336956", propcode: "123", postcode_full: "SE2 6RT", ppostcode_full: "SE2 6RT", tenancycode: "BZ737", startdate: Time.zone.local(2023, 4, 2, 10, 36, 49), voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
let(:expected_zip_filename) { "core_2023_2024_apr_mar_f0001_inc0001.zip" } let(:expected_zip_filename) { "core_2023_2024_apr_mar_f0001_inc0001.zip" }
let(:expected_data_filename) { "core_2023_2024_apr_mar_f0001_inc0001_pt001.xml" } let(:expected_data_filename) { "core_2023_2024_apr_mar_f0001_inc0001_pt001.xml" }
let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_23_24.xml", "r:UTF-8") } let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_23_24.xml", "r:UTF-8") }
@ -396,7 +397,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log with duplicate reference is available for export" do context "and one lettings log with duplicate reference is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, duplicate_set_id: 123) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", town_or_city: "London", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, duplicate_set_id: 123) }
def replace_duplicate_set_id(export_file) def replace_duplicate_set_id(export_file)
export_file.sub!("<duplicate_set_id/>", "<duplicate_set_id>123</duplicate_set_id>") export_file.sub!("<duplicate_set_id/>", "<duplicate_set_id>123</duplicate_set_id>")
@ -429,7 +430,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log is available for export" do context "and one lettings log is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, ppostcode_full: "A1 1AA", nationality_all_group: 13, propcode: "123", postcode_full: "SE2 6RT", tenancycode: "BZ737", startdate: Time.zone.local(2024, 4, 2, 10, 36, 49), voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, creation_method: 2, bulk_upload_id: 1, address_line1_as_entered: "address line 1 as entered", address_line2_as_entered: "address line 2 as entered", town_or_city_as_entered: "town or city as entered", county_as_entered: "county as entered", postcode_full_as_entered: "AB1 2CD", la_as_entered: "la as entered") } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", ppostcode_full: "A1 1AA", nationality_all_group: 13, propcode: "123", postcode_full: "SE2 6RT", tenancycode: "BZ737", startdate: Time.zone.local(2024, 4, 2, 10, 36, 49), voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, creation_method: 2, bulk_upload_id: 1, address_line1_as_entered: "address line 1 as entered", address_line2_as_entered: "address line 2 as entered", town_or_city_as_entered: "town or city as entered", county_as_entered: "county as entered", postcode_full_as_entered: "AB1 2CD", la_as_entered: "la as entered") }
let(:expected_zip_filename) { "core_2024_2025_apr_mar_f0001_inc0001.zip" } let(:expected_zip_filename) { "core_2024_2025_apr_mar_f0001_inc0001.zip" }
let(:expected_data_filename) { "core_2024_2025_apr_mar_f0001_inc0001_pt001.xml" } let(:expected_data_filename) { "core_2024_2025_apr_mar_f0001_inc0001_pt001.xml" }
let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_24_25.xml", "r:UTF-8") } let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_24_25.xml", "r:UTF-8") }
@ -450,13 +451,13 @@ RSpec.describe Exports::LettingsLogExportService do
context "when exporting a supported housing lettings logs in XML" do context "when exporting a supported housing lettings logs in XML" do
let(:export_file) { File.open("spec/fixtures/exports/supported_housing_logs.xml", "r:UTF-8") } let(:export_file) { File.open("spec/fixtures/exports/supported_housing_logs.xml", "r:UTF-8") }
let(:organisation) { FactoryBot.create(:organisation, provider_type: "LA") } let(:organisation) { FactoryBot.create(:organisation, name: "MHCLG", provider_type: "LA", housing_registration_no: 1234) }
let(:user) { FactoryBot.create(:user, organisation:, email: "fake@email.com") } let(:user) { FactoryBot.create(:user, organisation:, email: "fake@email.com") }
let(:other_user) { FactoryBot.create(:user, organisation:, email: "other@email.com") } let(:other_user) { FactoryBot.create(:user, organisation:, email: "other@email.com") }
let(:scheme) { FactoryBot.create(:scheme, :export, owning_organisation: organisation) } let(:scheme) { FactoryBot.create(:scheme, :export, owning_organisation: organisation) }
let(:location) { FactoryBot.create(:location, :export, scheme:, startdate: Time.zone.local(2021, 4, 1), old_id: "1a") } let(:location) { FactoryBot.create(:location, :export, scheme:, startdate: Time.zone.local(2021, 4, 1), old_id: "1a") }
let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, :export, :sh, scheme:, location:, assigned_to: user, updated_by: other_user, owning_organisation: organisation, startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), underoccupation_benefitcap: 4, sheltered: 1) } let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, :export, :sh, scheme:, location:, assigned_to: user, updated_by: other_user, owning_organisation: organisation, age1: 35, sex1: "F", age2: 32, sex2: "M", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), underoccupation_benefitcap: 4, sheltered: 1) }
before do before do
lettings_log.postcode_full = nil lettings_log.postcode_full = nil

2
spec/services/exports/organisation_export_service_spec.rb

@ -42,7 +42,7 @@ RSpec.describe Exports::OrganisationExportService do
end end
context "and one organisation is available for export" do context "and one organisation is available for export" do
let!(:organisation) { create(:organisation) } let!(:organisation) { create(:organisation, name: "MHCLG", address_line1: "2 Marsham Street", address_line2: "London", postcode: "SW1P 4DF", housing_registration_no: "1234") }
it "generates a ZIP export file with the expected filename" do it "generates a ZIP export file with the expected filename" do
expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args)

4
spec/services/exports/user_export_service_spec.rb

@ -12,7 +12,7 @@ RSpec.describe Exports::UserExportService do
let(:expected_data_filename) { "users_2024_2025_apr_mar_f0001_inc0001_pt001.xml" } let(:expected_data_filename) { "users_2024_2025_apr_mar_f0001_inc0001_pt001.xml" }
let(:expected_manifest_filename) { "manifest.xml" } let(:expected_manifest_filename) { "manifest.xml" }
let(:start_time) { Time.zone.local(2022, 5, 1) } let(:start_time) { Time.zone.local(2022, 5, 1) }
let(:organisation) { create(:organisation, with_dsa: false) } let(:organisation) { create(:organisation, name: "MHCLG", with_dsa: false) }
def replace_entity_ids(user, export_template) def replace_entity_ids(user, export_template)
export_template.sub!(/\{id\}/, user["id"].to_s) export_template.sub!(/\{id\}/, user["id"].to_s)
@ -42,7 +42,7 @@ RSpec.describe Exports::UserExportService do
end end
context "and one user is available for export" do context "and one user is available for export" do
let!(:user) { create(:user, organisation:, phone_extension: "123") } let!(:user) { create(:user, organisation:, name: "Danny Rojas", phone_extension: "123") }
it "generates a ZIP export file with the expected filename" do it "generates a ZIP export file with the expected filename" do
expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args)

28
spec/services/merge/merge_organisations_service_spec.rb

@ -28,7 +28,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "moves the users from merging organisation to absorbing organisation" do it "moves the users from merging organisation to absorbing organisation" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
merge_organisations_service.call merge_organisations_service.call
@ -477,7 +477,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "logs the merged schemes and locations" do it "logs the merged schemes and locations" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/) expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/)
@ -623,7 +623,7 @@ RSpec.describe Merge::MergeOrganisationsService do
context "and merging sales logs" do context "and merging sales logs" do
let(:owning_organisation) { create(:organisation, holds_own_stock: true) } let(:owning_organisation) { create(:organisation, holds_own_stock: true) }
let!(:sales_log) { create(:sales_log, saledate: Time.zone.today, owning_organisation: merging_organisation, purchid: "owned") } let!(:sales_log) { create(:sales_log, saledate: Time.zone.today, owning_organisation: merging_organisation, managing_organisation: merging_organisation, purchid: "owned") }
let!(:managed_sales_log) { create(:sales_log, saledate: Time.zone.today, purchid: "managed") } let!(:managed_sales_log) { create(:sales_log, saledate: Time.zone.today, purchid: "managed") }
before do before do
@ -744,7 +744,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "logs the merged schemes" do it "logs the merged schemes" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/) expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/)
@ -922,7 +922,7 @@ RSpec.describe Merge::MergeOrganisationsService do
let!(:merging_organisation_user) { create(:user, organisation: merging_organisation, name: "fake name", email: "fake@email.com") } let!(:merging_organisation_user) { create(:user, organisation: merging_organisation, name: "fake name", email: "fake@email.com") }
before do before do
create_list(:user, 5, organisation: merging_organisation_too) create_list(:user, 5, organisation: merging_organisation_too, name: "Danny Rojas")
end end
it "sets merge date and absorbing organisation on merged organisations" do it "sets merge date and absorbing organisation on merged organisations" do
@ -961,10 +961,11 @@ RSpec.describe Merge::MergeOrganisationsService do
context "and merging users" do context "and merging users" do
it "moves the users from merging organisations to absorbing organisation" do it "moves the users from merging organisations to absorbing organisation" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("Merged users from second org:") expect(Rails.logger).to receive(:info).with("Merged users from second org:")
expect(Rails.logger).to receive(:info).with(/\tDanny Rojas/).exactly(6).times expect(Rails.logger).to receive(:info).with(/\tDanny Rojas/).exactly(5).times
expect(Rails.logger).to receive(:info).with(/\t#{merging_organisation_too.data_protection_officers.first.name}/)
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with("New schemes from second org:") expect(Rails.logger).to receive(:info).with("New schemes from second org:")
merge_organisations_service.call merge_organisations_service.call
@ -1113,7 +1114,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "moves the users from merging organisation to absorbing organisation" do it "moves the users from merging organisation to absorbing organisation" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
merge_organisations_service.call merge_organisations_service.call
@ -1251,7 +1252,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "logs the merged schemes" do it "logs the merged schemes" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/) expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/)
@ -1462,7 +1463,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "logs the merged schemes" do it "logs the merged schemes" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/) expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/)
@ -1590,15 +1591,16 @@ RSpec.describe Merge::MergeOrganisationsService do
let!(:merging_organisation_user) { create(:user, organisation: merging_organisation, name: "fake name", email: "fake@email.com") } let!(:merging_organisation_user) { create(:user, organisation: merging_organisation, name: "fake name", email: "fake@email.com") }
before do before do
create_list(:user, 5, organisation: merging_organisation_too) create_list(:user, 5, organisation: merging_organisation_too, name: "Danny Rojas")
end end
it "moves the users from merging organisations to absorbing organisation" do it "moves the users from merging organisations to absorbing organisation" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:") expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})") expect(Rails.logger).to receive(:info).with("\t#{merging_organisation.data_protection_officers.first.name} (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)") expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("Merged users from second org:") expect(Rails.logger).to receive(:info).with("Merged users from second org:")
expect(Rails.logger).to receive(:info).with(/\tDanny Rojas/).exactly(6).times expect(Rails.logger).to receive(:info).with(/\tDanny Rojas/).exactly(5).times
expect(Rails.logger).to receive(:info).with(/\t#{merging_organisation_too.data_protection_officers.first.name}/)
expect(Rails.logger).to receive(:info).with("New schemes from fake org:") expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with("New schemes from second org:") expect(Rails.logger).to receive(:info).with("New schemes from second org:")
merge_organisations_service.call merge_organisations_service.call

Loading…
Cancel
Save