Browse Source

CLDC 2286 Delete logs (#1620)

* Add LogPolicy

* Add letting log delete flow

* Add delete sales log flow

* Test for presence of buttons

* Use govuk_button_link_to

* Move actions to helper

* Allow deletion of delete and in progress logs

* better handle 500 error

* Soft delete logs

* Move specs to shared spec file

* Address comments

* Add scoping for data coordinators
pull/1640/head
Jack 2 years ago committed by GitHub
parent
commit
7950f2ae14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 46
      app/controllers/lettings_logs_controller.rb
  2. 28
      app/controllers/sales_logs_controller.rb
  3. 46
      app/helpers/log_actions_helper.rb
  4. 8
      app/models/log.rb
  5. 27
      app/policies/lettings_log_policy.rb
  6. 27
      app/policies/sales_log_policy.rb
  7. 2
      app/services/csv/lettings_log_csv_service.rb
  8. 4
      app/services/exports/lettings_log_export_service.rb
  9. 28
      app/views/logs/delete_confirmation.html.erb
  10. 14
      app/views/logs/edit.html.erb
  11. 4
      config/routes.rb
  12. 6
      db/migrate/20230515114101_add_discarded_at_to_logs.rb
  13. 10
      db/schema.rb
  14. 4
      spec/factories/lettings_log.rb
  15. 4
      spec/factories/sales_log.rb
  16. 4
      spec/fixtures/files/lettings_logs_download.csv
  17. 4
      spec/fixtures/files/lettings_logs_download_codes_only.csv
  18. 82
      spec/models/lettings_log_spec.rb
  19. 85
      spec/models/sales_log_spec.rb
  20. 114
      spec/policies/lettings_log_policy_spec.rb
  21. 114
      spec/policies/sales_log_policy_spec.rb
  22. 96
      spec/requests/lettings_logs_controller_spec.rb
  23. 92
      spec/requests/sales_logs_controller_spec.rb
  24. 783
      spec/services/csv/lettings_log_csv_service_spec.rb
  25. 107
      spec/shared/shared_log_examples.rb

46
app/controllers/lettings_logs_controller.rb

@ -1,5 +1,8 @@
class LettingsLogsController < LogsController class LettingsLogsController < LogsController
before_action :find_resource, except: %i[create index edit] rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
before_action :find_resource, only: %i[update show]
before_action :session_filters, if: :current_user, only: %i[index email_csv download_csv] before_action :session_filters, if: :current_user, only: %i[index email_csv download_csv]
before_action :set_session_filters, if: :current_user, only: %i[index email_csv download_csv] before_action :set_session_filters, if: :current_user, only: %i[index email_csv download_csv]
before_action :authenticate_scope!, only: %i[download_csv email_csv] before_action :authenticate_scope!, only: %i[download_csv email_csv]
@ -55,28 +58,31 @@ class LettingsLogsController < LogsController
end end
def edit def edit
@log = current_user.lettings_logs.find_by(id: params[:id]) @log = current_user.lettings_logs.find(params[:id])
if @log
if @log.unresolved if @log.unresolved
redirect_to(send(@log.form.unresolved_log_path, @log)) redirect_to(send(@log.form.unresolved_log_path, @log))
else
render("logs/edit", locals: { current_user: })
end
else else
render_not_found render("logs/edit", locals: { current_user: })
end end
end end
def destroy def destroy
if @log @log = LettingsLog.visible.find(params[:id])
if @log.delete
head :no_content authorize @log
else
render json: { errors: @log.errors.messages }, status: :unprocessable_entity @log.discard!
end
else redirect_to lettings_logs_path, notice: "Log #{@log.id} has been deleted"
render_not_found_json("Log", params[:id]) end
end
def delete_confirmation
@log = LettingsLog.visible.find(params[:lettings_log_id])
authorize @log, :destroy?
render "logs/delete_confirmation"
end end
def download_csv def download_csv
@ -105,14 +111,14 @@ class LettingsLogsController < LogsController
end end
end end
private
def org_params def org_params
super.merge( super.merge(
{ "managing_organisation_id" => current_user.organisation.id }, { "managing_organisation_id" => current_user.organisation.id },
) )
end end
private
def authenticate_scope! def authenticate_scope!
head :unauthorized and return if codes_only_export? && !current_user.support? head :unauthorized and return if codes_only_export? && !current_user.support?
end end

28
app/controllers/sales_logs_controller.rb

@ -1,4 +1,6 @@
class SalesLogsController < LogsController class SalesLogsController < LogsController
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
before_action :session_filters, if: :current_user, only: %i[index email_csv download_csv] before_action :session_filters, if: :current_user, only: %i[index email_csv download_csv]
before_action :set_session_filters, if: :current_user, only: %i[index email_csv download_csv] before_action :set_session_filters, if: :current_user, only: %i[index email_csv download_csv]
before_action :authenticate_scope!, only: %i[download_csv email_csv] before_action :authenticate_scope!, only: %i[download_csv email_csv]
@ -32,12 +34,26 @@ class SalesLogsController < LogsController
end end
def edit def edit
@log = current_user.sales_logs.visible.find_by(id: params[:id]) @log = current_user.sales_logs.visible.find(params[:id])
if @log render "logs/edit", locals: { current_user: }
render "logs/edit", locals: { current_user: } end
else
render_not_found def destroy
end @log = SalesLog.visible.find(params[:id])
authorize @log
@log.discard!
redirect_to sales_logs_path, notice: "Log #{@log.id} has been deleted"
end
def delete_confirmation
@log = SalesLog.visible.find(params[:sales_log_id])
authorize @log, :destroy?
render "logs/delete_confirmation"
end end
def download_csv def download_csv

46
app/helpers/log_actions_helper.rb

@ -0,0 +1,46 @@
module LogActionsHelper
include GovukLinkHelper
def edit_actions_for_log(log)
back = back_button_for(log)
delete = delete_button_for_log(log)
return if back.nil? && delete.nil?
content_tag(:div, class: "govuk-button-group") do
safe_join([back, delete])
end
end
private
def back_button_for(log)
if log.completed?
if log.bulk_uploaded?
if log.lettings?
govuk_button_link_to "Back to uploaded logs", resume_bulk_upload_lettings_result_path(log.bulk_upload)
else
govuk_button_link_to "Back to uploaded logs", resume_bulk_upload_sales_result_path(log.bulk_upload)
end
elsif log.lettings?
govuk_button_link_to "Back to lettings logs", lettings_logs_path
elsif log.sales?
govuk_button_link_to "Back to sales logs", sales_logs_path
end
end
end
def policy_class_for(log)
log.lettings? ? LettingsLogPolicy : SalesLogPolicy
end
def delete_button_for_log(log)
if policy_class_for(log).new(current_user, log).destroy?
govuk_button_link_to(
"Delete log",
lettings_log_delete_confirmation_path(log),
warning: true,
)
end
end
end

8
app/models/log.rb

@ -15,11 +15,13 @@ class Log < ApplicationRecord
"in_progress" => 1, "in_progress" => 1,
"completed" => 2, "completed" => 2,
"pending" => 3, "pending" => 3,
"deleted" => 4,
}.freeze }.freeze
enum status: STATUS enum status: STATUS
enum status_cache: STATUS, _prefix: true enum status_cache: STATUS, _prefix: true
scope :visible, -> { where(status: %w[not_started in_progress completed]) } scope :visible, -> { where(status: %w[not_started in_progress completed]) }
scope :exportable, -> { where(status: %w[not_started in_progress completed deleted]) }
scope :filter_by_status, ->(status, _user = nil) { where status: } scope :filter_by_status, ->(status, _user = nil) { where status: }
scope :filter_by_years, lambda { |years, _user = nil| scope :filter_by_years, lambda { |years, _user = nil|
@ -129,7 +131,13 @@ class Log < ApplicationRecord
end end
end end
def discard!
update!(status: "deleted", discarded_at: Time.zone.now)
end
def calculate_status def calculate_status
return "deleted" if discarded_at.present?
if all_fields_completed? && errors.empty? if all_fields_completed? && errors.empty?
"completed" "completed"
elsif all_fields_nil? elsif all_fields_nil?

27
app/policies/lettings_log_policy.rb

@ -0,0 +1,27 @@
class LettingsLogPolicy
attr_reader :user, :log
def initialize(user, log)
@user = user
@log = log
end
def destroy?
return false unless log && user
# Can only delete editable logs
return false unless log.collection_period_open?
# Only delete logs with answered questions
return false unless log.in_progress? || log.completed?
# Support users can delete any log
return true if user.support?
# Data coordinators can delete any log visible to them
return true if user.data_coordinator? && user.lettings_logs.visible.include?(log)
# Data providers can only delete the log if it is assigned to them
log.created_by == user
end
end

27
app/policies/sales_log_policy.rb

@ -0,0 +1,27 @@
class SalesLogPolicy
attr_reader :user, :log
def initialize(user, log)
@user = user
@log = log
end
def destroy?
return false unless log && user
# Can only delete editable logs
return false unless log.collection_period_open?
# Only delete logs with answered questions
return false unless log.in_progress? || log.completed?
# Support users can delete any log
return true if user.support?
# Data coordinators can delete any log visible to them
return true if user.data_coordinator? && user.sales_logs.visible.include?(log)
# Data providers can only delete the log if it is assigned to them
log.created_by == user
end
end

2
app/services/csv/lettings_log_csv_service.rb

@ -1,6 +1,6 @@
module Csv module Csv
class LettingsLogCsvService class LettingsLogCsvService
CSV_FIELDS_TO_OMIT = %w[hhmemb net_income_value_check first_time_property_let_as_social_housing renttype needstype postcode_known is_la_inferred totchild totelder totadult net_income_known is_carehome previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 rent_type_detail wrent wscharge wpschrge wsupchrg wtcharge wtshortfall rent_value_check old_form_id old_id retirement_value_check tshortfall_known pregnancy_value_check hhtype new_old vacdays la prevloc unresolved updated_by_id bulk_upload_id uprn_confirmed status_cache].freeze CSV_FIELDS_TO_OMIT = %w[hhmemb net_income_value_check first_time_property_let_as_social_housing renttype needstype postcode_known is_la_inferred totchild totelder totadult net_income_known is_carehome previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 rent_type_detail wrent wscharge wpschrge wsupchrg wtcharge wtshortfall rent_value_check old_form_id old_id retirement_value_check tshortfall_known pregnancy_value_check hhtype new_old vacdays la prevloc unresolved updated_by_id bulk_upload_id uprn_confirmed status_cache discarded_at].freeze
def initialize(user, export_type:) def initialize(user, export_type:)
@user = user @user = user

4
app/services/exports/lettings_log_export_service.rb

@ -119,10 +119,10 @@ module Exports
if !full_update && recent_export if !full_update && recent_export
params = { from: recent_export.started_at, to: start_time } params = { from: recent_export.started_at, to: start_time }
LettingsLog.visible.where("updated_at >= :from and updated_at <= :to", params) LettingsLog.exportable.where("updated_at >= :from and updated_at <= :to", params)
else else
params = { to: start_time } params = { to: start_time }
LettingsLog.visible.where("updated_at <= :to", params) LettingsLog.exportable.where("updated_at <= :to", params)
end end
end end

28
app/views/logs/delete_confirmation.html.erb

@ -0,0 +1,28 @@
<% content_for :before_content do %>
<% content_for :title, "Are you sure you want to delete this log?" %>
<%= govuk_back_link href: @log.lettings? ? lettings_logs_path : sales_logs_path %>
<% end %>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds-from-desktop">
<span class="govuk-caption-xl">Delete log <%= @log.id %></span>
<h1 class="govuk-heading-xl">
<%= content_for(:title) %>
</h1>
<%= govuk_warning_text(text: "You will not be able to undo this action.") %>
<div class="govuk-button-group">
<%= govuk_button_to(
"Delete this log",
@log.lettings? ? lettings_log_path(@log) : sales_log_path(@log),
method: :delete,
) %>
<%= govuk_button_link_to(
"Cancel",
@log.lettings? ? lettings_log_path(@log) : sales_log_path(@log),
secondary: true,
) %>
</div>
</div>
</div>

14
app/views/logs/edit.html.erb

@ -38,18 +38,6 @@
<%= render "tasklist" %> <%= render "tasklist" %>
<% if @log.completed? %> <%= edit_actions_for_log(@log) %>
<% if @log.bulk_uploaded? %>
<% if @log.lettings? %>
<%= govuk_button_link_to "Back to uploaded logs", resume_bulk_upload_lettings_result_path(@log.bulk_upload) %>
<% else %>
<%= govuk_button_link_to "Back to uploaded logs", resume_bulk_upload_sales_result_path(@log.bulk_upload) %>
<% end %>
<% elsif @log.lettings? %>
<%= govuk_button_link_to "Back to lettings logs", lettings_logs_path %>
<% elsif @log.sales? %>
<%= govuk_button_link_to "Back to sales logs", sales_logs_path %>
<% end %>
<% end %>
</div> </div>
</div> </div>

4
config/routes.rb

@ -150,6 +150,8 @@ Rails.application.routes.draw do
end end
resources :lettings_logs, path: "/lettings-logs" do resources :lettings_logs, path: "/lettings-logs" do
get "delete-confirmation", to: "lettings_logs#delete_confirmation"
collection do collection do
post "bulk-upload", to: "bulk_upload#bulk_upload" post "bulk-upload", to: "bulk_upload#bulk_upload"
get "bulk-upload", to: "bulk_upload#show" get "bulk-upload", to: "bulk_upload#show"
@ -208,6 +210,8 @@ Rails.application.routes.draw do
end end
resources :sales_logs, path: "/sales-logs" do resources :sales_logs, path: "/sales-logs" do
get "delete-confirmation", to: "sales_logs#delete_confirmation"
collection do collection do
get "csv-download", to: "sales_logs#download_csv" get "csv-download", to: "sales_logs#download_csv"
post "email-csv", to: "sales_logs#email_csv" post "email-csv", to: "sales_logs#email_csv"

6
db/migrate/20230515114101_add_discarded_at_to_logs.rb

@ -0,0 +1,6 @@
class AddDiscardedAtToLogs < ActiveRecord::Migration[7.0]
def change
add_column :sales_logs, :discarded_at, :datetime
add_column :lettings_logs, :discarded_at, :datetime
end
end

10
db/schema.rb

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_05_05_105327) do ActiveRecord::Schema[7.0].define(version: 2023_05_15_114101) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -288,6 +288,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_05_05_105327) do
t.string "county" t.string "county"
t.integer "carehome_charges_value_check" t.integer "carehome_charges_value_check"
t.integer "status_cache", default: 0, null: false t.integer "status_cache", default: 0, null: false
t.datetime "discarded_at"
t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id" t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id"
t.index ["location_id"], name: "index_lettings_logs_on_location_id" t.index ["location_id"], name: "index_lettings_logs_on_location_id"
@ -584,6 +585,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_05_05_105327) do
t.integer "ethnicbuy2" t.integer "ethnicbuy2"
t.integer "proplen_asked" t.integer "proplen_asked"
t.string "old_id" t.string "old_id"
t.integer "buy2living"
t.integer "prevtenbuy2"
t.integer "pregblank" t.integer "pregblank"
t.string "uprn" t.string "uprn"
t.integer "uprn_known" t.integer "uprn_known"
@ -592,15 +595,14 @@ ActiveRecord::Schema[7.0].define(version: 2023_05_05_105327) do
t.string "address_line2" t.string "address_line2"
t.string "town_or_city" t.string "town_or_city"
t.string "county" t.string "county"
t.integer "buy2living"
t.integer "prevtenbuy2"
t.integer "nationalbuy2" t.integer "nationalbuy2"
t.integer "discounted_sale_value_check" t.integer "discounted_sale_value_check"
t.integer "student_not_child_value_check" t.integer "student_not_child_value_check"
t.integer "percentage_discount_value_check" t.integer "percentage_discount_value_check"
t.integer "buyer_livein_value_check" t.integer "buyer_livein_value_check"
t.integer "combined_income_value_check"
t.integer "status_cache", default: 0, null: false t.integer "status_cache", default: 0, null: false
t.integer "combined_income_value_check"
t.datetime "discarded_at"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true

