add merge roles param

pull/402/merge
Pete Matsyburka 8 months ago
parent 6b3726dbd5
commit 4fb9637e2d

@ -179,7 +179,7 @@ module Api
message: %i[subject body],
submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role,
:completed, :phone, :application_key, :external_id, :reply_to, :go_to_last,
{ metadata: {}, values: {}, readonly_fields: [], message: %i[subject body],
{ metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body],
fields: [:name, :uuid, :default_value, :value, :title, :description,
:readonly, :validation_pattern, :invalid_message,
{ default_value: [], value: [], preferences: {} }] }]]

@ -23,15 +23,33 @@ module Submissions
expire_at: attrs[:expire_at],
template_submitters: [], submitters_order:)
maybe_set_template_fields(submission, attrs[:submitters])
template_submitters = template.submitters.deep_dup
attrs[:submitters].each_with_index do |submitter_attrs, index|
uuid = find_submitter_uuid(template, submitter_attrs, index)
if submitter_attrs[:roles].present? && submitter_attrs[:roles].size > 1
template_submitter, template_submitters, submission.template_fields =
merge_submitters_and_fields(submitter_attrs, template_submitters,
submission.template_fields || submission.template.fields)
submission.template_schema = submission.template.schema if submission.template_schema.blank?
uuid = template_submitter['uuid']
else
if submitter_attrs[:roles].present? && submitter_attrs[:roles].size == 1
submitter_attrs[:role] = submitter_attrs[:roles].first
end
uuid = find_submitter_uuid(template_submitters, submitter_attrs, index)
next if uuid.blank?
next if submitter_attrs.slice('email', 'phone', 'name').compact_blank.blank?
next if uuid.blank?
next if submitter_attrs.slice('email', 'phone', 'name').compact_blank.blank?
submission.template_fields = submission.template.fields if submitter_attrs[:completed].present? &&
submission.template_fields.blank?
template_submitter = template_submitters.find { |e| e['uuid'] == uuid }
end
template_submitter = template.submitters.find { |e| e['uuid'] == uuid }
submission.template_submitters << template_submitter.except('optional_invite_by_uuid', 'invite_by_uuid')
is_order_sent = submitters_order == 'random' || index.zero?
@ -41,6 +59,8 @@ module Submissions
preferences: preferences.merge(submission_preferences))
end
maybe_set_template_fields(submission, attrs[:submitters])
if submission.submitters.size > template.submitters.size
raise BaseError, 'Defined more signing parties than in template'
end
@ -94,8 +114,10 @@ module Submissions
def maybe_set_template_fields(submission, submitters_attrs, default_submitter_uuid: nil)
template_fields = (submission.template_fields || submission.template.fields).deep_dup
submitters = submission.template_submitters || submission.template.submitters
submitters_attrs.each_with_index do |submitter_attrs, index|
submitter_uuid = default_submitter_uuid || find_submitter_uuid(submission.template, submitter_attrs, index)
submitter_uuid = default_submitter_uuid || find_submitter_uuid(submitters, submitter_attrs, index)
process_readonly_fields_param(submitter_attrs[:readonly_fields], template_fields, submitter_uuid)
process_field_values_param(submitter_attrs[:values], template_fields, submitter_uuid)
@ -112,6 +134,65 @@ module Submissions
submission
end
def merge_submitters_and_fields(submitter_attrs, template_submitters, template_fields)
selected_submitters = submitter_attrs[:roles].map do |role|
template_submitters.find { |e| e['name'].to_s.casecmp(role).zero? } ||
raise(BaseError, "#{role} role doesn't exist")
end
merge_role_uuids = selected_submitters.pluck('uuid')
old_role_uuids = template_submitters.pluck('uuid')
name = submitter_attrs[:role].presence || selected_submitters.pluck('name').join(' / ')
merged_submitter, template_submitters =
build_merged_submitter(template_submitters, role_uuids: merge_role_uuids, name:)
field_names_index = {}
sorted_fields = template_fields.sort_by { |e| old_role_uuids.index(e['submitter_uuid']) }
sorted_fields.each do |field|
next unless merge_role_uuids.include?(field['submitter_uuid'])
if (existing_field = field_names_index[field['name']])
existing_field['areas'] ||= []
existing_field['areas'].push(*field['areas'])
template_fields.delete(field)
else
field['submitter_uuid'] = merged_submitter['uuid']
field_names_index[field['name']] = field if field['name'].present?
end
end
[merged_submitter, template_submitters, template_fields]
end
def build_merged_submitter(submitters, role_uuids:, name:)
new_uuid = Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, role_uuids.sort.join(':'))
merged_submitter = nil
submitters =
submitters.filter_map do |submitter|
submitter['optional_invite_by_uuid'] = new_uuid if role_uuids.include?(submitter['optional_invite_by_uuid'])
submitter['invite_by_uuid'] = new_uuid if role_uuids.include?(submitter['invite_by_uuid'])
submitter['linked_to_uuid'] = new_uuid if role_uuids.include?(submitter['linked_to_uuid'])
if role_uuids.include?(submitter['uuid'])
next if merged_submitter
merged_submitter = submitter.deep_dup
merged_submitter['uuid'] = new_uuid
merged_submitter['name'] = name
merged_submitter.delete('linked_to_uuid')
end
submitter
end
[merged_submitter, submitters]
end
def process_readonly_fields_param(readonly_fields, template_fields, submitter_uuid)
return if readonly_fields.blank?
@ -190,11 +271,11 @@ module Submissions
field
end
def find_submitter_uuid(template, attrs, index)
def find_submitter_uuid(submitters, attrs, index)
uuid = attrs[:uuid].presence
uuid ||= template.submitters.find { |e| e['name'].to_s.casecmp(attrs[:role].to_s).zero? }&.dig('uuid')
uuid ||= submitters.find { |e| e['name'].to_s.casecmp(attrs[:role].to_s).zero? }&.dig('uuid')
uuid || template.submitters[index]&.dig('uuid')
uuid || submitters[index]&.dig('uuid')
end
def build_submitter(submission:, attrs:, uuid:, is_order_sent:, user:, preferences:, params:)

