From b358a67dde9cb57cca37691d129e139fa89cf9db Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Mon, 15 Nov 2021 15:42:11 +0000 Subject: [PATCH 1/4] CLDC-679: Update main tenancy type mappings (#91) * Update main tenancy type mappins * Fix the tests and validations --- app/constants/db_enums.rb | 9 ++++----- app/models/case_log.rb | 2 +- app/validations/tenancy_validations.rb | 6 +++--- config/forms/2021_2022.json | 11 +++++------ docs/api/DLUHC-CORE-Data.v1.json | 2 +- spec/fixtures/complete_case_log.json | 2 +- spec/models/case_log_spec.rb | 18 +++++++++--------- 7 files changed, 24 insertions(+), 26 deletions(-) diff --git a/app/constants/db_enums.rb b/app/constants/db_enums.rb index 23e4b4bd4..d28393105 100644 --- a/app/constants/db_enums.rb +++ b/app/constants/db_enums.rb @@ -166,11 +166,10 @@ module DbEnums def self.tenancy { - "Fixed term – Secure" => 1, - "Fixed term – Assured Shorthold Tenancy (AST)" => 4, - "Lifetime – Secure" => 100, - "Lifetime – Assured" => 2, - "License agreement" => 5, + "Secure (including flexible)" => 1, + "Assured" => 2, + "Assured Shorthold" => 4, + "Licence agreement (almshouses only)" => 5, "Other" => 3, } end diff --git a/app/models/case_log.rb b/app/models/case_log.rb index 5553b5a78..f73df0264 100644 --- a/app/models/case_log.rb +++ b/app/models/case_log.rb @@ -230,7 +230,7 @@ private dynamically_not_required << "incfreq" end - if tenancy == "Fixed term – Secure" + if tenancy == "Secure (including flexible)" dynamically_not_required << "tenancylength" end diff --git a/app/validations/tenancy_validations.rb b/app/validations/tenancy_validations.rb index 32ff8e2b0..fc275f91e 100644 --- a/app/validations/tenancy_validations.rb +++ b/app/validations/tenancy_validations.rb @@ -4,12 +4,12 @@ module TenancyValidations def validate_fixed_term_tenancy(record) is_present = record.tenancylength.present? is_in_range = record.tenancylength.to_i.between?(2, 99) - is_secure = record.tenancy == "Fixed term – Secure" - is_ast = record.tenancy == "Fixed term – Assured Shorthold Tenancy (AST)" + is_secure = record.tenancy == "Secure (including flexible)" + is_ast = record.tenancy == "Assured Shorthold" conditions = [ { condition: !(is_secure || is_ast) && is_present, error: "You must only answer the fixed term tenancy length question if the tenancy type is fixed term" }, { condition: is_ast && !is_in_range, error: "Fixed term – Assured Shorthold Tenancy (AST) should be between 2 and 99 years" }, - { condition: is_secure && (!is_in_range && is_present), error: "Fixed term – Secure should be between 2 and 99 years or not specified" }, + { condition: is_secure && (!is_in_range && is_present), error: "Secure (including flexible) should be between 2 and 99 years or not specified" }, ] conditions.each { |condition| condition[:condition] ? (record.errors.add :tenancylength, condition[:error]) : nil } diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json index 859e5fa14..7433f4d7b 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -1068,12 +1068,11 @@ "hint_text": "", "type": "radio", "answer_options": { - "0": "Fixed term – Secure", - "1": "Fixed term – Assured Shorthold Tenancy (AST)", - "2": "Lifetime – Secure", - "3": "Lifetime – Assured", - "4": "License agreement", - "5": "Other" + "0": "Secure (including flexible)", + "1": "Assured", + "2": "Assured Shorthold", + "3": "Licence agreement (almshouses only)", + "4": "Other" }, "conditional_for": { "other_tenancy_type": ["Other"] diff --git a/docs/api/DLUHC-CORE-Data.v1.json b/docs/api/DLUHC-CORE-Data.v1.json index 17560d14c..5723c9311 100644 --- a/docs/api/DLUHC-CORE-Data.v1.json +++ b/docs/api/DLUHC-CORE-Data.v1.json @@ -306,7 +306,7 @@ "startdate": "12/03/2019", "startertenancy": "No", "tenancylength": "No", - "tenancy": "Fixed term – Secure", + "tenancy": "Secure (including flexible)", "lettype": "Affordable Rent - General Needs", "landlord": "This landlord", "la": "Barnet", diff --git a/spec/fixtures/complete_case_log.json b/spec/fixtures/complete_case_log.json index 4656a04f8..81f2735fc 100644 --- a/spec/fixtures/complete_case_log.json +++ b/spec/fixtures/complete_case_log.json @@ -52,7 +52,7 @@ "startdate": "12/03/2019", "startertenancy": "No", "tenancylength": "5", - "tenancy": "Fixed term – Secure", + "tenancy": "Secure (including flexible)", "lettype": "Affordable Rent - General Needs", "landlord": "This landlord", "la": "Barnet", diff --git a/spec/models/case_log_spec.rb b/spec/models/case_log_spec.rb index e663937db..fad6ca4b9 100644 --- a/spec/models/case_log_spec.rb +++ b/spec/models/case_log_spec.rb @@ -182,39 +182,39 @@ RSpec.describe Form, type: :model do it "Must be completed and between 2 and 99 if type of tenancy is Assured shorthold" do expect { - CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)", + CaseLog.create!(tenancy: "Assured Shorthold", tenancylength: 1) }.to raise_error(ActiveRecord::RecordInvalid) expect { - CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)", + CaseLog.create!(tenancy: "Assured Shorthold", tenancylength: nil) }.to raise_error(ActiveRecord::RecordInvalid) expect { - CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)", + CaseLog.create!(tenancy: "Assured Shorthold", tenancylength: 2) }.not_to raise_error end it "Must be empty or between 2 and 99 if type of tenancy is Secure" do expect { - CaseLog.create!(tenancy: "Fixed term – Secure", + CaseLog.create!(tenancy: "Secure (including flexible)", tenancylength: 1) }.to raise_error(ActiveRecord::RecordInvalid) expect { - CaseLog.create!(tenancy: "Fixed term – Secure", + CaseLog.create!(tenancy: "Secure (including flexible)", tenancylength: 100) }.to raise_error(ActiveRecord::RecordInvalid) expect { - CaseLog.create!(tenancy: "Fixed term – Secure", + CaseLog.create!(tenancy: "Secure (including flexible)", tenancylength: nil) }.not_to raise_error expect { - CaseLog.create!(tenancy: "Fixed term – Secure", + CaseLog.create!(tenancy: "Secure (including flexible)", tenancylength: 2) }.not_to raise_error end @@ -294,12 +294,12 @@ RSpec.describe Form, type: :model do it "must not be provided if tenancy type is not other" do expect { - CaseLog.create!(tenancy: "Fixed term – Secure", + CaseLog.create!(tenancy: "Secure (including flexible)", tenancyother: "the other reason provided") }.to raise_error(ActiveRecord::RecordInvalid) expect { - CaseLog.create!(tenancy: "Fixed term – Secure", + CaseLog.create!(tenancy: "Secure (including flexible)", tenancyother: nil) }.not_to raise_error end From b787ad803fd0294bd7a193f5494909f8e5fac3a2 Mon Sep 17 00:00:00 2001 From: Daniel Baark <5101747+baarkerlounger@users.noreply.github.com> Date: Mon, 15 Nov 2021 16:38:21 +0000 Subject: [PATCH 2/4] CLDC-709: Conditional section status bugfix (#92) * Failing spec * Fix the failing spec * Fix rake spec --- app/helpers/check_answers_helper.rb | 32 +------------------ app/helpers/tasklist_helper.rb | 21 ++++++------ app/models/form.rb | 30 +++++++++++++++++ app/views/case_logs/_tasklist.html.erb | 4 +-- lib/tasks/form_definition.rake | 10 +++--- spec/factories/case_log.rb | 9 ++++++ spec/helpers/tasklist_helper_spec.rb | 27 ++++++++++------ .../tasks/form_definition_validator_spec.rb | 2 +- 8 files changed, 76 insertions(+), 59 deletions(-) diff --git a/app/helpers/check_answers_helper.rb b/app/helpers/check_answers_helper.rb index 6282f9d06..ba6373b72 100644 --- a/app/helpers/check_answers_helper.rb +++ b/app/helpers/check_answers_helper.rb @@ -16,7 +16,7 @@ module CheckAnswersHelper while page_name.to_s != "check_answers" && subsection_keys.include?(page_name) questions = form.questions_for_page(page_name) - applicable_questions = filter_conditional_questions(questions, case_log) + applicable_questions = form.filter_conditional_questions(questions, case_log) total_questions = total_questions.merge(applicable_questions) page_name = get_next_page_name(form, page_name, case_log) @@ -25,19 +25,6 @@ module CheckAnswersHelper total_questions end - def filter_conditional_questions(questions, case_log) - applicable_questions = questions - - questions.each do |k, question| - question.fetch("conditional_for", []).each do |conditional_question_key, condition| - if condition_not_met(case_log, k, question, condition) - applicable_questions = applicable_questions.reject { |z| z == conditional_question_key } - end - end - end - applicable_questions - end - def get_next_page_name(form, page_name, case_log) page = form.all_pages[page_name] if page.key?("conditional_route_to") @@ -50,23 +37,6 @@ module CheckAnswersHelper form.next_page(page_name) end - def condition_not_met(case_log, question_key, question, condition) - case question["type"] - when "numeric" - operator = condition[/[<>=]+/].to_sym - operand = condition[/\d+/].to_i - case_log[question_key].blank? || !case_log[question_key].send(operator, operand) - when "text" - case_log[question_key].blank? || !condition.include?(case_log[question_key]) - when "radio" - case_log[question_key].blank? || !condition.include?(case_log[question_key]) - when "select" - case_log[question_key].blank? || !condition.include?(case_log[question_key]) - else - raise "Not implemented yet" - end - end - def create_update_answer_link(case_log_answer, case_log_id, page) link_name = case_log_answer.blank? ? "Answer" : "Change" link_to(link_name, "/case_logs/#{case_log_id}/#{page}", class: "govuk-link").html_safe diff --git a/app/helpers/tasklist_helper.rb b/app/helpers/tasklist_helper.rb index 4ca9f182d..1d3f376c5 100644 --- a/app/helpers/tasklist_helper.rb +++ b/app/helpers/tasklist_helper.rb @@ -13,31 +13,32 @@ module TasklistHelper in_progress: "govuk-tag--blue", }.freeze - def get_subsection_status(subsection_name, case_log, questions) + def get_subsection_status(subsection_name, case_log, form, questions) + applicable_questions = form.filter_conditional_questions(questions, case_log).keys if subsection_name == "declaration" return case_log.completed? ? :not_started : :cannot_start_yet end - return :not_started if questions.all? { |question| case_log[question].blank? } - return :completed if questions.all? { |question| case_log[question].present? } + return :not_started if applicable_questions.all? { |question| case_log[question].blank? } + return :completed if applicable_questions.all? { |question| case_log[question].present? } :in_progress end def get_next_incomplete_section(form, case_log) subsections = form.all_subsections.keys - subsections.find { |subsection| is_incomplete?(subsection, case_log, form.questions_for_subsection(subsection).keys) } + subsections.find { |subsection| is_incomplete?(subsection, case_log, form, form.questions_for_subsection(subsection)) } end def get_subsections_count(form, case_log, status = :all) subsections = form.all_subsections.keys return subsections.count if status == :all - subsections.count { |subsection| get_subsection_status(subsection, case_log, form.questions_for_subsection(subsection).keys) == status } + subsections.count { |subsection| get_subsection_status(subsection, case_log, form, form.questions_for_subsection(subsection)) == status } end def get_first_page_or_check_answers(subsection, case_log, form, questions) - path = if is_started?(subsection, case_log, questions) + path = if is_started?(subsection, case_log, form, questions) "case_log_#{subsection}_check_answers_path" else "case_log_#{form.first_page_for_subsection(subsection)}_path" @@ -47,13 +48,13 @@ module TasklistHelper private - def is_incomplete?(subsection, case_log, questions) - status = get_subsection_status(subsection, case_log, questions) + def is_incomplete?(subsection, case_log, form, questions) + status = get_subsection_status(subsection, case_log, form, questions) %i[not_started in_progress].include?(status) end - def is_started?(subsection, case_log, questions) - status = get_subsection_status(subsection, case_log, questions) + def is_started?(subsection, case_log, form, questions) + status = get_subsection_status(subsection, case_log, form, questions) %i[in_progress completed].include?(status) end end diff --git a/app/models/form.rb b/app/models/form.rb index 3eeac8987..a2479e20b 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -97,6 +97,36 @@ class Form }.reduce(:merge) end + def filter_conditional_questions(questions, case_log) + applicable_questions = questions + + questions.each do |k, question| + question.fetch("conditional_for", []).each do |conditional_question_key, condition| + if condition_not_met(case_log, k, question, condition) + applicable_questions = applicable_questions.reject { |z| z == conditional_question_key } + end + end + end + applicable_questions + end + + def condition_not_met(case_log, question_key, question, condition) + case question["type"] + when "numeric" + operator = condition[/[<>=]+/].to_sym + operand = condition[/\d+/].to_i + case_log[question_key].blank? || !case_log[question_key].send(operator, operand) + when "text" + case_log[question_key].blank? || !condition.include?(case_log[question_key]) + when "radio" + case_log[question_key].blank? || !condition.include?(case_log[question_key]) + when "select" + case_log[question_key].blank? || !condition.include?(case_log[question_key]) + else + raise "Not implemented yet" + end + end + def get_answer_label(case_log, question_title) question = all_questions[question_title] if question["type"] == "checkbox" diff --git a/app/views/case_logs/_tasklist.html.erb b/app/views/case_logs/_tasklist.html.erb index fdf4c5aa9..1e75f207b 100644 --- a/app/views/case_logs/_tasklist.html.erb +++ b/app/views/case_logs/_tasklist.html.erb @@ -9,10 +9,10 @@
~s>2DZkY_CR^-3yHCd3CL4FEUie#0O;y(?OilfG>Vr*dULd>%bI4F^ z)F9JZZBc()8Pjj_F7NnbKa6}Hp&<)i42fKOWZrCwc=J0gk&l)b_5B6cYxq_YTlK+; z+W!%EemEpbChh-0)&CH6dmIW#rB$xb;VG~x_8TeiDjzrAaHuij#;lHJhsJj3&YrSM zC^PkAad9UmDX6#S;{O;E&dkt?o(7`#_kt9ZYWuGL7OFjpO#NIlqh$u?ChD?z$2at} zaJ(#D ft8mI$ zt8f_O0L5}!X$naw?^6p{-b~t&4apX1Xf=zetbUHBoewp7qbNffQWBEKNU?7NCaJ}A z2o~vHgX#0{xMIY8cV^x`6DKoSM(*K=$vL#50VWBtNlQx<^-}$>(6XNyDW-bk#E3ik zU-1O?PRx&`C@w(LI3P w{fZkm5Fs zw*yq@&wO%DsBrAxBa6|{rAy|{1RyqB9f6w*e)*cRoOef+i7YjJlyi8oKwWlH*RDI1 z%d_wh6<0`mUnxHcU>QDvn`t%arPM%PQn9I(p8-fi8pm}*<3J~<8;4vqf?5!$Zc zSj03N!n=Q@$U_Kt2i+Y)j)t%qLW#z(`G&{LkSl%^Av-y-<3kvwQHpxjXUxo`M4U8^ zFyD`eezE`qQ->?D6oL-;5x=~ue*}t;hVAFfz05w?RJvFwpA*%QSSLAvhVy4kA!^EU z{!tcUX)SchIp`} 9p^SVZ^XM;pGnG0eb!xj(PzWViAYf^prdF z%g{%v#%U0Q6nVFDh)B_aB+<{EY;UQy!)f_wtr<|Drr(4#VVXH&awsmYo5Lz$Ys7xe zgrGxXl;u VTvsfmrf&!$2mGMBYR*=NTk_zj?pyZVPN#brl!fE0#GmQ#$ zX8COvN`|Iuw$wU|BStP9i5gZmY6AgN0}z&iK}jnuhX__-y54L!!gSHq)vJW$AUaiH zS8RpE4)YPVD9$glv+Fzd%d;mBr&U4G&VEX%>i>tR1atDgh>{y-qTXlb8OkFM#;=T) z3Rl4u(zGj@)XR4drz?)|%a7I!w?Q&y;?ZTO*2ldHfm|gyAEymDfrblniwq%!jPOYM zVJ(S?umu+aDNcgX2Ps9O))!~j{jkKMFznq(Q> +N`LZexu zd$K}1^ESV4Lo{(7+WsG5IW|*~y30sD?Us_rZf}m$?G&tGV 0$g$c$5rJ~5*@4xoFvJkD+CVa@QpX{#Qb%D}t9hEH$${42b&lx> zivk|znylJDyFP)gE;E$NF?0e3Trems*^oX=Gj~i5 !^6Dm z#(>9pM@__mQ%zGW!z^b%RT27?p-_O8nunT_)xZ h|$5=EJ!ujDo6!y->Bw6WHlHjGin-XgBgN^?34u;^EkO6`x(NP zotIfz!BK}4dOHrnm%4k6%Jp+%X7i$8Z_(@>r?cI7wE9RUE|3xOQaU6~VY`Wfx00#A zeKE$9f?0Y939|tZR)z7-{VDrXsuDb{;}YEa>v~g%K&ojIMQ~}-0ZmqONgs%%T|*J> zDF9+oiRe_@zf~w>>PcQGW9&s;`tAuB&>Z62JBb0SFR?4Mj$3JIRdJiKX~Wx!I`6R@ z a;r#}{ip&{C*g+6wR0TAs| zOX!#fV;ES*$nzHbNMA80Kj4OaH7lM6UtvnH%*p^{9i $0y9Jm3BrSH3=8-fYY+H_%Ek?;L}JjeY4hf^I~-B61ffpz<377VLj_e^ z a{P-ahkr4}`X~z W5$C!)@W|B9#v8AotLb^S*~ z)xBhan^zF=Kv;+Ly9{B!eFo*&h#vXk-Y%`dZG4zh1~kk~ejkh|$2_# W-#qDOFc#R_^;9Ik4>^2)OSV}W32~S-XHfSU1CZ(1V{j}D z=?!U6_W=XHYL*DUDkZMmtXSTzM*+0)L3^H7;t73U#GtOif;^Hc?d&tfTM63_AGF~i z<*6m65$fs@vZ#;S%s$oaY!%JIa5&rbL< l>d _u&Qtv*P?WM{6o3zgNTCbhum-=kiw?(b2rT=$<*k8c?? zu!iL>NJm(%YYh_^4mbO0yy<^nX@ULYzg{C0j 9hv8Hvagu-IDq|!en&R5b_p&z?nVO9G_ z0v@9OnxIfb)#jnC{}GnmGas7AL>6e+D)c;Yx*h+Xo}zyfh4{w*8daDss*DU!0l(`X zmDhzbC5mONxQGQ93Sc#ld1l%ekWkda*u?s5u!Z#*izl`2D}5r?=i?sQDi)KF6pYF2 zrZDY(F{Tl6V%BD6@8FP1fEl8O1Q9{bM7$7YV7(C071M=eNGs|g7{wVg!##e6 zD5vh8pe^`jhgccCPj)_|GZ&_WNvSD4goEilx?XP1x$lT-2$b9iJWeyni|Sh-0)}Cf z;8vS^7J=U*NGJjEQHj)4+ffLDRNwi8{}od9e}&XCBCglpA?5T4&wJdstjcD#QVV_X zHcKzROs!zD3jmKq%H&ZrSq~t`J!Ixl``=ch0rtaX1XV4eu-XrF)fWD4tfz*nA{ zEs<8WhlYFCU7~$n>sc1o3xKaYGrK3P`UVXpU={+6B(M iNMto|#>cR&|B$c-Ot4A#8*|qA`FQP|Pr4c|dnvG)SK%XY;Sk0jBuq!7Sf5K_JeX zdKd3 z1HY?g`tOCA@@RS&z*9Oi#-0xg1akGzH(n2C<@7Bo(I=?J&(M=!408m!$*W>5D2;!h zwma#^vu^@{5XqZBKhw#+j{Z)2x2T{WuljJ1jQw|+SOPyhhi%Q9+(oHQ2YpA#EqV?^ z6#aNmMx9APR;(Itn$xiYbA^6(M*j9RC*oF>f3$s&-xN=Gf!{k=q=sKFSmdYC?F=a% z#g sLS$abpBWUHBsZ$i2l`?P4mWQzu)@`4|bEq < z<5Y^ETAig}&h9TqUw-7yc((a3fAjVE>Cqe!xv(&t`^EV_@^ PC {P~a*GV8VO)y%0LzKcAlbBGef#Slh6pO{gQss_ejC48fOYH)y;P&}Xyw zo+xZwG_0UfzA)StdZNxgdMQ7X1v!qZS#1d2^p;tz-TnJ(o#g^5nrWebF2@im; Pp)bEy2J-_#x2G^Swe7@rUezpSV@3R$l=5E$jnjUWUZ*Bh^u`qJhq;AE0$uZ5R z($@9rcNDR7I&Kd{932IGhk|eS{*rJR>vZI0vrTLdu{ZM)r$uXe7J0%h@9pRm`+kK? zDx?D0v!y%lZS#Y&Y70-${VtbsU+YLU-%@3B-jV?}Q;bqo<5XpH0y)U!dOpmPE5_P_ z>&C&k;&}PXLa?8GHMT_NlCGoW9^HCv?TTHMhW!_t0 v26FpUF=N>fAUrM}&YyB0^u2p=8n>{|BWGYpsz4glh0y>?zDb2(gV?{z(b(pQ+ zb>jEh4}9MT@{6*6KP%Y_e^|ZlNdNXF2mi@?=Bl9^eCJVjG(f0^9Rb*sw-2DKj+#@m z4MB#}q@+)lmJM;zQ%V>TwJun_?(rehqikgCc7<5Ev|}b8z}}ca*m7Lt$^aHY|mb zG6EAjb54`-eLa}b4P#~-K#z#TCR62(E7+$fvx(pompTzX1HlOSghVJ9Sd*=TN0<$5 zb?wngg!^$U3I7G~{TybEbA)Xeao0-?7lNLEkE-fmZgk6M<6ba9<2^cy`~e~>{I=q? zEo@~Z4VRi?uuMa~JeE5o@?%b^i#z2s6%n-{g|Zqgj&j&HO}zyUe#UujJ>6kx>Abfm zM6?58mk2SeF#uF8IF+rcvhq;|#=1kSDZNlGwWBhk0F8KusDza(Tc&)Zd`al~*k})` ztPUJtx{}gqqVUV%UJZLWN93!@2Kl4vJ2vdHM+3*Bb31gF4RWW@NOZS2)kv cAoVM_znK1d zgOlcm** !q+G~l ;`DeK! zh-$$!hA=Ef?DPu*+rZXYK|_p>3nr{-8Z{PC2+HyaEH2@N=Y|g5>^9$^21&?>>N;5A zbOvW&C1|MxAvps_G3O=Fuz(- I^IzH@`Qu;ytv}x zEKt3JW2-QyWN5d(h(6rZdNv5rVX-?fqU8=MMs7?;F;};eQL9abj-y41afJz!En%7q zGCocp^N+>O<#z9JEQ_y&nsLy*<9kR1vN+?57?(0`TeynWO-uAZ?8s^zT%2hziT(s6 zbP+g)Tp=gH2)>%z2tsBd<5KCw3 p&irT<8jMC!wx6EudwSvIL?KW71sRE*6M;iW z#8tRF75R(Ql2KFg4PWb6#tRg#wng`$rLUoRS>yM#+G68?O+_V`_cX{M+=4pWiC8oP zEE)1WbiSO8I0^}c*%oA5Pw^sJYH8)S00)a)JK-N%qZ<7_WJQ$uqOn%+$YO%;E5rty z8unA;+zRz#(`*`tw_dK|cH$+r2x%ykX0fJo1>Uow;(d})E7&h_@MAP9_C%V!?-J@% zCN?@L4XI^Kjde3aigZ-MXnYuVR=SxAkC3q`n8Bs`tZ8UlFLs@Ww(ntMT|(+(Cq*FP zqyCo7Vx5q2LsexZ{~BIL`|=o%06#sXqt2A^8k-0I00N^wTp{A?J9Ay8nEZ2i1Wmjb zH_HCY&ka1d0cm@0df&2Nr3;m96EHP13F;Opeg||Y+om3iy60p#mSS-!NR9_&D7#!6 zgeeVOAyzDvhsT<)M=gU^q}CqD?b@DaWV7EMh4HUuFkVJsarGObk@2j 3f2)h+RSu0=4!;-^xtc47_62)Y~ijA0wZ2!w QkmJfSZuXTj)^x3@rmTzlh`(dw^APtUZ-tfR!Q;~m zgg0fqdst^Yf*38pviuaHI`dO7D_=kPo{r7axq*uGt{u{fo_Q!`dMZ1+q%0}ACkqb9 z-@Rr>d+;<6>lH%OV{X1VB9<8`!1`J};c}XlV>Dim5E NoJ>>j;1-(*KI z7o=jw;=?i8wY;(Hv+If$4>oGhPQ9;gh=MtLUnkOY1 Y4b&M^J@rJ6~S?CLBl6n*MW znv65pB1d`GRazo;neV3&; vCpud>2TIl;@5tKHftM8@ehNiofkVn!)E}x+|G9x6&5Q9 zpFXqyER-&Ve)uAFK4|%^kgaDx_X%5+26bjCV(f~s-2WVTf0-`~encZcXXgEToC&AW zZokH9CoSY3=G+R-TuLiG{GVHYb?BPun-ute+t>U_JPffzLyEI)*8Yxh7h{_kcg$i& z+HAK-#2LaiQu@mbbgiX5YrMo>KM04ft4TRrCUO9atO{un{X-Yf6R63)GC}*b-U4|* z@+Q$R_cKw`DwNr<$XKKTHB_HaM70R}*|rkC;OX(%tglUBa!4vyBu*qo*DhUj^=z`< z=Ex7rs;%;Q3HEGN<);&Olf?}(=%r=GHaE(k>dTrQRW8PK(f1M^Aw>gZBg9KGX-hDr z1ongYh3jXH10|OlFeep1eQ#04C4igGt0op}lW2^s;Rb@%>c_l&j}do$^aA!y{7fh= z`4X&Mp&SbzrP5Bd#cZ1KL@JTIPTgV^(0B*i6N!1G4fFEb_k*1p&)*&a1904yKH$j8 ze0o~n;0}#coi4HyVP - U{{hC)=+|U*BPymEF!>>?Q`vivb{W>`5}5Z>VALuL~3x)PC{HlCI%fJ2@28 z+^IIzEMgn=X@8YAqcR$T IvK%)-!15yc!hdoG(FJN1F)gS|-O)-~>8SMr$NCIq&a)O~1h}fqUkIES zpe~{VNPkvQV!*4t8+D=?OGl}{4Weguh@OhVcyq3CqCBC;&g(j}=oHnZx0uhw;-O9U zss?;7^58KH1!5x;%2Zyx)r{1;p!`|JV_V)DV#Wb7STPoIF)z#_EX3GFf6VFMjb@SX zKlyAsWtar}6<)&EV#+iLmY|LlD<*C}nx$K6#rX%7UR*dr&&NCxN-}d^vJZqsjjb4E z>oX5gS7-LmdG0Pp@T>lY;)@+EH}z|+r8o6P22*znu|z-D%YJpn5dqJfXI;0}-k=KK z@;NMawy5`xM{+rQtq`h>C90{IfGzw-Fc$)Kwf9ohInB=OwNMsESf;;kR MxUBH{ZeA;gG zv2E7z|1`0S=Qm(@c<&+(&pU?ZP2S$~NHYJjnb3Y+difIJ9ef=$GT{G1lJMqXCV-(= z`PDzVW!kY>RIMBN?&UP0Ch9rdX=v5FJ)7xE3;jh|RXgWvNG9bbQUF}TAptwqUS{hI zG9*HQp%*@jbCZuKp-Y88n}cbW^epBbU}K2FGC|+QgKUt;RqKr?oyi$8-t>{0Zo}w& z_l1S*U^E$M+Mmn}G;#@_heZ5kb)?2!Rm`Fg{>WYv+A(>4u F4!eT3dwZUQUvm%AJ|Lv`X?c;g&Vzg%V6zQV^m#>;JXwXNO zWS1i?AuoYE57#GdaIT)-1bMT6f-96PL21f!Tl9g%2q`oB!y1a~U3_A+*wqtHjFL)j z#QCY+vlF@L1L6LdsW%;)wLpFPxEPOa)}}3^Q6L*&(E#1I&B)+GZh)sk&f=L?$@$@S zlE%f;K;BOKF<#LTAuhXO@bl%_J?jktyRhX4jkM*qTGN-AZR_;bhAYPrw0Wr^!6n#7 z(vOYzNBWOD?M@3k-B -{wO~@dyTq z<<3I2mx$LI-<$v+d|Ifs109avw7<4&t?E=Z_7ml_*|20g#aoFvmpEjWJ=NZc;dXsS zY&LYan)m{Xet1!nkXC7bRYNwegMDr?zEauOWa#YEJ+trRQ@ebAy5jJ2so|A0(nZJU z5Hxr0>9~6I`q!$*#v5svCJYD&JInuV)dLf}>S5(#spjV5>dtQI;%5E(gm9pSy6SiE z|2?_YWeFsAZn3L-pOn{wFR#>R7f`thIoIsC486U+g371 +xYVurr=6w?qNB z5n6MSehx{EsHdH_Tr;q3$mgUH~_Sh@T?{g^UQ{vD@=O4)L6Xf3JFEXF4Wt5CJK zO7l@FYDBX{u_&QKb^l*8R~Z)Nwzlb%4k;0k7Nk=^a_9~Pq@`2Ip_FdvW 5y&?!#>|3wtIiy*}uMLuK6+7^{#u?v+nh-r`Gj+s`^+LPN3Y7CYOg%4U@p) zAcppVfl6u|DXZ`~rTAy1y$Gux`D!0jaOs(KSri0jb`yhUWVu~Z3zC>a+UvYZM+(1| zKJ(fL08d&KcWas@r3}X&of(*Oj8*{Y;WG#xAYyfSiPA>WlA*8HblJMwg5$y|43aV} z;*2bs;&nxuw!dJV**9SEwU#qs@>}R_nwt~phjJxhdv1^Gy)+)ge+$J@l%ZugH*sHg z7;GxNoNAOGeUCfzM8}La`y}Tz!m2Nu_?nI*p*)Z;7S(}qJ9Q>|gV&?NmOV4k`o+BE z@FmCSiIt8DPQ@cMEPxO^l9?x`I~+kwkTg~B!!xNj&`?l6|29o^$>=p 777A7RJ+HkTS))r6|;i4J{(e$x=g@DP+~? zA4WqMIizVVDwC_DJaHh^oFA pYT9&O?lc9ZX9G+UP7AwBI)-Hcdy>4!+5X zB&r?4^Ykz~Pti|?NCT|(V1f1}3G$@d6d;3^>UQmquVFAwQDKmnxV}9FY&p3yvZot^ z2J_EOF(8YXtJU9xak-c+m*2n6`QhALOapscJ8MhGdX`7Yh9)v&Leij}U%HwIdc@(> zsRSu2WGgL86s;e_Qm4Wb>(P+s9Z#>CNT;i;WU9VT|5dxmmQLu0Au>TAKGv HkIy+Gebr`IVO%n6a!tGR`!(ok zczf-$u-&Ai(N92hd3jG>Py~u}SFy4P7pjwFU^A|{cY8dqTUI>Fe?=FF3i@u<2O3NC zX=v>SjONt@Hy(JmN(y6oaHHv)kefrpKHVbQ#%e|-Ve$eV!xBs`upl607i_q?E4U0A zXSxFWDvDrTnmT`#Hz~>{ZcwT|E3F-<1*Gz5T+n#)3%7bco?OZ-{aE`N06Rp4l >zZEU(w22DuojE4!(3O}XyS0iBQEILC(TcXn6ici>Fcxb4SnSJz4X z0Am6lh1UlL$66fr N(6%RQHI XVKIG PK*} zEedl_P2I4a%ZeoYOg3rvYGK=4%@~$!h6u6=d^62+4Qq`V2PnGLM$UT3_9Tr;@bF%1 zhDW|S(3_307-o-Xshf3yC+ZJARK<#jH-~=AioQEpbv_y=fR^f=T!|a2d0tPW`c8)V zRTMFz?W%C42=aL+mhUrP%eOiH9{68eNeHmYps;9I%ni~OIK*5x2Xo#gFDc+WntYkE zi=E}BJhWRSP375TkT5!uK#^4q(kS&e9aA=s(MeF3ls_*$#(^y6{YHW!+{?v8xNI}= z_wUXhugnWe3no)LL(8k~66+e8wi6ZD?wdt3TYS>B0TG$G zSC94V($5cD9H$Mc8^1@6M6RaGr)(wHNI>V%;J S{HRLJS^&}6RhP6`{YpVJ&Pkp z{Uoalhw_)~1ZgS?35tRYSy{Yl6Mu?lGXiLo=@j*jj}03+Q!|8B8<(bI^75)^FSMN3 z#pj1IYv#D^X64S7PezqSF>0VM?9L`9TfPtNeeU%Fy0EeQJg(zldA@JqY`t1~0(@{X zog|ljZXyPc9>?^f!x366f?nd+QjoBcNV|O}4g#X`&aj|Zd+O&_PDWdi&nnq5mi@*% zM@B)Pa;GhR#<-;mkDz-pi1Mh}JX$ yf$FmWk)jV 1ctyn}IK< o-FRUF}1QO zuq^c=7>a5}-^3bx2AE9pJsC0|hWk1E@)`~d`!Qk%X9re!luSyew-kWTj~Uj%jw{H$ zBcMlu5SHQG;-R(%i@i;BYDs%UwBCxjmJMc_)E%2M4TX_9@0dS-4!tn-uma{`JX>c^ zN{%=zu6;I#?J_3XLI2j0G3CBv(mkbO&zLHJPA(U_Xv4q{<32tf|97^!1)a(T@vRz? zjt=U1?+g8_2+uML606e0nJmW2sGC5wUME$FtUoQQL+1sCc!vej1%-c3HjSV jx0e1%R|C#himg &k5F$!mw8q!oDn~a)J&Iov(X*H1^M^7QE5tJm4(E zBceWP*vhTps *xK!6+)OqS(+(WtF2w!?AT z@UoHaVnb=U;_+o4rbRbKzA(e{J3Mnv2y`wUhHF56)3sXa8E5)TKTpazObNaoS$M^~ z&ofH>nbPGGn3qok#1G5K_?1gOaO&FpvVYXS)P7O8)?cs&22GuMsqOc|zDs-4(;Xez z7>zWo^whFzB0mcVh@7gH?xSX#z_20Di^k1$_s0BG3)BAqM{H=*BYQlCnBnQG=c$#m z
Kx8hR X6CQCqJ zv~cnKtTg{+!?s1%3T_wrH)AW&rBbS5E*mk1=kNI&2KlPw`JGC9_I)$_U3l5!iv|LT zre$Gx%}A3DlE~Lew)}y@6cQlU1l+S}3|Jap%#WE*P )H6v0Ze1e6mnw zZ)EL*)!vOn&bL%*u3c|FXV}h`w@FhoW=pV~M>$|wxo5vXpNqnsRzVCqjwaP{5?nz% zk0szY4ECzkLh3b=a3arl;N#Xdl}uweQ#z%ufjRC$pzWp~+^G^>{vK@gN_u@a`OTbh zoiRmxE6OXpps!eg-$fSuHhd9Krs-k$Tlh(7<9+n+G3Sv@JH8mI!c~AtpYSujhfjvm z15dT92ldY91LIrxapBjGacA8MExwy+uzoWa$e8x+O4feK&NE2PLi20M$ V53Lc#-z$7U( zd0>M9t3~SPgMgd4^~7ZwpLdpCKIf%*8f*VbkDsk)wqf#nVWk7N8bWTS#Bi7g%=gzY zw}cgittZcwg?K_%@0tE8d|b9+u{csqt%q%~87QY4pQy7GgTOvDz6XVqo>KKq{`(4z zz%q^11u`g?3Lm62^NRWSL%^W&)Eb@jUR26%ROQpIqI9a>V*P**APjt+M~}AeqjOfe zNOo+RB@PtLiiTSBt(oAAZBuF64eoQbK0Aemm}BE!40Sm~C@2qxzca^>j!(DE@l{NB zWs}i*CQ-b|px|dt_ =*pwncN)U#kA-Z(|nHTSWii&O*E|cE}=J`L!XTy(pLAyZ5Gm z*jKRZV+smc7pzpSa1?Ek8cVNUjL&Mj>uAXgPFq!_Y}3q!XY4pGy8h$p&|)#LBKa?~ z*U4talgC_g@>PLNl1e45iYJ{)?EvUU;m>SHNBsfqJ;1W%VX!V`CfmL5()O{i+p@`< zPKQQ<<+>$VIG72AP-FFc=PeFyMR=s31T>9f#imh`&+&=zeNCBwu`XsZ b-xs^dPi4ysn`8~q&eGPXr52@|6lV>(SgN(uKCr*|1;;46^K}-<3UJu z0V-QWLzcuA?h;Cam0V6GGfhAG`dnL7dX@Xvgal~KxpCFegM-WJSReVBJC1Lp=5met z7-2 DwW;lF PSJj0=BohEjbJXHs4<2WyV|y>h_PUlEoX3r9M2cRFz)sYOQd z?FdnAn^oo@l_ Keu%t-o0(!`r!MjdZ` zPWHrs^Q4}_xSgv0uQHMIo<#1nsSn;GSL?bT#yIEV!A!>p@C;zrS2Co1 *#GcE~UV`<_BQe+xO!UabhHq+Pz%|Lt*p^*&qneM0wS#%%vJnN2pCN_5{q zN *DhBkC{REHvP+6sfAFbo)kHX}~IfV;5A}xL7)>w>feJ3wx2FIjDSJfY4MIq+hHdisDA_ z9OYap3j4Rm*Iy8Nr7c>I5b7Tm+TF*Ai?P}471oOZH!rQWkKQ8+#9p5+1VT6Yr@rhz zw0&2(E%dZoHyH~lD%xt$!C>nsP66#?W9-Rny+5t6op!GxVVD)Cy+;#&`_B8 oPH&N)xaz=ddr9acoR&tm~eJYLftm_xy}fFxWhdenq; zJrde9)lqgJzv{5WTTI6*I?u+xlYjUJbY2-IpMHMSW@cQU*-0J6jbv(BJcCa)Jj?Tl zg}?Um!gm1)`g_xwLhv*P2OhRrJ1*;y#2kb0PspY5C|e2WJF>AW5`CDNQ_!*o#Zq?Z zI_5~VkQXcJ@Rc02VjX})36UdGhHn})3V+Fz &ad%Ny}t)9kDB^125fWl=P^Klc1Hhm&6@b};E<6>6N(`M99ePn0t64Lo?ibP<&~ zdy^T tg3&rAPn%O$1xwRlfj>ydHBCty**V-XcjXvDAM z8q@smH|y$jM%{N4YBP7b5{O8K?@ N|_31D=bTP1-+1RM C6#Yq1@5v(a oLoV&LF?oV$HcnMSI}dhYCcoAqcE?Y zJJ2Tlin4j!J3J&!Dal(#6)KitD!=a}zlW=nPdrmJC$R;^vv(g3sl0E^jb~0%kcSe3 zpeNt7l9GiRhhYyjiyFFsb+={VG-#( dlKQzjMc+mny#VLoq>-g(&AY#J;^wW`JTxtL5GIq@`$Ec@^ zg?TMAG!dwV`>M^$VivBNWi jA5^sRe9?t5^T5-9zPf;LVH#7_`)OCaWn{CM< z4f1cxop$+m2j6T}3+Y^bEg6?3j?2N lMmhT!X%gbF-8Nxh8x=*#A)E?xo?o2sdjxkdoWA?2F#0=lo9r?(XoL)eJ}h z=vuM?H-`Va9CUZ|&Ez v;Dr%FV#)_B3*p@1k7!S9bw!#wU>Y>soSDZUX!+8oP^i z)8oI5m8SZ8tn2vZF4j#S`ZiXQ+V8QhBZj+JH@(u^STWCkk9F;X-^IG=`Q4^1?8Qwi zNZfiw+izF>rdxHJHYfGFC|7HAcN#Z6mfO?N)3^(8HI3h*+_e9 x3Gj{w=I_?Mra%Tmrm9mubL0dpq_Pyhe` literal 0 HcmV?d00001 diff --git a/spec/fixtures/files/2021_22_lettings_bulk_upload_empty.xlsx b/spec/fixtures/files/2021_22_lettings_bulk_upload_empty.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f1b7de0bbd3a9f1cce894328a3c5e2df7c2760af GIT binary patch literal 24693 zcmeEuWq2G-lBU37i jMw@+w{y3*JGV3U z^H$H(74b$!WMxN2WmJW-T3!nL0~!c4G&G2ylerSe|MG_j 4H$v6qQj7NQ+9gvSMR0(J M2w`DOtgv4qm4!W`0Li=`}0xoCuy{x*~w zF0{=!=c?pur-K3>$N9xZN hHUS^ktugh@r^O)Wij}d!|A%vQo K>2dkyG^QASSQ&7MeMM>0ayA`_M4xZWN}%Zc+{8&mr(-p&a6DlGv~ zd4Lp@ftqyHl7Os$`!b|{F5O-ey+K2G^~(Af`SY;YvxQfw1k7ucj2`T2QiQF2rYM*K zHFh{VD3!>Qb3Dd-KN3=Y0fe=(K=jlv+1PLnDR2Z&icimYu(>{s`0f_5c?w?-go`DA zakix>HsYMp5N9H6Z>jz;x3vnei)P8-lbpqFpo3aX5uPh1R4+d%_C`ANTfH-GH(gHG zy$y bDp 5l beu2ei_tJ4#W(kp; }y@n7N4=Ijk5>?;qa!r6A6Q-ve2~x&-(|ka|a)3 zW?1kk(qvmaf`y$9ZxCcs`?RL2=r_Guvwj`v4(`$SM4T-fSsySDY$VsD iEf(CpjU|OVHQN!x-2w4V$p7SRY(>W+aVZ2`Hr@5&SNk*q`~Kx zq!|Zu(WJ;Ucx91fj1Kv#c6cw_4AExBC 1;5 6~-8A52UK{o PwS=~lu;Q wt0fhpt?pL<>MEKR}K7H&lYG`O $X2vi_XF$%`QJ?TYs4!H-bGd}`^s5hJb*20qNMaVn&W}*&r!=TwGByoo zRYHIg(qKUw#*rem(2k8TBRvpKEa;JN^PdrqRV=6=Hk!elu%yz_5{d4gtH{e%ohY5{ z`4t%}3|7O)R*c^;7v30#6OF?dG$E`N2Nob=a+||*!X{UHI0K2PWbs*}&aqB-2-{Fv z$-B2-Oy4Opr7#4vS6ifvtlGCUre1_iesGZ(m&$Ms%3BH jHk18Rg<%{(Ej z#+od-x9n_dd}+b4$ro~IS|wESeWT00>K7=Mhh(Yl<3uXMX=_8co@2imX&Df!Vrea8 z|L#r_&-*j?BQfNshuIYBcyz+l=g?z(lGFm%WBkyewEo-Ijkxmu!qL|GzUcX{kh`!F z$MjNUrJ?ZX)k(dgVOR-qrITwo3;sgnSC&H$4aJm$LC-qbPbROM{mdY#Af=sXqx~Sv zg8Hc;x;;sRz%lMh%1Lvkrf@=@7wRL&hVC0p2Dm2Q#5LuP#u{tGZW;2U)vO9*2S`Vb zNO=(wl_tZWzU&CjHYN*pYN_;+zC0`T>S@RsqSub3q_UqqJGB0yTpzRyE$d*J?XynB zn}nQH6%`r7(QY14XGpr9g%EX3Pg*RO`>EB? 5mjm=9DSAU_^- zp o58!E zTYSO>@GQTi6+<1u$LYNYy4`;^IQNjY|2R9z P%)ylnFzxfdqjW|JYqLkawXi-BzNd+2i~hJ{2oR7KvwxH( zu>O84V{d9? e>q)yd$_E-vEuOZ#N+K;qwl1$vVqU$ zk2)pH=5Jr?=vaJFvv5Chw7c{0zGHPG=vaHTxNmtmLwvhAeKLLCJKEc@tx3#Sf4F(M z-5c6A+B;dAi_Q+#J^i{C@ik~-C^mTNeq@F8;piT)G?#pFe(I&VKLS{iES+(A+Bv;& zb@vL&yddAh;^pD-!h77`nq%nM8+s<)+5oJOHb2izL^D(#EWFxxPCc9sIIqQP$y8F< zhw|~)@aQ%}?mb=Jf9G+-=apXd!1L75##uFbvT{G+>-1RO?(SHQe0zSptlaKp7#e%I zxWDFjuyBf8B3vDl_2OG~bMZ*~I6#sA)SDdKT0Ey`cf4~7sN&Ah?i`Jhs}S7_jUn)Q z+E`f<*+4uyC5%UtwOYeLBwV$TaxFI4*=04xu)E@TeocG0nmyW^x?9 A9z+8Wr?%aiTb#oXN4Z;i~ljaMeMG(!9sBr&e2_k4d~Zx=bx6FhX85Z}t*(o+n~ z+vj{*r^iRzRHX$^bIJUoawDkAh=ivdd@@DJG0N;X#gC2KVQV)0a;T398Ftsq<=sJY zasb?w)kls =H?scQ-}a>AO2~v+5c%>O`N}R%d>6cJv?S^;4HtYg2ENTZB_v zlnoE3yIswxY3M3zn5ZPJ)g5+r4EN^^LzdQPh)0fzM9R3ucXo8l=5=6*6^Ce9GW@W- zq7FCxw4=BPmmpqPE~F{$x^Q(~QS5`EDBGIFeB=&$2s3PUrewS#_Y)~#*z8WJ=tZtP z1y^RtIQ3TGH~SdaqKT0Ny;W`^d!j06V$r@TR!g6{rUYHNyc688HCK^xNnxL1V@t-T zD!sxS?((98@@WYnLFcrh#z$N&>CgCeKWW?hy0o;$yY`!OMk8mF>=|ca8ep--ElTr0 z@0zxzY!?O1nz~aN*Jwy_KjGNdEz%aW&rC0 ^h~=;O&08+>LXr0Jh><0|>R;83 cbrcz9mVZ;n@&m9@m|{}owut@P)kL`$t+o0XOWkCKb~Cj!)(H-NmW~y+gz*Fg zr%b8@t+s4Z{3!r3^R*rhdmP6sdooAP>_#6+k~Zdmd^HIc5VOluBf`jRZ!l zjMWL7*C3Rp=+&j(ipeYzqSx}wN 2!%Vs^zooJOcUhxCC7&EZ)=%FPj1T5i6G5LatC1OiqiK^)CrrubOa} FrW2gi zEFBu7PXmBHcdR8qA2R9o5}#dXfN~S!?hu~+2$5Q(Er5=0%{F;{xnOx7Z!xezuYF{0 znQRulKD_Doj@0Qi;%YYfWq)&>$AnHEO9JtaGKQbqs0qa6%{z()8Z<{?)I;$$g(2q2 zmDf`I>Kb&r)> Tg<_te~Mt%l*{HT7s-EH*psC|44;%7&X+xQK|!T$(W z98;ODn!P@0V@n-4(|nwE&(6`u1D`xHavJI#2%v;6HhNPoik9yyvrSOT#!J+AQ%381 zZ*x!{#c^wHJI)&Zd0P7DtvUHB1_<4mliiUFozd!b$g6pjuk5y|M>3!p@yb)&`HdlT zaS5nc$evg1>gRc3F-R^C_F7d5sU9g(%9Yt8 !SrZQz_OEsxcDhL49r41d0pV~YD`Sb3IPzE!~+>E zpgH#^BBEAeQt|>dah9@xXIP66qF+L3`ecUc;s#|wXmDmxzhev*NSKI*gwhN@8)}H> zmj$uHnI-*BF_~uk$uv=5q-u~Q0VwO|iEq$|bS00h#ki8zG@;u~Wu4F*y&?+@bv=zs zN!b&DvobQ!&yqkb@8gMQ(+me{*1c<*y=wy8Mp?{?Z(>ZyPU;9Q%L+1Qg|iat0B(b| zaZZ|uuBy|rM?@3DL1X`3K{P`q#%VFcmHea*`AT}xjAS>p4j}s8S0r$FvbezEWwHTJ z%5Bxl6aP0w>?;ou{l8?uAv-Nbyc=V`8?(F{8^0R^&qD$fURnaJg|i~-0IGwvu}+I& zR|eCvT0|3~i)J+23*y{Xfjqco#pN+32Jy>(S)jjnL-XE^>U%dx!i!YB!0| QAb^~Vbwx>h7@Kl0N885^MiMiDM!w>J3^K_&M;$SNkFqi6qX4p? zgaWf$VpU221UDs7Kuz#8pCl9|{`658;WT~bx^Ib43vp-_H%6OH*MMS7WK3^sGiB{p?8%b(eAxEf`$1{$)h6hIy1mE| z0m;^{>d=R@`O|2J^pftBC;1LOim(rh+sLYErj;-jGE{dKQioNG4np~xR}WO>OnkZ7 zOn`4=FiSCCCjmWRFpk`-PRU=tv?(8F-r$f~GKRHR- ^ dSgB{lp)#9@%^fB~E%F-7&G^mo zqEJcqNTfY13rM839UQs3dyUiv`uFDVGh}y3Kx9p>z9Y{es@rWcR{+Ri_wr;|>F?YY zzswQ9Z~0XM$Z@zKie=F7B-2fwiubro6k>jd8_i5dNhP#U>f|~^PQy#`COlHE {>vbyNA<_$Tu3^W7aWIA6&3f}>B%*>7~8&-p4HUN(3;SSG3S`JF^r zDQ^i?n3JO_;kk~bFWP@ue`dRHZ&uXE=jo7~U)xqiSYHm#!J7*IIFAR&nY7BFt#~R< zb{O{CYz=3@L0jDAgolmNoy@V7NoJ+wSTz#72>gZqE~+)`FMP$tL9;xV%K0Xh4H+1* zHk}i50SX^>b`>bvCjzmEww2ad)u0|4{<_IZ&8Jg4s~$S?S|gRe3AiDM42zyFi&Whl z?!=ocxu^7OlGs9-O`*Af_pO@M4y}aV4iFUymeo-9koaW6O3mdUo1Z6)`OY*;yiw}x zBkaJE&3>b~DD D|bscdH0CaO4LKT4lroAXM zc!N`jn}DQSxCOU7Nr!>wW9S!`SC> `wk|GZC1!~_1~bMKrR>)rRU zyv_(sj5ZN7kT{0(@)>WZ8`;*yCg?3udh`hqqG ({2^I1! zq6d(L1d^T!)(SXPxM4O<+(P;5xS$-K6emMV{DX&!H9}SxT2DhYLO)+elF@e)E9hvH zH=j&1p;YGl^|PBkYLa6nAW*jE98V1kg|7wcL*?N4*?kyhqNK1lYM1CUc@`=CJyO9U zKQ7n|vV)R9PpOupZDSkAF8>2ck}yF_9x^8+r+^Y$GD;DuP$%J5eo^cIq_78`nT!f; zq45~5G|6=&YMM&YgfcVV!FQVM{}{AS0nq=3l$?_I2~G-&!e)ep;0Xu{TtYA_st#IH zRw9k){~06P2*1MSurz5U+(_rxn&pbNkTZqT;N5d;6HJMp>ku&wBRRi^>+~4Z-l5lM zGk>O)yyED=?~({vo&_uLD{IXy-OxdB@R63uYtNt&=urbOar$fR?_YnU&+Io$HGAaS zJDw{#D@eAc_fL?2>gW_yeDV3Jn&HO4IL2p+pPQiHaw`sE^P*_SqO`1JS9tN0QnxCD z$_Zf@f-*VBL9iKY2PXkn-Yw@^uo=QAhI&COQuhEB&b+tTgU6ZTWNVk-Yhrxqs1`ht zP;QClguU}oY1K8ezTQ0~JT*L}KGfm)coai0u|DU1vgM s3=WxGW_j8hsh{) FZm0qM#m0QvER0->jYghF$Bn3`|-!&ig0b1GTiUUQ0*YLR)bBC+ms&&c%Nc!ZeYD zsYhl>-JV}I5n<(uEDkz<5AQDv4iPF5cPsM`{OWwg3Ks?|;hzmK8?odZC2W}J h%tz~@;o#qGCA&Kf`h@6$E+VIWAN2?%eAMT(q;U$G=9I*w)XAGMN=7F{sK(l~ zDjSHdw55aaI#D3;x;HHY1gix#S`=%35NU;^rR2-4aza_d !nXrAsJW1kv*(sk@C ;7*|1f-ilngyi$KpG3Ar$Cwt zq}L-?2ZR?O&f4z~#g?WY2n9j!Oy41f?bSQ<1$B0Ohd8#a13>r-^v?Gk z64?3=0wE}vbJRN|wv`%sw*|XPdxzw L|hk=lu<5xd} zYaj~= IIqEG(_1wf0;<)w8;O;K&GZd%p$)l* znFP|3KAl}(-MH6B$K*=%<46Qn6~5JKh+Zl($*c9s AEV&G~JbW>YMV(980v|=nZ5Y2QY3Xf|jHGrAr+7l$zz-qY_ucldBxOLRs=G#N3 zh2s^KthV@$``U7QxEH1`>J3)4U?(E*n-*+V*EigOl0ePX{f(!E>2qw`uLu5?X7go~ zl@7P{5SEl}SOSNIgo$6>?U6M`a0PjuF2TI$LWBp|YoNY!sg`-te@I8l29yjALWKKS zg)o>YU$;r+=QRRvx!qi3^7GW#fy{Ki0@Ix*4!XU!RKETx6f3oLEh#Om6ND-by4{+_ z_4k`a%^B)D3!9Ymi %uHE{HR7*0IV}Ct47Y`KrOb =Eg z5H#cjG&12Kg~Ob>@M!|cCrbPrhY*xSn*GY0Uw#O1nzZ}XIYWN*aErA2wK-FMvT&Mo z`}H{se%3TC<@*hJOJV;4le-jTjoV_i-|$Z}+$|^j4f#t^*8eo)WHNSAU#k0LqSX0V znRQ zFGbj2fyFHFFF0&PV#Qjzupavx_AP+U0hXhjzAH2?e@4&@v+(^ng-hT7sgNWgN`Xu8 z0IiTEVO*g_-~gqNUQ&%xC*Q$e5wVa@vXK&A9)$?!LMvoL2oF=g8EGOgg}&F3r~&Rm zC*(pX15>{p=`1jXq1Th>7Vbh98bk;h$ ad00pKR6pxwTx2!HVucpMvD zFi^4_w*LiDrX#{EMefcTHw+zk)BpKUaPVHVkX7Ik1{SH|66h5U^Be-FKTEPx-pC*3 zJA_Yz6dIz0{eSGZs&@VA_(@ow@P8rVB*}A2kUImh=zG5tCBa>2ha3oLW9qjetp#E+ z^tuww!d-j~c@SF0)bB)k3k3NT073)}ttSBeL5LE`&ll-minPCnC@|8F-eCT@Nc(#{ z{uNzp$e;e1Nc*>VoYdI+=82;D(jGra{ojuJC$8E_4LgAjnDUoZ2~+qkk$;y6r;#NG zC^K^$!ltn$_b7GV>o1svGzk?7ErO-NiiCw)36PXz@$xevYeF9}H=B?~0$u2PfyFzx zYMqcXp$N>)Hl(9K7lvLBqEonP-H 7%9#TFW*e3armD%BeL>bA_pG}?GxzbTfUTrPoqozt= 8# zKMrv-5<6J9rscGgjdqA9;dLv>#>1{6Nz$%A0g(6)N5OG#N{nZak4?mrG+v9_H6ZY6 z6}QxCkv)1j?!_F~X{^N3xNVbjPMe6${FGoji0#=PMCP^2z~jsn8;>JNz7}WaoX!_} z{Ee^V)Ej5Pk_IYO(ItBjyA2!h)t5}|8~e3511Ix0F`j0yVzu?Xp;#@a0+QdE2 6X|k&EopKYlY*{K^{Ex35H?H>{Nd@GozoH1^N0(&)Z(dIarw@Fb zds1 S{EO^bjsD;_i1(dfBo}?1y<{LD$7rDcV8bxZpPgX3c1D)=|J&Af z`gcirtc*nu T`l__kB4%*}zsE%UfMHC5x^iMETipO1PXT-kox} zn?D+kxdv_{s+ks^slbTjMWEq^tZx;vVy&! dYgyK*%n43a~4*SsKcepYNtjb BWm7@xzEhOU_?2%7s(cwm_P+I|{l_9;c(|8gQyvD@nxQ7xWPSmNA z$;+!&PU{s*YvGYoiR~HKxpYzr2d~cp7jNXcy==CA!~N84&oRqd3XS;Yv~Hl{Rl)Z4 zMVazQU>B3_?ob2{>UC&68W4(NOo_6CM;jq>H8Kxv6^Kg{+jWT=KTxR=P;6dMK0+o* z!3^M9L~bRNUF+5~=+i&{YHU}an8?XAEW@OSoSA!z?j7fu=?@_lc#d(aV1#0*FZX@d z@KkyAapO$zX`p9xhn$|+
{J4$l^M@os5)z~Fw^HipEU~da1~mw7*qrAXOP*^ zmuMlA&0^b0r1&oqKPLw=)5eJKMu+BLkdDz;*J<-Ik?Hn7 D== z7r7pSdnS 5kZ)oynK=0~sUH*@l{OM`~wzhiwO2hkhsc-CYm z;EtCLT#>!Fc^PJGiud}SPp;e6J2SJAA*_q{3jG_cGeAG G^%S>{Xm-oJ_e<$GA0(Vw`gV*JH;s=Dwq6I zA$AbYb%TNQque@g{&8H!H)|*rP+LDelJ2yx?L1MzS=m>V==WW530afC+vG3a3RQ06 z#NhSUYNWVnq)eDqReL<1>2R?aQ&>ZwW`5MUro_*g-7P`Q64hD1S|rJd!5l5-D4EC; z#MCV{(9Cm~ZE;LQWOPI&d{vS|`f(C`HN}3f$J;3jdn{)1E5WEh!{dY)DHot_Y!_Db z8S2{wFJGwfJ9|n5ay~nQz0G@v*{2Gu%&nUK%J;1D@ved+;2ZqRhd-?Bzq$WC1Tn9A zw453W^1eW1^tI0N{`N+ I$*60BDP@o@`RMK#01k%+z@ Na{`ypVUi2Apn&T;Cf zdjzU3v;8lNlBh~BfVtW|+ha@vtraGZPBGQCzAbOnw7@Tr9WmvDi_Su2w>p0UPo`Or zJxpR4yVsXdJ1`DR>Mvy&k&g3x#o6|bQRvud(*>oW4=)D#SgRyG!Uz;R@KnsKhNAWP zh&@{UibZ}AmUgKuFA&r}dVPKmTo!f9n*=iGO10kiCZ|AyNnn7O*p&?uk%>oWFvt7J zT l_wn>Upt_di&?}t<&h+w4Ic1e56^32#hzkp~5)L6?df0)fct)8SP0`@) zh*o1Uj2Xudyd)>?L <1gS4jGN|dho*H#{?l}~+62_|?QQu`! z4J*1w@}6jqHN#a3SIIUObv-qwT7guzP@9ZN<}t5*R;ooY3bUl(m`AFNnj4)E`S!zy z-^VjT{Z*ABR(E5_HZOOqE58o>WgG3g(@#gyT))7iZqh*^rk(jGB3R3*EPTHZ#}d4S zUe@!Y6C|MbBq@&)_-HJA_0c^bmfB?V#BAokpKRRJ`Jv9lXyj+N17T#3d8XVt2K3-Z zWKpIfqOYu(E>*`4*M-YmzIY!~sboY2SHea|%alYb7!{PItMqp1Dre`Hol8RNl#g?` z>oDwYgjfuk7tv8ARL~`lEcDTP5d7N>I>SJ3Lm;+ITPTF0vN!1v;#?W;@D$)4Tlmsl z$b%)Xp_y)$X}%|XJyolyWj#B#r`32AZ^oi2acdf}>!?Lqg{9Q-XKH2__F~zmMx~^p zy-mygK+@E=E1%Z@*1%gw;kYFAyGvC6g$zZTlGaO7jNYXn1`GsO2^GI#+eY`z^irs( z4Oj1iU=W^|>6%@g}9 Y4tZnnz6IIioH=%KTzPqf3-gDQN!(c zbspyGttshEAzj~Mb&fJNoi*$TmC{Ks6Nh@W23Z(_WiE7ZFe#=oFVJT!_C0~GV%L=5 z>SW5t&k?m%Pid-&-X)S<^8R_1&RtBQW>4F_v2lEi7%{T68@&gIQ kSE8(Wjm-jH(8!+i4T&LS~Ys zT=t>tl=gev?T2)kBO#uymaFJFit}*ai-kI=!*L~_U}+IBVedInzj&+Lf90iwQ=kD* zH=-CQ_&*Z16(dA3`W+5Ex@B8)5S&(Xc>0}TOVixeOS;_0lMj$;FU3dYJ!ub+_66e> zAbG4QDG@%%^HK@$I<&xtYx68y3us^f 8%6 QjIP0okZyRka88G7az%6f?}>yxc8*H#n$GPqm4x9i+?CW>cR<$zYHw)!A3f_bWt z2LOE;Bf8(JUQ -#Ep!BU>!;I}m z;9eDWAscp)RU7Wevh6BO6)nS5yY4mBX{4c#T^s_eUDZkxnmzPoB&>0@88M^1ViucE zt#IDhf$v;(9fnxWmA*SHuI^${cb>2T45BK;F_fV066ey-WUD=tW%X+CtsJ+(aycpZ zMQhM1LxNr5LS#^V{2tY;WM{jgaJ)N&+e4n(DTyx4RN*iZXx-W{eVQB6q^8R&tRt5n zypvLUN~qpX8JKKM0|E_BVHMgTYd_m8&TFM%jpaTeO?)b?4!#t OAkXc5GiW2Jsz6Yc_G-Dy zv;<`C$kHL#CmUh;ei(sD!Qu_{mEgBV!HHh_ %o84@F z?+VXdP-!ep8Ny{WJYvDSAen2yT3v9DSE}aEvjc*Gyol{Vh_r5bN!S!E@Pg;e&@OyP z=egr#9-kQ)7A(2joL&6b$VgY`Wdp013ItczZ~0w#dT@m=D%(nJE_iWJgnLZtR!R1P zG!m|} ?2?}Y5Mr31+;+=A-Ko$(JLk%l@LA0ePX65(Ni D4feJ*?T-DNPob;*j;vMpKEfFPbY@PvQk#UTDb;b#}%67bsv+Bjx>S189z?1*H% zGylf_G_#!W`qc8}+tK*!fZJZw?0}t_%$6>Txvg`4kTaY4d~>Zr&lorE=i}9d61}r= zQTWEwk&=y;!!~B~rV1|1h?c({DkBy()H2mX`+VAg|F!-`Q!5S^-q_-i3~_JeguE-y za47c3m^aG0JK !Mnv0@vfnnW`aT&6p&youQHOg2PuF>YRd zOPM)_e;vU-bG7CPYo3CC%IDyJM^*N+pzC}Pz4HQp_PYO)5P6sF$9#A*@E{+g^5!1V zIBikyDc{9%|9V j7DFh{b@im(~n`1BK30 zbHb#xs&nDRw)w%)Vy@fqWd{9TXnpXLL9~Xk1Hk~Rt+FUD`PVZzjOjB)wVHw1uHe3? zD0I)`!aLrs xgpD34xa!dXBr `P{dOhL<@l$I%xR9HV;l zgo55p!K&+@3DgF%T iyaqRaJ)w}R~ zQ|5oE(_n$K{;+weGnPLrsqIQ-3Qu64c<+AJrlc^0%eD?5?$YDJhkt1Z=UNj8PR_lG z!&bN(xh2s!hH9 MiYVaGB%fvkzF>Fj4#(j4v%LvOKH^I&Xc7F|Y=3#n1f9 zkKySoR(`(yRgUm>nB|c{0s$%c_K(UD$iQ-hp^bsOosF$MgMp2m(fhl4o{GO@f%Td8 zD|D4pooR$gG^ x%ZYC*q-ZB3`eK`P#k)E&B_@pw|MLGy%b~oU|H+Ui*-5k^ zBuVLT2czyhzl$-qsWbxvOHoapW;>YDrzk>437*o<*RR2^8Xs*)fjQZ~V5PYRb&xC& zg%#_X6`SljJ$${6-#zzd24j79f47FYF5Z0hSNPtR3bC7}{GbQa$C?)J cj2|#sj7ntKrQ9NNE?biViSry;5Haf?+RI!p0i3XD4t@Ax!eXeDA zuOBT;dY;&Uf`IJ)!}<|$M*luxdbYOj^OYI%w|d$W`mgIW4mu09u&o+INdNBs!C~t@ z` ANww^pe)eF=(mG*{!)6w!8`JYKzqox`hEMMrgDqx`;^%{l zX2Jm;?)c|h%ShDuD>>*-ZI-p{5$hNCnx>)?T={BG4}ZO|8dS}Cga~wI5AgG!7voU> zS7#bH+B?`-z5BC1UdLwX6I#&O9SyBDg?U6IKQV=hK6hNJvCbUpqD~;Zbz9#z(1+=| zH@>{_NW1EEndUE0S$CYa;x>pY{R`g }z#b pfIZ0j-2A8`lCdv-TYdJI?))$sGFQ$=eQ`Q%>{ zTJ}^95vJa#HV{!#(fZlk4$BNNhxUDF!HHOFDLf7Pc3p6wzWTxPcX5Vx`{k5~S8QT_ z^!k0bL6_yyu2Rmq3J9~Im*$r;5&VtFt*7>#$RwG Q(_i^b036b6pF|u6hMNC}IQ~{= zYV%$;$HQMgSz$x_<01_>t>fVTXlmhrQ~Rg<{8!1jeTG-AhY<;Ky}gt8a+O0us#HFX z9=a4)NJRhhEm<{+_h5(6{hc~`9vV6zci8mlw0(d;+gkK9sm*#DYYVY!TI>f_cA>)t z;)&MahcwGWjfW55J@T8}W}YZ+b(P}5re~BlZQy+#=Cu2^(^$n=L4_8jMr|f^lf)yc zGcTi`ZX}Fr(9yqZ#l{=n>21VW0$AgE+Be)Ga3&(|RgmLSEkJ3Q5w2I7UVo?X!RH2K zHKHYJy>?Kj_((GvCg4KZ9|<)I!@Le62k{44d6$IvV$6BqVIkLnAX6||8077I7V$Wn zD)G+Rmq#U8(ayd`De_dBzHX8t^BXou`#qCJT-2PYSsP+Dt7MU+o2DTl_gedi`o8F3 zc41WlEBPRhz?ZxK@pba&@=&+3WH56uvij?t?h{Qd`=tgHud~Yaa~`R-(73|V#qYGO zW2~~w)o$aiM*<+ExkNBQAXW!!&aR!3#8i!2vPV1|q<31UUhd!m-fvsK91~1%p!?ek z%_AIDatU?=Tw4ntj~?|L@?Y vd^ sN5T=AdQGGy~#O+_FOQW&-doIyq6sKqb#!-W)u`yB^SA)%D600JWYxkJ5d zboRnS%Ed`m6DC&=#^KeaYnHo7p7}yE2!6C*I8|*)_U?CfjGpx)U8};eKG(hRdx>xU z*zI01dN~qGF1-k7R;J4BKkhFgvG6}P_1k@fma#rJHP j(jS(*hx|d4xwbL z9m`13a+flhsdCK30hAgoCRm4 JUa$P&Hl<=?t7?F#YLATSyoi>~!G|2#eX8arofSs!WnaK&7`I z3ORukGr)=_z;VT=hX)x`;MU`-dJK+oiSukl`G9lMi*#Jv%CPcncGD~xO!9SL`&A8e zXO*x4j4+jDa5TF_3>?j|__O^168zo7`MwG1t#igl#VWs~CQ;o|cGfSQlUpX^Je(mu z_TS0}mC93lH6@G=4-?gfwBl6qctq<%uy^&eoCt%53w0YD#C`wQ7#u=9}gM@Z}2# z?XLWqfpbY{i8NlZqAalFJMYq&qJzcXpI8I_ywU#HwnKFL>JtF|-i>*&^(wR?1Y?xs zx=PvRTLa^OAZ~DyF`8bt^W?>rE4sTV^o=BA2{ew&V6%_^&Bupr&H=R4LZ Tj_@`E2=?F(KrEG#G@<1tOU$0`-!da-!v9djX?Q$kXxw{{+Ze86>4NT~4YXuhc}~ zp6?#?-)fw#MNkho EL<^e3#*~x!Z?{{r )p8p*h~xzzv%ZwW`h5bAo^myh@TI %KWiX50d#i zIm6qz%5>jV2tHQqXHj0rfl=Qca|4GvwcYGtVy&c#i2G@h(Q6cM=M+zq9Is1F;B8Pr zh&vZ+YUN}Y&YBDumpMVkT?Wx{&3TBc5V3fsM;hA88X`DF5K>toJ=_=;t|k%OcN&>& z=1*R6Qg)_on3`ruA8^)UMh5PCQhE6G(Gom0en1C&l`!10eg5oyO}Nd0Ndds7MvdmP zjfk5Nq4EpB4R(#aVWPj$0?!V-g|G8TPAZaPUHOn{;PSA8Jd2Sv=i*-WQ(vgw=8HLB zGI7lHuhtuzdMM4>qhg%2n!Qd6q_(apHFkoGR5sBkjqitYc|L55UYHPYkVmfAMpB)3 zCJu=msab-JWASbHM`NeyY~Ez59>aD+1@;^DeNyCf#o|n_2~Nn?Ud8GNn+a%Z%1|+n zi3GYX0*6qq$ymHb5&msD&|}8pE<`__csRbAN#xPKC_YoSfIW^vQjSnhT{V3 aqn(-}n_-J=SWXxVJe=4Li)8wX@ Y{G-Sc`W}$D zD<#{8ctf8`U2Uu;%ERk6Xt{h n z-g}B(YKB**_@;fXNZ+UKP}hJW%gh)>y)VA?3>O8{;&GXUPOVUFC_)sSC%#`%kc?g? zxBXnsSGDG_F!Yl17LCJtgtl2qn(1N^q1YsR2SA&bRX3*d@e`Na5|`5vNk$0=eTLrj zZK3__@PR9nD?H9SiCNo;wbGpxc^o~@%)_%YDCtev**8y7h}U|ncdXl`^;gVXigoB+ zv7sH= 8Qqo2AKtyrpoWdz=i@h=m0q9n-UiCT1&bY;+#+V+9ny-+nqPcS+hpR0|rHK^^)C zZb8$*K(G32NW+l|-y1mBXt6OaAy6RO1DT}2lUgtiNF`&|O&a9qvc1bL{8i!RA&RMK zj0{yif=3 ?W}1{Bfb(=||}saN)A7`m&x zkFB6SVs7l2_x00+HRrqTs3_;TEYvi))7^ k83q3EC|WBkiCN2j~-n(b`1JMquN zU%I|9bOMNVC+hk} Mq?FmT-vTr}D{a6F m5}p$DX3;9^G(2;}yBKQV^;%u8 zvJG E-b@gDsQ^Is+Qiv%)kYr P?>NlWQ{U7#}3Da1 ~w;e)(?|ln2k2bkooZt+o!o+DG|(X2?kK*O{a4wI7*lEh}8o z{Oh!9{czet|FGrSeU%*Lfs5!F3eo;Lc~M{*o-rbA^J#b{AR*sDJ&z=OK1u^uB^S|) zP(od%8BDpjX}vLUxzl<`M$PRB gQeXQ+w41?ftQqyYWY)_@lr?+ZC9t<%yv^y0Ha9ld)FK^?d zQnEmk8OvgvQ?A`^vlTCCl`+;n9Yoqtcxa_@J$?Lclz?fFxwu$b|M&Fn^5m_$zERDD zxd28#?i}VAl9y(Fdr9|8=y0c! |7M%i) D)2<;c_DIw5ecbocpzi*&%`_rHy-7|sDkK|(4WhX!Eo^^d#yQv`EWtK@zocP#j zz};fwYqBozU~T05Oj8)Q;ysfd2t%BcxSRiL**9A;cj90oY=|Bx@o4ClN*m}fWTM`# zq%PqJM0_@YDq{XI|CR_5{=1RzbjiRef2zT#29 |7{3+_Y(rr |NGJ ng$|T8&6A76C zn!;uiXVQ1~h;+AzkVG>yv?%lbCkGoTIXm66bh>A%@8x3YYK)A(?N_^;5Tc`Diw;t5 zU~W=c%ImLmwu8Pz|5MrB1mK h}+(|fSVi+zNz=LrzriL zf1YF}&L tU zR38rMylTZfTg|r%Za(lka4(|fc^v7XeUL`jRF#;~hkded3+1J)(_D|pEO!lBmXsZQ zjH