4
spec/factories/lettings_log.rb

@ -164,6 +164,10 @@ FactoryBot.define do
trait :startdate_today do trait :startdate_today do
startdate { Time.zone.today } startdate { Time.zone.today }
end end
trait :deleted do
status { 4 }
discarded_at { Time.zone.now }
end
created_at { Time.zone.today } created_at { Time.zone.today }
updated_at { Time.zone.today } updated_at { Time.zone.today }
end end

4
spec/factories/sales_log.rb

@ -129,5 +129,9 @@ FactoryBot.define do
trait :with_uprn do trait :with_uprn do
uprn { rand(999_999_999_999).to_s } uprn { rand(999_999_999_999).to_s }
end end
trait :deleted do
status { 4 }
discarded_at { Time.zone.now }
end
end end
end end

4
spec/fixtures/files/lettings_logs_download.csv vendored

@ -1,2 +1,2 @@
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,rent_value_check,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,status_cache,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,rent_value_check,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,status_cache,discarded_at,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,not_started,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} {id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,not_started,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate}

1 id status created_at updated_at created_by_name is_dpo owning_organisation_name managing_organisation_name collection_start_year rent_value_check needstype renewal startdate rent_type_detail irproduct_other tenancycode propcode age1 sex1 ecstat1 hhmemb relat2 age2 sex2 retirement_value_check ecstat2 armedforces leftreg illness housingneeds_a housingneeds_b housingneeds_c housingneeds_h is_previous_la_inferred prevloc_label prevloc illness_type_1 illness_type_2 is_la_inferred la_label la postcode_known postcode_full previous_la_known wchair preg_occ cbl earnings incfreq net_income_value_check benefits hb period brent scharge pscharge supcharg tcharge offered layear ppostcode_full mrcdate declaration ethnic national prevten age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap reservist startertenancy tenancylength tenancy rsnvac unittype_gn beds waityear reasonpref chr cap reasonother housingneeds_f housingneeds_g illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother property_owner_organisation property_manager_organisation purchaser_code reason majorrepairs hbrentshortfall property_relet incref first_time_property_let_as_social_housing unitletas builtype voiddate renttype lettype totchild totelder totadult net_income_known nocharge is_carehome household_charge referral tshortfall chcharge ppcodenk age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known ethnic_group letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 has_benefits wrent wscharge wpschrge wsupchrg wtcharge wtshortfall refused housingneeds wchchrg newprop relat3 relat4 relat5 relat6 relat7 relat8 old_form_id lar irproduct old_id joint tshortfall_known sheltered pregnancy_value_check hhtype new_old vacdays major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other unresolved updated_by_id uprn uprn_known uprn_confirmed address_line1 address_line2 town_or_city county carehome_charges_value_check status_cache discarded_at unittype_sh scheme_code scheme_service_name scheme_sensitive scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_admin_district location_startdate
2 {id} in_progress 2022-02-08 16:52:15 +0000 2022-02-08 16:52:15 +0000 Danny Rojas No DLUHC DLUHC 2021 Supported housing 2 October 2021 London Affordable Rent No No Westminster E09000033 SE1 1TE No 2 8 0 0 0 0 0 0 9 1 not_started 6 {scheme_code} {scheme_service_name} {scheme_sensitive} Missing No DLUHC {scheme_primary_client_group} {scheme_secondary_client_group} {scheme_support_type} {scheme_intended_stay} 2021-04-01 00:00:00 +0100 {location_code} SE1 1TE Downing Street 20 Bungalow Fitted with equipment and adaptations Westminster {location_startdate}

