From 5f9151158adde342d1b74873a2940eb120c1a3ec Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Wed, 22 Feb 2023 09:53:57 +0000 Subject: [PATCH] CLDC-1889 Bulk upload schemes + locations (#1329) * bulk upload validates scheme data * bulk upload schemes can use new core IDs * bulk upload handles locations --- app/models/location.rb | 6 + app/models/scheme.rb | 10 ++ .../bulk_upload/lettings/row_parser.rb | 50 ++++++++- spec/factories/location.rb | 5 + spec/factories/scheme.rb | 4 + .../bulk_upload/lettings/row_parser_spec.rb | 106 +++++++++++++++++- 6 files changed, 177 insertions(+), 4 deletions(-) diff --git a/app/models/location.rb b/app/models/location.rb index 36a134f81..3798c57e8 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -366,6 +366,12 @@ class Location < ApplicationRecord enum type_of_unit: TYPE_OF_UNIT + def self.find_by_id_on_mulitple_fields(id) + return if id.nil? + + where(id:).or(where(old_visible_id: id)).first + end + def postcode=(postcode) if postcode super UKPostcode.parse(postcode).to_s diff --git a/app/models/scheme.rb b/app/models/scheme.rb index f8cf6bf63..ca3624e3a 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -110,6 +110,16 @@ class Scheme < ApplicationRecord enum arrangement_type: ARRANGEMENT_TYPE, _suffix: true + def self.find_by_id_on_mulitple_fields(id) + return if id.nil? + + if id.start_with?("S") + where(id: id[1..]).first + else + where(old_visible_id: id).first + end + end + def id_to_display "S#{id}" end diff --git a/app/services/bulk_upload/lettings/row_parser.rb b/app/services/bulk_upload/lettings/row_parser.rb index 9cb3edb78..dcba8be28 100644 --- a/app/services/bulk_upload/lettings/row_parser.rb +++ b/app/services/bulk_upload/lettings/row_parser.rb @@ -8,7 +8,7 @@ class BulkUpload::Lettings::RowParser attribute :field_1, :integer attribute :field_2 attribute :field_3 - attribute :field_4, :integer + attribute :field_4, :string attribute :field_5, :integer attribute :field_6 attribute :field_7, :string @@ -164,6 +164,12 @@ class BulkUpload::Lettings::RowParser validate :validate_managing_org_related validate :validate_managing_org_exists + validate :validate_scheme_related + validate :validate_scheme_exists + + validate :validate_location_related + validate :validate_location_exists + def valid? errors.clear @@ -199,6 +205,45 @@ class BulkUpload::Lettings::RowParser private + def validate_location_related + return if scheme.blank? || location.blank? + + unless location.scheme == scheme + block_log_creation! + errors.add(:field_5, "Scheme code must relate to a location that is owned by owning organisation or managing organisation") + end + end + + def location + return if scheme.nil? + + @location ||= scheme.locations.find_by_id_on_mulitple_fields(field_5) + end + + def validate_location_exists + if scheme && field_5.present? && location.nil? + errors.add(:field_5, "Location could be found with provided scheme code") + end + end + + def validate_scheme_related + return unless field_4.present? && scheme.present? + + owned_by_owning_org = owning_organisation && scheme.owning_organisation == owning_organisation + owned_by_managing_org = managing_organisation && scheme.owning_organisation == managing_organisation + + unless owned_by_owning_org || owned_by_managing_org + block_log_creation! + errors.add(:field_4, "This management group code does not belong to your organisation, or any of your stock owners / managing agents") + end + end + + def validate_scheme_exists + if field_4.present? && scheme.nil? + errors.add(:field_4, "The management group code is not correct") + end + end + def validate_managing_org_related if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation) block_log_creation! @@ -566,6 +611,7 @@ private attributes["managing_organisation_id"] = managing_organisation_id attributes["renewal"] = renewal attributes["scheme"] = scheme + attributes["location"] = location attributes["created_by"] = bulk_upload.user attributes["needstype"] = bulk_upload.needstype attributes["rent_type"] = rent_type @@ -943,6 +989,6 @@ private end def scheme - @scheme ||= Scheme.find_by(old_visible_id: field_4) + @scheme ||= Scheme.find_by_id_on_mulitple_fields(field_4) end end diff --git a/spec/factories/location.rb b/spec/factories/location.rb index 75b4380f5..f43da0ac8 100644 --- a/spec/factories/location.rb +++ b/spec/factories/location.rb @@ -10,6 +10,7 @@ FactoryBot.define do startdate { Time.zone.local(2022, 4, 1) } confirmed { true } scheme + trait :export do postcode { "SW1A 2AA" } name { "Downing Street" } @@ -19,5 +20,9 @@ FactoryBot.define do scheme { FactoryBot.create(:scheme, :export) } old_visible_id { "111" } end + + trait :with_old_visible_id do + old_visible_id { rand(9_999_999).to_s } + end end end diff --git a/spec/factories/scheme.rb b/spec/factories/scheme.rb index 6c08e269d..155dea11a 100644 --- a/spec/factories/scheme.rb +++ b/spec/factories/scheme.rb @@ -21,5 +21,9 @@ FactoryBot.define do primary_client_group { "G" } secondary_client_group { "M" } end + + trait :with_old_visible_id do + old_visible_id { rand(9_999_999) } + end end end diff --git a/spec/services/bulk_upload/lettings/row_parser_spec.rb b/spec/services/bulk_upload/lettings/row_parser_spec.rb index d1792e9df..7a09ba4b8 100644 --- a/spec/services/bulk_upload/lettings/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/row_parser_spec.rb @@ -11,6 +11,8 @@ RSpec.describe BulkUpload::Lettings::RowParser do let(:owning_org) { create(:organisation, :with_old_visible_id) } let(:managing_org) { create(:organisation, :with_old_visible_id) } + let(:scheme) { create(:scheme, :with_old_visible_id, owning_organisation: owning_org) } + let(:location) { create(:location, :with_old_visible_id, scheme:) } let(:setup_section_params) do { @@ -85,7 +87,7 @@ RSpec.describe BulkUpload::Lettings::RowParser do { bulk_upload:, field_1: "1", - field_4: "1", + field_4: scheme.old_visible_id, field_7: "123", field_96: now.day.to_s, field_97: now.month.to_s, @@ -296,10 +298,90 @@ RSpec.describe BulkUpload::Lettings::RowParser do context "when matching scheme cannot be found" do let(:attributes) { { bulk_upload:, field_1: "1", field_4: "123" } } - xit "returns an error" do + it "returns an error" do expect(parser.errors[:field_4]).to be_present end end + + context "when scheme belongs to someone else" do + let(:other_scheme) { create(:scheme, :with_old_visible_id) } + let(:attributes) { { bulk_upload:, field_1: "1", field_4: other_scheme.old_visible_id, field_111: owning_org.old_visible_id } } + + it "returns an error" do + expect(parser.errors[:field_4]).to include("This management group code does not belong to your organisation, or any of your stock owners / managing agents") + end + end + + context "when scheme belongs to owning org" do + let(:scheme) { create(:scheme, :with_old_visible_id, owning_organisation: owning_org) } + let(:attributes) { { bulk_upload:, field_1: "1", field_4: scheme.old_visible_id, field_111: owning_org.old_visible_id } } + + it "does not return an error" do + expect(parser.errors[:field_4]).to be_blank + end + end + + context "when scheme belongs to managing org" do + let(:scheme) { create(:scheme, :with_old_visible_id, owning_organisation: managing_org) } + let(:attributes) { { bulk_upload:, field_1: "1", field_4: scheme.old_visible_id, field_113: managing_org.old_visible_id } } + + it "does not return an error" do + expect(parser.errors[:field_4]).to be_blank + end + end + end + + describe "#field_5" do + context "when location does not exist" do + let(:scheme) { create(:scheme, :with_old_visible_id, owning_organisation: owning_org) } + let(:attributes) do + { + bulk_upload:, + field_1: "1", + field_4: scheme.old_visible_id, + field_5: "dontexist", + field_111: owning_org.old_visible_id, + } + end + + it "returns an error" do + expect(parser.errors[:field_5]).to be_present + end + end + + context "when location exists" do + let(:scheme) { create(:scheme, :with_old_visible_id, owning_organisation: owning_org) } + let(:attributes) do + { + bulk_upload:, + field_1: "1", + field_4: scheme.old_visible_id, + field_5: location.old_visible_id, + field_111: owning_org.old_visible_id, + } + end + + it "does not return an error" do + expect(parser.errors[:field_5]).to be_blank + end + end + + context "when location exists but not related" do + let(:location) { create(:scheme, :with_old_visible_id) } + let(:attributes) do + { + bulk_upload:, + field_1: "1", + field_4: scheme.old_visible_id, + field_5: location.old_visible_id, + field_111: owning_org.old_visible_id, + } + end + + it "returns an error" do + expect(parser.errors[:field_5]).to be_present + end + end end describe "#field_7" do @@ -592,6 +674,26 @@ RSpec.describe BulkUpload::Lettings::RowParser do end describe "#log" do + describe "#location" do + context "when lookup is via new core id" do + let(:attributes) { { bulk_upload:, field_4: scheme.old_visible_id, field_5: location.id, field_111: owning_org } } + + it "assigns the correct location" do + expect(parser.log.location).to eql(location) + end + end + end + + describe "#scheme" do + context "when lookup is via id prefixed with S" do + let(:attributes) { { bulk_upload:, field_4: "S#{scheme.id}", field_111: owning_org } } + + it "assigns the correct scheme" do + expect(parser.log.scheme).to eql(scheme) + end + end + end + describe "#owning_organisation" do context "when lookup is via id prefixed with ORG" do let(:attributes) { { bulk_upload:, field_111: "ORG#{owning_org.id}" } }