mirror of https://github.com/docusealco/docuseal
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.2 KiB
140 lines
4.2 KiB
# frozen_string_literal: true
|
|
|
|
class ExportSubmissionService < ExportService
|
|
attr_reader :submission
|
|
|
|
def initialize(submission)
|
|
super()
|
|
@submission = submission
|
|
end
|
|
|
|
def call
|
|
export_location = ExportLocation.default_location
|
|
|
|
if export_location&.submissions_endpoint.blank?
|
|
record_error('Export failed: Submission export endpoint is not configured.')
|
|
return false
|
|
end
|
|
|
|
payload = build_payload
|
|
response = post_to_api(payload, export_location.submissions_endpoint, export_location.extra_params)
|
|
|
|
if response&.success?
|
|
true
|
|
else
|
|
record_error("Failed to export submission ##{submission.id} events.")
|
|
false
|
|
end
|
|
rescue Faraday::Error => e
|
|
Rails.logger.error("Failed to export submission Faraday: #{e.message}")
|
|
Rollbar.error("Failed to export submission: #{e.message}") if defined?(Rollbar)
|
|
record_error("Network error occurred during export: #{e.message}")
|
|
false
|
|
rescue StandardError => e
|
|
Rails.logger.error("Failed to export submission: #{e.message}")
|
|
Rollbar.error(e) if defined?(Rollbar)
|
|
record_error("An unexpected error occurred during export: #{e.message}")
|
|
false
|
|
end
|
|
|
|
private
|
|
|
|
def build_payload
|
|
{
|
|
external_submission_id: submission.id,
|
|
template_name: submission.template&.name,
|
|
status: submission_status,
|
|
submitter_data: submission.submitters.map do |submitter|
|
|
{
|
|
external_submitter_id: submitter.slug,
|
|
name: submitter.name,
|
|
email: submitter.email,
|
|
status: submitter.status,
|
|
completed_at: submitter.completed_at,
|
|
declined_at: submitter.declined_at
|
|
}
|
|
end,
|
|
created_at: submission.created_at,
|
|
updated_at: submission.updated_at,
|
|
# Include form field values for each submitter
|
|
values: build_values_array,
|
|
# Include granular submission events for audit trail
|
|
submission_events: build_submission_events_array
|
|
}
|
|
end
|
|
|
|
def submission_status
|
|
# The status is tracked for each submitter, so we need to check the status of all submitters
|
|
statuses = submission.submitters.map(&:status)
|
|
|
|
if statuses.include?('declined')
|
|
'declined'
|
|
elsif statuses.all?('completed')
|
|
'completed'
|
|
elsif statuses.include?('changes_requested')
|
|
'changes_requested'
|
|
elsif statuses.any?('opened')
|
|
'in_progress'
|
|
elsif statuses.any?('sent')
|
|
'sent'
|
|
else
|
|
'pending'
|
|
end
|
|
end
|
|
|
|
# Build array of form field values from all submitters
|
|
# Returns array of {field: name, value: value} hashes
|
|
def build_values_array
|
|
submission.submitters.flat_map do |submitter|
|
|
build_submitter_values(submitter)
|
|
end
|
|
end
|
|
|
|
# Build values for a single submitter
|
|
def build_submitter_values(submitter)
|
|
fields = submission.template_fields.presence || submission.template&.fields || []
|
|
attachments_index = submitter.attachments.index_by(&:uuid)
|
|
|
|
fields.filter_map do |field|
|
|
next if field['submitter_uuid'] != submitter.uuid
|
|
next if field['type'] == 'heading'
|
|
|
|
field_name = field['name'].presence || "#{field['type'].titleize} Field"
|
|
next unless submitter.values.key?(field['uuid']) || submitter.completed_at?
|
|
|
|
value = fetch_field_value(field, submitter.values[field['uuid']], attachments_index)
|
|
|
|
{ field: field_name, value: }
|
|
end
|
|
end
|
|
|
|
# Build array of submission events for audit trail
|
|
def build_submission_events_array
|
|
submission.submission_events.order(:event_timestamp).map do |event|
|
|
{
|
|
id: event.id,
|
|
event_type: event.event_type,
|
|
event_timestamp: event.event_timestamp.iso8601,
|
|
data: event.data
|
|
}
|
|
end
|
|
end
|
|
|
|
# Fetch the value for a field, handling special types
|
|
def fetch_field_value(field, value, attachments_index)
|
|
if field['type'].in?(%w[image signature initials stamp payment])
|
|
rails_storage_proxy_url(attachments_index[value])
|
|
elsif field['type'] == 'file'
|
|
Array.wrap(value).compact_blank.filter_map { |e| rails_storage_proxy_url(attachments_index[e]) }
|
|
else
|
|
value
|
|
end
|
|
end
|
|
|
|
def rails_storage_proxy_url(attachment)
|
|
return if attachment.blank?
|
|
|
|
ActiveStorage::Blob.proxy_url(attachment.blob)
|
|
end
|
|
end
|