4
spec/fixtures/files/lettings_logs_download_codes_only.csv vendored

@ -1,2 +1,2 @@
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,rent_value_check,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,status_cache,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,rent_value_check,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,status_cache,discarded_at,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,not_started,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate} {id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,not_started,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate}

1 id status created_at updated_at created_by_name is_dpo owning_organisation_name managing_organisation_name collection_start_year rent_value_check needstype renewal startdate rent_type_detail irproduct_other tenancycode propcode age1 sex1 ecstat1 hhmemb relat2 age2 sex2 retirement_value_check ecstat2 armedforces leftreg illness housingneeds_a housingneeds_b housingneeds_c housingneeds_h is_previous_la_inferred prevloc_label prevloc illness_type_1 illness_type_2 is_la_inferred la_label la postcode_known postcode_full previous_la_known wchair preg_occ cbl earnings incfreq net_income_value_check benefits hb period brent scharge pscharge supcharg tcharge offered layear ppostcode_full mrcdate declaration ethnic national prevten age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap reservist startertenancy tenancylength tenancy rsnvac unittype_gn beds waityear reasonpref chr cap reasonother housingneeds_f housingneeds_g illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother property_owner_organisation property_manager_organisation purchaser_code reason majorrepairs hbrentshortfall property_relet incref first_time_property_let_as_social_housing unitletas builtype voiddate renttype lettype totchild totelder totadult net_income_known nocharge is_carehome household_charge referral tshortfall chcharge ppcodenk age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known ethnic_group letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 has_benefits wrent wscharge wpschrge wsupchrg wtcharge wtshortfall refused housingneeds wchchrg newprop relat3 relat4 relat5 relat6 relat7 relat8 old_form_id lar irproduct old_id joint tshortfall_known sheltered pregnancy_value_check hhtype new_old vacdays major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other unresolved updated_by_id uprn uprn_known uprn_confirmed address_line1 address_line2 town_or_city county carehome_charges_value_check status_cache discarded_at unittype_sh scheme_code scheme_service_name scheme_sensitive scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_admin_district location_startdate
2 {id} in_progress 2022-02-08 16:52:15 +0000 2022-02-08 16:52:15 +0000 Danny Rojas false DLUHC DLUHC 2021 2 2 October 2021 2 false false Westminster E09000033 SE1 1TE 2 2 8 0 0 0 0 0 0 9 1 not_started 6 {scheme_code} {scheme_service_name} {scheme_sensitive} 0 1 DLUHC {scheme_primary_client_group} {scheme_secondary_client_group} {scheme_support_type} {scheme_intended_stay} 2021-04-01 00:00:00 +0100 {location_code} SE1 1TE Downing Street 20 6 A Westminster {location_startdate}

