elsifincorrect_accuracy||value.to_d!=value.to_i# if the user enters a value in exponent notation (eg '4e1') the to_i method does not convert this to the correct value
<span class="govuk-caption-l">Upload lettings logs in bulk (<%= @form.year_combo %>)</span>
<h1 class="govuk-heading-l">Prepare your file</h1>
<p class="govuk-body govuk-!-margin-bottom-2"><%= govuk_link_to "Read the full guidance", bulk_upload_lettings_log_path(id: "guidance", form: { year: @form.year }, referrer: "prepare-your-file") %> before you start if you have not used bulk upload before.</p>
<p class="govuk-body govuk-!-margin-bottom-2">Use one of these templates to upload logs for 2023/24:</p>
<ul class="govuk-list govuk-list--bullet">
<li>
<%= govuk_link_to "Download the new template", @form.template_path %>: In this template, the questions are in the same order as the 2023/24 paper form and web form.
</li>
</ul>
<p class="govuk-body govuk-!-margin-bottom-2">There are 7 or 8 rows of content in the templates. These rows are called the ‘headers’. They contain the CORE form questions and guidance about which questions are required and how to format your answers.</p>
<h2 class="govuk-heading-s">Create your file</h2>
<ul class="govuk-list govuk-list--bullet">
<li>Fill in the template with data from your housing management system. Your data should go below the headers, with one row per log. Leave column A blank - the bulk upload fields start in column B.</li>
<li>Make sure each column of your data aligns with the matching headers above. You may need to reorder your data.</li>
<li>Use the <%= govuk_link_to "Lettings #{@form.year_combo} Bulk Upload Specification", @form.specification_path %> to check your data is in the correct format.</li>
<li><strong>Username field:</strong> To assign a log to someone else, enter the email address they use to log into CORE.</li>
<li>If you are using the new template, keep the headers. If you are using the legacy template, you can either keep or remove the headers. If you remove the headers, you should also remove the blank column A.</li>
</ul>
<%= govuk_inset_text(text: "You can upload both general needs and supported housing logs in the same file for 2023 to 2024 data.") %>
<span class="govuk-caption-l">Upload sales logs in bulk (<%= @form.year_combo %>)</span>
<h1 class="govuk-heading-l">Prepare your file</h1>
<p class="govuk-body govuk-!-margin-bottom-2"><%= govuk_link_to "Read the full guidance", bulk_upload_sales_log_path(id: "guidance", form: { year: @form.year }, referrer: "prepare-your-file") %> before you start if you have not used bulk upload before.</p>
<p class="govuk-body govuk-!-margin-bottom-2">Use one of these templates to upload logs for 2023/24:</p>
<ul class="govuk-list govuk-list--bullet">
<li><%= govuk_link_to "Download the new template", @form.template_path %>: In this template, the questions are in the same order as the 2023/24 paper form and web form.</li>
</ul>
<p class="govuk-body govuk-!-margin-bottom-2">There are 7 or 8 rows of content in the templates. These rows are called the ‘headers’. They contain the CORE form questions and guidance about which questions are required and how to format your answers.</p>
<h2 class="govuk-heading-s">Create your file</h2>
<ul class="govuk-list govuk-list--bullet">
<li>Fill in the template with data from your housing management system. Your data should go below the headers, with one row per log. The bulk upload fields start at column B. Leave column A blank.</li>
<li>Make sure each column of your data aligns with the matching headers above. You may need to reorder your data.</li>
<li>Use the <%= govuk_link_to "Sales #{@form.year_combo} Bulk Upload Specification", @form.specification_path %> to check your data is in the correct format.</li>
<li><strong>Username field:</strong> To assign a log to someone else, enter the email address they use to log into CORE.</li>
<li>If you are using the new template, keep the headers. If you are using the legacy template, you can either keep or remove the headers. If you remove the headers, you should also remove the blank column A.</li>
<%= accordion.with_section(heading_text: "Using the bulk upload template") do %>
<%= accordion.with_section(heading_text: "Using the bulk upload template") do %>
<p class="govuk-body">For each collection year, we publish a bulk upload template and specification.</p>
<p class="govuk-body">For each collection year, we publish a bulk upload template and specification.</p>
<% if @form.year == 2023 %>
<p class="govuk-body">The bulk upload templates contain 8 rows of ‘headers’ with information about how to fill in the template, including:</p>
<p class="govuk-body">The bulk upload templates contain 7 or 8 rows of ‘headers’ with information about how to fill in the template, including:</p>
<% else %>
<p class="govuk-body">The bulk upload templates contain 8 rows of ‘headers’ with information about how to fill in the template, including:</p>
<% end %>
<%= govuk_list ["the CORE form questions and their field numbers", "each field’s valid responses", "if/when certain fields can be left blank", "which fields are used to check for duplicate logs"], type: :bullet %>
<%= govuk_list ["the CORE form questions and their field numbers", "each field’s valid responses", "if/when certain fields can be left blank", "which fields are used to check for duplicate logs"], type: :bullet %>
<p class="govuk-body">You can paste your data below the headers or copy the headers and insert them above the data in your file. The bulk upload fields start at column B. Leave column A blank.</p>
<p class="govuk-body">You can paste your data below the headers or copy the headers and insert them above the data in your file. The bulk upload fields start at column B. Leave column A blank.</p>
<p class="govuk-body">Make sure that each column of data aligns with the corresponding question in the headers. We recommend ordering your data to match the headers, but you can also reorder the headers to match your data. When processing the file, we check what each column of data represents based on the headers above.</p>
<p class="govuk-body">Make sure that each column of data aligns with the corresponding question in the headers. We recommend ordering your data to match the headers, but you can also reorder the headers to match your data. When processing the file, we check what each column of data represents based on the headers above.</p>
<% if @form.year == 2023 %>
<p class="govuk-body"><%= govuk_link_to "Download the lettings bulk upload template (2024 to 2025)", @form.lettings_template_path %></p>
<p class="govuk-body">For 2023/24 uploads, there are 2 templates to choose from, a new template and a legacy template. They outline suggested ways of ordering your data.</p>
<p class="govuk-body"><%= govuk_link_to "Download the sales bulk upload template (2024 to 2025)", @form.sales_template_path %></p>
<p class="govuk-body">You must include the headers in your file when you upload, unless your data matches the exact order of the legacy template. If you choose to remove the headers, you must also remove the blank column A.</p>
<p class="govuk-body"><strong>New template</strong>: In this template, the questions are in the same order as the 2023/24 paper form and web form. Use this template if your organisation is new to bulk upload or if your housing management system matches the new column ordering.</p>
<p class="govuk-body"><%= govuk_link_to "Download the lettings bulk upload template (2023 to 2024) – New question ordering", @form.lettings_template_path %></p>
<p class="govuk-body"><%= govuk_link_to "Download the sales bulk upload template (2023 to 2024) – New question ordering", @form.sales_template_path %></p>
<p class="govuk-body"><strong>Legacy template</strong>: In this template, the questions are in the same order as the 2022/23 template, with new questions added on to the end. Use this template if you have not updated your system to match the new template yet.</p>
<% else %>
<p class="govuk-body"><%= govuk_link_to "Download the lettings bulk upload template (2024 to 2025)", @form.lettings_template_path %></p>
<p class="govuk-body"><%= govuk_link_to "Download the sales bulk upload template (2024 to 2025)", @form.sales_template_path %></p>
<% end %>
<% end %>
<% end %>
<%= accordion.with_section(heading_text: "Using the bulk upload specification") do %>
<%= accordion.with_section(heading_text: "Using the bulk upload specification") do %>
discounted_ownership_value:"The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.</br></br>The full purchase price%{discount_sentence} is %{value_with_discount}.</br></br>These two amounts should be the same."
discounted_ownership_value:"The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.</br></br>The full purchase price%{discount_sentence} is %{value_with_discount}.</br></br>These two amounts should be the same."
outright_sale_value:"The mortgage%{mortgage} and cash deposit (%{deposit}) when added together is %{mortgage_and_deposit_total}.</br></br>The full purchase price is %{value}.</br></br>These two amounts should be the same."
outright_sale_value:"The mortgage%{mortgage} and cash deposit (%{deposit}) when added together is %{mortgage_and_deposit_total}.</br></br>The full purchase price is %{value}.</br></br>These two amounts should be the same."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London."
non_staircasing_mortgage:
non_staircasing_mortgage:
mortgage_used:"The mortgage (%{mortgage}) and cash deposit (%{deposit}) added together is %{mortgage_and_deposit_total}.</br></br>The full purchase price (%{value}) multiplied by the percentage equity stake purchased (%{equity}) is %{expected_shared_ownership_deposit_value}.</br></br>These two amounts should be the same."
mortgage_used:"The mortgage (%{mortgage}) and cash deposit (%{deposit}) added together is %{mortgage_and_deposit_total}.</br></br>The full purchase price (%{value}) multiplied by the percentage equity stake purchased (%{equity}) is %{expected_shared_ownership_deposit_value}.</br></br>These two amounts should be the same."
mortgage_not_used:"The cash deposit is %{deposit}.</br></br>The full purchase price (%{value}) multiplied by the percentage bought is %{expected_shared_ownership_deposit_value}.</br></br>These two amounts should be the same."
mortgage_not_used:"The cash deposit is %{deposit}.</br></br>The full purchase price (%{value}) multiplied by the percentage bought is %{expected_shared_ownership_deposit_value}.</br></br>These two amounts should be the same."
@ -87,8 +87,8 @@ en:
mortgage_not_used_socialhomebuy:"The cash deposit (%{deposit}) and cash discount (%{cashdis}) added together is %{deposit_and_discount_total}.</br></br>The full purchase price (%{value}) multiplied by the percentage bought (%{equity}) is %{expected_shared_ownership_deposit_value}.</br></br>These two amounts should be the same."
mortgage_not_used_socialhomebuy:"The cash deposit (%{deposit}) and cash discount (%{cashdis}) added together is %{deposit_and_discount_total}.</br></br>The full purchase price (%{value}) multiplied by the percentage bought (%{equity}) is %{expected_shared_ownership_deposit_value}.</br></br>These two amounts should be the same."
discount:
discount:
discounted_ownership_value:"The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.</br></br>The full purchase price%{discount_sentence} is %{value_with_discount}.</br></br>These two amounts should be the same."
discounted_ownership_value:"The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.</br></br>The full purchase price%{discount_sentence} is %{value_with_discount}.</br></br>These two amounts should be the same."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London."
grant:
grant:
discounted_ownership_value:"The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.</br></br>The full purchase price%{discount_sentence} is %{value_with_discount}.</br></br>These two amounts should be the same."
discounted_ownership_value:"The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.</br></br>The full purchase price%{discount_sentence} is %{value_with_discount}.</br></br>These two amounts should be the same."
out_of_range:"Loan, grants or subsidies must be between £9,000 and £16,000."
out_of_range:"Loan, grants or subsidies must be between £9,000 and £16,000."
@ -119,14 +119,14 @@ en:
staircase:
staircase:
mortgage_used_value:"You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions."
mortgage_used_value:"You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions."
la:
la:
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London."
uprn:
uprn:
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London."
postcode_full:
postcode_full:
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London."
value_over_discounted_london_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London."
value_over_discounted_max:"The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London."
numstair:
numstair:
must_be_greater_than_one:"The number of staircasing transactions must be greater than 1 when this is not the first staircasing transaction."
must_be_greater_than_one:"The number of staircasing transactions must be greater than 1 when this is not the first staircasing transaction."
expect(record.errors["value"]).toinclude("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.")
expect(record.errors["discount"]).toinclude("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.")
expect(record.errors["la"]).toinclude("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.")
expect(record.errors["postcode_full"]).toinclude("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.")
expect(record.errors["uprn"]).toinclude("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.")
expect(record.errors["value"]).toinclude("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.")
expect(record.errors["discount"]).toinclude("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.")
expect(record.errors["la"]).toinclude("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.")
expect(record.errors["postcode_full"]).toinclude("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.")
expect(record.errors["uprn"]).toinclude("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.")
expect(log.errors[:owning_organisation_id]).toeq(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."])
end
end
it"is not valid if the Data Protection Confirmation is not signed"do
expect(log.errors[:owning_organisation_id]).toeq(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."])
it"invalid when changing to another org without a signed Data Protection Confirmation"do
it"invalid when changing to another org without a signed Data Protection Confirmation"do
expect{log.owning_organisation=org_without_dpc}.tochange(log,:valid?).from(true).to(false).and(change{log.errors[:owning_organisation_id]}.to(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."]))
expect{log.owning_organisation=org_without_dpc}.tochange(log,:valid?).from(true).to(false).and(change{log.errors[:owning_organisation_id]}.to(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."]))
end
end
end
end
end
end
end
@ -229,6 +249,12 @@ RSpec.describe Validations::SharedValidations do
@ -1915,6 +1915,15 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
expect(parser.errors.where(:field_125,category::soft_validation).first.message).toeql("You told us the rent is £120.00 every week. This is higher than we would expect.")
expect(parser.errors.where(:field_125,category::soft_validation).first.message).toeql("You told us the rent is £120.00 every week. This is higher than we would expect.")