mirror of https://github.com/docusealco/docuseal
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							130 lines
						
					
					
						
							5.0 KiB
						
					
					
				
			
		
		
	
	
							130 lines
						
					
					
						
							5.0 KiB
						
					
					
				| # frozen_string_literal: true
 | |
| 
 | |
| module Submissions
 | |
|   module GeneratePreviewAttachments
 | |
|     module_function
 | |
| 
 | |
|     # rubocop:disable Metrics
 | |
|     def call(submission, values_hash: nil, submitter: nil)
 | |
|       values_hash ||= if submitter
 | |
|                         build_submitter_values_hash(submitter)
 | |
|                       else
 | |
|                         build_values_hash(submission)
 | |
|                       end
 | |
| 
 | |
|       configs = submission.account.account_configs.where(key: [AccountConfig::FLATTEN_RESULT_PDF_KEY,
 | |
|                                                                AccountConfig::WITH_SIGNATURE_ID,
 | |
|                                                                AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY,
 | |
|                                                                AccountConfig::WITH_FILE_LINKS_KEY,
 | |
|                                                                AccountConfig::WITH_SIGNATURE_ID_REASON_KEY])
 | |
| 
 | |
|       with_signature_id = configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true
 | |
|       with_file_links = configs.find { |c| c.key == AccountConfig::WITH_FILE_LINKS_KEY }&.value == true
 | |
|       is_flatten = configs.find { |c| c.key == AccountConfig::FLATTEN_RESULT_PDF_KEY }&.value != false
 | |
|       with_submitter_timezone = configs.find { |c| c.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true
 | |
|       with_signature_id_reason =
 | |
|         configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false
 | |
| 
 | |
|       pdfs_index = GenerateResultAttachments.build_pdfs_index(submission, flatten: is_flatten)
 | |
| 
 | |
|       submitters = if submitter
 | |
|                      submission.submitters.where(id: submitter.id)
 | |
|                    else
 | |
|                      submission.submitters.where(completed_at: nil)
 | |
|                    end
 | |
| 
 | |
|       submitters.preload(attachments_attachments: :blob).each_with_index do |s, index|
 | |
|         GenerateResultAttachments.fill_submitter_fields(s, submission.account, pdfs_index,
 | |
|                                                         with_signature_id:, is_flatten:, with_headings: index.zero?,
 | |
|                                                         with_submitter_timezone:, with_file_links:,
 | |
|                                                         with_signature_id_reason:)
 | |
|       end
 | |
| 
 | |
|       template = submission.template
 | |
| 
 | |
|       image_pdfs = []
 | |
|       original_documents = submission.schema_documents.preload(:blob)
 | |
| 
 | |
|       result_attachments =
 | |
|         (submission.template_schema || template.schema).filter_map do |item|
 | |
|           pdf = pdfs_index[item['attachment_uuid']]
 | |
| 
 | |
|           next if pdf.nil?
 | |
| 
 | |
|           if original_documents.find { |a| a.uuid == item['attachment_uuid'] }.image?
 | |
|             pdf = GenerateResultAttachments.normalize_image_pdf(pdf)
 | |
| 
 | |
|             image_pdfs << pdf
 | |
|           end
 | |
| 
 | |
|           build_pdf_attachment(pdf:, submission:, submitter:,
 | |
|                                uuid: item['attachment_uuid'],
 | |
|                                values_hash:,
 | |
|                                name: item['name'])
 | |
|         end
 | |
| 
 | |
|       return ApplicationRecord.no_touching { result_attachments.map { |e| e.tap(&:save!) } } if image_pdfs.size < 2
 | |
| 
 | |
|       images_pdf =
 | |
|         image_pdfs.each_with_object(HexaPDF::Document.new) do |pdf, doc|
 | |
|           pdf.pages.each { |page| doc.pages << doc.import(page) }
 | |
|         end
 | |
| 
 | |
|       images_pdf = GenerateResultAttachments.normalize_image_pdf(images_pdf)
 | |
| 
 | |
|       images_pdf_attachment =
 | |
|         build_pdf_attachment(
 | |
|           pdf: images_pdf,
 | |
|           submission:,
 | |
|           submitter:,
 | |
|           uuid: GenerateResultAttachments.images_pdf_uuid(original_documents.select(&:image?)),
 | |
|           values_hash:,
 | |
|           name: submission.name || template.name
 | |
|         )
 | |
| 
 | |
|       ApplicationRecord.no_touching do
 | |
|         (result_attachments + [images_pdf_attachment]).map { |e| e.tap(&:save!) }
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def build_values_hash(submission)
 | |
|       Digest::MD5.hexdigest(
 | |
|         submission.submitters.reduce({}) { |acc, s| acc.merge(s.values) }.to_json
 | |
|       )
 | |
|     end
 | |
| 
 | |
|     def build_submitter_values_hash(submitter)
 | |
|       submission = submitter.submission
 | |
| 
 | |
|       Digest::MD5.hexdigest(
 | |
|         submission.submitters.where.not(completed_at: nil).or(submission.submitters.where(id: submitter.id))
 | |
|                   .reduce({}) { |acc, s| acc.merge(s.values) }.to_json
 | |
|       )
 | |
|     end
 | |
| 
 | |
|     def build_pdf_attachment(pdf:, submission:, submitter:, uuid:, name:, values_hash:)
 | |
|       io = StringIO.new
 | |
| 
 | |
|       begin
 | |
|         pdf.write(io, incremental: true, validate: false)
 | |
|       rescue HexaPDF::MalformedPDFError => e
 | |
|         Rollbar.error(e) if defined?(Rollbar)
 | |
| 
 | |
|         pdf.write(io, incremental: false, validate: false)
 | |
|       end
 | |
| 
 | |
|       ActiveStorage::Attachment.new(
 | |
|         blob: ActiveStorage::Blob.create_and_upload!(io: io.tap(&:rewind), filename: "#{name}.pdf"),
 | |
|         io_data: io.string,
 | |
|         metadata: { original_uuid: uuid,
 | |
|                     values_hash:,
 | |
|                     analyzed: true,
 | |
|                     sha256: Base64.urlsafe_encode64(Digest::SHA256.digest(io.string)) },
 | |
|         name: 'preview_documents',
 | |
|         record: submitter || submission
 | |
|       )
 | |
|     end
 | |
|     # rubocop:enable Metrics
 | |
|   end
 | |
| end
 |