82
spec/models/lettings_log_spec.rb

@ -1,8 +1,8 @@
require "rails_helper" require "rails_helper"
require "shared/shared_examples_for_derived_fields" require "shared/shared_examples_for_derived_fields"
require "shared/shared_log_examples"
# rubocop:disable RSpec/MessageChain # rubocop:disable RSpec/MessageChain
# rubocop:disable RSpec/AnyInstance
RSpec.describe LettingsLog do RSpec.describe LettingsLog do
let(:different_managing_organisation) { create(:organisation) } let(:different_managing_organisation) { create(:organisation) }
let(:created_by_user) { create(:user) } let(:created_by_user) { create(:user) }
@ -23,6 +23,7 @@ RSpec.describe LettingsLog do
end end
include_examples "shared examples for derived fields", :lettings_log include_examples "shared examples for derived fields", :lettings_log
include_examples "shared log examples", :lettings_log
it "inherits from log" do it "inherits from log" do
expect(described_class).to be < Log expect(described_class).to be < Log
@ -183,27 +184,7 @@ RSpec.describe LettingsLog do
end end
describe "status" do describe "status" do
let!(:empty_lettings_log) { create(:lettings_log) } let(:completed_lettings_log) { create(:lettings_log, :completed) }
let!(:in_progress_lettings_log) { create(:lettings_log, :in_progress) }
let!(:completed_lettings_log) { create(:lettings_log, :completed) }
it "is set to not started for an empty lettings log" do
expect(empty_lettings_log.not_started?).to be(true)
expect(empty_lettings_log.in_progress?).to be(false)
expect(empty_lettings_log.completed?).to be(false)
end
it "is set to in progress for a started lettings log" do
expect(in_progress_lettings_log.in_progress?).to be(true)
expect(in_progress_lettings_log.not_started?).to be(false)
expect(in_progress_lettings_log.completed?).to be(false)
end
it "is set to completed for a completed lettings log" do
expect(completed_lettings_log.in_progress?).to be(false)
expect(completed_lettings_log.not_started?).to be(false)
expect(completed_lettings_log.completed?).to be(true)
end
context "when only a subsection that is hidden in tasklist is not completed" do context "when only a subsection that is hidden in tasklist is not completed" do
let(:household_characteristics_subsection) { completed_lettings_log.form.get_subsection("household_characteristics") } let(:household_characteristics_subsection) { completed_lettings_log.form.get_subsection("household_characteristics") }
@ -3009,62 +2990,6 @@ RSpec.describe LettingsLog do
end end
end end
describe "#process_uprn_change!" do
context "when UPRN set to a value" do
let(:lettings_log) do
create(
:lettings_log,
uprn: "123456789",
uprn_confirmed: 1,
county: "county",
)
end
it "updates sales log fields" do
lettings_log.uprn = "1111111"
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:result).and_return({
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
})
expect { lettings_log.process_uprn_change! }.to change(lettings_log, :address_line1).from(nil).to("0, Building Name, Thoroughfare")
.and change(lettings_log, :town_or_city).from(nil).to("Posttown")
.and change(lettings_log, :postcode_full).from(nil).to("POSTCODE")
.and change(lettings_log, :uprn_confirmed).from(1).to(nil)
.and change(lettings_log, :county).from("county").to(nil)
.and change(lettings_log, :uprn_known).from(nil).to(1)
end
end
context "when UPRN nil" do
let(:lettings_log) { create(:lettings_log, uprn: nil) }
it "does not update sales log" do
expect { lettings_log.process_uprn_change! }.not_to change(lettings_log, :attributes)
end
end
context "when service errors" do
let(:lettings_log) { create(:lettings_log, uprn: "123456789", uprn_confirmed: 1) }
let(:error_message) { "error" }
it "adds error to sales log" do
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:error).and_return(error_message)
expect { lettings_log.process_uprn_change! }.to change { lettings_log.errors[:uprn] }.from([]).to([error_message])
end
end
end
describe "#beds_for_la_rent_range" do describe "#beds_for_la_rent_range" do
context "when beds nil" do context "when beds nil" do
let(:lettings_log) { build(:lettings_log, beds: nil) } let(:lettings_log) { build(:lettings_log, beds: nil) }
@ -3140,5 +3065,4 @@ RSpec.describe LettingsLog do
end end
end end
end end
# rubocop:enable RSpec/AnyInstance
# rubocop:enable RSpec/MessageChain # rubocop:enable RSpec/MessageChain

85
spec/models/sales_log_spec.rb

