diff --git a/app/controllers/form_controller.rb b/app/controllers/form_controller.rb
index a7ee469b8..4da903999 100644
--- a/app/controllers/form_controller.rb
+++ b/app/controllers/form_controller.rb
@@ -4,22 +4,22 @@ class FormController < ApplicationController
before_action :find_resource_by_named_id, except: %i[submit_form review]
def submit_form
- if @lettings_log
- @page = @lettings_log.form.get_page(params[:lettings_log][:page])
+ if @log
+ @page = @log.form.get_page(params[@log.model_name.param_key][:page])
responses_for_page = responses_for_page(@page)
mandatory_questions_with_no_response = mandatory_questions_with_no_response(responses_for_page)
- if mandatory_questions_with_no_response.empty? && @lettings_log.update(responses_for_page)
+ if mandatory_questions_with_no_response.empty? && @log.update(responses_for_page)
session[:errors] = session[:fields] = nil
redirect_to(successful_redirect_path)
else
- redirect_path = "lettings_log_#{@page.id}_path"
+ redirect_path = "#{@log.class.name.underscore}_#{@page.id}_path"
mandatory_questions_with_no_response.map do |question|
- @lettings_log.errors.add question.id.to_sym, question.unanswered_error_message
+ @log.errors.add question.id.to_sym, question.unanswered_error_message
end
- session[:errors] = @lettings_log.errors.to_json
- Rails.logger.info "User triggered validation(s) on: #{@lettings_log.errors.map(&:attribute).join(', ')}"
- redirect_to(send(redirect_path, @lettings_log))
+ session[:errors] = @log.errors.to_json
+ Rails.logger.info "User triggered validation(s) on: #{@log.errors.map(&:attribute).join(', ')}"
+ redirect_to(send(redirect_path, @log))
end
else
render_not_found
@@ -27,9 +27,9 @@ class FormController < ApplicationController
end
def check_answers
- if @lettings_log
+ if @log
current_url = request.env["PATH_INFO"]
- subsection = @lettings_log.form.get_subsection(current_url.split("/")[-2])
+ subsection = @log.form.get_subsection(current_url.split("/")[-2])
render "form/check_answers", locals: { subsection:, current_user: }
else
render_not_found
@@ -37,29 +37,26 @@ class FormController < ApplicationController
end
def review
- if @lettings_log
+ if @log
render "form/review"
else
render_not_found
end
end
- FormHandler.instance.forms.each do |_key, form|
- form.pages.map do |page|
- define_method(page.id) do |_errors = {}|
- if @lettings_log
- restore_error_field_values
- @subsection = @lettings_log.form.subsection_for_page(page)
- @page = @lettings_log.form.get_page(page.id)
- if @page.routed_to?(@lettings_log, current_user)
- render "form/page"
- else
- redirect_to lettings_log_path(@lettings_log)
- end
- else
- render_not_found
- end
+ def show_page
+ if @log
+ restore_error_field_values
+ page_id = request.path.split("/")[-1].underscore
+ @page = @log.form.get_page(page_id)
+ @subsection = @log.form.subsection_for_page(@page)
+ if @page.routed_to?(@log, current_user)
+ render "form/page"
+ else
+ redirect_to lettings_log_path(@log)
end
+ else
+ render_not_found
end
end
@@ -68,13 +65,13 @@ private
def restore_error_field_values
if session["errors"]
JSON(session["errors"]).each do |field, messages|
- messages.each { |message| @lettings_log.errors.add field.to_sym, message }
+ messages.each { |message| @log.errors.add field.to_sym, message }
end
end
if session["fields"]
session["fields"].each do |field, value|
- unless @lettings_log.form.get_question(field, @lettings_log)&.type == "date"
- @lettings_log[field] = value
+ unless @log.form.get_question(field, @log)&.type == "date"
+ @log[field] = value
end
end
end
@@ -82,11 +79,11 @@ private
def responses_for_page(page)
page.questions.each_with_object({}) do |question, result|
- question_params = params["lettings_log"][question.id]
+ question_params = params[@log.class.name.underscore][question.id]
if question.type == "date"
- day = params["lettings_log"]["#{question.id}(3i)"]
- month = params["lettings_log"]["#{question.id}(2i)"]
- year = params["lettings_log"]["#{question.id}(1i)"]
+ day = params[@log.class.name.underscore]["#{question.id}(3i)"]
+ month = params[@log.class.name.underscore]["#{question.id}(2i)"]
+ year = params[@log.class.name.underscore]["#{question.id}(1i)"]
next unless [day, month, year].any?(&:present?)
result[question.id] = if Date.valid_date?(year.to_i, month.to_i, day.to_i) && year.to_i.between?(2000, 2200)
@@ -109,11 +106,19 @@ private
end
def find_resource
- @lettings_log = current_user.lettings_logs.find_by(id: params[:id])
+ @log = if params.key?("sales_log")
+ current_user.sales_logs.find_by(id: params[:id])
+ else
+ current_user.lettings_logs.find_by(id: params[:id])
+ end
end
def find_resource_by_named_id
- @lettings_log = current_user.lettings_logs.find_by(id: params[:lettings_log_id])
+ @log = if params["sales_log_id"].present?
+ current_user.sales_logs.find_by(id: params[:sales_log_id])
+ else
+ current_user.lettings_logs.find_by(id: params[:lettings_log_id])
+ end
end
def is_referrer_check_answers?
@@ -123,18 +128,18 @@ private
def successful_redirect_path
if is_referrer_check_answers?
- page_ids = @lettings_log.form.subsection_for_page(@page).pages.map(&:id)
+ page_ids = @log.form.subsection_for_page(@page).pages.map(&:id)
page_index = page_ids.index(@page.id)
- next_page = @lettings_log.form.next_page(@page, @lettings_log, current_user)
- previous_page = @lettings_log.form.previous_page(page_ids, page_index, @lettings_log, current_user)
+ next_page = @log.form.next_page(@page, @log, current_user)
+ previous_page = @log.form.previous_page(page_ids, page_index, @log, current_user)
if next_page.to_s.include?("value_check") || next_page == previous_page
- return "/logs/#{@lettings_log.id}/#{next_page.dasherize}?referrer=check_answers"
+ return "/logs/#{@log.id}/#{next_page.dasherize}?referrer=check_answers"
else
- return send("lettings_log_#{@lettings_log.form.subsection_for_page(@page).id}_check_answers_path", @lettings_log)
+ return send("#{@log.class.name.underscore}_#{@log.form.subsection_for_page(@page).id}_check_answers_path", @log)
end
end
- redirect_path = @lettings_log.form.next_page_redirect_path(@page, @lettings_log, current_user)
- send(redirect_path, @lettings_log)
+ redirect_path = @log.form.next_page_redirect_path(@page, @log, current_user)
+ send(redirect_path, @log)
end
def mandatory_questions_with_no_response(responses_for_page)
@@ -153,7 +158,7 @@ private
def required_questions
@required_questions ||= begin
- log = @lettings_log
+ log = @log
log.assign_attributes(responses_for_page(@page))
@page.subsection.applicable_questions(log).select { |q| q.enabled?(log) }.map(&:id)
end
@@ -162,12 +167,12 @@ private
def question_missing_response?(responses_for_page, question)
if %w[checkbox validation_override].include?(question.type)
answered = question.answer_options.keys.reject { |x| x.match(/divider/) }.map do |option|
- session["fields"][option] = @lettings_log[option] = params["lettings_log"][question.id].include?(option) ? 1 : 0
+ session["fields"][option] = @log[option] = params["lettings_log"][question.id].include?(option) ? 1 : 0
params["lettings_log"][question.id].exclude?(option)
end
answered.all?
else
- session["fields"][question.id] = @lettings_log[question.id] = responses_for_page[question.id]
+ session["fields"][question.id] = @log[question.id] = responses_for_page[question.id]
responses_for_page[question.id].nil? || responses_for_page[question.id].blank?
end
end
diff --git a/app/controllers/lettings_logs_controller.rb b/app/controllers/lettings_logs_controller.rb
index a19fdbe6d..641a71214 100644
--- a/app/controllers/lettings_logs_controller.rb
+++ b/app/controllers/lettings_logs_controller.rb
@@ -1,10 +1,8 @@
-class LettingsLogsController < ApplicationController
+class LettingsLogsController < LogsController
include Pagy::Backend
include Modules::LettingsLogsFilter
include Modules::SearchFilter
- skip_before_action :verify_authenticity_token, if: :json_api_request?
- before_action :authenticate, if: :json_api_request?
before_action :authenticate_user!, unless: :json_api_request?
before_action :find_resource, except: %i[create index edit]
@@ -28,25 +26,12 @@ class LettingsLogsController < ApplicationController
end
def create
- lettings_log = LettingsLog.new(lettings_log_params)
- respond_to do |format|
- format.html do
- lettings_log.save!
- redirect_to lettings_log_url(lettings_log)
- end
- format.json do
- if lettings_log.save
- render json: lettings_log, status: :created
- else
- render json: { errors: lettings_log.errors.messages }, status: :unprocessable_entity
- end
- end
- end
+ super { LettingsLog.new(log_params) }
end
def update
if @lettings_log
- if @lettings_log.update(api_lettings_log_params)
+ if @lettings_log.update(api_log_params)
render json: @lettings_log, status: :ok
else
render json: { errors: @lettings_log.errors.messages }, status: :unprocessable_entity
@@ -99,40 +84,15 @@ private
params["search"]
end
- def json_api_request?
- API_ACTIONS.include?(request["action"]) && request.format.json?
- end
-
- def authenticate
- http_basic_authenticate_or_request_with name: ENV["API_USER"], password: ENV["API_KEY"]
- end
-
- def lettings_log_params
- if current_user && !current_user.support?
- org_params.merge(api_lettings_log_params)
- else
- api_lettings_log_params
- end
- end
-
- def org_params
- {
- "owning_organisation_id" => current_user.organisation.id,
- "managing_organisation_id" => current_user.organisation.id,
- "created_by_id" => current_user.id,
- }
- end
-
- def api_lettings_log_params
- return {} unless params[:lettings_log]
-
- permitted = params.require(:lettings_log).permit(LettingsLog.editable_fields)
- owning_id = permitted["owning_organisation_id"]
- permitted["owning_organisation"] = Organisation.find(owning_id) if owning_id
- permitted
- end
+ def permitted_log_params
+ params.require(:lettings_log).permit(LettingsLog.editable_fields)
+ end
def find_resource
@lettings_log = LettingsLog.find_by(id: params[:id])
end
+
+ def post_create_redirect_url(log)
+ lettings_log_url(log)
+ end
end
diff --git a/app/controllers/logs_controller.rb b/app/controllers/logs_controller.rb
new file mode 100644
index 000000000..fb274993b
--- /dev/null
+++ b/app/controllers/logs_controller.rb
@@ -0,0 +1,64 @@
+class LogsController < ApplicationController
+ skip_before_action :verify_authenticity_token, if: :json_api_request?
+ before_action :authenticate, if: :json_api_request?
+
+private
+
+ def create
+ log = yield
+ raise "Caller must pass a block that implements model creation" if log.blank?
+
+ respond_to do |format|
+ format.html do
+ log.save!
+ redirect_to post_create_redirect_url(log)
+ end
+ format.json do
+ if log.save
+ render json: log, status: :created
+ else
+ render json: { errors: log.errors.messages }, status: :unprocessable_entity
+ end
+ end
+ end
+ end
+
+ def post_create_redirect_url
+ raise "implement in sub class"
+ end
+
+ API_ACTIONS = %w[create show update destroy].freeze
+
+ def json_api_request?
+ API_ACTIONS.include?(request["action"]) && request.format.json?
+ end
+
+ def authenticate
+ http_basic_authenticate_or_request_with name: ENV["API_USER"], password: ENV["API_KEY"]
+ end
+
+ def log_params
+ if current_user && !current_user.support?
+ org_params.merge(api_log_params)
+ else
+ api_log_params
+ end
+ end
+
+ def api_log_params
+ return {} unless params[:lettings_log] || params[:sales_log]
+
+ permitted = permitted_log_params
+ owning_id = permitted["owning_organisation_id"]
+ permitted["owning_organisation"] = Organisation.find(owning_id) if owning_id
+ permitted
+ end
+
+ def org_params
+ {
+ "owning_organisation_id" => current_user.organisation.id,
+ "managing_organisation_id" => current_user.organisation.id,
+ "created_by_id" => current_user.id,
+ }
+ end
+end
diff --git a/app/controllers/sales_logs_controller.rb b/app/controllers/sales_logs_controller.rb
new file mode 100644
index 000000000..84cf0d275
--- /dev/null
+++ b/app/controllers/sales_logs_controller.rb
@@ -0,0 +1,28 @@
+class SalesLogsController < LogsController
+ def create
+ super { SalesLog.new(log_params) }
+ end
+
+ def show
+ respond_to do |format|
+ format.html { edit }
+ end
+ end
+
+ def edit
+ @sales_log = current_user.sales_logs.find_by(id: params[:id])
+ if @sales_log
+ render :edit, locals: { current_user: }
+ else
+ render_not_found
+ end
+ end
+
+ def post_create_redirect_url(log)
+ sales_log_url(log)
+ end
+
+ def permitted_log_params
+ params.require(:sales_log).permit(SalesLog.editable_fields)
+ end
+end
diff --git a/app/helpers/tasklist_helper.rb b/app/helpers/tasklist_helper.rb
index e4308d97e..4256979e0 100644
--- a/app/helpers/tasklist_helper.rb
+++ b/app/helpers/tasklist_helper.rb
@@ -11,13 +11,13 @@ module TasklistHelper
lettings_log.form.subsections.count { |subsection| subsection.status(lettings_log) == status && subsection.applicable_questions(lettings_log).count.positive? }
end
- def next_page_or_check_answers(subsection, lettings_log, current_user)
- path = if subsection.is_started?(lettings_log)
- "lettings_log_#{subsection.id}_check_answers_path"
+ def next_page_or_check_answers(subsection, log, current_user)
+ path = if subsection.is_started?(log)
+ "#{log.class.name.underscore}_#{subsection.id}_check_answers_path"
else
- "lettings_log_#{next_question_page(subsection, lettings_log, current_user)}_path"
+ "#{log.class.name.underscore}_#{next_question_page(subsection, log, current_user)}_path"
end
- send(path, lettings_log)
+ send(path, log)
end
def next_question_page(subsection, lettings_log, current_user)
diff --git a/app/models/form.rb b/app/models/form.rb
index 6fa92bba0..6e683ed5a 100644
--- a/app/models/form.rb
+++ b/app/models/form.rb
@@ -5,20 +5,38 @@ class Form
include Form::Setup
- def initialize(form_path, name)
- raise "No form definition file exists for given year".freeze unless File.exist?(form_path)
-
- @name = name
- @setup_sections = [Form::Setup::Sections::Setup.new(nil, nil, self)]
- @form_definition = JSON.parse(File.open(form_path).read)
- @form_sections = form_definition["sections"].map { |id, s| Form::Section.new(id, s, self) }
- @type = form_definition["form_type"]
- @sections = setup_sections + form_sections
- @subsections = sections.flat_map(&:subsections)
- @pages = subsections.flat_map(&:pages)
- @questions = pages.flat_map(&:questions)
- @start_date = Time.iso8601(form_definition["start_date"])
- @end_date = Time.iso8601(form_definition["end_date"])
+ def initialize(form_path, name, sections_in_form = [], type = "lettings")
+ if type == "sales"
+ # @form_definition = sections.map do |s|
+ # s.new(nil, nil, self)
+ # end
+ @name = name
+ # @setup_sections = [Form::Setup::Sections::Setup.new(nil, nil, self)]
+ # @form_definition = JSON.parse(File.open(form_path).read)
+ @form_sections = sections_in_form.map { |sec| sec.new(nil, nil, self) }
+ @type = "sales"
+ @sections = form_sections
+ @subsections = sections.flat_map(&:subsections)
+ @pages = subsections.flat_map(&:pages)
+ @questions = pages.flat_map(&:questions)
+ @start_date = Time.zone.local(name[0..3], 4, 1)
+ @end_date = Time.zone.local(start_date.year + 1, 4, 1)
+
+ else
+ raise "No form definition file exists for given year".freeze unless File.exist?(form_path)
+
+ @name = name
+ @setup_sections = [Form::Setup::Sections::Setup.new(nil, nil, self)]
+ @form_definition = JSON.parse(File.open(form_path).read)
+ @form_sections = form_definition["sections"].map { |id, s| Form::Section.new(id, s, self) }
+ @type = form_definition["form_type"]
+ @sections = setup_sections + form_sections
+ @subsections = sections.flat_map(&:subsections)
+ @pages = subsections.flat_map(&:pages)
+ @questions = pages.flat_map(&:questions)
+ @start_date = Time.iso8601(form_definition["start_date"])
+ @end_date = Time.iso8601(form_definition["end_date"])
+ end
end
def get_subsection(id)
@@ -58,28 +76,28 @@ class Form
def next_page_redirect_path(page, lettings_log, current_user)
nxt_page = next_page(page, lettings_log, current_user)
if nxt_page == :check_answers
- "lettings_log_#{subsection_for_page(page).id}_check_answers_path"
+ "#{type}_log_#{subsection_for_page(page).id}_check_answers_path"
else
- "lettings_log_#{nxt_page}_path"
+ "#{type}_log_#{nxt_page}_path"
end
end
- def next_incomplete_section_redirect_path(subsection, lettings_log)
+ def next_incomplete_section_redirect_path(subsection, log)
subsection_ids = subsections.map(&:id)
- if lettings_log.status == "completed"
+ if log.status == "completed"
return first_question_in_last_subsection(subsection_ids)
end
- next_subsection = next_subsection(subsection, lettings_log, subsection_ids)
+ next_subsection = next_subsection(subsection, log, subsection_ids)
- case next_subsection.status(lettings_log)
+ case next_subsection.status(log)
when :completed
- next_incomplete_section_redirect_path(next_subsection, lettings_log)
+ next_incomplete_section_redirect_path(next_subsection, log)
when :in_progress
"#{next_subsection.id}/check_answers".dasherize
when :not_started
- first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(lettings_log, nil) }.id
+ first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(log, nil) }.id
first_question_in_subsection.to_s.dasherize
else
"error"
@@ -92,11 +110,11 @@ class Form
first_question_in_subsection.to_s.dasherize
end
- def next_subsection(subsection, lettings_log, subsection_ids)
+ def next_subsection(subsection, log, subsection_ids)
next_subsection_id_index = subsection_ids.index(subsection.id) + 1
next_subsection = get_subsection(subsection_ids[next_subsection_id_index])
- if subsection_ids[subsection_ids.length - 1] == subsection.id && lettings_log.status != "completed"
+ if subsection_ids[subsection_ids.length - 1] == subsection.id && log.status != "completed"
next_subsection = get_subsection(subsection_ids[0])
end
diff --git a/app/models/form/sales/setup/pages/sale_date.rb b/app/models/form/sales/setup/pages/sale_date.rb
new file mode 100644
index 000000000..4cdfe5a71
--- /dev/null
+++ b/app/models/form/sales/setup/pages/sale_date.rb
@@ -0,0 +1,15 @@
+class Form::Sales::Setup::Pages::SaleDate < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @id = "sale_date"
+ @header = ""
+ @description = ""
+ @subsection = subsection
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Setup::Questions::SaleDate.new(nil, nil, self),
+ ]
+ end
+end
diff --git a/app/models/form/sales/setup/questions/sale_date.rb b/app/models/form/sales/setup/questions/sale_date.rb
new file mode 100644
index 000000000..4f9088aaf
--- /dev/null
+++ b/app/models/form/sales/setup/questions/sale_date.rb
@@ -0,0 +1,10 @@
+class Form::Sales::Setup::Questions::SaleDate < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "saledate"
+ @check_answer_label = "Sale completion date"
+ @header = "What is the sale completion date?"
+ @type = "date"
+ @page = page
+ end
+end
diff --git a/app/models/form/sales/setup/sections/setup.rb b/app/models/form/sales/setup/sections/setup.rb
new file mode 100644
index 000000000..42835ec39
--- /dev/null
+++ b/app/models/form/sales/setup/sections/setup.rb
@@ -0,0 +1,10 @@
+class Form::Sales::Setup::Sections::Setup < ::Form::Section
+ def initialize(id, hsh, form)
+ super
+ @id = "setup"
+ @label = "Before you start"
+ @description = ""
+ @form = form
+ @subsections = [Form::Sales::Setup::Subsections::Setup.new(nil, nil, self)] || []
+ end
+end
diff --git a/app/models/form/sales/setup/subsections/setup.rb b/app/models/form/sales/setup/subsections/setup.rb
new file mode 100644
index 000000000..ee0af6350
--- /dev/null
+++ b/app/models/form/sales/setup/subsections/setup.rb
@@ -0,0 +1,14 @@
+class Form::Sales::Setup::Subsections::Setup < ::Form::Subsection
+ def initialize(id, hsh, section)
+ super
+ @id = "setup"
+ @label = "Set up this sales log"
+ @section = section
+ end
+
+ def pages
+ @pages ||= [
+ Form::Sales::Setup::Pages::SaleDate.new(nil, nil, self),
+ ]
+ end
+end
diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb
index 13efcb9ca..41414eb7d 100644
--- a/app/models/form_handler.rb
+++ b/app/models/form_handler.rb
@@ -14,9 +14,12 @@ class FormHandler
forms[forms.keys.max_by(&:to_i)]
end
-private
+ def sales_forms
+ sales_sections = [Form::Sales::Setup::Sections::Setup]
+ { "2022_2023_sales" => Form.new(nil, "2022_2023_sales", sales_sections, "sales") }
+ end
- def get_all_forms
+ def lettings_forms
forms = {}
directories.each do |directory|
Dir.glob("#{directory}/*.json").each do |form_path|
@@ -27,7 +30,15 @@ private
forms
end
+private
+
+ def get_all_forms
+ lettings_forms.merge(sales_forms)
+ end
+
def directories
Rails.env.test? ? ["spec/fixtures/forms"] : ["config/forms"]
end
+
+ # SALES_FORM = [Form::Sales::Sections::Setup, Form::Sales::Sections::Property]
end
diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb
index 142c48e52..81c69f1f5 100644
--- a/app/models/lettings_log.rb
+++ b/app/models/lettings_log.rb
@@ -14,7 +14,7 @@ class LettingsLogValidator < ActiveModel::Validator
end
end
-class LettingsLog < ApplicationRecord
+class LettingsLog < Log
include Validations::SoftValidations
include DerivedVariables::LettingsLogVariables
@@ -31,9 +31,6 @@ class LettingsLog < ApplicationRecord
before_validation :set_derived_fields!
before_save :update_status!
- belongs_to :owning_organisation, class_name: "Organisation", optional: true
- belongs_to :managing_organisation, class_name: "Organisation", optional: true
- belongs_to :created_by, class_name: "User", optional: true
belongs_to :scheme, optional: true
belongs_to :location, optional: true
diff --git a/app/models/log.rb b/app/models/log.rb
new file mode 100644
index 000000000..316af6d06
--- /dev/null
+++ b/app/models/log.rb
@@ -0,0 +1,7 @@
+class Log < ApplicationRecord
+ self.abstract_class = true
+
+ belongs_to :owning_organisation, class_name: "Organisation", optional: true
+ belongs_to :managing_organisation, class_name: "Organisation", optional: true
+ belongs_to :created_by, class_name: "User", optional: true
+end
diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb
new file mode 100644
index 000000000..cdeaf0695
--- /dev/null
+++ b/app/models/sales_log.rb
@@ -0,0 +1,72 @@
+class SalesLogValidator < ActiveModel::Validator
+ def validate(record); end
+end
+
+class SalesLog < Log
+ has_paper_trail
+
+ validates_with SalesLogValidator
+ before_save :update_status!
+
+ scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org).or(where(managing_organisation: org)) }
+
+ STATUS = { "not_started" => 0, "in_progress" => 1, "completed" => 2 }.freeze
+ enum status: STATUS
+
+ def self.editable_fields
+ attribute_names
+ end
+
+ def form_name
+ return unless saledate
+
+ "#{collection_start_year}_#{collection_start_year + 1}_sales"
+ end
+
+ def collection_start_year
+ return @sale_year if @sale_year
+ return unless saledate
+
+ window_end_date = Time.zone.local(saledate.year, 4, 1)
+ @sale_year = saledate < window_end_date ? saledate.year - 1 : saledate.year
+ end
+
+ def form
+ FormHandler.instance.get_form(form_name) || FormHandler.instance.get_form("2022_2023_sales")
+ end
+
+ def optional_fields
+ []
+ end
+
+ def not_started?
+ status == "not_started"
+ end
+
+ def completed?
+ status == "completed"
+ end
+
+ private
+
+ def update_status!
+ self.status = if all_fields_completed? && errors.empty?
+ "completed"
+ elsif all_fields_nil?
+ "not_started"
+ else
+ "in_progress"
+ end
+ end
+
+ def all_fields_completed?
+ subsection_statuses = form.subsections.map { |subsection| subsection.status(self) }.uniq
+ subsection_statuses == [:completed]
+ end
+
+ def all_fields_nil?
+ not_started_statuses = %i[not_started cannot_start_yet]
+ subsection_statuses = form.subsections.map { |subsection| subsection.status(self) }.uniq
+ subsection_statuses.all? { |status| not_started_statuses.include?(status) }
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 22cc14b77..4384bc495 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -9,6 +9,8 @@ class User < ApplicationRecord
belongs_to :organisation, optional: true
has_many :owned_lettings_logs, through: :organisation, dependent: :delete_all
has_many :managed_lettings_logs, through: :organisation
+ has_many :owned_sales_logs, through: :organisation, dependent: :delete_all
+ has_many :managed_sales_logs, through: :organisation
validates :name, presence: true
validates :email, presence: true
@@ -58,6 +60,14 @@ class User < ApplicationRecord
end
end
+ def sales_logs
+ if support?
+ SalesLog.all
+ else
+ SalesLog.filter_by_organisation(organisation)
+ end
+ end
+
def completed_lettings_logs
lettings_logs.completed
end
diff --git a/app/views/form/_check_answers_summary_list.html.erb b/app/views/form/_check_answers_summary_list.html.erb
index 85c29beca..68a9cf00a 100644
--- a/app/views/form/_check_answers_summary_list.html.erb
+++ b/app/views/form/_check_answers_summary_list.html.erb
@@ -1,21 +1,21 @@
<%= govuk_summary_list do |summary_list| %>
- <% total_applicable_questions(subsection, @lettings_log, current_user).each do |question| %>
+ <% total_applicable_questions(subsection, @log, current_user).each do |question| %>
<% summary_list.row do |row| %>
<% row.key { question.check_answer_label.to_s.presence || question.header.to_s } %>
<% row.value do %>
- <%= get_answer_label(question, @lettings_log) %>
- <% extra_value = question.get_extra_check_answer_value(@lettings_log) %>
+ <%= get_answer_label(question, @log) %>
+ <% extra_value = question.get_extra_check_answer_value(@log) %>
<% if extra_value %>
<%= extra_value %>
<% end %>
- <% question.get_inferred_answers(@lettings_log).each do |inferred_answer| %>
+ <% question.get_inferred_answers(@log).each do |inferred_answer| %>
<%= inferred_answer %>
<% end %>
<% end %>
<% row.action(
- text: question.action_text(@lettings_log),
- href: question.action_href(@lettings_log, question.page.id),
+ text: question.action_text(@log),
+ href: question.action_href(@log, question.page.id),
visually_hidden_text: question.check_answer_label.to_s.downcase,
) %>
<% end %>
diff --git a/app/views/form/_checkbox_question.html.erb b/app/views/form/_checkbox_question.html.erb
index 245056c39..c855e2d88 100644
--- a/app/views/form/_checkbox_question.html.erb
+++ b/app/views/form/_checkbox_question.html.erb
@@ -6,7 +6,7 @@
hint: { text: question.hint_text&.html_safe } do %>
<% after_divider = false %>
- <% question.displayed_answer_options(@lettings_log).map do |key, options| %>
+ <% question.displayed_answer_options(@log).map do |key, options| %>
<% if key.starts_with?("divider") %>
<% after_divider = true %>
<%= f.govuk_check_box_divider %>
@@ -14,7 +14,7 @@
<%= f.govuk_check_box question.id, key,
label: { text: options["value"] },
hint: { text: options["hint"] },
- checked: @lettings_log[key] == 1,
+ checked: @log[key] == 1,
exclusive: after_divider,
**stimulus_html_attributes(question) %>
<% end %>
diff --git a/app/views/form/_numeric_question.html.erb b/app/views/form/_numeric_question.html.erb
index fc6aa274a..0aeb63801 100644
--- a/app/views/form/_numeric_question.html.erb
+++ b/app/views/form/_numeric_question.html.erb
@@ -8,7 +8,7 @@
width: question.width,
readonly: question.read_only?,
prefix_text: question.prefix.to_s,
- suffix_text: question.suffix_label(@lettings_log),
+ suffix_text: question.suffix_label(@log),
**stimulus_html_attributes(question) %>
<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %>
diff --git a/app/views/form/_radio_question.html.erb b/app/views/form/_radio_question.html.erb
index f153a838b..ed5e71a0b 100644
--- a/app/views/form/_radio_question.html.erb
+++ b/app/views/form/_radio_question.html.erb
@@ -5,7 +5,7 @@
legend: legend(question, page_header, conditional),
hint: { text: question.hint_text&.html_safe } do %>
- <% question.displayed_answer_options(@lettings_log).map do |key, options| %>
+ <% question.displayed_answer_options(@log).map do |key, options| %>
<% if key.starts_with?("divider") %>
<%= f.govuk_radio_divider %>
<% else %>
diff --git a/app/views/form/_select_question.html.erb b/app/views/form/_select_question.html.erb
index fbdb20e9a..63f50fb94 100644
--- a/app/views/form/_select_question.html.erb
+++ b/app/views/form/_select_question.html.erb
@@ -1,7 +1,7 @@
<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %>
-<% selected = @lettings_log.public_send(question.id) || "" %>
-<% answers = question.displayed_answer_options(@lettings_log).map { |key, value| OpenStruct.new(id: key, name: value.respond_to?(:service_name) ? value.service_name : nil, resource: value) } %>
+<% selected = @log.public_send(question.id) || "" %>
+<% answers = question.displayed_answer_options(@log).map { |key, value| OpenStruct.new(id: key, name: value.respond_to?(:service_name) ? value.service_name : nil, resource: value) } %>
<%= f.govuk_select(question.id.to_sym,
label: legend(question, page_header, conditional),
"data-controller": "accessible-autocomplete",
@@ -12,7 +12,7 @@
data-synonyms="<%= question.answer_option_synonyms(answer.resource) %>"
data-append="<%= question.answer_option_append(answer.resource) %>"
data-hint="<%= question.answer_option_hint(answer.resource) %>"
- <%= question.answer_selected?(@lettings_log, answer) ? "selected" : "" %>
+ <%= question.answer_selected?(@log, answer) ? "selected" : "" %>
<%= answer.id == "" ? "disabled" : "" %>><%= answer.name || answer.resource %>
<% end %>
<% end %>
diff --git a/app/views/form/check_answers.html.erb b/app/views/form/check_answers.html.erb
index a2bcb09bc..ec85104c5 100644
--- a/app/views/form/check_answers.html.erb
+++ b/app/views/form/check_answers.html.erb
@@ -1,7 +1,7 @@
<% content_for :title, "#{subsection.id.humanize} - Check your answers" %>
<% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: {
"Logs" => "/logs",
- "Log #{@lettings_log.id}" => "/logs/#{@lettings_log.id}",
+ "Log #{@log.id}" => "/logs/#{@log.id}",
subsection.label => "",
}) %>
@@ -12,27 +12,27 @@
Check your answers
- <% if subsection.id == "setup" && subsection.status(@lettings_log) == :completed %>
+ <% if subsection.id == "setup" && subsection.status(@log) == :completed %>
<%= govuk_inset_text(text: "Changing these answers might remove answers you’ve already given in other sections.") %>
<% end %>
- <%= display_answered_questions_summary(subsection, @lettings_log, current_user) %>
+ <%= display_answered_questions_summary(subsection, @log, current_user) %>
- <% if any_questions_have_summary_card_number?(subsection, @lettings_log) %>
- <% subsection.applicable_questions(@lettings_log).group_by(&:check_answers_card_number).values.each do |question_group| %>
- <%= render CheckAnswersSummaryListCardComponent.new(questions: question_group, lettings_log: @lettings_log, user: current_user) %>
+ <% if any_questions_have_summary_card_number?(subsection, @log) %>
+ <% subsection.applicable_questions(@log).group_by(&:check_answers_card_number).values.each do |question_group| %>
+ <%= render CheckAnswersSummaryListCardComponent.new(questions: question_group, lettings_log: @log, user: current_user) %>
<% end %>
<% else %>
<%= render partial: "form/check_answers_summary_list", locals: {
subsection:,
- lettings_log: @lettings_log,
+ lettings_log: @log,
} %>
<% end %>
- <%= form_with model: @lettings_log, method: "get" do |f| %>
+ <%= form_with model: @log, method: "get" do |f| %>
<%= f.govuk_submit "Save and return to log" do %>
- <% next_incomplete_section_redirect_path = @lettings_log.form.next_incomplete_section_redirect_path(subsection, @lettings_log) %>
- <% if @lettings_log.status == "in_progress" && next_incomplete_section_redirect_path != "error" %>
- <%= govuk_button_link_to "Save and go to next incomplete section", "/logs/#{@lettings_log.id}/#{next_incomplete_section_redirect_path}", secondary: true %>
+ <% next_incomplete_section_redirect_path = @log.form.next_incomplete_section_redirect_path(subsection, @log) %>
+ <% if @log.status == "in_progress" && next_incomplete_section_redirect_path != "error" %>
+ <%= govuk_button_link_to "Save and go to next incomplete section", "/logs/#{@log.id}/#{next_incomplete_section_redirect_path}", secondary: true %>
<% end %>
<% end %>
<% end %>
diff --git a/app/views/form/page.html.erb b/app/views/form/page.html.erb
index 0fe72f647..542f5fd51 100644
--- a/app/views/form/page.html.erb
+++ b/app/views/form/page.html.erb
@@ -5,10 +5,10 @@
<% end %>
- You can review and make changes to this log until 2nd June <%= @lettings_log.collection_start_year.present? ? @lettings_log.collection_start_year + 1 : "" %>. + You can review and make changes to this log until 2nd June <%= @log.collection_start_year.present? ? @log.collection_start_year + 1 : "" %>.
- <% @lettings_log.form.sections.map do |section| %> + <% @log.form.sections.map do |section| %><%= section.description.html_safe %>
+ <% end %> +<%= get_subsections_count(@sales_log, :completed) %> of <%= get_subsections_count(@sales_log, :all) %> sections completed.
++ <% next_incomplete_section = get_next_incomplete_section(@sales_log) %> +
++ <% if next_incomplete_section.present? %> + + Skip to next incomplete section: <%= next_incomplete_section.label %> + + <% end %> +
+ <% elsif @sales_log.status == "not_started" %> +This log has not been started.
+ <% elsif @sales_log.status == "completed" %> ++ <%= status_tag(@sales_log.status) %> +
++ You can <%= govuk_link_to "review and make changes to this log", "/logs/#{@sales_log.id}/review" %> until 2nd June <%= @sales_log.collection_start_year.present? ? @sales_log.collection_start_year + 1 : "" %>. +
+ <% end %> + <%= render "tasklist" %> +