From 62cea05084bc019d3a256e432b7df9b341eb0410 Mon Sep 17 00:00:00 2001 From: Alex Turchyn Date: Sun, 10 Sep 2023 02:10:01 +0300 Subject: [PATCH] add preserve submitters order option --- .rubocop.yml | 3 ++ app/controllers/api/submissions_controller.rb | 21 +++++------ app/controllers/submissions_controller.rb | 8 ++--- app/jobs/process_submitter_completion_job.rb | 21 ++++++++++- .../send_submitter_invitation_email_job.rb | 10 ++++++ app/models/submission.rb | 7 ++++ app/views/submissions/_detailed_form.html.erb | 1 + app/views/submissions/_email_form.html.erb | 5 ++- app/views/submissions/_phone_form.html.erb | 1 + app/views/submissions/_send_email.html.erb | 2 +- .../submissions/_submitters_order.html.erb | 11 ++++++ ...212_add_submitters_order_to_submissions.rb | 15 ++++++++ db/schema.rb | 3 +- lib/submissions.rb | 36 ++++++++++++++----- lib/submitters.rb | 2 +- 15 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 app/jobs/send_submitter_invitation_email_job.rb create mode 100644 app/views/submissions/_submitters_order.html.erb create mode 100644 db/migrate/20230909213212_add_submitters_order_to_submissions.rb diff --git a/.rubocop.yml b/.rubocop.yml index ab266ac2..623c3db2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -26,6 +26,9 @@ Style/Documentation: Lint/MissingSuper: Enabled: false +Metrics/ParameterLists: + Max: 10 + Metrics/MethodLength: Max: 25 Exclude: diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index 433f183a..b5d57583 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -9,25 +9,26 @@ module Api template = current_account.templates.find(params[:template_id]) submissions = - if (params[:emails] || params[:email]).present? + if (emails = (params[:emails] || params[:email]).presence) Submissions.create_from_emails(template:, user: current_user, source: :api, mark_as_sent: params[:send_email] != 'false', - emails: params[:emails] || params[:email]) + emails:) else submissions_attrs = normalize_submissions_params!(submissions_params[:submission], template) - Submissions.create_from_submitters(template:, - user: current_user, - source: :api, - mark_as_sent: params[:send_email] != 'false', - submissions_attrs:) + Submissions.create_from_submitters( + template:, + user: current_user, + source: :api, + mark_as_sent: params[:send_email] != 'false', + submitters_order: params[:submitters_order] || 'preserved', + submissions_attrs: + ) end - submitters = submissions.flat_map(&:submitters) - - Submitters.send_signature_requests(submitters, send_email: params[:send_email] != 'false') + Submissions.send_signature_requests(submissions, send_email: params[:send_email] != 'false') render json: submitters rescue UnknownFieldName, UnknownSubmitterName => e diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index f4a99853..854908d5 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -26,16 +26,14 @@ class SubmissionsController < ApplicationController Submissions.create_from_submitters(template: @template, user: current_user, source: :invite, + submitters_order: params[:preserve_order] == '1' ? 'preserved' : 'random', mark_as_sent: params[:send_email] == '1', submissions_attrs: submissions_params[:submission].to_h.values) end - submitters = submissions.flat_map(&:submitters) + Submissions.send_signature_requests(submissions, params) - Submitters.send_signature_requests(submitters, params) - - redirect_to template_path(@template), - notice: "#{submitters.size} #{'recipient'.pluralize(submitters.size)} added" + redirect_to template_path(@template), notice: 'New recipients have been added' end def destroy diff --git a/app/jobs/process_submitter_completion_job.rb b/app/jobs/process_submitter_completion_job.rb index 9effc871..89178615 100644 --- a/app/jobs/process_submitter_completion_job.rb +++ b/app/jobs/process_submitter_completion_job.rb @@ -4,6 +4,10 @@ class ProcessSubmitterCompletionJob < ApplicationJob def perform(submitter) is_all_completed = !submitter.submission.submitters.exists?(completed_at: nil) + if !is_all_completed && submitter.submission.submitters_order_preserved? + enqueue_next_submitter_request_notification(submitter) + end + Submissions::EnsureResultGenerated.call(submitter) if submitter.account.encrypted_configs.exists?(key: EncryptedConfig::WEBHOOK_URL_KEY) @@ -25,8 +29,23 @@ class ProcessSubmitterCompletionJob < ApplicationJob SubmitterMailer.completed_email(submitter, user, bcc:).deliver_later! end - to = submitter.submission.submitters.order(:completed_at).select(&:email?).map(&:friendly_name).join(', ') + to = submitter.submission.submitters.sort_by(&:completed_at).select(&:email?).map(&:friendly_name).join(', ') SubmitterMailer.documents_copy_email(submitter, to:).deliver_later! if to.present? 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'] } + + sub.completed_at.blank? && sub.sent_at.blank? + end + + return unless next_submitter_item + + next_submitter = submitter.submission.submitters.find { |s| s.uuid == next_submitter_item['uuid'] } + + Submitters.send_signature_requests([next_submitter], send_email: true) + end end diff --git a/app/jobs/send_submitter_invitation_email_job.rb b/app/jobs/send_submitter_invitation_email_job.rb new file mode 100644 index 00000000..2bc4fddb --- /dev/null +++ b/app/jobs/send_submitter_invitation_email_job.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class SendSubmitterInvitationEmailJob < ApplicationJob + def perform(submitter) + SubmitterMailer.invitation_email(submitter).deliver_now! + + submitter.sent_at ||= Time.current + submitter.save + end +end diff --git a/app/models/submission.rb b/app/models/submission.rb index 323b7586..1283c7b5 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -7,6 +7,7 @@ # id :bigint not null, primary key # deleted_at :datetime # source :text not null +# submitters_order :string not null # template_fields :text # template_schema :text # template_submitters :text @@ -37,6 +38,7 @@ class Submission < ApplicationRecord serialize :template_submitters, JSON attribute :source, :string, default: 'link' + attribute :submitters_order, :string, default: 'random' has_many :template_schema_documents, ->(e) { where(uuid: (e.template_schema.presence || e.template.schema).pluck('attachment_uuid')) }, @@ -50,4 +52,9 @@ class Submission < ApplicationRecord embed: 'embed', link: 'link' }, scope: false, prefix: true + + enum :submitters_order, { + random: 'random', + preserved: 'preserved' + }, scope: false, prefix: true end diff --git a/app/views/submissions/_detailed_form.html.erb b/app/views/submissions/_detailed_form.html.erb index e42e05be..c54fbf4a 100644 --- a/app/views/submissions/_detailed_form.html.erb +++ b/app/views/submissions/_detailed_form.html.erb @@ -34,6 +34,7 @@
+ <%= render('submitters_order', f:, template:) if Accounts.can_send_emails?(current_account) %> <%= render 'send_email', f:, template: %> <%= render 'send_sms', f: %>
diff --git a/app/views/submissions/_email_form.html.erb b/app/views/submissions/_email_form.html.erb index 786ccf51..c7513b61 100644 --- a/app/views/submissions/_email_form.html.erb +++ b/app/views/submissions/_email_form.html.erb @@ -35,7 +35,10 @@ <% end %> - <%= render 'send_email', f:, template: %> +
+ <%= render 'send_email', f:, template: %> + <%= render('submitters_order', f:, template:) if Accounts.can_send_emails?(current_account) %> +
<%= f.button button_title(title: 'Add Recipients'), class: 'base-button' %>
diff --git a/app/views/submissions/_phone_form.html.erb b/app/views/submissions/_phone_form.html.erb index 1ed62d74..321d6713 100644 --- a/app/views/submissions/_phone_form.html.erb +++ b/app/views/submissions/_phone_form.html.erb @@ -38,6 +38,7 @@ <%= render 'send_sms', f: %> + <%= render('submitters_order', f:, template:) if Accounts.can_send_emails?(current_account) %>
<%= f.button button_title(title: 'Add Recipients'), class: 'base-button' %>
diff --git a/app/views/submissions/_send_email.html.erb b/app/views/submissions/_send_email.html.erb index 1aa640ed..1bee1be9 100644 --- a/app/views/submissions/_send_email.html.erb +++ b/app/views/submissions/_send_email.html.erb @@ -2,7 +2,7 @@ <% is_smtp_configured = Accounts.can_send_emails?(current_account) %> <%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %> <%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !is_smtp_configured, checked: is_smtp_configured %> - Send Email + Send emails <% end %> <% unless is_smtp_configured %>
diff --git a/app/views/submissions/_submitters_order.html.erb b/app/views/submissions/_submitters_order.html.erb new file mode 100644 index 00000000..a37de594 --- /dev/null +++ b/app/views/submissions/_submitters_order.html.erb @@ -0,0 +1,11 @@ +<% if template.submitters.size > 1 %> +
+ <%= f.label :preserve_order, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %> + <%= f.check_box :preserve_order, id: uuid, class: 'base-checkbox', checked: template.submissions.last&.submitters_order.in?(['preserved', nil]) %> + Preserve submitters order + + <%= svg_icon('info_circle', class: 'w-4 h-4') %> + + <% end %> +
+<% end %> diff --git a/db/migrate/20230909213212_add_submitters_order_to_submissions.rb b/db/migrate/20230909213212_add_submitters_order_to_submissions.rb new file mode 100644 index 00000000..b462f554 --- /dev/null +++ b/db/migrate/20230909213212_add_submitters_order_to_submissions.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddSubmittersOrderToSubmissions < ActiveRecord::Migration[7.0] + class MigrationSubmission < ApplicationRecord + self.table_name = 'submissions' + end + + def change + add_column :submissions, :submitters_order, :string + + MigrationSubmission.where(submitters_order: nil).update_all(submitters_order: 'random') + + change_column_null :submissions, :submitters_order, false + end +end diff --git a/db/schema.rb b/db/schema.rb index 89264725..c16b0b99 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_09_02_171216) do +ActiveRecord::Schema[7.0].define(version: 2023_09_09_213212) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -101,6 +101,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_02_171216) do t.text "template_schema" t.text "template_submitters" t.text "source", null: false + t.string "submitters_order", null: false t.index ["created_by_user_id"], name: "index_submissions_on_created_by_user_id" t.index ["template_id"], name: "index_submissions_on_template_id" end diff --git a/lib/submissions.rb b/lib/submissions.rb index b329627b..f1276466 100644 --- a/lib/submissions.rb +++ b/lib/submissions.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true module Submissions + DEFAULT_SUBMITTERS_ORDER = 'random' + module_function def update_template_fields!(submission) @@ -24,9 +26,11 @@ module Submissions end end - def create_from_submitters(template:, user:, submissions_attrs:, source:, mark_as_sent: false) + def create_from_submitters(template:, user:, submissions_attrs:, source:, mark_as_sent: false, + submitters_order: DEFAULT_SUBMITTERS_ORDER) submissions_attrs.map do |attrs| - submission = template.submissions.new(created_by_user: user, source:, template_submitters: template.submitters) + submission = template.submissions.new(created_by_user: user, source:, + template_submitters: template.submitters, submitters_order:) attrs[:submitters].each_with_index do |submitter_attrs, index| uuid = @@ -36,15 +40,31 @@ module Submissions next if uuid.blank? - submission.submitters.new(email: submitter_attrs[:email], - phone: submitter_attrs[:phone].to_s.gsub(/[^0-9+]/, ''), - name: submitter_attrs[:name], - sent_at: mark_as_sent && submitter_attrs[:email].present? ? Time.current : nil, - values: submitter_attrs[:values] || {}, - uuid:) + is_order_sent = submitters_order == 'random' || index.zero? + + submission.submitters.new( + email: submitter_attrs[:email], + phone: submitter_attrs[:phone].to_s.gsub(/[^0-9+]/, ''), + name: submitter_attrs[:name], + sent_at: mark_as_sent && submitter_attrs[:email].present? && is_order_sent ? Time.current : nil, + values: submitter_attrs[:values] || {}, + uuid: + ) end submission.tap(&:save!) end end + + def send_signature_requests(submissions, params) + submissions.each do |submission| + if submission.submitters_order_preserved? + first_submitter = submission.submitters.find { |e| e.uuid == submission.template_submitters.first['uuid'] } + + Submitters.send_signature_requests([first_submitter], params) + else + Submitters.send_signature_requests(submission.submitters, params) + end + end + end end diff --git a/lib/submitters.rb b/lib/submitters.rb index a23684bc..ee3b5e8d 100644 --- a/lib/submitters.rb +++ b/lib/submitters.rb @@ -35,7 +35,7 @@ module Submitters submitters.each do |submitter| next if submitter.email.blank? - SubmitterMailer.invitation_email(submitter, message: params[:message]).deliver_later! + SendSubmitterInvitationEmailJob.perform_later(submitter) end end end