|
|
|
@ -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: [
|
|
|
|
width: attachment.metadata['width'] * scale,
|
|
|
|
(area['x'] * width) + (area['w'] * width / 2) - ((attachment.metadata['width'] * scale) / 2),
|
|
|
|
height: attachment.metadata['height'] * scale)
|
|
|
|
height - (area['y'] * height) - (attachment.metadata['height'] * scale / 2) - (area['h'] * height / 2)
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
width: attachment.metadata['width'] * 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
|
|
|
|
|
|
|
|
|
|
|
|
canvas.font(FONT_NAME, size: FONT_SIZE)
|
|
|
|
acc << HexaPDF::Layout::TextFragment.create("#{attachment.filename}\n", font: pdf.fonts.add(FONT_NAME),
|
|
|
|
canvas.text(attachment.filename.to_s,
|
|
|
|
font_size: FONT_SIZE)
|
|
|
|
at: [(area['x'] * width) + FONT_SIZE,
|
|
|
|
|
|
|
|
height - ((area['y'] * height) + FONT_SIZE - (FONT_SIZE * index))])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
page[:Annots] ||= []
|
|
|
|
|
|
|
|
page[:Annots] << pdf.add({
|
|
|
|
|
|
|
|
Type: :Annot, Subtype: :Link,
|
|
|
|
|
|
|
|
Rect: [
|
|
|
|
|
|
|
|
area['x'] * width,
|
|
|
|
|
|
|
|
height - (area['y'] * height),
|
|
|
|
|
|
|
|
(area['x'] * width) + (area['w'] * width),
|
|
|
|
|
|
|
|
height - (area['y'] * height) - FONT_SIZE
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
A: { Type: :Action, S: :URI, URI: attachment.url }
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
when 'checkbox'
|
|
|
|
|
|
|
|
Array.wrap(value).each_with_index do |value, index|
|
|
|
|
lines = layouter.fit(items, area['w'] * width, height).lines
|
|
|
|
canvas.image(PdfIcons.check_io,
|
|
|
|
|
|
|
|
at: [area['x'] * width,
|
|
|
|
box_height = lines.sum(&:height)
|
|
|
|
height - ((area['y'] * height) + (1.2 * FONT_SIZE) - (FONT_SIZE * index))],
|
|
|
|
height_diff = [0, box_height - (area['h'] * height)].max
|
|
|
|
width: FONT_SIZE, height: FONT_SIZE)
|
|
|
|
|
|
|
|
|
|
|
|
lines.each_with_index.reduce(0) do |acc, (line, index)|
|
|
|
|
canvas.font(FONT_NAME, size: FONT_SIZE)
|
|
|
|
next acc unless line.items.first.is_a?(HexaPDF::Layout::InlineBox)
|
|
|
|
canvas.text(value,
|
|
|
|
|
|
|
|
at: [(area['x'] * width) + FONT_SIZE,
|
|
|
|
attachment_uuid = Array.wrap(value)[acc]
|
|
|
|
height - ((area['y'] * height) + FONT_SIZE - (FONT_SIZE * index))])
|
|
|
|
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,
|
|
|
|
|
|
|
|
Rect: [
|
|
|
|
|
|
|
|
area['x'] * width,
|
|
|
|
|
|
|
|
height - (area['y'] * height) - lines[...index].sum(&:height) + height_diff,
|
|
|
|
|
|
|
|
(area['x'] * width) + (area['w'] * width),
|
|
|
|
|
|
|
|
height - (area['y'] * height) - lines[..next_index].sum(&:height) + height_diff
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
A: { Type: :Action, S: :URI, URI: attachment.url }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
acc + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
when 'date'
|
|
|
|
|
|
|
|
canvas.font(FONT_NAME, size: FONT_SIZE)
|
|
|
|
layouter.fit(items, area['w'] * width, height_diff.positive? ? box_height : area['h'] * height)
|
|
|
|
canvas.text(I18n.l(Date.parse(value)),
|
|
|
|
.draw(canvas, area['x'] * width, height - (area['y'] * height) + height_diff)
|
|
|
|
at: [area['x'] * width, height - ((area['y'] * height) + FONT_SIZE)])
|
|
|
|
when 'checkbox'
|
|
|
|
|
|
|
|
next unless value == true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scale = [(area['w'] * width) / PdfIcons::WIDTH, (area['h'] * height) / PdfIcons::HEIGHT].min
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
canvas.image(
|
|
|
|
|
|
|
|
PdfIcons.check_io,
|
|
|
|
|
|
|
|
at: [
|
|
|
|
|
|
|
|
(area['x'] * width) + (area['w'] * width / 2) - (PdfIcons::WIDTH * scale / 2),
|
|
|
|
|
|
|
|
height - (area['y'] * height) - (area['h'] * height / 2) - (PdfIcons::HEIGHT * scale / 2)
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
width: PdfIcons::WIDTH * scale,
|
|
|
|
|
|
|
|
height: PdfIcons::HEIGHT * scale
|
|
|
|
|
|
|
|
)
|
|
|
|
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']),
|
|
|
|
|