@ -1,13 +1,14 @@
require "rails_helper" require "rails_helper"
require "shared/shared_examples_for_derived_fields" require "shared/shared_examples_for_derived_fields"
require "shared/shared_log_examples"
# rubocop:disable RSpec/MessageChain # rubocop:disable RSpec/MessageChain
# rubocop:disable RSpec/AnyInstance
RSpec.describe SalesLog, type: :model do RSpec.describe SalesLog, type: :model do
let(:owning_organisation) { create(:organisation) } let(:owning_organisation) { create(:organisation) }
let(:created_by_user) { create(:user) } let(:created_by_user) { create(:user) }
include_examples "shared examples for derived fields", :sales_log include_examples "shared examples for derived fields", :sales_log
include_examples "shared log examples", :sales_log
it "inherits from log" do it "inherits from log" do
expect(described_class).to be < Log expect(described_class).to be < Log
@ -112,27 +113,7 @@ RSpec.describe SalesLog, type: :model do
end end
describe "status" do describe "status" do
let!(:empty_sales_log) { create(:sales_log) } let(:completed_sales_log) { create(:sales_log, :completed) }
let!(:in_progress_sales_log) { create(:sales_log, :in_progress) }
let!(:completed_sales_log) { create(:sales_log, :completed) }
it "is set to not started for an empty sales log" do
expect(empty_sales_log.not_started?).to be(true)
expect(empty_sales_log.in_progress?).to be(false)
expect(empty_sales_log.completed?).to be(false)
end
it "is set to in progress for a started sales log" do
expect(in_progress_sales_log.in_progress?).to be(true)
expect(in_progress_sales_log.not_started?).to be(false)
expect(in_progress_sales_log.completed?).to be(false)
end
it "is set to completed for a completed sales log" do
expect(completed_sales_log.in_progress?).to be(false)
expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(true)
end
context "when proplen is not given" do context "when proplen is not given" do
before do before do
@ -148,6 +129,7 @@ RSpec.describe SalesLog, type: :model do
expect(completed_sales_log.in_progress?).to be(false) expect(completed_sales_log.in_progress?).to be(false)
expect(completed_sales_log.not_started?).to be(false) expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(true) expect(completed_sales_log.completed?).to be(true)
expect(completed_sales_log.deleted?).to be(false)
end end
it "is set to in_progress for a log with a saledate after 23/24" do it "is set to in_progress for a log with a saledate after 23/24" do
@ -155,6 +137,7 @@ RSpec.describe SalesLog, type: :model do
expect(completed_sales_log.in_progress?).to be(true) expect(completed_sales_log.in_progress?).to be(true)
expect(completed_sales_log.not_started?).to be(false) expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(false) expect(completed_sales_log.completed?).to be(false)
expect(completed_sales_log.deleted?).to be(false)
end end
end end
end end
@ -591,63 +574,6 @@ RSpec.describe SalesLog, type: :model do
end end
end end
describe "#process_uprn_change!" do
context "when UPRN set to a value" do
let(:sales_log) do
create(
:sales_log,
uprn: "123456789",
uprn_confirmed: 1,
county: "county",
)
end
it "updates sales log fields" do
sales_log.uprn = "1111111"
sales_log.uprn_confirmed = 1
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:result).and_return({
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
})
expect { sales_log.process_uprn_change! }.to change(sales_log, :address_line1).from(nil).to("0, Building Name, Thoroughfare")
.and change(sales_log, :town_or_city).from(nil).to("Posttown")
.and change(sales_log, :postcode_full).from(nil).to("POSTCODE")
.and change(sales_log, :uprn_confirmed).from(1).to(nil)
.and change(sales_log, :county).from("county").to(nil)
.and change(sales_log, :uprn_known).from(nil).to(1)
end
end
context "when UPRN nil" do
let(:sales_log) { create(:sales_log, uprn: nil) }
it "does not update sales log" do
expect { sales_log.process_uprn_change! }.not_to change(sales_log, :attributes)
end
end
context "when the API returns an error" do
let(:sales_log) { build(:sales_log, :outright_sale_setup_complete, uprn_known: 1, uprn: "123456789", uprn_confirmed: 1) }
let(:error_message) { "error" }
it "adds error to sales log" do
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:error).and_return(error_message)
expect { sales_log.process_uprn_change! }.to change { sales_log.errors[:uprn] }.from([]).to([error_message])
end
end
end
describe "#beds_for_la_sale_range" do describe "#beds_for_la_sale_range" do
context "when beds nil" do context "when beds nil" do
let(:sales_log) { build(:sales_log, beds: nil) } let(:sales_log) { build(:sales_log, beds: nil) }
@ -723,5 +649,4 @@ RSpec.describe SalesLog, type: :model do
end end
end end
end end
# rubocop:enable RSpec/AnyInstance
# rubocop:enable RSpec/MessageChain # rubocop:enable RSpec/MessageChain

114
spec/policies/lettings_log_policy_spec.rb

@ -0,0 +1,114 @@
require "rails_helper"
RSpec.describe LettingsLogPolicy do
subject(:policy) { described_class }
permissions :destroy? do
let(:log) { create(:lettings_log, :in_progress) }
context "when log nil" do
before do
allow(log).to receive(:collection_period_open?).and_return(false)
end
it "does not allow deletion of log" do
expect(policy).not_to permit(build(:user, :support), nil)
end
end
context "when user nil" do
before do
allow(log).to receive(:collection_period_open?).and_return(false)
end
it "does not allow deletion of log" do
expect(policy).not_to permit(nil, build(:lettings_log, :in_progress))
end
end
context "when collection period closed" do
before do
allow(log).to receive(:collection_period_open?).and_return(false)
end
it "does not allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(build(:user, :support), log)
end
end
context "when collection period open" do
before do
allow(log).to receive(:collection_period_open?).and_return(true)
end
context "when not started" do
before do
allow(log).to receive(:in_progress?).and_return(false)
allow(log).to receive(:completed?).and_return(false)
end
it "does not allow deletion of log" do
expect(log).to receive(:in_progress?)
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(build(:user, :support), log)
end
end
[
%i[lettings_log in_progress],
%i[lettings_log completed],
].each do |type, status|
let(:log) { create(type, status) }
context "when #{type} status: #{status}" do
context "when user is data coordinator" do
let(:user) { create(:user, :data_coordinator) }
let(:user_of_managing_org) { create(:user, :data_coordinator, organisation: log.managing_organisation) }
it "does not allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(user, log)
end
it "allows deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).to permit(user_of_managing_org, log)
end
end
context "when user is support" do
let(:user) { create(:user, :support) }
it "does allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).to permit(user, log)
end
end
context "when user is data provider" do
let(:user) { create(:user) }
it "does not allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(user, log)
end
context "when the log is assigned to the user" do
let(:log) { create(:lettings_log, :in_progress, created_by: user) }
it "does allow deletion of log" do
expect(policy).to permit(user, log)
end
end
end
end
end
end
end
end

114
spec/policies/sales_log_policy_spec.rb

