diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index 17899d1a..2770e283 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -22,7 +22,7 @@ module Api audit_trail_attachment: :blob)) render json: { - data: submissions.as_json(serialize_params), + data: submissions.as_json(Submissions::SerializeForApi::SERIALIZE_PARAMS), pagination: { count: submissions.size, next: submissions.last&.id, @@ -44,29 +44,7 @@ module Api @submission.audit_trail_attachment = Submissions::GenerateAuditTrail.call(@submission) end - serialized_submitters = submitters.map { |submitter| Submitters::SerializeForApi.call(submitter) } - - json = @submission.as_json( - serialize_params.deep_merge( - include: { submission_events: { only: %i[id submitter_id event_type event_timestamp] } } - ) - ) - - if submitters.all?(&:completed_at?) - last_submitter = submitters.max_by(&:completed_at) - - json[:documents] = serialized_submitters.find { |e| e['id'] == last_submitter.id }['documents'] - json[:status] = 'completed' - json[:completed_at] = last_submitter.completed_at - else - json[:documents] = [] - json[:status] = 'pending' - json[:completed_at] = nil - end - - json[:submitters] = serialized_submitters - - render json: + render json: Submissions::SerializeForApi.call(@submission, submitters) end def create @@ -85,6 +63,10 @@ module Api submissions = create_submissions(@template, params) + submissions.each do |submission| + SendSubmissionCreatedWebhookRequestJob.perform_later(submission) + end + Submissions.send_signature_requests(submissions) submissions.each do |submission| @@ -153,22 +135,6 @@ module Api end end - def serialize_params - { - only: %i[id source submitters_order created_at updated_at archived_at], - methods: %i[audit_log_url], - include: { - submitters: { only: %i[id slug uuid name email phone - completed_at opened_at sent_at - created_at updated_at external_id metadata], - methods: %i[status application_key] }, - template: { only: %i[id name external_id created_at updated_at], - methods: %i[folder_name] }, - created_by_user: { only: %i[id email first_name last_name] } - } - } - end - def submissions_params permitted_attrs = [ :send_email, :send_sms, :bcc_completed, :completed_redirect_url, :reply_to, :go_to_last, diff --git a/app/controllers/start_form_controller.rb b/app/controllers/start_form_controller.rb index 7a919f88..5cb51e2e 100644 --- a/app/controllers/start_form_controller.rb +++ b/app/controllers/start_form_controller.rb @@ -33,7 +33,11 @@ class StartFormController < ApplicationController assign_submission_attributes(@submitter, @template) if @submitter.new_record? + is_new_record = @submitter.new_record? + if @submitter.save + SendSubmissionCreatedWebhookRequestJob.perform_later(@submitter.submission) if is_new_record + redirect_to submit_form_path(@submitter.slug) else render :show diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 5257da04..1b88e67f 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -44,6 +44,10 @@ class SubmissionsController < ApplicationController params: params.merge('send_completed_email' => true)) end + submissions.each do |submission| + SendSubmissionCreatedWebhookRequestJob.perform_later(submission) + end + Submissions.send_signature_requests(submissions) redirect_to template_path(@template), notice: 'New recipients have been added' diff --git a/app/controllers/webhook_preferences_controller.rb b/app/controllers/webhook_preferences_controller.rb index eadd37dc..15a05be8 100644 --- a/app/controllers/webhook_preferences_controller.rb +++ b/app/controllers/webhook_preferences_controller.rb @@ -7,6 +7,7 @@ class WebhookPreferencesController < ApplicationController form.completed template.created template.updated + submission.created submission.archived ].freeze diff --git a/app/jobs/send_submission_created_webhook_request_job.rb b/app/jobs/send_submission_created_webhook_request_job.rb new file mode 100644 index 00000000..5909021a --- /dev/null +++ b/app/jobs/send_submission_created_webhook_request_job.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class SendSubmissionCreatedWebhookRequestJob < ApplicationJob + USER_AGENT = 'DocuSeal.co Webhook' + + MAX_ATTEMPTS = 10 + + def perform(submission, params = {}) + attempt = params[:attempt].to_i + url = Accounts.load_webhook_url(submission.account) + + return if url.blank? + + preferences = Accounts.load_webhook_preferences(submission.account) + + return if preferences['submission.created'].blank? + + resp = begin + Faraday.post(url, + { + event_type: 'submission.created', + timestamp: Time.current, + data: Submissions::SerializeForApi.call(submission) + }.to_json, + 'Content-Type' => 'application/json', + 'User-Agent' => USER_AGENT) + rescue Faraday::Error + nil + end + + if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && + (!Docuseal.multitenant? || submission.account.account_configs.exists?(key: :plan)) + SendSubmissionCreatedWebhookRequestJob.set(wait: (2**attempt).minutes) + .perform_later(submission, { + attempt: attempt + 1, + last_status: resp&.status.to_i + }) + end + end +end diff --git a/app/views/webhook_settings/show.html.erb b/app/views/webhook_settings/show.html.erb index 4a5a9f4c..c9b1e3c1 100644 --- a/app/views/webhook_settings/show.html.erb +++ b/app/views/webhook_settings/show.html.erb @@ -15,22 +15,24 @@ <% end %> <% preference = current_account.account_configs.find_by(key: AccountConfig::WEBHOOK_PREFERENCES_KEY)&.value || {} %> -
- <% WebhookPreferencesController::EVENTS.each do |event| %> - <%= form_for '', url: webhook_preferences_path, method: :post do |f| %> - <%= f.hidden_field :event, value: event %> - <% uuid = SecureRandom.uuid %> -
- -
+ <% WebhookPreferencesController::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %> +
+ <% events.each do |event| %> + <%= form_for '', url: webhook_preferences_path, method: :post do |f| %> + <%= f.hidden_field :event, value: event %> + <% uuid = SecureRandom.uuid %> +
+ +
+ <% end %> <% end %> - <% end %> -
+
+ <% end %> <% submitter = current_account.submitters.where.not(completed_at: nil).order(:id).last %> diff --git a/lib/submissions/serialize_for_api.rb b/lib/submissions/serialize_for_api.rb new file mode 100644 index 00000000..a2b1b4b1 --- /dev/null +++ b/lib/submissions/serialize_for_api.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Submissions + module SerializeForApi + SERIALIZE_PARAMS = { + only: %i[id source submitters_order created_at updated_at archived_at], + methods: %i[audit_log_url], + include: { + submitters: { only: %i[id slug uuid name email phone + completed_at opened_at sent_at + created_at updated_at external_id metadata], + methods: %i[status application_key] }, + template: { only: %i[id name external_id created_at updated_at], + methods: %i[folder_name] }, + created_by_user: { only: %i[id email first_name last_name] } + } + }.freeze + + module_function + + def call(submission, submitters = nil) + submitters ||= submission.submitters.preload(documents_attachments: :blob, attachments_attachments: :blob) + + serialized_submitters = submitters.map { |submitter| Submitters::SerializeForApi.call(submitter) } + + json = submission.as_json( + SERIALIZE_PARAMS.deep_merge( + include: { submission_events: { only: %i[id submitter_id event_type event_timestamp] } } + ) + ) + + if submitters.all?(&:completed_at?) + last_submitter = submitters.max_by(&:completed_at) + + json[:documents] = serialized_submitters.find { |e| e['id'] == last_submitter.id }['documents'] + json[:status] = 'completed' + json[:completed_at] = last_submitter.completed_at + else + json[:documents] = [] + json[:status] = 'pending' + json[:completed_at] = nil + end + + json[:submitters] = serialized_submitters + + json + end + end +end