answer_opts[org.id]="#{org.name} (inactive as of #{org.merge_date.to_fs(:govuk_date)})"iforg.merge_date>=FormHandler.instance.start_date_of_earliest_open_for_editing_collection_period
answer_opts[org.id]="#{org.name} (inactive as of #{org.merge_date.to_fs(:govuk_date)})"iforg.merge_date>=FormHandler.instance.start_date_of_earliest_open_for_editing_collection_period
<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 }) %> before you start if you have not used bulk upload before.</p>
<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>
<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 }) %> before you start if you have not used bulk upload before.</p>
<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>
<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 }) %> before you start if you have not used bulk upload before.</p>
<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>
<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 }) %> before you start if you have not used bulk upload before.</p>
<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>
<%= accordion.with_section(heading_text: "How to create logs", expanded: true) do %>
<p class="govuk-body">There are 2 ways to create logs on CORE.</p>
<p class="govuk-body">You can create logs one at a time by answering questions using the online form. Click the “Create a new log” button on the logs page to create logs this way.</p>
<p class="govuk-body">You can also create many logs at once by uploading a CSV file. This might be faster than creating logs individually if your organisation has its own database and a way to export the data. Click the “Upload logs in bulk” button on the logs page to create logs this way. For more information, <%= govuk_link_to "read the full guidance on bulk upload", bulk_upload_lettings_log_path(id: "guidance", form: { year: current_collection_start_year }) %>.</p>
<p class="govuk-body">You can also create many logs at once by uploading a CSV file. This might be faster than creating logs individually if your organisation has its own database and a way to export the data. Click the “Upload logs in bulk” button on the logs page to create logs this way. For more information, <%= govuk_link_to "read the full guidance on bulk upload", bulk_upload_lettings_log_path(id: "guidance", form: { year: current_collection_start_year }, referrer: "guidance") %>.</p>
<p class="govuk-body">Once you have created and completed a log, there is nothing more you need to do to submit the data.</p>
## Factories for Lettings Log, Sales Log, Organisation, and User
Each of these factories has nested relationships and callbacks that ensure associated objects are created and linked properly. For instance, creating a `lettings_log` involves creating or associating with a `user`, which in turn is linked to an `organisation`, potentially leading to creating `organisation_rent_periods` and a `data_protection_confirmation`.
This documentation outlines the objects that are created and/or persisted to the database when using FactoryBot to create or build models for LettingsLog, SalesLog, Organisation, and User. There are other factories, but they are simpler, less frequently used and don't have as much resource hierarchy.
### Lettings Log
Objects Created/Persisted:
- **User**: The `assigned_to` user is created.
- **Organisation**: The `assigned_to` user’s organisation created by `User` factory.
- **DataProtectionConfirmation**: If `organisation` does not have DSA signed, `DataProtectionConfirmation` gets created with `assigned_to` user as a `data_protection_officer`
- **OrganisationRentPeriod**: If `log.period` is present and the `managing_organisation` does not have an `OrganisationRentPeriod` for that period, a new `OrganisationRentPeriod` is created and associated with `managing_organisation`.
Example Usage:
```
let(:lettings_log) { create(:lettings_log) }
```
### Sales Log
Objects Created/Persisted:
- **User**: The `assigned_to` user is created.
- **Organisation**: The `assigned_to` user’s organisation created by `User` factory.
- **DataProtectionConfirmation**: If `organisation` does not have DSA signed, `DataProtectionConfirmation` gets created with `assigned_to` user as a `data_protection_officer`
Example Usage:
```
let(:sales_log) { create(:sales_log) }
```
### Organisation
Objects Created/Persisted:
- **OrganisationRentPeriod**: For each rent period in transient attribute `rent_periods`, an `OrganisationRentPeriod` is created.
- **DataProtectionConfirmation**: If `with_dsa` is `true` (default), a `DataProtectionConfirmation` is created with a `data_protection_officer`
- **User**: Data protection officer that signs the data protection confirmation
- **DataProtectionConfirmation**: If `organisation` does not have DSA signed, `DataProtectionConfirmation` gets created with this user as a `data_protection_officer`
query="SELECT \"versions\".* FROM \"versions\" WHERE \"versions\".\"item_type\" = 'LettingsLog' AND whodunnit is null AND ((object_changes like '%status:\n- 3\n- 1%') OR (object_changes like '%status:\n- 3\n- 2%'))"
csv<<[id,log.collection_start_year,log.status,log.owning_organisation_name,log.assigned_to_id,log.assigned_to.email,"Leave","Log has no visible duplicates and at least one duplicate has been deleted since being affected"]
next
end
ifvisible_duplicates.length.zero?
seen.add(id)
csv<<[id,log.collection_start_year,log.status,log.owning_organisation_name,log.assigned_to_id,log.assigned_to.email,"Leave","Log has no visible duplicates"]
next
end
unaffected_duplicates=[]
affected_updated_duplicates=[]
affected_non_updated_duplicates=[log]
visible_duplicates.eachdo|dup|
vquery="SELECT \"versions\".* FROM \"versions\" WHERE \"versions\".\"item_type\" = 'LettingsLog' AND \"versions\".\"item_id\" = #{dup.id} AND whodunnit is null AND ((object_changes like '%status:\n- 3\n- 1%') OR (object_changes like '%status:\n- 3\n- 2%'))"
csv<<[d.id,d.collection_start_year,d.status,d.owning_organisation_name,d.assigned_to_id,d.assigned_to.email,"Leave","Log updated in UI"]
end
end
affected_non_updated_duplicates.eachdo|d|
seen.add(d.id)
csv<<[d.id,d.collection_start_year,d.status,d.owning_organisation_name,d.assigned_to_id,d.assigned_to.email,"Delete","Log is a duplicate of unaffected log(s)",unaffected_logs_reference]
csv<<[d.id,d.collection_start_year,d.status,d.owning_organisation_name,d.assigned_to_id,d.assigned_to.email,"Leave","Log updated in UI"]
end
end
affected_non_updated_duplicates.eachdo|d|
seen.add(d.id)
csv<<[d.id,d.collection_start_year,d.status,d.owning_organisation_name,d.assigned_to_id,d.assigned_to.email,"Delete","Log is a duplicate of log(s) which have been updated since being affected",updated_logs_reference]
csv<<[latest_created.id,latest_created.collection_start_year,latest_created.status,latest_created.owning_organisation_name,latest_created.assigned_to_id,latest_created.assigned_to.email,"Leave","Log is the most recently created of a duplicate group"]
affected_non_updated_duplicates.eachdo|d|
nextunlessd.id!=latest_created.id
seen.add(d.id)
csv<<[d.id,d.collection_start_year,d.status,d.owning_organisation_name,d.assigned_to_id,d.assigned_to.email,"Delete","Log is a duplicate of more recently created affected log",latest_created.id]
@ -83,6 +84,7 @@ RSpec.describe Form::Sales::Questions::ManagingOrganisation, type: :model do
it"shows current managing agent at top, followed by the current owning organisation (with hint), followed by the active managing agents of the current owning organisation"do