Skip to content

Commit

Permalink
add submitter update endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
omohokcoj committed Dec 17, 2023
1 parent 1ad3e45 commit 990e402
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 64 deletions.
50 changes: 4 additions & 46 deletions app/controllers/api/submissions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def create_submissions(template, params)
emails:,
params:)
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(
template:,
Expand All @@ -97,7 +98,8 @@ def create_submissions(template, params)
params:
)

save_default_value_attachments!(attachments, submissions.flat_map(&:submitters))
Submissions::NormalizeParamUtils.save_default_value_attachments!(attachments,
submissions.flat_map(&:submitters))

submissions
end
Expand Down Expand Up @@ -133,49 +135,5 @@ def submissions_params
]
).fetch(key, [])
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
74 changes: 74 additions & 0 deletions app/controllers/api/submitters_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,79 @@ def show

render json: Submitters::SerializeForApi.call(@submitter, with_template: true, with_events: true)
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
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
resources :template_folders_autocomplete, only: %i[index]
resources :submitter_email_clicks, 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
collection do
resources :emails, only: %i[create], controller: 'submissions', as: :submissions_emails
Expand Down
6 changes: 3 additions & 3 deletions lib/submissions/create_from_submitters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ def call(template:, user:, submissions_attrs:, source:, submitters_order:, mark_
end
end

def maybe_set_template_fields(submission, submitters_attrs)
template_fields = submission.template.fields.deep_dup
def maybe_set_template_fields(submission, submitters_attrs, submitter_uuid: nil)
template_fields = (submission.template_fields || submission.template.fields).deep_dup

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)

Expand Down
2 changes: 1 addition & 1 deletion lib/submissions/generate_result_attachments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def build_pdfs_index(submitter)
Submissions::EnsureResultGenerated.call(latest_submitter) if latest_submitter

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|
pdf =
Expand Down
61 changes: 61 additions & 0 deletions lib/submissions/normalize_param_utils.rb
Original file line number Diff line number Diff line change
@@ -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
40 changes: 27 additions & 13 deletions lib/submitters/normalize_values.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ module NormalizeValues

module_function

def call(template, values, submitter_name, throw_errors: false)
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'] }
def call(template, values, submitter_name: nil, for_submitter: nil, throw_errors: false)
fields = fetch_fields(template, submitter_name:, for_submitter:)

fields_uuid_index = fields.index_by { |e| e['uuid'] }
fields_name_index = build_fields_index(fields)
Expand All @@ -31,7 +27,7 @@ def call(template, values, submitter_name, throw_errors: false)
next if key.blank?

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)

Expand All @@ -44,27 +40,45 @@ def call(template, values, submitter_name, throw_errors: false)
[normalized_values, attachments]
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)
fields.index_by { |e| e['name'] }.merge(fields.index_by { |e| e['name'].to_s.parameterize.underscore })
end

def normalize_attachment_value(value, account)
def normalize_attachment_value(value, account, for_submitter = nil)
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]
else
new_attachment = build_attachment(value, account)
new_attachment = find_or_build_attachment(value, account, for_submitter)

[new_attachment.uuid, new_attachment]
end
end

def build_attachment(value, account)
ActiveStorage::Attachment.new(
blob: find_or_create_blobs(account, value),
def find_or_build_attachment(value, account, for_submitter = nil)
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'
)

attachment
end

def find_or_create_blobs(account, url)
Expand Down

0 comments on commit 990e402

Please sign in to comment.