mirror of https://github.com/docusealco/docuseal
parent
a6bf8a9870
commit
b0786580ad
@ -0,0 +1,78 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SendSignatureCallbackJob
|
||||||
|
include Sidekiq::Job
|
||||||
|
|
||||||
|
sidekiq_options queue: :webhooks
|
||||||
|
|
||||||
|
TRACKED_FIELD_NAMES = %w[provider_signature client_caregiver_signature supervisor_signature].freeze
|
||||||
|
CALLBACK_ENDPOINT = 'https://app.therapypms.com/v1/note/signed'.freeze
|
||||||
|
|
||||||
|
def perform(params = {})
|
||||||
|
submitter = Submitter.find_by(id: params['submitter_id'])
|
||||||
|
|
||||||
|
return unless submitter&.completed_at?
|
||||||
|
|
||||||
|
callback_url = AccountConfig.find_by(
|
||||||
|
account_id: submitter.account_id,
|
||||||
|
key: AccountConfig::SIGNATURE_CALLBACK_URL_KEY
|
||||||
|
)&.value.presence || CALLBACK_ENDPOINT
|
||||||
|
|
||||||
|
fields = submitter.submission.template_fields || submitter.submission.template&.fields
|
||||||
|
|
||||||
|
return unless fields
|
||||||
|
|
||||||
|
tracked_fields = fields.select do |f|
|
||||||
|
f['submitter_uuid'] == submitter.uuid &&
|
||||||
|
f['type'] == 'signature' &&
|
||||||
|
TRACKED_FIELD_NAMES.include?(f['name'])
|
||||||
|
end
|
||||||
|
|
||||||
|
return if tracked_fields.empty?
|
||||||
|
|
||||||
|
attachments_index = submitter.attachments.preload(:blob).index_by(&:uuid)
|
||||||
|
|
||||||
|
signatures = tracked_fields.filter_map do |field|
|
||||||
|
attachment_uuid = submitter.values[field['uuid']]
|
||||||
|
next unless attachment_uuid.present?
|
||||||
|
|
||||||
|
attachment = attachments_index[attachment_uuid]
|
||||||
|
next unless attachment
|
||||||
|
|
||||||
|
{
|
||||||
|
field_name: field['name'],
|
||||||
|
field_uuid: field['uuid'],
|
||||||
|
signature: Base64.strict_encode64(attachment.download)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return if signatures.empty?
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
admin_id: submitter.submission.created_by_user_id,
|
||||||
|
template_id: submitter.submission.template_id,
|
||||||
|
submission_id: submitter.submission_id,
|
||||||
|
embed_src: build_embed_src(submitter),
|
||||||
|
email: submitter.email,
|
||||||
|
signatures: signatures
|
||||||
|
}
|
||||||
|
|
||||||
|
Faraday.post(callback_url) do |req|
|
||||||
|
req.headers['Content-Type'] = 'application/json'
|
||||||
|
req.body = payload.to_json
|
||||||
|
req.options.read_timeout = 10
|
||||||
|
req.options.open_timeout = 10
|
||||||
|
end
|
||||||
|
rescue Faraday::Error => e
|
||||||
|
Rails.logger.error("SendSignatureCallbackJob error for submitter #{params['submitter_id']}: #{e.message}")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build_embed_src(submitter)
|
||||||
|
opts = Docuseal.default_url_options
|
||||||
|
port = opts[:port] ? ":#{opts[:port]}" : ''
|
||||||
|
|
||||||
|
"#{opts[:protocol]}://#{opts[:host]}#{port}/submissions/#{submitter.submission_id}"
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::SIGNATURE_CALLBACK_URL_KEY) %>
|
||||||
|
<% if can?(:manage, account_config) %>
|
||||||
|
<div class="collapse collapse-plus bg-base-200 mt-4">
|
||||||
|
<input type="checkbox" <%= 'checked' if account_config.value.present? %>>
|
||||||
|
<div class="collapse-title text-xl font-medium">
|
||||||
|
Signature Callback URL
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<p class="text-sm text-base-content/60 mb-3">
|
||||||
|
When a Provider, Client/Caregiver, or Supervisor signature is collected, DocuSeal will POST
|
||||||
|
<code class="font-mono">{ template_id, form_id, email, signatures }</code> to this URL.
|
||||||
|
Leave blank to disable.
|
||||||
|
</p>
|
||||||
|
<%= form_for account_config, url: account_configs_path, method: :post,
|
||||||
|
html: { autocomplete: 'off', class: 'space-y-3' } do |f| %>
|
||||||
|
<%= f.hidden_field :key %>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= f.url_field :value,
|
||||||
|
class: 'base-input w-full font-mono',
|
||||||
|
placeholder: 'https://your-app.example.com/api/signature-callback',
|
||||||
|
value: account_config.value.presence %>
|
||||||
|
</div>
|
||||||
|
<div class="form-control pt-1">
|
||||||
|
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
Loading…
Reference in new issue