diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb
index d12968cc7..e275d5b60 100644
--- a/app/controllers/locations_controller.rb
+++ b/app/controllers/locations_controller.rb
@@ -60,7 +60,7 @@ private
end
def location_params
- required_params = params.require(:location).permit(:postcode, :name, :total_units, :type_of_unit, :wheelchair_adaptation, :add_another_location).merge(scheme_id: @scheme.id)
+ required_params = params.require(:location).permit(:postcode, :name, :units, :type_of_unit, :wheelchair_adaptation, :add_another_location).merge(scheme_id: @scheme.id)
required_params[:postcode] = required_params[:postcode].delete(" ").upcase.encode("ASCII", "UTF-8", invalid: :replace, undef: :replace, replace: "") if required_params[:postcode]
required_params
end
diff --git a/app/models/location.rb b/app/models/location.rb
index c8be513eb..3980f3957 100644
--- a/app/models/location.rb
+++ b/app/models/location.rb
@@ -17,8 +17,8 @@ class Location < ApplicationRecord
"Self-contained flat or bedsit with common facilities": 2,
"Shared flat": 3,
"Shared house or hostel": 4,
- "Bungalow": 5,
- "Self-contained house": 6,
+ "Bungalow": 6,
+ "Self-contained house": 7,
}.freeze
enum type_of_unit: TYPE_OF_UNIT
diff --git a/app/models/scheme.rb b/app/models/scheme.rb
index 9dc9c62a0..b236689dd 100644
--- a/app/models/scheme.rb
+++ b/app/models/scheme.rb
@@ -17,10 +17,10 @@ class Scheme < ApplicationRecord
enum sensitive: SENSITIVE, _suffix: true
REGISTERED_UNDER_CARE_ACT = {
- "No": 0,
- "Yes – registered care home providing nursing care": 1,
- "Yes – registered care home providing personal care": 2,
- "Yes – part registered as a care home": 3,
+ "No": 1,
+ "Yes – registered care home providing nursing care": 4,
+ "Yes – registered care home providing personal care": 3,
+ "Yes – part registered as a care home": 2,
}.freeze
enum registered_under_care_act: REGISTERED_UNDER_CARE_ACT
diff --git a/app/services/imports/scheme_location_import_service.rb b/app/services/imports/scheme_location_import_service.rb
index 31689c761..aa958632c 100644
--- a/app/services/imports/scheme_location_import_service.rb
+++ b/app/services/imports/scheme_location_import_service.rb
@@ -4,21 +4,163 @@ module Imports
import_from(folder, :create_scheme_location)
end
+ def create_scheme_location(xml_document)
+ management_group = location_field_value(xml_document, "mgmtgroup")
+ schemes = Scheme.where(old_id: management_group)
+ raise "Scheme not found with legacy ID #{management_group}" if schemes.empty?
+
+ if schemes.size == 1 && schemes.first&.locations&.empty?
+ scheme = update_scheme(schemes.first, xml_document)
+ else
+ scheme = find_scheme_to_merge(schemes, xml_document)
+ scheme ||= duplicate_scheme(schemes, xml_document)
+ end
+ add_location(scheme, xml_document)
+ end
+
private
- def create_scheme_location(xml_document)
- old_visible_id = location_field_value(xml_document, "visible-id")
- Scheme.create!(
- old_id: location_field_value(xml_document, "id"),
- old_visible_id:,
- )
- rescue ActiveRecord::RecordNotUnique
- name = location_field_value(xml_document, "name")
- @logger.warn("Location #{name} is already present with old visible ID #{old_visible_id}, skipping.")
- end
-
- def location_field_value(xml_document, field)
- field_value(xml_document, "scheme", field)
+ REGISTERED_UNDER_CARE_ACT = {
+ 2 => "(Part-registered care home)",
+ 3 => "(Registered personal care home)",
+ 4 => "(Registered nursing care home)",
+ }.freeze
+
+ def update_scheme(scheme, xml_doc)
+ attributes = scheme_attributes(xml_doc)
+ scheme.update!(attributes)
+ scheme
+ end
+
+ def scheme_attributes(xml_doc)
+ attributes = {}
+ attributes["scheme_type"] = safe_string_as_integer(xml_doc, "scheme-type")
+ registered_under_care_act = safe_string_as_integer(xml_doc, "reg-home-type")
+ attributes["registered_under_care_act"] = registered_under_care_act.zero? ? nil : registered_under_care_act
+ attributes["support_type"] = safe_string_as_integer(xml_doc, "support-type")
+ attributes["intended_stay"] = string_or_nil(xml_doc, "intended-stay")
+ attributes["primary_client_group"] = string_or_nil(xml_doc, "client-group-1")
+ attributes["secondary_client_group"] = string_or_nil(xml_doc, "client-group-2")
+ attributes["secondary_client_group"] = nil if attributes["primary_client_group"] == attributes["secondary_client_group"]
+ attributes["sensitive"] = sensitive(xml_doc)
+ attributes["end_date"] = parse_end_date(xml_doc)
+ attributes
+ end
+
+ def add_location(scheme, xml_doc)
+ end_date = parse_end_date(xml_doc)
+ old_id = string_or_nil(xml_doc, "id")
+
+ if end_date.nil? || end_date >= Time.zone.now
+ # wheelchair_adaptation: string_or_nil(xml_doc, "mobility-type"),
+ begin
+ Location.create!(
+ postcode: string_or_nil(xml_doc, "postcode"),
+ units: safe_string_as_integer(xml_doc, "total-units"),
+ type_of_unit: safe_string_as_integer(xml_doc, "unit-type"),
+ old_visible_id: safe_string_as_integer(xml_doc, "visible-id"),
+ old_id:,
+ scheme:,
+ )
+ rescue ActiveRecord::RecordNotUnique
+ @logger.warn("Location is already present with legacy ID #{old_id}, skipping")
+ end
+ else
+ @logger.warn("Location with legacy ID #{old_id} is expired (#{end_date}), skipping")
+ end
+ end
+
+ def find_scheme_to_merge(schemes, xml_doc)
+ attributes = scheme_attributes(xml_doc)
+
+ schemes.each do |scheme|
+ if scheme.scheme_type_before_type_cast == attributes["scheme_type"] &&
+ scheme.registered_under_care_act_before_type_cast == attributes["registered_under_care_act"] &&
+ scheme.support_type_before_type_cast == attributes["support_type"] &&
+ scheme.intended_stay_before_type_cast == attributes["intended_stay"] &&
+ scheme.primary_client_group_before_type_cast == attributes["primary_client_group"] &&
+ scheme.secondary_client_group_before_type_cast == attributes["secondary_client_group"]
+ return scheme
+ end
+ end
+
+ nil
+ end
+
+ def duplicate_scheme(schemes, xml_doc)
+ # Since all schemes in the array are different, pick the first one
+ # In the future, consider a better selection method if needed
+ old_scheme = schemes.first
+ new_scheme = old_scheme.dup
+ update_scheme(new_scheme, xml_doc)
+
+ if old_scheme.scheme_type != new_scheme.scheme_type
+ rename_schemes(old_scheme, new_scheme, :scheme_type)
+ elsif old_scheme.registered_under_care_act != new_scheme.registered_under_care_act
+ rename_registered_care(old_scheme, new_scheme)
+ elsif old_scheme.support_type != new_scheme.support_type
+ rename_schemes(old_scheme, new_scheme, :support_type)
+ elsif old_scheme.intended_stay != new_scheme.intended_stay
+ rename_schemes(old_scheme, new_scheme, :intended_stay)
+ elsif old_scheme.primary_client_group != new_scheme.primary_client_group
+ rename_schemes(old_scheme, new_scheme, :primary_client_group)
+ elsif old_scheme.secondary_client_group != new_scheme.secondary_client_group
+ rename_schemes(old_scheme, new_scheme, :secondary_client_group)
+ end
+
+ new_scheme
+ end
+
+ def rename_registered_care(*schemes)
+ schemes.each do |scheme|
+ if REGISTERED_UNDER_CARE_ACT.key?(scheme.registered_under_care_act_before_type_cast)
+ suffix = REGISTERED_UNDER_CARE_ACT[scheme.registered_under_care_act_before_type_cast]
+ scheme.update!(service_name: "#{scheme.service_name} - #{suffix}")
+ end
+ end
+ end
+
+ def rename_schemes(old_scheme, new_scheme, attribute)
+ old_scheme_attribute = old_scheme.send(attribute)
+ new_scheme_attribute = new_scheme.send(attribute)
+
+ if old_scheme_attribute
+ old_scheme_name = "#{old_scheme.service_name} - #{old_scheme_attribute}"
+ old_scheme.update!(service_name: old_scheme_name)
+ end
+ if new_scheme_attribute
+ new_scheme_name = "#{new_scheme.service_name} - #{new_scheme_attribute}"
+ new_scheme.update!(service_name: new_scheme_name)
+ end
+ end
+
+ def location_field_value(xml_doc, field)
+ field_value(xml_doc, "scheme", field)
+ end
+
+ def string_or_nil(xml_doc, attribute)
+ str = location_field_value(xml_doc, attribute)
+ str.presence
+ end
+
+ # Safe: A string that represents only an integer (or empty/nil)
+ def safe_string_as_integer(xml_doc, attribute)
+ str = location_field_value(xml_doc, attribute)
+ Integer(str, exception: false)
+ end
+
+ def sensitive(xml_doc)
+ value = string_or_nil(xml_doc, "sensitive")
+ if value == "true"
+ 1
+ else
+ 0
+ end
+ end
+
+ def parse_end_date(xml_doc)
+ end_date = string_or_nil(xml_doc, "end-date")
+ Time.zone.parse(end_date) if end_date
end
end
end
diff --git a/app/views/locations/edit.html.erb b/app/views/locations/edit.html.erb
index bbcccdef6..221c17ba4 100644
--- a/app/views/locations/edit.html.erb
+++ b/app/views/locations/edit.html.erb
@@ -23,7 +23,7 @@
label: { text: "Name (optional)", size: "m" },
hint: { text: "This is how you refer to this location within your organisation" } %>
- <%= f.govuk_number_field :total_units,
+ <%= f.govuk_number_field :units,
label: { text: "Total number of units at this location", size: "m" },
width: 2,
hint: { text: "A unit can be a bedroom in a shared house or flat, or a house with 4 bedrooms. Do not include bedrooms used for wardens, managers, volunteers or sleep-in staff.s" },
diff --git a/app/views/locations/index.html.erb b/app/views/locations/index.html.erb
index 6d3cc3de3..65a6ebb0b 100644
--- a/app/views/locations/index.html.erb
+++ b/app/views/locations/index.html.erb
@@ -37,7 +37,7 @@
<%= body.row do |row| %>
<% row.cell(text: location.id) %>
<% row.cell(text: location.postcode) %>
- <% row.cell(text: location.total_units) %>
+ <% row.cell(text: location.units) %>
<% row.cell(text: simple_format("#{location.type_of_unit}#{location.wheelchair_adaptation == 'Yes' ? "\nWith wheelchair adaptations" : ''}")) %>
<% end %>
<% end %>
diff --git a/app/views/locations/new.html.erb b/app/views/locations/new.html.erb
index 8c8ff23c5..33eba6af7 100644
--- a/app/views/locations/new.html.erb
+++ b/app/views/locations/new.html.erb
@@ -23,7 +23,7 @@
label: { text: "Name (optional)", size: "m" },
hint: { text: "This is how you refer to this location within your organisation" } %>
- <%= f.govuk_number_field :total_units,
+ <%= f.govuk_number_field :units,
label: { text: "Total number of units at this location", size: "m" },
width: 2,
hint: { text: "A unit can be a bedroom in a shared house or flat, or a house with 4 bedrooms. Do not include bedrooms used for wardens, managers, volunteers or sleep-in staff.s" },
diff --git a/app/views/schemes/check_answers.html.erb b/app/views/schemes/check_answers.html.erb
index 2b521fcd6..f9923e685 100644
--- a/app/views/schemes/check_answers.html.erb
+++ b/app/views/schemes/check_answers.html.erb
@@ -90,7 +90,7 @@
<%= body.row do |row| %>
<% row.cell(text: location.id) %>
<% row.cell(text: simple_format(location_cell(location), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %>
- <% row.cell(text: location.total_units) %>
+ <% row.cell(text: location.units) %>
<% row.cell(text: simple_format("#{location.type_of_unit}#{location.wheelchair_adaptation == 'Yes' ? "\nWith wheelchair adaptations" : ''}")) %>
<% end %>
<% end %>
diff --git a/db/migrate/20220708133052_add_missing_fields_to_location.rb b/db/migrate/20220708133052_add_missing_fields_to_location.rb
new file mode 100644
index 000000000..2d140c49e
--- /dev/null
+++ b/db/migrate/20220708133052_add_missing_fields_to_location.rb
@@ -0,0 +1,8 @@
+class AddMissingFieldsToLocation < ActiveRecord::Migration[7.0]
+ def change
+ change_table :locations, bulk: true do |t|
+ t.column :old_id, :string
+ t.column :old_visible_id, :integer
+ end
+ end
+end
diff --git a/db/migrate/20220711081400_rename_units_from_locations.rb b/db/migrate/20220711081400_rename_units_from_locations.rb
new file mode 100644
index 000000000..fef1c4132
--- /dev/null
+++ b/db/migrate/20220711081400_rename_units_from_locations.rb
@@ -0,0 +1,6 @@
+class RenameUnitsFromLocations < ActiveRecord::Migration[7.0]
+ def change
+ rename_column :locations, :total_units, :units
+ add_column :schemes, :total_units, :integer
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a34ffb64a..e6e2cc033 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2022_07_08_112603) do
+ActiveRecord::Schema[7.0].define(version: 2022_07_11_081400) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -246,8 +246,10 @@ ActiveRecord::Schema[7.0].define(version: 2022_07_08_112603) do
t.string "county"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
- t.integer "total_units"
+ t.integer "units"
t.integer "type_of_unit"
+ t.string "old_id"
+ t.integer "old_visible_id"
t.index ["scheme_id"], name: "index_locations_on_scheme_id"
end
@@ -316,6 +318,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_07_08_112603) do
t.string "arrangement_type"
t.string "old_id"
t.integer "old_visible_id"
+ t.integer "total_units"
t.index ["managing_organisation_id"], name: "index_schemes_on_managing_organisation_id"
t.index ["owning_organisation_id"], name: "index_schemes_on_owning_organisation_id"
end
diff --git a/spec/factories/location.rb b/spec/factories/location.rb
index 53f8d2cd0..cd2464e86 100644
--- a/spec/factories/location.rb
+++ b/spec/factories/location.rb
@@ -3,7 +3,7 @@ FactoryBot.define do
location_code { Faker::Name.initials(number: 10) }
postcode { Faker::Address.postcode.delete(" ") }
name { Faker::Address.street_name }
- type_of_unit { Faker::Number.within(range: 1..6) }
+ type_of_unit { [1, 2, 3, 4, 6, 7].sample }
type_of_building { Faker::Lorem.word }
wheelchair_adaptation { 0 }
county { Faker::Address.state }
diff --git a/spec/factories/scheme.rb b/spec/factories/scheme.rb
index 5317d9e1d..ecd83a930 100644
--- a/spec/factories/scheme.rb
+++ b/spec/factories/scheme.rb
@@ -2,7 +2,7 @@ FactoryBot.define do
factory :scheme do
service_name { Faker::Name.name }
sensitive { Faker::Number.within(range: 0..1) }
- registered_under_care_act { Faker::Number.within(range: 0..1) }
+ registered_under_care_act { 1 }
support_type { Faker::Number.within(range: 0..6) }
scheme_type { 0 }
intended_stay { %w[M P S V X].sample }
diff --git a/spec/fixtures/imports/scheme_locations/0bb3836b70b4dd9903263d5a764a5c45b964a89d.xml b/spec/fixtures/imports/scheme_locations/0bb3836b70b4dd9903263d5a764a5c45b964a89d.xml
index 260213b64..d62b40b78 100644
--- a/spec/fixtures/imports/scheme_locations/0bb3836b70b4dd9903263d5a764a5c45b964a89d.xml
+++ b/spec/fixtures/imports/scheme_locations/0bb3836b70b4dd9903263d5a764a5c45b964a89d.xml
@@ -9,7 +9,7 @@
7
6
1
- 0
+ 2
W
False
P
diff --git a/spec/requests/locations_controller_spec.rb b/spec/requests/locations_controller_spec.rb
index cba28a541..91459257b 100644
--- a/spec/requests/locations_controller_spec.rb
+++ b/spec/requests/locations_controller_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe LocationsController, type: :request do
context "when signed in as a data coordinator" do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) }
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
before do
sign_in user
@@ -108,13 +108,13 @@ RSpec.describe LocationsController, type: :request do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
expect(Location.last.postcode).to eq("ZZ11ZZ")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
context "when postcode is submitted with lower case" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
it "creates a new location for scheme with postcode " do
expect(Location.last.postcode).to eq("ZZ11ZZ")
@@ -123,7 +123,7 @@ RSpec.describe LocationsController, type: :request do
context "when trying to add location to a scheme that belongs to another organisation" do
let(:another_scheme) { FactoryBot.create(:scheme) }
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
it "displays the new page with an error message" do
post "/schemes/#{another_scheme.id}/locations", params: params
@@ -132,7 +132,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when required postcode param is missing" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No" } } }
it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity)
@@ -141,7 +141,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when do you want to add another location is selected as yes" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
it "creates a new location for scheme with valid params and redirects to correct page" do
expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1)
@@ -153,14 +153,14 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is selected as no" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
it "creates a new location for scheme with valid params and redirects to correct page" do
expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1)
@@ -172,14 +172,14 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is not selected" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
it "creates a new location for scheme with valid params and redirects to correct page" do
expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1)
@@ -191,7 +191,7 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
@@ -201,7 +201,7 @@ RSpec.describe LocationsController, type: :request do
context "when signed in as a support user" do
let(:user) { FactoryBot.create(:user, :support) }
let!(:scheme) { FactoryBot.create(:scheme) }
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
@@ -219,13 +219,13 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
expect(Location.last.postcode).to eq("ZZ11ZZ")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
context "when postcode is submitted with lower case" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
it "creates a new location for scheme with postcode " do
expect(Location.last.postcode).to eq("ZZ11ZZ")
@@ -233,7 +233,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when required postcode param is missing" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No" } } }
it "displays the new page with an error message" do
post "/schemes/#{scheme.id}/locations", params: params
@@ -243,7 +243,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when do you want to add another location is selected as yes" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
it "creates a new location for scheme with valid params and redirects to correct page" do
expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1)
@@ -254,14 +254,14 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is selected as no" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
it "creates a new location for scheme with valid params and redirects to correct page" do
expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1)
@@ -272,14 +272,14 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is not selected" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
it "creates a new location for scheme with valid params and redirects to correct page" do
expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1)
@@ -290,7 +290,7 @@ RSpec.describe LocationsController, type: :request do
it "creates a new location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
@@ -390,7 +390,7 @@ RSpec.describe LocationsController, type: :request do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) }
let!(:location) { FactoryBot.create(:location, scheme:) }
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
before do
sign_in user
@@ -407,13 +407,13 @@ RSpec.describe LocationsController, type: :request do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
expect(Location.last.postcode).to eq("ZZ11ZZ")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
context "when postcode is submitted with lower case" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
it "updates existing location for scheme with postcode " do
expect(Location.last.postcode).to eq("ZZ11ZZ")
@@ -423,7 +423,7 @@ RSpec.describe LocationsController, type: :request do
context "when trying to update location for a scheme that belongs to another organisation" do
let(:another_scheme) { FactoryBot.create(:scheme) }
let(:another_location) { FactoryBot.create(:location) }
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
it "displays the new page with an error message" do
patch "/schemes/#{another_scheme.id}/locations/#{another_location.id}", params: params
@@ -432,7 +432,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when required postcode param is invalid" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "invalid" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "invalid" } } }
it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity)
@@ -441,7 +441,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when do you want to add another location is selected as yes" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
it "updates existing location for scheme with valid params and redirects to correct page" do
follow_redirect!
@@ -452,14 +452,14 @@ RSpec.describe LocationsController, type: :request do
it "updates existing location for scheme with valid params" do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is selected as no" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
it "updates existing location for scheme with valid params and redirects to correct page" do
follow_redirect!
@@ -470,14 +470,14 @@ RSpec.describe LocationsController, type: :request do
it "updates existing location for scheme with valid params" do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is not selected" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
it "updates existing location for scheme with valid params and redirects to correct page" do
follow_redirect!
@@ -488,7 +488,7 @@ RSpec.describe LocationsController, type: :request do
it "updates existing location for scheme with valid params" do
expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id)
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
@@ -499,7 +499,7 @@ RSpec.describe LocationsController, type: :request do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) }
let!(:location) { FactoryBot.create(:location, scheme:) }
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
@@ -516,13 +516,13 @@ RSpec.describe LocationsController, type: :request do
it "updates existing location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
expect(Location.last.postcode).to eq("ZZ11ZZ")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
context "when postcode is submitted with lower case" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "zz1 1zz" } } }
it "updates a location for scheme with postcode " do
expect(Location.last.postcode).to eq("ZZ11ZZ")
@@ -530,7 +530,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when required postcode param is missing" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "invalid" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "invalid" } } }
it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity)
@@ -539,7 +539,7 @@ RSpec.describe LocationsController, type: :request do
end
context "when do you want to add another location is selected as yes" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "Yes", postcode: "ZZ1 1ZZ" } } }
it "updates location for scheme with valid params and redirects to correct page" do
follow_redirect!
@@ -549,14 +549,14 @@ RSpec.describe LocationsController, type: :request do
it "updates existing location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is selected as no" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", add_another_location: "No", postcode: "ZZ1 1ZZ" } } }
it "updates a location for scheme with valid params and redirects to correct page" do
follow_redirect!
@@ -566,14 +566,14 @@ RSpec.describe LocationsController, type: :request do
it "updates existing location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
end
context "when do you want to add another location is not selected" do
- let(:params) { { location: { name: "Test", total_units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
+ let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", wheelchair_adaptation: "No", postcode: "ZZ1 1ZZ" } } }
it "updates a location for scheme with valid params and redirects to correct page" do
follow_redirect!
@@ -583,7 +583,7 @@ RSpec.describe LocationsController, type: :request do
it "updates a location for scheme with valid params" do
expect(Location.last.name).to eq("Test")
- expect(Location.last.total_units).to eq(5)
+ expect(Location.last.units).to eq(5)
expect(Location.last.type_of_unit).to eq("Bungalow")
expect(Location.last.wheelchair_adaptation).to eq("No")
end
diff --git a/spec/services/imports/scheme_import_service_spec.rb b/spec/services/imports/scheme_import_service_spec.rb
index 518db62dc..95d93ad26 100644
--- a/spec/services/imports/scheme_import_service_spec.rb
+++ b/spec/services/imports/scheme_import_service_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Imports::SchemeImportService do
File.open("#{directory}/#{filename}.xml")
end
- context "when importing case logs" do
+ context "when importing schemes" do
let(:remote_folder) { "mgmtgroups" }
before do
@@ -25,10 +25,10 @@ RSpec.describe Imports::SchemeImportService do
.and_return(%W[#{remote_folder}/#{scheme_id}.xml])
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{scheme_id}.xml")
- .and_return(open_file(fixture_directory, scheme_id), open_file(fixture_directory, scheme_id))
+ .and_return(open_file(fixture_directory, scheme_id))
end
- it "successfully create all case logs" do
+ it "successfully create all schemes" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info)
@@ -55,8 +55,8 @@ RSpec.describe Imports::SchemeImportService do
before { scheme_xml.at_xpath("//mgmtgroup:status").content = "Temporary" }
it "does not create the scheme" do
- scheme = scheme_service.create_scheme(scheme_xml)
- expect(scheme).to be_nil
+ expect { scheme_service.create_scheme(scheme_xml) }
+ .not_to change(Scheme, :count)
end
end
end
diff --git a/spec/services/imports/scheme_location_import_service_spec.rb b/spec/services/imports/scheme_location_import_service_spec.rb
new file mode 100644
index 000000000..3173c9a44
--- /dev/null
+++ b/spec/services/imports/scheme_location_import_service_spec.rb
@@ -0,0 +1,147 @@
+require "rails_helper"
+
+RSpec.describe Imports::SchemeLocationImportService do
+ subject(:location_service) { described_class.new(storage_service, logger) }
+
+ let(:storage_service) { instance_double(StorageService) }
+ let(:logger) { instance_double(ActiveSupport::Logger) }
+
+ let(:fixture_directory) { "spec/fixtures/imports/scheme_locations" }
+ let(:first_location_id) { "0ae7ad6dc0f1cf7ef33c18cc8c108bebc1b4923e" }
+ let(:second_location_id) { "0bb3836b70b4dd9903263d5a764a5c45b964a89d" }
+
+ let!(:scheme) { FactoryBot.create(:scheme, service_name: "Management Group", old_id: "6d6d7618b58affe2a150a5ef2e9f4765fa6cd05d") }
+
+ def open_file(directory, filename)
+ File.open("#{directory}/#{filename}.xml")
+ end
+
+ context "when importing scheme locations" do
+ let(:remote_folder) { "schemes" }
+
+ before do
+ # Stub the S3 file listing and download
+ allow(storage_service).to receive(:list_files)
+ .and_return(%W[#{remote_folder}/#{first_location_id}.xml #{remote_folder}/#{second_location_id}.xml])
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{first_location_id}.xml")
+ .and_return(open_file(fixture_directory, first_location_id))
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{second_location_id}.xml")
+ .and_return(open_file(fixture_directory, second_location_id))
+ end
+
+ it "successfully create all scheme locations" do
+ expect(logger).not_to receive(:error)
+ expect(logger).not_to receive(:warn)
+ expect(logger).not_to receive(:info)
+ expect { location_service.create_scheme_locations(remote_folder) }
+ .to change(Location, :count).by(2)
+ .and(change(Scheme, :count).by(0))
+ end
+ end
+
+ context "when importing different scheme locations" do
+ let(:location_xml_1) { Nokogiri::XML(open_file(fixture_directory, first_location_id)) }
+ let(:location_xml_2) { Nokogiri::XML(open_file(fixture_directory, second_location_id)) }
+
+ before { location_service.create_scheme_location(location_xml_1) }
+
+ context "and the scheme type is different" do
+ before { location_xml_2.at_xpath("//scheme:scheme-type").content = "5" }
+
+ it "renames the location scheme name" do
+ location = location_service.create_scheme_location(location_xml_2)
+ old_scheme = Scheme.find(scheme.id)
+ new_scheme = location.scheme
+
+ expect(old_scheme.service_name).to eq("Management Group - Housing for older people")
+ expect(new_scheme.service_name).to eq("Management Group - Direct Access Hostel")
+ end
+ end
+
+ context "and the registered under care act is different" do
+ before { location_xml_2.at_xpath("//scheme:reg-home-type").content = "2" }
+
+ it "renames both scheme names" do
+ location = location_service.create_scheme_location(location_xml_2)
+ old_scheme = Scheme.find(scheme.id)
+ new_scheme = location.scheme
+
+ expect(old_scheme.service_name).to eq("Management Group")
+ expect(new_scheme.service_name).to eq("Management Group - (Part-registered care home)")
+ end
+ end
+
+ context "and the support type is different" do
+ before { location_xml_2.at_xpath("//scheme:support-type").content = "3" }
+
+ it "renames both scheme names" do
+ location = location_service.create_scheme_location(location_xml_2)
+ old_scheme = Scheme.find(scheme.id)
+ new_scheme = location.scheme
+
+ expect(old_scheme.service_name).to eq("Management Group - Low levels of support")
+ expect(new_scheme.service_name).to eq("Management Group - Medium levels of support")
+ end
+ end
+
+ context "and the intended stay is different" do
+ before { location_xml_2.at_xpath("//scheme:intended-stay").content = "S" }
+
+ it "renames both scheme names" do
+ location = location_service.create_scheme_location(location_xml_2)
+ old_scheme = Scheme.find(scheme.id)
+ new_scheme = location.scheme
+
+ expect(old_scheme.service_name).to eq("Management Group - Permanent")
+ expect(new_scheme.service_name).to eq("Management Group - Short stay")
+ end
+ end
+
+ context "and the primary client group is different" do
+ before { location_xml_2.at_xpath("//scheme:client-group-1").content = "F" }
+
+ it "renames both scheme names" do
+ location = location_service.create_scheme_location(location_xml_2)
+ old_scheme = Scheme.find(scheme.id)
+ new_scheme = location.scheme
+
+ expect(old_scheme.service_name).to eq("Management Group - Older people with support needs")
+ expect(new_scheme.service_name).to eq("Management Group - People with drug problems")
+ end
+ end
+
+ context "and the secondary client group is different" do
+ before { location_xml_2.at_xpath("//scheme:client-group-2").content = "S" }
+
+ it "renames both scheme names" do
+ location = location_service.create_scheme_location(location_xml_2)
+ old_scheme = Scheme.find(scheme.id)
+ new_scheme = location.scheme
+
+ expect(old_scheme.service_name).to eq("Management Group")
+ expect(new_scheme.service_name).to eq("Management Group - Rough sleepers")
+ end
+ end
+ end
+
+ context "when importing a specific scheme location" do
+ let(:location_xml) { Nokogiri::XML(open_file(fixture_directory, first_location_id)) }
+
+ context "and the end date is before the current date" do
+ before do
+ Timecop.freeze(2022, 6, 1)
+ location_xml.at_xpath("//scheme:end-date").content = "2022-05-01"
+ end
+
+ after { Timecop.unfreeze }
+
+ it "does not create the location" do
+ expect(logger).to receive(:warn).with("Location with legacy ID 0ae7ad6dc0f1cf7ef33c18cc8c108bebc1b4923e is expired (2022-05-01 00:00:00 +0100), skipping")
+ expect { location_service.create_scheme_location(location_xml) }
+ .not_to change(Location, :count)
+ end
+ end
+ end
+end