@ -33,6 +33,7 @@ module Submissions
default_values,
submitter_name: submitter_params[:role] ||
template.submitters.dig(index, 'name'),
role_names: submitter_params[:roles],
for_submitter:,
throw_errors: true)

@ -17,38 +17,47 @@ module Submitters
module_function
def call(template, values, submitter_name: nil, for_submitter: nil, throw_errors: false)
fields = fetch_fields(template, submitter_name:, for_submitter:)
def call(template, values, submitter_name: nil, role_names: nil, for_submitter: nil, throw_errors: false)
fields =
if role_names.present?
fetch_roles_fields(template, roles: role_names)
else
fetch_fields(template, submitter_name:, for_submitter:)
end
fields_uuid_index = fields.index_by { |e| e['uuid'] }
fields_name_index = build_fields_index(fields)
attachments = []
normalized_values = values.to_h.filter_map do |key, value|
if fields_uuid_index[key].blank?
original_key = key
normalized_values = values.to_h.each_with_object({}) do |(key, value), acc|
next if key.blank?
uuid_field = fields_uuid_index[key]
key = fields_name_index[key]&.dig('uuid') || fields_name_index[key.to_s.downcase]&.dig('uuid')
value_fields = [uuid_field] if uuid_field
raise(UnknownFieldName, "Unknown field: #{original_key}") if key.blank? && throw_errors
if value_fields.blank?
value_fields = fields_name_index[key].presence || fields_name_index[key.to_s.downcase]
raise(UnknownFieldName, "Unknown field: #{key}") if value_fields.blank? && throw_errors
end
next if key.blank?
next if value_fields.blank?
field = fields_uuid_index[key]
value_fields.each do |field|
if field['type'].in?(%w[initials signature image file stamp]) && value.present?
new_value, new_attachments =
normalize_attachment_value(value, field, template.account, attachments, for_submitter)
if field['type'].in?(%w[initials signature image file stamp]) && value.present?
new_value, new_attachments =
normalize_attachment_value(value, field, template.account, attachments, for_submitter)
attachments.push(*new_attachments)
attachments.push(*new_attachments)
value = new_value
end
value = new_value
acc[field['uuid']] = normalize_value(field, value)
end
[key, normalize_value(field, value)]
end.to_h
end
[normalized_values, attachments]
end
@ -103,10 +112,24 @@ module Submitters
end
end
def fetch_roles_fields(template, roles:)
submitters = roles.map do |submitter_name|
template.submitters.find { |e| e['name'] == submitter_name } ||
raise(UnknownSubmitterName,
"Unknown submitter role: #{submitter_name}. Template defines #{template.submitters.pluck('name')}")
end
role_uuids = submitters.pluck('uuid')
template.fields.select do |e|
role_uuids.include?(e['submitter_uuid'])
end
end
def build_fields_index(fields)
fields.index_by { |e| e['name'] }
.merge(fields.index_by { |e| e['name'].to_s.parameterize.underscore })
.merge(fields.index_by { |e| e['name'].to_s.downcase })
fields.group_by { |e| e['name'] }
.merge(fields.group_by { |e| e['name'].to_s.parameterize.underscore })
.merge(fields.group_by { |e| e['name'].to_s.downcase })
end
def normalize_attachment_value(value, field, account, attachments, for_submitter = nil)

Loading…
Cancel
Save