@ -0,0 +1,114 @@
require "rails_helper"
RSpec.describe SalesLogPolicy do
subject(:policy) { described_class }
permissions :destroy? do
let(:log) { create(:sales_log, :in_progress) }
context "when log nil" do
before do
allow(log).to receive(:collection_period_open?).and_return(false)
end
it "does not allow deletion of log" do
expect(policy).not_to permit(build(:user, :support), nil)
end
end
context "when user nil" do
before do
allow(log).to receive(:collection_period_open?).and_return(false)
end
it "does not allow deletion of log" do
expect(policy).not_to permit(nil, build(:sales_log, :in_progress))
end
end
context "when collection period closed" do
before do
allow(log).to receive(:collection_period_open?).and_return(false)
end
it "does not allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(build(:user, :support), log)
end
end
context "when collection period open" do
before do
allow(log).to receive(:collection_period_open?).and_return(true)
end
context "when not started" do
before do
allow(log).to receive(:in_progress?).and_return(false)
allow(log).to receive(:completed?).and_return(false)
end
it "does not allow deletion of log" do
expect(log).to receive(:in_progress?)
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(build(:user, :support), log)
end
end
[
%i[sales_log in_progress],
%i[sales_log completed],
].each do |type, status|
let(:log) { create(type, status) }
context "when #{type} status: #{status}" do
context "when user is data coordinator" do
let(:user) { create(:user, :data_coordinator) }
let(:user_of_owning_org) { create(:user, :data_coordinator, organisation: log.owning_organisation) }
it "does not allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(user, log)
end
it "allows deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).to permit(user_of_owning_org, log)
end
end
context "when user is support" do
let(:user) { create(:user, :support) }
it "does allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).to permit(user, log)
end
end
context "when user is data provider" do
let(:user) { create(:user) }
it "does not allow deletion of log" do
expect(log).to receive(:collection_period_open?)
expect(policy).not_to permit(user, log)
end
context "when the log is assigned to the user" do
let(:log) { create(:sales_log, :in_progress, created_by: user) }
it "does allow deletion of log" do
expect(policy).to permit(user, log)
end
end
end
end
end
end
end
end

96
spec/requests/lettings_logs_controller_spec.rb

