diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index 77751066..f75d7299 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -185,7 +185,7 @@ module Api message: %i[subject body], submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role, :completed, :phone, :application_key, :external_id, :reply_to, :go_to_last, - :require_phone_2fa, + :require_phone_2fa, :order, { metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body], fields: [:name, :uuid, :default_value, :value, :title, :description, :readonly, :required, :validation_pattern, :invalid_message, diff --git a/app/jobs/process_submitter_completion_job.rb b/app/jobs/process_submitter_completion_job.rb index e8380a44..647aab5f 100644 --- a/app/jobs/process_submitter_completion_job.rb +++ b/app/jobs/process_submitter_completion_job.rb @@ -135,19 +135,32 @@ class ProcessSubmitterCompletionJob end def enqueue_next_submitter_request_notification(submitter) - next_submitter_item = - submitter.submission.template_submitters.find do |e| - sub = submitter.submission.submitters.find { |s| s.uuid == e['uuid'] } + submission = submitter.submission + submitters_index = submission.submitters.index_by(&:uuid) - next unless sub + next_submitter_items = + if submission.template_submitters.any? { |s| s['order'] } + submitter_groups = + submission.template_submitters.group_by.with_index { |s, index| s['order'] || index } - sub.completed_at.blank? && sub.sent_at.blank? - end + current_group_index = submitter_groups.find { |_, group| group.any? { |s| s['uuid'] == submitter.uuid } }&.first + + if submitter_groups[current_group_index + 1] && + submitters_index.values_at(*submitter_groups[current_group_index].pluck('uuid')).all?(&:completed_at?) + submitter_groups[current_group_index + 1] + end + else + submission.template_submitters.find do |e| + sub = submitters_index[e['uuid']] - return unless next_submitter_item + next unless sub + + sub.completed_at.blank? && sub.sent_at.blank? + end + end - next_submitter = submitter.submission.submitters.find { |s| s.uuid == next_submitter_item['uuid'] } + next_submitters = submitters_index.values_at(*Array.wrap(next_submitter_items).pluck('uuid')) - Submitters.send_signature_requests([next_submitter]) + Submitters.send_signature_requests(next_submitters) end end diff --git a/lib/params/submission_create_validator.rb b/lib/params/submission_create_validator.rb index 5737e1dd..8ce3becf 100644 --- a/lib/params/submission_create_validator.rb +++ b/lib/params/submission_create_validator.rb @@ -76,6 +76,7 @@ module Params type(submitter_params, :name, String) type(submitter_params, :reply_to, String) type(submitter_params, :email, String) + type(submitter_params, :order, Integer) email_format(submitter_params, :email, message: 'email is invalid') email_format(submitter_params, :reply_to, message: 'reply_to email is invalid') type(submitter_params, :phone, String) diff --git a/lib/submissions.rb b/lib/submissions.rb index e8085169..2870fb01 100644 --- a/lib/submissions.rb +++ b/lib/submissions.rb @@ -142,15 +142,23 @@ module Submissions submissions.each_with_index do |submission, index| delay_seconds = (delay + index).seconds if delay - submitters = submission.submitters.reject(&:completed_at?) + template_submitters = submission.template_submitters + submitters_index = submission.submitters.reject(&:completed_at?).index_by(&:uuid) - if submission.submitters_order_preserved? - first_submitter = - submission.template_submitters.filter_map { |s| submitters.find { |e| e.uuid == s['uuid'] } }.first + if template_submitters.any? { |s| s['order'] } + min_order = template_submitters.map.with_index { |s, i| s['order'] || i }.min + + first_submitters = template_submitters.filter_map do |s| + submitters_index[s['uuid']] if s['order'] == min_order + end + + Submitters.send_signature_requests(first_submitters, delay_seconds:) + elsif submission.submitters_order_preserved? + first_submitter = template_submitters.filter_map { |s| submitters_index[s['uuid']] }.first Submitters.send_signature_requests([first_submitter], delay_seconds:) if first_submitter else - Submitters.send_signature_requests(submitters, delay_seconds:) + Submitters.send_signature_requests(submitters_index.values, delay_seconds:) end end end diff --git a/lib/submissions/create_from_submitters.rb b/lib/submissions/create_from_submitters.rb index 4ad407df..f90720bb 100644 --- a/lib/submissions/create_from_submitters.rb +++ b/lib/submissions/create_from_submitters.rb @@ -52,9 +52,12 @@ module Submissions template_submitter = template_submitters.find { |e| e['uuid'] == uuid } end - submission.template_submitters << template_submitter.except('optional_invite_by_uuid', 'invite_by_uuid') + template_submitter = template_submitter.except('optional_invite_by_uuid', 'invite_by_uuid') + template_submitter['order'] = submitter_attrs['order'] if submitter_attrs['order'].present? - is_order_sent = submitters_order == 'random' || index.zero? + submission.template_submitters << template_submitter + + is_order_sent = submitters_order == 'random' || (template_submitter['order'] || index).zero? build_submitter(submission:, attrs: submitter_attrs, uuid:, is_order_sent:, user:, params:, diff --git a/lib/submitters.rb b/lib/submitters.rb index 8e7fd137..2e04b7b3 100644 --- a/lib/submitters.rb +++ b/lib/submitters.rb @@ -162,13 +162,22 @@ module Submitters end def current_submitter_order?(submitter) - submitter_items = submitter.submission.template_submitters || submitter.submission.template.submitters + submission = submitter.submission - before_items = submitter_items[0...(submitter_items.find_index { |e| e['uuid'] == submitter.uuid })] + submitter_items = submission.template_submitters || submission.template.submitters - before_items.reduce(true) do |acc, item| - acc && submitter.submission.submitters.find { |e| e.uuid == item['uuid'] }&.completed_at? - end + before_items = + if submitter_items.any? { |s| s['order'] } + submitter_groups = submitter_items.group_by.with_index { |s, index| s['order'] || index }.sort_by(&:first) + + current_group_index = submitter_groups.find_index { |_, group| group.any? { |s| s['uuid'] == submitter.uuid } } + + submitter_groups.first(current_group_index).flat_map(&:last) + else + submitter_items.first(submitter_items.find_index { |e| e['uuid'] == submitter.uuid }) + end + + before_items.all? { |item| submission.submitters.find { |e| e.uuid == item['uuid'] }&.completed_at? } end def build_document_filename(submitter, blob, filename_format)