add submitter update endpoint

pull/150/merge
Pete Matsyburka 2 years ago
parent 1ad3e45519
commit 990e4020e9

@ -85,7 +85,8 @@ module Api
emails:, emails:,
params:) params:)
else else
submissions_attrs, attachments = normalize_submissions_params!(submissions_params, template) submissions_attrs, attachments =
Submissions::NormalizeParamUtils.normalize_submissions_params!(submissions_params, template)
submissions = Submissions.create_from_submitters( submissions = Submissions.create_from_submitters(
template:, template:,
@ -97,7 +98,8 @@ module Api
params: params:
) )
save_default_value_attachments!(attachments, submissions.flat_map(&:submitters)) Submissions::NormalizeParamUtils.save_default_value_attachments!(attachments,
submissions.flat_map(&:submitters))
submissions submissions
end end
@ -133,49 +135,5 @@ module Api
] ]
).fetch(key, []) ).fetch(key, [])
end end
def normalize_submissions_params!(submissions_params, template)
attachments = []
Array.wrap(submissions_params).each do |submission|
submission[:submitters].each_with_index do |submitter, index|
default_values = submitter[:values] || {}
submitter[:fields]&.each { |f| default_values[f[:name]] = f[:default_value] if f[:default_value].present? }
next if default_values.blank?
values, new_attachments =
Submitters::NormalizeValues.call(template,
default_values,
submitter[:role] || template.submitters[index]['name'],
throw_errors: true)
attachments.push(*new_attachments)
submitter[:values] = values
end
end
[submissions_params, attachments]
end
def save_default_value_attachments!(attachments, submitters)
return if attachments.blank?
attachments_index = attachments.index_by(&:uuid)
submitters.each do |submitter|
submitter.values.to_a.each do |_, value|
attachment = attachments_index[value]
next unless attachment
attachment.record = submitter
attachment.save!
end
end
end
end end
end end

@ -30,5 +30,79 @@ module Api
render json: Submitters::SerializeForApi.call(@submitter, with_template: true, with_events: true) render json: Submitters::SerializeForApi.call(@submitter, with_template: true, with_events: true)
end end
def update
if @submitter.completed_at?
return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_entity
end
role = @submitter.submission.template_submitters.find { |e| e['uuid'] == @submitter.uuid }['name']
normalized_params, new_attachments =
Submissions::NormalizeParamUtils.normalize_submitter_params!(submitter_params.merge(role:), @submitter.template,
for_submitter: @submitter)
Submissions::CreateFromSubmitters.maybe_set_template_fields(@submitter.submission,
[normalized_params],
submitter_uuid: @submitter.uuid)
assign_submitter_attrs(@submitter, normalized_params)
ApplicationRecord.transaction do
Submissions::NormalizeParamUtils.save_default_value_attachments!(new_attachments, [@submitter])
@submitter.save!
@submitter.submission.save!
end
if @submitter.completed_at?
ProcessSubmitterCompletionJob.perform_later(@submitter)
elsif normalized_params[:send_email] || normalized_params[:send_sms]
Submitters.send_signature_requests([@submitter])
end
render json: Submitters::SerializeForApi.call(@submitter, with_template: false, with_events: false)
end
def submitter_params
submitter_params = params.key?(:submitter) ? params.require(:submitter) : params
submitter_params.permit(
:send_email, :send_sms, :uuid, :name, :email, :role, :completed, :phone, :application_key,
{ values: {}, readonly_fields: [], message: %i[subject body],
fields: [%i[name default_value readonly validation_pattern invalid_message]] }
)
end
private
def assign_submitter_attrs(submitter, attrs)
submitter.email = Submissions.normalize_email(attrs[:email]) if attrs.key?(:email)
submitter.phone = attrs[:phone].to_s.gsub(/[^0-9+]/, '') if attrs.key?(:phone)
submitter.values = submitter.values.merge(attrs[:values].to_unsafe_h) if attrs[:values]
submitter.completed_at = attrs[:completed] ? Time.current : submitter.completed_at
submitter.application_key = attrs[:application_key] if attrs.key?(:application_key)
assign_preferences(submitter, attrs)
submitter
end
def assign_preferences(submitter, attrs)
submitter_preferences = Submitters.normalize_preferences(submitter.account, current_user, attrs)
if submitter_preferences.key?('send_email')
submitter.preferences['send_email'] = submitter_preferences['send_email']
end
submitter.preferences['send_sms'] = submitter_preferences['send_sms'] if submitter_preferences.key?('send_sms')
return unless submitter_preferences.key?('email_message_uuid')
submitter.preferences['email_message_uuid'] = submitter_preferences['email_message_uuid']
submitter
end
end end
end end

@ -35,7 +35,7 @@ Rails.application.routes.draw do
resources :template_folders_autocomplete, only: %i[index] resources :template_folders_autocomplete, only: %i[index]
resources :submitter_email_clicks, only: %i[create] resources :submitter_email_clicks, only: %i[create]
resources :submitter_form_views, only: %i[create] resources :submitter_form_views, only: %i[create]
resources :submitters, only: %i[index show] resources :submitters, only: %i[index show update]
resources :submissions, only: %i[index show create destroy] do resources :submissions, only: %i[index show create destroy] do
collection do collection do
resources :emails, only: %i[create], controller: 'submissions', as: :submissions_emails resources :emails, only: %i[create], controller: 'submissions', as: :submissions_emails