@ -1309,55 +1309,93 @@ RSpec.describe LettingsLogsController, type: :request do
end end
describe "DELETE" do describe "DELETE" do
let(:headers) { { "Accept" => "text/html" } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { create(:user, :support) }
let!(:lettings_log) do let!(:lettings_log) do
FactoryBot.create(:lettings_log, :in_progress) create(:lettings_log, :completed)
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }
let(:delete_request) { delete "/lettings-logs/#{id}", headers: }
context "when deleting a lettings log" do before do
before do allow(user).to receive(:need_two_factor_authentication?).and_return(false)
delete "/lettings-logs/#{id}", headers: sign_in user
end end
it "returns http success" do context "when delete permitted" do
expect(response).to have_http_status(:success) it "redirects to lettings logs and shows message" do
delete_request
expect(response).to redirect_to(lettings_logs_path)
follow_redirect!
expect(page).to have_content("Log #{id} has been deleted")
end end
it "deletes the lettings log" do it "marks the log as deleted" do
expect { LettingsLog.find(id) }.to raise_error(ActiveRecord::RecordNotFound) expect { delete_request }.to change { lettings_log.reload.status }.from("completed").to("deleted")
end end
end
context "with an invalid lettings log id" do context "when log does not exist" do
let(:id) { (LettingsLog.order(:id).last&.id || 0) + 1 } let(:id) { -1 }
it "returns 404" do it "returns 404" do
expect(response).to have_http_status(:not_found) delete_request
end expect(response).to have_http_status(:not_found)
end end
end
context "with a request containing invalid credentials" do context "when user not authorised" do
let(:basic_credentials) do let(:user) { create(:user) }
ActionController::HttpAuthentication::Basic.encode_credentials(api_username, "Oops")
end
it "returns 401" do it "returns 404" do
expect(response).to have_http_status(:unauthorized) delete_request
end expect(response).to have_http_status(:unauthorized)
end end
end end
end
context "when a lettings log deletion fails" do describe "GET delete-confirmation" do
let(:mock_scope) { instance_double("LettingsLog::ActiveRecord_Relation", find_by: lettings_log) } let(:headers) { { "Accept" => "text/html" } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { create(:user, :support) }
let!(:lettings_log) do
create(:lettings_log, :completed)
end
let(:id) { lettings_log.id }
let(:request) { get "/lettings-logs/#{id}/delete-confirmation", headers: }
before do before do
allow(LettingsLog).to receive(:visible).and_return(mock_scope) allow(user).to receive(:need_two_factor_authentication?).and_return(false)
allow(lettings_log).to receive(:delete).and_return(false) sign_in user
end
delete "/lettings-logs/#{id}", headers: context "when delete permitted" do
it "renders page" do
request
expect(response).to have_http_status(:ok)
expect(page).to have_content("Are you sure you want to delete this log?")
expect(page).to have_button(text: "Delete this log")
expect(page).to have_link(text: "Cancel", href: lettings_log_path(id))
end end
end
it "returns an unprocessable entity 422" do context "when log does not exist" do
expect(response).to have_http_status(:unprocessable_entity) let(:id) { -1 }
it "returns 404" do
request
expect(response).to have_http_status(:not_found)
end
end
context "when user not authorised" do
let(:user) { create(:user) }
it "returns 404" do
request
expect(response).to have_http_status(:unauthorized)
end end
end end
end end

92
spec/requests/sales_logs_controller_spec.rb

@ -652,4 +652,96 @@ RSpec.describe SalesLogsController, type: :request do
end end
end end
end end
describe "DELETE" do
let(:headers) { { "Accept" => "text/html" } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { create(:user, :support) }
let!(:sales_log) do
create(:sales_log, :completed)
end
let(:id) { sales_log.id }
let(:delete_request) { delete "/sales-logs/#{id}", headers: }
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
sign_in user
end
context "when delete permitted" do
it "redirects to sales logs and shows message" do
delete_request
expect(response).to redirect_to(sales_logs_path)
follow_redirect!
expect(page).to have_content("Log #{id} has been deleted")
end
it "marks the log as deleted" do
expect { delete_request }.to change { sales_log.reload.status }.from("completed").to("deleted")
end
end
context "when log does not exist" do
let(:id) { -1 }
it "returns 404" do
delete_request
expect(response).to have_http_status(:not_found)
end
end
context "when user not authorised" do
let(:user) { create(:user) }
it "returns 404" do
delete_request
expect(response).to have_http_status(:unauthorized)
end
end
end
describe "GET delete-confirmation" do
let(:headers) { { "Accept" => "text/html" } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { create(:user, :support) }
let!(:sales_log) do
create(:sales_log, :completed)
end
let(:id) { sales_log.id }
let(:request) { get "/sales-logs/#{id}/delete-confirmation", headers: }
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
sign_in user
end
context "when delete permitted" do
it "renders page" do
request
expect(response).to have_http_status(:ok)
expect(page).to have_content("Are you sure you want to delete this log?")
expect(page).to have_button(text: "Delete this log")
expect(page).to have_link(text: "Cancel", href: sales_log_path(id))
end
end
context "when log does not exist" do
let(:id) { -1 }
it "returns 404" do
request
expect(response).to have_http_status(:not_found)
end
end
context "when user not authorised" do
let(:user) { create(:user) }
it "returns 404" do
request
expect(response).to have_http_status(:unauthorized)
end
end
end
end end

783
spec/services/csv/lettings_log_csv_service_spec.rb

@ -2,7 +2,7 @@ require "rails_helper"
RSpec.describe Csv::LettingsLogCsvService do RSpec.describe Csv::LettingsLogCsvService do
context "when the user is support" do context "when the user is support" do
let(:user) { FactoryBot.create(:user, :support) } let(:user) { create(:user, :support) }
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") } let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
before do before do
@ -11,226 +11,229 @@ RSpec.describe Csv::LettingsLogCsvService do
end end
it "sets csv attributes in correct order" do it "sets csv attributes in correct order" do
expected_csv_attributes = %w[id expected_csv_attributes = %w[
status id
created_at status
updated_at created_at
created_by_name updated_at
is_dpo created_by_name
owning_organisation_name is_dpo
managing_organisation_name owning_organisation_name
collection_start_year managing_organisation_name
rent_value_check collection_start_year
needstype rent_value_check
renewal needstype
startdate renewal
rent_type_detail startdate
irproduct_other rent_type_detail
tenancycode irproduct_other
propcode tenancycode
postcode_known propcode
postcode_full postcode_known
is_la_inferred postcode_full
la_label is_la_inferred
la la_label
first_time_property_let_as_social_housing la
unitletas first_time_property_let_as_social_housing
rsnvac unitletas
offered rsnvac
unittype_gn offered
builtype unittype_gn
wchair builtype
beds wchair
voiddate beds
void_date_value_check voiddate
majorrepairs void_date_value_check
mrcdate majorrepairs
major_repairs_date_value_check mrcdate
startertenancy major_repairs_date_value_check
tenancy startertenancy
tenancyother tenancy
tenancylength tenancyother
sheltered tenancylength
declaration sheltered
hhmemb declaration
pregnancy_value_check hhmemb
age1_known pregnancy_value_check
age1 age1_known
sex1 age1
ethnic_group sex1
ethnic ethnic_group
national ethnic
ecstat1 national
retirement_value_check ecstat1
details_known_2 retirement_value_check
relat2 details_known_2
age2_known relat2
age2 age2_known
sex2 age2
ecstat2 sex2
details_known_3 ecstat2
relat3 details_known_3
age3_known relat3
age3 age3_known
sex3 age3
ecstat3 sex3
details_known_4 ecstat3
relat4 details_known_4
age4_known relat4
age4 age4_known
sex4 age4
ecstat4 sex4
details_known_5 ecstat4
relat5 details_known_5
age5_known relat5
age5 age5_known
sex5 age5
ecstat5 sex5
details_known_6 ecstat5
relat6 details_known_6
age6_known relat6
age6 age6_known
sex6 age6
ecstat6 sex6
details_known_7 ecstat6
relat7 details_known_7
age7_known relat7
age7 age7_known
sex7 age7
ecstat7 sex7
details_known_8 ecstat7
relat8 details_known_8
age8_known relat8
age8 age8_known
sex8 age8
ecstat8 sex8
armedforces ecstat8
leftreg armedforces
reservist leftreg
preg_occ reservist
housingneeds preg_occ
housingneeds_type housingneeds
housingneeds_other housingneeds_type
illness housingneeds_other
illness_type_4 illness
illness_type_5 illness_type_4
illness_type_2 illness_type_5
illness_type_6 illness_type_2
illness_type_7 illness_type_6
illness_type_3 illness_type_7
illness_type_9 illness_type_3
illness_type_8 illness_type_9
illness_type_1 illness_type_8
illness_type_10 illness_type_1
layear illness_type_10
waityear layear
reason waityear
reasonother reason
prevten reasonother
underoccupation_benefitcap prevten
homeless underoccupation_benefitcap
ppcodenk homeless
ppostcode_full ppcodenk
previous_la_known ppostcode_full
is_previous_la_inferred previous_la_known
prevloc_label is_previous_la_inferred
prevloc prevloc_label
reasonpref prevloc
rp_homeless reasonpref
rp_insan_unsat rp_homeless
rp_medwel rp_insan_unsat
rp_hardship rp_medwel
rp_dontknow rp_hardship
cbl rp_dontknow
cap cbl
chr cap
letting_allocation_unknown chr
referral letting_allocation_unknown
net_income_known referral
earnings net_income_known
incfreq earnings
net_income_value_check incfreq
hb net_income_value_check
benefits hb
household_charge benefits
period household_charge
is_carehome period
chcharge is_carehome
carehome_charges_value_check chcharge
brent carehome_charges_value_check
scharge brent
pscharge scharge
supcharg pscharge
tcharge supcharg
hbrentshortfall tcharge
tshortfall_known hbrentshortfall
tshortfall tshortfall_known
housingneeds_a tshortfall
housingneeds_b housingneeds_a
housingneeds_c housingneeds_b
housingneeds_f housingneeds_c
housingneeds_g housingneeds_f
housingneeds_h housingneeds_g
property_owner_organisation housingneeds_h
property_manager_organisation property_owner_organisation
purchaser_code property_manager_organisation
property_relet purchaser_code
incref property_relet
renttype incref
lettype renttype
totchild lettype
totelder totchild
totadult totelder
nocharge totadult
has_benefits nocharge
wrent has_benefits
wscharge wrent
wpschrge wscharge
wsupchrg wpschrge
wtcharge wsupchrg
wtshortfall wtcharge
refused wtshortfall
wchchrg refused
newprop wchchrg
old_form_id newprop
lar old_form_id
irproduct lar
old_id irproduct
joint old_id
hhtype joint
new_old hhtype
vacdays new_old
unresolved vacdays
updated_by_id unresolved
uprn updated_by_id
uprn_known uprn
uprn_confirmed uprn_known
address_line1 uprn_confirmed
address_line2 address_line1
town_or_city address_line2
county town_or_city
status_cache county
unittype_sh status_cache
scheme_code discarded_at
scheme_service_name unittype_sh
scheme_sensitive scheme_code
scheme_type scheme_service_name
scheme_registered_under_care_act scheme_sensitive
scheme_owning_organisation_name scheme_type
scheme_primary_client_group scheme_registered_under_care_act
scheme_has_other_client_group scheme_owning_organisation_name
scheme_secondary_client_group scheme_primary_client_group
scheme_support_type scheme_has_other_client_group
scheme_intended_stay scheme_secondary_client_group
scheme_created_at scheme_support_type
location_code scheme_intended_stay
location_postcode scheme_created_at
location_name location_code
location_units location_postcode
location_type_of_unit location_name
location_mobility_type location_units
location_admin_district location_type_of_unit
location_startdate] location_mobility_type
location_admin_district
location_startdate
]
csv = CSV.parse(described_class.new(user, export_type: "labels").to_csv) csv = CSV.parse(described_class.new(user, export_type: "labels").to_csv)
@ -248,174 +251,176 @@ RSpec.describe Csv::LettingsLogCsvService do
end end
it "sets csv attributes in correct order and without omitted values" do it "sets csv attributes in correct order and without omitted values" do
expected_csv_attributes = %w[id expected_csv_attributes = %w[
status id
created_at status
updated_at created_at
created_by_name updated_at
is_dpo created_by_name
owning_organisation_name is_dpo
managing_organisation_name owning_organisation_name
collection_start_year managing_organisation_name
renewal collection_start_year
startdate renewal
irproduct_other startdate
tenancycode irproduct_other
propcode tenancycode
postcode_full propcode
la_label postcode_full
unitletas la_label
rsnvac unitletas
offered rsnvac
unittype_gn offered
builtype unittype_gn
wchair builtype
beds wchair
voiddate beds
void_date_value_check voiddate
majorrepairs void_date_value_check
mrcdate majorrepairs
major_repairs_date_value_check mrcdate
startertenancy major_repairs_date_value_check
tenancy startertenancy
tenancyother tenancy
tenancylength tenancyother
sheltered tenancylength
declaration sheltered
age1 declaration
sex1 age1
ethnic_group sex1
ethnic ethnic_group
national ethnic
ecstat1 national
relat2 ecstat1
age2 relat2
sex2 age2
ecstat2 sex2
relat3 ecstat2
age3 relat3
sex3 age3
ecstat3 sex3
relat4 ecstat3
age4 relat4
sex4 age4
ecstat4 sex4
relat5 ecstat4
age5 relat5
sex5 age5
ecstat5 sex5
relat6 ecstat5
age6 relat6
sex6 age6
ecstat6 sex6
relat7 ecstat6
age7 relat7
sex7 age7
ecstat7 sex7
relat8 ecstat7
age8 relat8
sex8 age8
ecstat8 sex8
armedforces ecstat8
leftreg armedforces
reservist leftreg
preg_occ reservist
housingneeds preg_occ
housingneeds_type housingneeds
housingneeds_other housingneeds_type
illness housingneeds_other
illness_type_4 illness
illness_type_5 illness_type_4
illness_type_2 illness_type_5
illness_type_6 illness_type_2
illness_type_7 illness_type_6
illness_type_3 illness_type_7
illness_type_9 illness_type_3
illness_type_8 illness_type_9
illness_type_1 illness_type_8
illness_type_10 illness_type_1
layear illness_type_10
waityear layear
reason waityear
reasonother reason
prevten reasonother
underoccupation_benefitcap prevten
homeless underoccupation_benefitcap
ppcodenk homeless
ppostcode_full ppcodenk
prevloc_label ppostcode_full
reasonpref prevloc_label
rp_homeless reasonpref
rp_insan_unsat rp_homeless
rp_medwel rp_insan_unsat
rp_hardship rp_medwel
rp_dontknow rp_hardship
cbl rp_dontknow
cap cbl
chr cap
referral chr
earnings referral
incfreq earnings
hb incfreq
benefits hb
household_charge benefits
period household_charge
chcharge period
carehome_charges_value_check chcharge
brent carehome_charges_value_check
scharge brent
pscharge scharge
supcharg pscharge
tcharge supcharg
hbrentshortfall tcharge
tshortfall hbrentshortfall
housingneeds_a tshortfall
housingneeds_b housingneeds_a
housingneeds_c housingneeds_b
housingneeds_f housingneeds_c
housingneeds_g housingneeds_f
housingneeds_h housingneeds_g
property_owner_organisation housingneeds_h
property_manager_organisation property_owner_organisation
purchaser_code property_manager_organisation
property_relet purchaser_code
incref property_relet
lettype incref
nocharge lettype
has_benefits nocharge
refused has_benefits
wchchrg refused
newprop wchchrg
lar newprop
irproduct lar
joint irproduct
uprn joint
uprn_known uprn
address_line1 uprn_known
address_line2 address_line1
town_or_city address_line2
county town_or_city
unittype_sh county
scheme_code unittype_sh
scheme_service_name scheme_code
scheme_sensitive scheme_service_name
scheme_type scheme_sensitive
scheme_registered_under_care_act scheme_type
scheme_owning_organisation_name scheme_registered_under_care_act
scheme_primary_client_group scheme_owning_organisation_name
scheme_has_other_client_group scheme_primary_client_group
scheme_secondary_client_group scheme_has_other_client_group
scheme_support_type scheme_secondary_client_group
scheme_intended_stay scheme_support_type
scheme_created_at scheme_intended_stay
location_code scheme_created_at
location_postcode location_code
location_name location_postcode
location_units location_name
location_type_of_unit location_units
location_mobility_type location_type_of_unit
location_admin_district location_mobility_type
location_startdate] location_admin_district
location_startdate
]
csv = CSV.parse(described_class.new(user, export_type: "labels").to_csv) csv = CSV.parse(described_class.new(user, export_type: "labels").to_csv)

107
spec/shared/shared_log_examples.rb

@ -0,0 +1,107 @@
require "rails_helper"
# rubocop:disable RSpec/AnyInstance
RSpec.shared_examples "shared log examples" do |log_type|
describe "status" do
let(:empty_log) { create(log_type) }
let(:in_progress_log) { create(log_type, :in_progress) }
let(:completed_log) { create(log_type, :completed) }
it "is set to not started for an empty #{log_type} log" do
expect(empty_log.not_started?).to be(true)
expect(empty_log.in_progress?).to be(false)
expect(empty_log.completed?).to be(false)
expect(empty_log.deleted?).to be(false)
end
it "is set to in progress for a started #{log_type} log" do
expect(in_progress_log.in_progress?).to be(true)
expect(in_progress_log.not_started?).to be(false)
expect(in_progress_log.completed?).to be(false)
expect(in_progress_log.deleted?).to be(false)
end
it "is set to completed for a completed #{log_type} log" do
expect(completed_log.in_progress?).to be(false)
expect(completed_log.not_started?).to be(false)
expect(completed_log.completed?).to be(true)
expect(completed_log.deleted?).to be(false)
end
end
describe "discard!" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
example.run
end
Timecop.return
end
let(:log) { create(log_type) }
it "updates discarded at with current time" do
expect { log.discard! }.to change { log.reload.discarded_at }.from(nil).to(Time.zone.now)
end
it "updates status to deleted" do
expect { log.discard! }.to change { log.reload.status }.to("deleted")
end
end
describe "#process_uprn_change!" do
context "when UPRN set to a value" do
let(:log) do
create(
log_type,
uprn: "123456789",
uprn_confirmed: 1,
county: "county",
)
end
it "updates log fields" do
log.uprn = "1111111"
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:result).and_return({
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
})
expect { log.process_uprn_change! }.to change(log, :address_line1).from(nil).to("0, Building Name, Thoroughfare")
.and change(log, :town_or_city).from(nil).to("Posttown")
.and change(log, :postcode_full).from(nil).to("POSTCODE")
.and change(log, :uprn_confirmed).from(1).to(nil)
.and change(log, :county).from("county").to(nil)
.and change(log, :uprn_known).from(nil).to(1)
end
end
context "when UPRN nil" do
let(:log) { create(log_type, uprn: nil) }
it "does not update log" do
expect { log.process_uprn_change! }.not_to change(log, :attributes)
end
end
context "when service errors" do
let(:log) { create(log_type, uprn: "123456789", uprn_confirmed: 1) }
let(:error_message) { "error" }
it "adds error to log" do
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:error).and_return(error_message)
expect { log.process_uprn_change! }.to change { log.errors[:uprn] }.from([]).to([error_message])
end
end
end
end
# rubocop:enable RSpec/AnyInstance
Loading…
Cancel
Save