These logs have the same values for the following fields. Choose one to keep or correct the answers.
+ <% end %>
+
+ <% @all_duplicates.each_with_index do |log, index| %>
+ <%= render partial: "duplicate_log", locals: { log: log } %>
+ <%= render partial: "duplicate_log_check_answers", locals: { log: log } %>
+ <%= govuk_button_link_to "Keep this log and delete duplicates", "#" %>
+ <% if index < @all_duplicates.count - 1 %>
+
+ <% end %>
+ <% end %>
+
+
diff --git a/config/routes.rb b/config/routes.rb
index 8b61f1ece..707e8e942 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -170,6 +170,7 @@ Rails.application.routes.draw do
resources :lettings_logs, path: "/lettings-logs" do
get "delete-confirmation", to: "lettings_logs#delete_confirmation"
+ get "duplicate-logs", to: "duplicate_logs#show"
collection do
post "bulk-upload", to: "bulk_upload#bulk_upload"
@@ -235,6 +236,7 @@ Rails.application.routes.draw do
resources :sales_logs, path: "/sales-logs" do
get "delete-confirmation", to: "sales_logs#delete_confirmation"
+ get "duplicate-logs", to: "duplicate_logs#show"
collection do
get "csv-download", to: "sales_logs#download_csv"
diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb
index b5b5e99cb..e2a15874a 100644
--- a/spec/models/lettings_log_spec.rb
+++ b/spec/models/lettings_log_spec.rb
@@ -2862,14 +2862,6 @@ RSpec.describe LettingsLog do
end
end
- context "when there is a log with a different propcode" do
- let!(:different_propcode) { create(:lettings_log, :duplicate, propcode: "different") }
-
- it "does not return a log with a different propcode as a duplicate" do
- expect(described_class.duplicate_logs(log)).not_to include(different_propcode)
- end
- end
-
context "when there is a log with a different tenancycode" do
let!(:different_tenancycode) { create(:lettings_log, :duplicate, tenancycode: "different") }
@@ -2887,10 +2879,10 @@ RSpec.describe LettingsLog do
end
context "when there is a log with nil values for duplicate check fields" do
- let!(:duplicate_check_fields_not_given) { create(:lettings_log, :duplicate, age1: nil, sex1: nil, ecstat1: nil, propcode: nil, postcode_known: 2, postcode_full: nil) }
+ let!(:duplicate_check_fields_not_given) { create(:lettings_log, :duplicate, age1: nil, sex1: nil, ecstat1: nil, postcode_known: 2, postcode_full: nil) }
it "does not return a log with nil values as a duplicate" do
- log.update!(age1: nil, sex1: nil, ecstat1: nil, propcode: nil, postcode_known: 2, postcode_full: nil)
+ log.update!(age1: nil, sex1: nil, ecstat1: nil, postcode_known: 2, postcode_full: nil)
expect(described_class.duplicate_logs(log)).not_to include(duplicate_check_fields_not_given)
end
end
@@ -2904,6 +2896,15 @@ RSpec.describe LettingsLog do
end
end
+ context "when there is a log with age1 not known" do
+ let!(:age1_not_known) { create(:lettings_log, :duplicate, age1_known: 1, age1: nil) }
+
+ it "returns the log as a duplicate if age1 is not known" do
+ log.update!(age1_known: 1, age1: nil)
+ expect(described_class.duplicate_logs(log)).to include(age1_not_known)
+ end
+ end
+
context "when there is a duplicate supported housing log" do
let(:scheme) { create(:scheme) }
let(:location) { create(:location, scheme:) }
@@ -2919,6 +2920,24 @@ RSpec.describe LettingsLog do
duplicate_supported_housing_log.update!(location: location_2)
expect(described_class.duplicate_logs(supported_housing_log)).not_to include(duplicate_supported_housing_log)
end
+
+ it "does not compare tcharge if there are no household charges" do
+ supported_housing_log.update!(household_charge: 1, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil)
+ duplicate_supported_housing_log.update!(household_charge: 1, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil)
+ expect(described_class.duplicate_logs(supported_housing_log)).to include(duplicate_supported_housing_log)
+ end
+
+ it "compares chcharge if it's a carehome" do
+ supported_housing_log.update!(is_carehome: 1, chcharge: 100, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil)
+ duplicate_supported_housing_log.update!(is_carehome: 1, chcharge: 100, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil)
+ expect(described_class.duplicate_logs(supported_housing_log)).to include(duplicate_supported_housing_log)
+ end
+
+ it "does not return a duplicate if carehome charge is not given" do
+ supported_housing_log.update!(is_carehome: 1, chcharge: nil, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil)
+ duplicate_supported_housing_log.update!(is_carehome: 1, chcharge: nil, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil)
+ expect(described_class.duplicate_logs(supported_housing_log)).not_to include(duplicate_supported_housing_log)
+ end
end
end
end
diff --git a/spec/models/sales_log_spec.rb b/spec/models/sales_log_spec.rb
index c382c364b..d032293c8 100644
--- a/spec/models/sales_log_spec.rb
+++ b/spec/models/sales_log_spec.rb
@@ -249,6 +249,33 @@ RSpec.describe SalesLog, type: :model do
expect(described_class.duplicate_logs(log)).to include(purchid_not_given)
end
end
+
+ context "when there is a log age not known" do
+ let!(:age1_not_known) { create(:sales_log, :duplicate, age1_known: 1, age1: nil) }
+
+ it "returns the log as a duplicate if age is not known" do
+ log.update!(age1_known: 1, age1: nil)
+ expect(described_class.duplicate_logs(log)).to include(age1_not_known)
+ end
+ end
+
+ context "when there is a log age pefers not to say" do
+ let!(:age1_prefers_not_to_say) { create(:sales_log, :duplicate, age1_known: 2, age1: nil) }
+
+ it "returns the log as a duplicate if age is prefers not to say" do
+ log.update!(age1_known: 2, age1: nil)
+ expect(described_class.duplicate_logs(log)).to include(age1_prefers_not_to_say)
+ end
+ end
+
+ context "when there is a log age pefers not to say and not known" do
+ let!(:age1_prefers_not_to_say) { create(:sales_log, :duplicate, age1_known: 2, age1: nil) }
+
+ it "does not return the log as a duplicate if age is prefers not to say" do
+ log.update!(age1_known: 1, age1: nil)
+ expect(described_class.duplicate_logs(log)).not_to include(age1_prefers_not_to_say)
+ end
+ end
end
describe "derived variables" do
diff --git a/spec/requests/duplicate_logs_controller_spec.rb b/spec/requests/duplicate_logs_controller_spec.rb
new file mode 100644
index 000000000..3ba94c218
--- /dev/null
+++ b/spec/requests/duplicate_logs_controller_spec.rb
@@ -0,0 +1,112 @@
+require "rails_helper"
+
+RSpec.describe DuplicateLogsController, type: :request do
+ let(:page) { Capybara::Node::Simple.new(response.body) }
+ let(:user) { create(:user) }
+
+ context "when a user is signed in" do
+ let(:lettings_log) do
+ create(
+ :lettings_log,
+ :completed,
+ created_by: user,
+ )
+ end
+ let(:sales_log) do
+ create(
+ :sales_log,
+ :completed,
+ created_by: user,
+ )
+ end
+
+ describe "GET" do
+ context "when user is not signed in" do
+ it "redirects to sign in page" do
+ get "/lettings-logs/#{lettings_log.id}/duplicate-logs"
+ expect(response).to redirect_to("/account/sign-in")
+ end
+ end
+
+ context "when the user is from different organisation" do
+ let(:other_user) { create(:user) }
+
+ before do
+ allow(other_user).to receive(:need_two_factor_authentication?).and_return(false)
+ sign_in other_user
+ end
+
+ it "renders page not found" do
+ get "/lettings-logs/#{lettings_log.id}/duplicate-logs"
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context "when user is signed in" do
+ before do
+ allow(user).to receive(:need_two_factor_authentication?).and_return(false)
+ sign_in user
+ end
+
+ context "with multiple duplicate lettings logs" do
+ let(:duplicate_logs) { create_list(:lettings_log, 2, :completed) }
+
+ before do
+ allow(LettingsLog).to receive(:duplicate_logs).and_return(duplicate_logs)
+ get "/lettings-logs/#{lettings_log.id}/duplicate-logs"
+ end
+
+ it "displays links to all the duplicate logs" do
+ expect(page).to have_link("Log #{lettings_log.id}", href: "/lettings-logs/#{lettings_log.id}")
+ expect(page).to have_link("Log #{duplicate_logs.first.id}", href: "/lettings-logs/#{duplicate_logs.first.id}")
+ expect(page).to have_link("Log #{duplicate_logs.second.id}", href: "/lettings-logs/#{duplicate_logs.second.id}")
+ end
+
+ it "displays check your answers for each log with correct questions" do
+ expect(page).to have_content("Q5 - Tenancy start date", count: 3)
+ expect(page).to have_content("Q7 - Tenant code", count: 3)
+ expect(page).to have_content("Q12 - Postcode", count: 3)
+ expect(page).to have_content("Q32 - Lead tenant’s age", count: 3)
+ expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 3)
+ expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 3)
+ expect(page).to have_content("Household rent and charges", count: 3)
+ expect(page).to have_link("Change", count: 21)
+ end
+
+ it "displays buttons to delete" do
+ expect(page).to have_link("Keep this log and delete duplicates", count: 3)
+ end
+ end
+
+ context "with multiple duplicate sales logs" do
+ let(:duplicate_logs) { create_list(:sales_log, 2, :completed) }
+
+ before do
+ allow(SalesLog).to receive(:duplicate_logs).and_return(duplicate_logs)
+ get "/sales-logs/#{sales_log.id}/duplicate-logs"
+ end
+
+ it "displays links to all the duplicate logs" do
+ expect(page).to have_link("Log #{sales_log.id}", href: "/sales-logs/#{sales_log.id}")
+ expect(page).to have_link("Log #{duplicate_logs.first.id}", href: "/sales-logs/#{duplicate_logs.first.id}")
+ expect(page).to have_link("Log #{duplicate_logs.second.id}", href: "/sales-logs/#{duplicate_logs.second.id}")
+ end
+
+ it "displays check your answers for each log with correct questions" do
+ expect(page).to have_content("Q1 - Sale completion date", count: 3)
+ expect(page).to have_content("Q2 - Purchaser code", count: 3)
+ expect(page).to have_content("Q20 - Lead buyer’s age", count: 3)
+ expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 3)
+ expect(page).to have_content("Q25 - Buyer 1's working situation", count: 3)
+ expect(page).to have_content("Q15 - Postcode", count: 3)
+ expect(page).to have_link("Change", count: 18)
+ end
+
+ it "displays buttons to delete" do
+ expect(page).to have_link("Keep this log and delete duplicates", count: 3)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/form_controller_spec.rb b/spec/requests/form_controller_spec.rb
index 0f086d27a..a6143f91a 100644
--- a/spec/requests/form_controller_spec.rb
+++ b/spec/requests/form_controller_spec.rb
@@ -532,6 +532,54 @@ RSpec.describe FormController, type: :request do
expect(whodunnit_actor).to be_a(User)
expect(whodunnit_actor.id).to eq(user.id)
end
+
+ context "and duplicate logs" do
+ let(:duplicate_logs) { create_list(:lettings_log, 2) }
+
+ before do
+ allow(LettingsLog).to receive(:duplicate_logs).and_return(duplicate_logs)
+ post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
+ end
+
+ it "redirects to the duplicate logs page" do
+ expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/duplicate-logs")
+ follow_redirect!
+ expect(page).to have_content("These logs are duplicates")
+ end
+ end
+ end
+
+ context "with valid sales answers" do
+ let(:sales_log) do
+ create(
+ :sales_log,
+ created_by: user,
+ )
+ end
+ let(:params) do
+ {
+ id: sales_log.id,
+ sales_log: {
+ page: "buyer-1-age",
+ age1: 20,
+ },
+ }
+ end
+
+ context "and duplicate logs" do
+ let(:duplicate_logs) { create_list(:sales_log, 2) }
+
+ before do
+ allow(SalesLog).to receive(:duplicate_logs).and_return(duplicate_logs)
+ post "/sales-logs/#{sales_log.id}/buyer-1-age", params:
+ end
+
+ it "redirects to the duplicate logs page" do
+ expect(response).to redirect_to("/sales-logs/#{sales_log.id}/duplicate-logs")
+ follow_redirect!
+ expect(page).to have_content("These logs are duplicates")
+ end
+ end
end
context "when the question has a conditional question" do
diff --git a/spec/services/bulk_upload/lettings/validator_spec.rb b/spec/services/bulk_upload/lettings/validator_spec.rb
index 26134735e..fa913e091 100644
--- a/spec/services/bulk_upload/lettings/validator_spec.rb
+++ b/spec/services/bulk_upload/lettings/validator_spec.rb
@@ -305,7 +305,7 @@ RSpec.describe BulkUpload::Lettings::Validator do
end
it "creates errors" do
- expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file"), :count).by(22)
+ expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file"), :count).by(20)
end
end
diff --git a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
index 4d2c28ee8..b91caa969 100644
--- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
@@ -258,7 +258,6 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
field_96: [error_message], # startdate
field_97: [error_message], # startdate
field_98: [error_message], # startdate
- field_100: [error_message], # propcode
field_108: [error_message], # postcode_full
field_109: [error_message], # postcode_full
field_111: [error_message], # owning_organisation
@@ -295,7 +294,6 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
:field_96, # startdate
:field_97, # startdate
:field_98, # startdate
- :field_100, # propcode
:field_111, # owning_organisation
].each do |field|
expect(parser.errors[field]).to include("This is a duplicate log")
@@ -329,7 +327,6 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
:field_96, # startdate
:field_97, # startdate
:field_98, # startdate
- :field_100, # propcode
:field_108, # postcode_full
:field_109, # postcode_full
:field_111, # owning_organisation
diff --git a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
index e177eb859..e12785738 100644
--- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
@@ -289,7 +289,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
:field_8, # startdate
:field_9, # startdate
:field_13, # tenancycode
- :field_14, # propcode
:field_23, # postcode_full
:field_24, # postcode_full
:field_25, # postcode_full
@@ -328,7 +327,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
:field_8, # startdate
:field_9, # startdate
:field_13, # tenancycode
- :field_14, # propcode
:field_17, # location
:field_46, # age1
:field_47, # sex1
@@ -363,7 +361,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
:field_7, # startdate
:field_8, # startdate
:field_9, # startdate
- :field_14, # propcode
:field_17, # location
:field_23, # postcode_full
:field_24, # postcode_full