diff --git a/app/controllers/api/submission_documents_controller.rb b/app/controllers/api/submission_documents_controller.rb index 56940f0f..2f3fd78b 100644 --- a/app/controllers/api/submission_documents_controller.rb +++ b/app/controllers/api/submission_documents_controller.rb @@ -9,7 +9,7 @@ module Api (@submission.schema_documents || @submission.template.schema_documents).size > 1 documents = - if @submission.submitters.all?(&:completed_at?) + if @submission.completed_at? build_completed_documents(@submission, merge: is_merge) else build_preview_documents(@submission, merge: is_merge) diff --git a/app/controllers/api/submission_events_controller.rb b/app/controllers/api/submission_events_controller.rb index 54d01443..009a1e85 100644 --- a/app/controllers/api/submission_events_controller.rb +++ b/app/controllers/api/submission_events_controller.rb @@ -5,7 +5,7 @@ module Api load_and_authorize_resource :submission, parent: false def index - submissions = build_completed_query(@submissions) + submissions = @submissions.active.where.not(completed_at: nil) params[:after] = Time.zone.at(params[:after].to_i) if params[:after].present? params[:before] = Time.zone.at(params[:before].to_i) if params[:before].present? @@ -36,20 +36,5 @@ module Api } } end - - private - - def build_completed_query(submissions) - submissions = submissions.where( - Submitter.where(completed_at: nil).where( - Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]) - ).select(1).arel.exists.not - ) - - submissions.joins(:submitters) - .group(:id) - .select(Submission.arel_table[Arel.star], - Submitter.arel_table[:completed_at].maximum.as('completed_at')) - end end end diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index 2a1154f0..b620025c 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -2,7 +2,7 @@ module Api class SubmissionsController < ApiBaseController - SUBMISSION_COLUMNS = %i[id name slug source submitters_order expire_at created_at updated_at + SUBMISSION_COLUMNS = %i[id name slug source submitters_order expire_at completed_at created_at updated_at archived_at variables template_id template_submitters created_by_user_id].freeze TEMPLATE_COLUMNS = %i[id name external_id created_at updated_at folder_id submitters].freeze @@ -13,6 +13,8 @@ module Api authorize!(:create, Submission) end + before_action :maybe_return_template_error, only: :create + def index submissions = Submissions.search(current_user, @submissions, params[:q]) submissions = filter_submissions(submissions, params) @@ -58,7 +60,7 @@ module Api end end - if @submission.audit_trail_attachment.blank? && submitters.all?(&:completed_at?) + if @submission.audit_trail_attachment.blank? && @submission.completed_at? @submission.audit_trail_attachment = Submissions::EnsureAuditGenerated.call(@submission) end @@ -68,20 +70,6 @@ module Api def create Params::SubmissionCreateValidator.call(params) - return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil? - - if @template.archived_at? - Rollbar.warning("Archived template submission: #{@template.id}") if defined?(Rollbar) - - return render json: { error: 'Template has been archived' }, status: :unprocessable_content - end - - if @template.fields.blank? - Rollbar.warning("Template does not contain fields: #{@template.id}") if defined?(Rollbar) - - return render json: { error: 'Template does not contain fields' }, status: :unprocessable_content - end - params[:send_email] = true unless params.key?(:send_email) params[:send_sms] = false unless params.key?(:send_sms) @@ -129,6 +117,22 @@ module Api private + def maybe_return_template_error + return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil? + + if @template.archived_at? + Rollbar.warning("Archived template submission: #{@template.id}") if defined?(Rollbar) + + return render json: { error: 'Template has been archived' }, status: :unprocessable_content + end + + return if @template.fields.present? + + Rollbar.warning("Template does not contain fields: #{@template.id}") if defined?(Rollbar) + + render json: { error: 'Template does not contain fields' }, status: :unprocessable_content + end + def filter_submissions(submissions, params) submissions = submissions.where(template_id: params[:template_id]) if params[:template_id].present? submissions = submissions.where(slug: params[:slug]) if params[:slug].present? diff --git a/app/controllers/api/submitters_controller.rb b/app/controllers/api/submitters_controller.rb index 2827ba47..ec15ab11 100644 --- a/app/controllers/api/submitters_controller.rb +++ b/app/controllers/api/submitters_controller.rb @@ -4,6 +4,8 @@ module Api class SubmittersController < ApiBaseController load_and_authorize_resource :submitter + before_action :maybe_return_submitter_error, only: :update + def index submitters = Submitters.search(current_user, @submitters, params[:q]) @@ -36,14 +38,6 @@ module Api # rubocop:disable Metrics/MethodLength def update - if @submitter.completed_at? - return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_content - end - - if @submitter.declined_at? - return render json: { error: 'Submitter has already declined the submission.' }, status: :unprocessable_content - end - submission = @submitter.submission role = submission.template_submitters.find { |e| e['uuid'] == @submitter.uuid }['name'] @@ -106,6 +100,16 @@ module Api private + def maybe_return_submitter_error + if @submitter.completed_at? + return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_content + end + + return unless @submitter.declined_at? + + render json: { error: 'Submitter has already declined the submission.' }, status: :unprocessable_content + end + def maybe_filter_by_completed_at(submitters, params) if params[:completed_after].present? submitters = submitters.where(completed_at: Time.zone.parse(params[:completed_after])..) diff --git a/app/controllers/submissions_archived_controller.rb b/app/controllers/submissions_archived_controller.rb index 662e0950..46fa8278 100644 --- a/app/controllers/submissions_archived_controller.rb +++ b/app/controllers/submissions_archived_controller.rb @@ -12,11 +12,12 @@ class SubmissionsArchivedController < ApplicationController @submissions = Submissions.search(current_user, @submissions, params[:q], search_template: true) @submissions = Submissions::Filter.call(@submissions, current_user, params) - @submissions = if params[:completed_at_from].present? || params[:completed_at_to].present? - @submissions.order(Submitter.arel_table[:completed_at].maximum.desc) - else - @submissions.order(id: :desc) - end + @submissions = + if params[:status] == 'completed' || params[:completed_at_from].present? || params[:completed_at_to].present? + @submissions.order(completed_at: :desc) + else + @submissions.order(id: :desc) + end @pagy, @submissions = pagy_auto(@submissions.select_for_list.preload(submitters: :start_form_submission_events)) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 04bc5e94..f4aebb36 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -21,7 +21,7 @@ class SubmissionsController < ApplicationController def show @submission = Submissions.preload_with_pages(@submission) - unless @submission.submitters.all?(&:completed_at?) + unless @submission.completed_at? ActiveRecord::Associations::Preloader.new( records: [@submission], associations: [{ submitters: :start_form_submission_events }] diff --git a/app/controllers/submissions_dashboard_controller.rb b/app/controllers/submissions_dashboard_controller.rb index f04e9bea..dea9a6f3 100644 --- a/app/controllers/submissions_dashboard_controller.rb +++ b/app/controllers/submissions_dashboard_controller.rb @@ -13,11 +13,12 @@ class SubmissionsDashboardController < ApplicationController @submissions = Submissions.search(current_user, @submissions, params[:q], search_template: true) @submissions = Submissions::Filter.call(@submissions, current_user, params) - @submissions = if params[:completed_at_from].present? || params[:completed_at_to].present? - @submissions.order(Submitter.arel_table[:completed_at].maximum.desc) - else - @submissions.order(id: :desc) - end + @submissions = + if params[:status] == 'completed' || params[:completed_at_from].present? || params[:completed_at_to].present? + @submissions.order(completed_at: :desc) + else + @submissions.order(id: :desc) + end @pagy, @submissions = pagy_auto(@submissions.select_for_list.preload(submitters: :start_form_submission_events)) diff --git a/app/controllers/submissions_preview_controller.rb b/app/controllers/submissions_preview_controller.rb index ed83c407..7a0e96ce 100644 --- a/app/controllers/submissions_preview_controller.rb +++ b/app/controllers/submissions_preview_controller.rb @@ -25,7 +25,7 @@ class SubmissionsPreviewController < ApplicationController raise ActionController::RoutingError, I18n.t('not_found') if @submission.account.archived_at? - if !@submission.submitters.all?(&:completed_at?) && !signature_valid && + if !@submission.completed_at? && !signature_valid && (!current_user || !current_ability.can?(:read, @submission)) raise ActionController::RoutingError, I18n.t('not_found') end diff --git a/app/controllers/templates_archived_submissions_controller.rb b/app/controllers/templates_archived_submissions_controller.rb index cbe7e45a..662590d0 100644 --- a/app/controllers/templates_archived_submissions_controller.rb +++ b/app/controllers/templates_archived_submissions_controller.rb @@ -10,7 +10,7 @@ class TemplatesArchivedSubmissionsController < ApplicationController @submissions = Submissions::Filter.call(@submissions, current_user, params) @submissions = if params[:completed_at_from].present? || params[:completed_at_to].present? - @submissions.order(Submitter.arel_table[:completed_at].maximum.desc) + @submissions.order(completed_at: :desc) else @submissions.order(id: :desc) end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index edf73faa..b0d3446f 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -14,7 +14,7 @@ class TemplatesController < ApplicationController submissions = Submissions::Filter.filter_by_status(submissions, params) submissions = if params[:completed_at_from].present? || params[:completed_at_to].present? - submissions.order(Submitter.arel_table[:completed_at].maximum.desc) + submissions.order(completed_at: :desc) else submissions.order(id: :desc) end diff --git a/app/jobs/process_submission_expired_job.rb b/app/jobs/process_submission_expired_job.rb index d8303568..b3838c00 100644 --- a/app/jobs/process_submission_expired_job.rb +++ b/app/jobs/process_submission_expired_job.rb @@ -11,7 +11,7 @@ class ProcessSubmissionExpiredJob return if submission.archived_at? return if submission.template&.archived_at? return if submission.submitters.where.not(declined_at: nil).exists? - return unless submission.submitters.exists?(completed_at: nil) + return if submission.completed_at? WebhookUrls.enqueue_events(submission, 'submission.expired') end diff --git a/app/models/submission.rb b/app/models/submission.rb index 41cc6b8b..5a8c90f2 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -26,7 +26,9 @@ # # Indexes # +# index_submissions_on_account_id_and_completed_at (account_id,completed_at) WHERE ((completed_at IS NOT NULL) AND (archived_at IS NULL)) # index_submissions_on_account_id_and_id (account_id,id) +# index_submissions_on_account_id_and_id_pending (account_id,id) WHERE ((completed_at IS NULL) AND (archived_at IS NULL)) # index_submissions_on_account_id_and_template_id_and_id (account_id,template_id,id) WHERE (archived_at IS NULL) # index_submissions_on_account_id_and_template_id_and_id_archived (account_id,template_id,id) WHERE (archived_at IS NOT NULL) # index_submissions_on_created_by_user_id (created_by_user_id) @@ -90,26 +92,17 @@ class Submission < ApplicationRecord scope :active, -> { where(archived_at: nil) } scope :archived, -> { where.not(archived_at: nil) } scope :pending, lambda { - where(expire_at: nil).or(where(expire_at: Time.current..)) - .where(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]) - .and(Submitter.arel_table[:completed_at].eq(nil))).select(1).arel.exists) - } - scope :completed, lambda { - where.not(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]) - .and(Submitter.arel_table[:completed_at].eq(nil))).select(1).arel.exists) + where(expire_at: nil).or(where(expire_at: Time.current..)).where(completed_at: nil) } + scope :completed, -> { where.not(completed_at: nil) } scope :declined, lambda { where(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]) .and(Submitter.arel_table[:declined_at].not_eq(nil))).select(1).arel.exists) } - scope :expired, lambda { - where(expire_at: ..Time.current) - .where(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]) - .and(Submitter.arel_table[:completed_at].eq(nil))).select(1).arel.exists) - } + scope :expired, -> { where(expire_at: ..Time.current).where(completed_at: nil) } scope :select_for_list, lambda { - select(:id, :name, :created_by_user_id, :account_id, + select(:id, :name, :created_by_user_id, :account_id, :completed_at, :created_at, :archived_at, :expire_at, :template_id, :template_submitters) } diff --git a/app/views/submissions/show.html.erb b/app/views/submissions/show.html.erb index add9b01f..7dbe5723 100644 --- a/app/views/submissions/show.html.erb +++ b/app/views/submissions/show.html.erb @@ -15,7 +15,7 @@