@ -39,11 +39,11 @@ module Submissions
end end
end end
def maybe_set_template_fields(submission, submitters_attrs) def maybe_set_template_fields(submission, submitters_attrs, submitter_uuid: nil)
template_fields = submission.template.fields.deep_dup template_fields = (submission.template_fields || submission.template.fields).deep_dup
submitters_attrs.each_with_index do |submitter_attrs, index| submitters_attrs.each_with_index do |submitter_attrs, index|
submitter_uuid = find_submitter_uuid(submission.template, submitter_attrs, index) submitter_uuid ||= find_submitter_uuid(submission.template, submitter_attrs, index)
process_readonly_fields_param(submitter_attrs[:readonly_fields], template_fields, submitter_uuid) process_readonly_fields_param(submitter_attrs[:readonly_fields], template_fields, submitter_uuid)

@ -268,7 +268,7 @@ module Submissions
Submissions::EnsureResultGenerated.call(latest_submitter) if latest_submitter Submissions::EnsureResultGenerated.call(latest_submitter) if latest_submitter
documents = latest_submitter&.documents&.preload(:blob).to_a.presence documents = latest_submitter&.documents&.preload(:blob).to_a.presence
documents ||= submitter.submission.template.documents.preload(:blob) documents ||= submitter.submission.template.schema_documents.preload(:blob)
documents.to_h do |attachment| documents.to_h do |attachment|
pdf = pdf =

@ -0,0 +1,61 @@
# frozen_string_literal: true
module Submissions
module NormalizeParamUtils
module_function
def normalize_submissions_params!(submissions_params, template)
attachments = []
Array.wrap(submissions_params).each do |submission|
submission[:submitters].each_with_index do |submitter, index|
_, new_attachments = normalize_submitter_params!(submitter, template, index)
attachments.push(*new_attachments)
end
end
[submissions_params, attachments]
end
def normalize_submitter_params!(submitter_params, template, index = nil, for_submitter: nil)
default_values = submitter_params[:values] || {}
submitter_params[:fields]&.each do |f|
default_values[f[:name]] = f[:default_value] if f[:default_value].present?
end
return submitter_params if default_values.blank?
values, new_attachments =
Submitters::NormalizeValues.call(template,
default_values,
submitter_name: submitter_params[:role] ||
template.submitters.dig(index, 'name'),
for_submitter:,
throw_errors: true)
submitter_params[:values] = values
[submitter_params, new_attachments]
end
def save_default_value_attachments!(attachments, submitters)
return if attachments.blank?
attachments_index = attachments.index_by(&:uuid)
submitters.each do |submitter|
submitter.values.to_a.each do |_, value|
attachment = attachments_index[value]
next unless attachment
attachment.record = submitter
attachment.save!
end
end
end
end
end

@ -9,12 +9,8 @@ module Submitters
module_function module_function
def call(template, values, submitter_name, throw_errors: false) def call(template, values, submitter_name: nil, for_submitter: nil, throw_errors: false)
submitter = fields = fetch_fields(template, submitter_name:, for_submitter:)
template.submitters.find { |e| e['name'] == submitter_name } ||
raise(UnknownSubmitterName, "Unknown submitter: #{submitter_name}")
fields = template.fields.select { |e| e['submitter_uuid'] == submitter['uuid'] }
fields_uuid_index = fields.index_by { |e| e['uuid'] } fields_uuid_index = fields.index_by { |e| e['uuid'] }
fields_name_index = build_fields_index(fields) fields_name_index = build_fields_index(fields)
@ -31,7 +27,7 @@ module Submitters
next if key.blank? next if key.blank?
if fields_uuid_index[key]['type'].in?(%w[initials signature image file]) if fields_uuid_index[key]['type'].in?(%w[initials signature image file])
new_value, new_attachments = normalize_attachment_value(value, template.account) new_value, new_attachments = normalize_attachment_value(value, template.account, for_submitter)
attachments.push(*new_attachments) attachments.push(*new_attachments)
@ -44,27 +40,45 @@ module Submitters
[normalized_values, attachments] [normalized_values, attachments]
end end
def fetch_fields(template, submitter_name: nil, for_submitter: nil)
if submitter_name
submitter =
template.submitters.find { |e| e['name'] == submitter_name } ||
raise(UnknownSubmitterName, "Unknown submitter: #{submitter_name}")
end
fields = for_submitter&.submission&.template_fields || template.fields
fields.select { |e| e['submitter_uuid'] == (for_submitter&.uuid || submitter['uuid']) }
end
def build_fields_index(fields) def build_fields_index(fields)
fields.index_by { |e| e['name'] }.merge(fields.index_by { |e| e['name'].to_s.parameterize.underscore }) fields.index_by { |e| e['name'] }.merge(fields.index_by { |e| e['name'].to_s.parameterize.underscore })
end end
def normalize_attachment_value(value, account) def normalize_attachment_value(value, account, for_submitter = nil)
if value.is_a?(Array) if value.is_a?(Array)
new_attachments = value.map { |v| build_attachment(v, account) } new_attachments = value.map { |v| find_or_build_attachment(v, account, for_submitter) }
[new_attachments.map(&:uuid), new_attachments] [new_attachments.map(&:uuid), new_attachments]
else else
new_attachment = build_attachment(value, account) new_attachment = find_or_build_attachment(value, account, for_submitter)
[new_attachment.uuid, new_attachment] [new_attachment.uuid, new_attachment]
end end
end end
def build_attachment(value, account) def find_or_build_attachment(value, account, for_submitter = nil)
ActiveStorage::Attachment.new( blob = find_or_create_blobs(account, value)
blob: find_or_create_blobs(account, value),
attachment = for_submitter.attachments.find_by(blob_id: blob.id) if for_submitter
attachment ||= ActiveStorage::Attachment.new(
blob:,
name: 'attachments' name: 'attachments'
) )
attachment
end end
def find_or_create_blobs(account, url) def find_or_create_blobs(account, url)

Loading…
Cancel
Save