|  |  | @ -2,13 +2,14 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | module Submissions |  |  |  | module Submissions | 
			
		
	
		
		
			
				
					
					|  |  |  |   module GenerateResultAttachments |  |  |  |   module GenerateResultAttachments | 
			
		
	
		
		
			
				
					
					|  |  |  |     FONT_SIZE = 12 |  |  |  |     FONT_SIZE = 11 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     FONT_NAME = 'Helvetica' |  |  |  |     FONT_NAME = 'Helvetica' | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     module_function |  |  |  |     module_function | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     # rubocop:disable Metrics |  |  |  |     # rubocop:disable Metrics | 
			
		
	
		
		
			
				
					
					|  |  |  |     def call(submitter) |  |  |  |     def call(submitter) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       layouter = HexaPDF::Layout::TextLayouter.new(valign: :center) | 
			
		
	
		
		
			
				
					
					|  |  |  |       template = submitter.submission.template |  |  |  |       template = submitter.submission.template | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       cert = submitter.submission.template.account.encrypted_configs |  |  |  |       cert = submitter.submission.template.account.encrypted_configs | 
			
		
	
	
		
		
			
				
					|  |  | @ -36,61 +37,91 @@ module Submissions | 
			
		
	
		
		
			
				
					
					|  |  |  |             attachment = submitter.attachments.find { |a| a.uuid == value } |  |  |  |             attachment = submitter.attachments.find { |a| a.uuid == value } | 
			
		
	
		
		
			
				
					
					|  |  |  |             io = StringIO.new(attachment.download) |  |  |  |             io = StringIO.new(attachment.download) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             Vips::Image.new_from_buffer(io.read, '') |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             scale = [(area['w'] * width) / attachment.metadata['width'], |  |  |  |             scale = [(area['w'] * width) / attachment.metadata['width'], | 
			
		
	
		
		
			
				
					
					|  |  |  |                      (area['h'] * height) / attachment.metadata['height']].min |  |  |  |                      (area['h'] * height) / attachment.metadata['height']].min | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             canvas.image(io, at: [area['x'] * width, |  |  |  |             canvas.image( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                   height - (area['y'] * height) - |  |  |  |               io, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                   (((attachment.metadata['height'] * scale) + (area['h'] * height)) / 2)], |  |  |  |               at: [ | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 (area['x'] * width) + (area['w'] * width / 2) - ((attachment.metadata['width'] * scale) / 2), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 height - (area['y'] * height) - (attachment.metadata['height'] * scale / 2) - (area['h'] * height / 2) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               ], | 
			
		
	
		
		
			
				
					
					|  |  |  |               width: attachment.metadata['width'] * scale, |  |  |  |               width: attachment.metadata['width'] * scale, | 
			
		
	
		
		
			
				
					
					|  |  |  |                              height: attachment.metadata['height'] * scale) |  |  |  |               height: attachment.metadata['height'] * scale | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ) | 
			
		
	
		
		
			
				
					
					|  |  |  |           when 'file' |  |  |  |           when 'file' | 
			
		
	
		
		
			
				
					
					|  |  |  |             Array.wrap(value).each_with_index do |uuid, index| |  |  |  |             page[:Annots] ||= [] | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             items = Array.wrap(value).each_with_object([]) do |uuid, acc| | 
			
		
	
		
		
			
				
					
					|  |  |  |               attachment = submitter.attachments.find { |a| a.uuid == uuid } |  |  |  |               attachment = submitter.attachments.find { |a| a.uuid == uuid } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               canvas.image(PdfIcons.paperclip_io, |  |  |  |               acc << HexaPDF::Layout::InlineBox.create(width: FONT_SIZE, height: FONT_SIZE, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                            at: [area['x'] * width, |  |  |  |                                                        margin: [0, 1, -2, 0]) do |cv, box| | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                 height - ((area['y'] * height) + (1.2 * FONT_SIZE) - (FONT_SIZE * index))], |  |  |  |                 cv.image(PdfIcons.paperclip_io, at: [0, 0], width: box.content_width) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                            width: FONT_SIZE, height: FONT_SIZE) |  |  |  |               end | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               acc << HexaPDF::Layout::TextFragment.create("#{attachment.filename}\n", font: pdf.fonts.add(FONT_NAME), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                                                                       font_size: FONT_SIZE) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             end | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               canvas.font(FONT_NAME, size: FONT_SIZE) |  |  |  |             lines = layouter.fit(items, area['w'] * width, height).lines | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               canvas.text(attachment.filename.to_s, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                           at: [(area['x'] * width) + FONT_SIZE, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                                height - ((area['y'] * height) + FONT_SIZE - (FONT_SIZE * index))]) |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               page[:Annots] ||= [] |  |  |  |             box_height = lines.sum(&:height) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               page[:Annots] << pdf.add({ |  |  |  |             height_diff = [0, box_height - (area['h'] * height)].max | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             lines.each_with_index.reduce(0) do |acc, (line, index)| | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               next acc unless line.items.first.is_a?(HexaPDF::Layout::InlineBox) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               attachment_uuid = Array.wrap(value)[acc] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               attachment = submitter.attachments.find { |a| a.uuid == attachment_uuid } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               next_index = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 lines[(index + 1)..].index { |l| l.items.first.is_a?(HexaPDF::Layout::InlineBox) } || (lines.size - 1) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               page[:Annots] << pdf.add( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 { | 
			
		
	
		
		
			
				
					
					|  |  |  |                   Type: :Annot, Subtype: :Link, |  |  |  |                   Type: :Annot, Subtype: :Link, | 
			
		
	
		
		
			
				
					
					|  |  |  |                   Rect: [ |  |  |  |                   Rect: [ | 
			
		
	
		
		
			
				
					
					|  |  |  |                     area['x'] * width, |  |  |  |                     area['x'] * width, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                            height - (area['y'] * height), |  |  |  |                     height - (area['y'] * height) - lines[...index].sum(&:height) + height_diff, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                     (area['x'] * width) + (area['w'] * width), |  |  |  |                     (area['x'] * width) + (area['w'] * width), | 
			
		
	
		
		
			
				
					
					|  |  |  |                                            height - (area['y'] * height) - FONT_SIZE |  |  |  |                     height - (area['y'] * height) - lines[..next_index].sum(&:height) + height_diff | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                   ], |  |  |  |                   ], | 
			
		
	
		
		
			
				
					
					|  |  |  |                   A: { Type: :Action, S: :URI, URI: attachment.url } |  |  |  |                   A: { Type: :Action, S: :URI, URI: attachment.url } | 
			
		
	
		
		
			
				
					
					|  |  |  |                                        }) |  |  |  |                 } | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               acc + 1 | 
			
		
	
		
		
			
				
					
					|  |  |  |             end |  |  |  |             end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             layouter.fit(items, area['w'] * width, height_diff.positive? ? box_height : area['h'] * height) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     .draw(canvas, area['x'] * width, height - (area['y'] * height) + height_diff) | 
			
		
	
		
		
			
				
					
					|  |  |  |           when 'checkbox' |  |  |  |           when 'checkbox' | 
			
		
	
		
		
			
				
					
					|  |  |  |             Array.wrap(value).each_with_index do |value, index| |  |  |  |             next unless value == true | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               canvas.image(PdfIcons.check_io, |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                            at: [area['x'] * width, |  |  |  |             scale = [(area['w'] * width) / PdfIcons::WIDTH, (area['h'] * height) / PdfIcons::HEIGHT].min | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                 height - ((area['y'] * height) + (1.2 * FONT_SIZE) - (FONT_SIZE * index))], |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                            width: FONT_SIZE, height: FONT_SIZE) |  |  |  |             canvas.image( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |               PdfIcons.check_io, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               canvas.font(FONT_NAME, size: FONT_SIZE) |  |  |  |               at: [ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               canvas.text(value, |  |  |  |                 (area['x'] * width) + (area['w'] * width / 2) - (PdfIcons::WIDTH * scale / 2), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                           at: [(area['x'] * width) + FONT_SIZE, |  |  |  |                 height - (area['y'] * height) - (area['h'] * height / 2) - (PdfIcons::HEIGHT * scale / 2) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                height - ((area['y'] * height) + FONT_SIZE - (FONT_SIZE * index))]) |  |  |  |               ], | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             end |  |  |  |               width: PdfIcons::WIDTH * scale, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           when 'date' |  |  |  |               height: PdfIcons::HEIGHT * scale | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             canvas.font(FONT_NAME, size: FONT_SIZE) |  |  |  |             ) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             canvas.text(I18n.l(Date.parse(value)), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                         at: [area['x'] * width, height - ((area['y'] * height) + FONT_SIZE)]) |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           else |  |  |  |           else | 
			
		
	
		
		
			
				
					
					|  |  |  |             canvas.font(FONT_NAME, size: FONT_SIZE) |  |  |  |             value = I18n.l(Date.parse(value)) if field['type'] == 'date' | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             canvas.text(value.to_s, at: [area['x'] * width, height - ((area['y'] * height) + FONT_SIZE)]) |  |  |  | 
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             text = HexaPDF::Layout::TextFragment.create(Array.wrap(value).join(', '), font: pdf.fonts.add(FONT_NAME), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                                                                       font_size: FONT_SIZE) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             lines = layouter.fit([text], area['w'] * width, height).lines | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             box_height = lines.sum(&:height) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             height_diff = [0, box_height - (area['h'] * height)].max | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             layouter.fit([text], area['w'] * width, height_diff.positive? ? box_height : area['h'] * height) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     .draw(canvas, area['x'] * width, height - (area['y'] * height) + height_diff) | 
			
		
	
		
		
			
				
					
					|  |  |  |           end |  |  |  |           end | 
			
		
	
		
		
			
				
					
					|  |  |  |         end |  |  |  |         end | 
			
		
	
		
		
			
				
					
					|  |  |  |       end |  |  |  |       end | 
			
		
	
	
		
		
			
				
					|  |  | @ -103,7 +134,6 @@ module Submissions | 
			
		
	
		
		
			
				
					
					|  |  |  |         pdf = pdfs_index[item['attachment_uuid']] |  |  |  |         pdf = pdfs_index[item['attachment_uuid']] | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         pdf.sign(io, reason: "Signed by #{submitter.email}", |  |  |  |         pdf.sign(io, reason: "Signed by #{submitter.email}", | 
			
		
	
		
		
			
				
					
					|  |  |  |                      # doc_mdp_permissions: :no_changes, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                      certificate: OpenSSL::X509::Certificate.new(cert['cert']), |  |  |  |                      certificate: OpenSSL::X509::Certificate.new(cert['cert']), | 
			
		
	
		
		
			
				
					
					|  |  |  |                      key: OpenSSL::PKey::RSA.new(cert['key']), |  |  |  |                      key: OpenSSL::PKey::RSA.new(cert['key']), | 
			
		
	
		
		
			
				
					
					|  |  |  |                      certificate_chain: [OpenSSL::X509::Certificate.new(cert['sub_ca']), |  |  |  |                      certificate_chain: [OpenSSL::X509::Certificate.new(cert['sub_ca']), | 
			
		
	
	
		
		
			
				
					|  |  | 
 |