# frozen_string_literal: true # Will generate a ZIP archive file containing all invoicing data for the given period. # This file will be asynchronously generated by sidekiq and a notification will be sent to the requesting user when it's done. class ArchiveWorker include Sidekiq::Worker def perform(accounting_period_id) period = AccountingPeriod.find(accounting_period_id) data = period.invoices.includes(:invoice_items).order(id: :asc) previous_file = period.previous_period&.archive_file last_archive_checksum = previous_file ? Checksum.file(previous_file) : nil json_data = to_json_archive(period, data, previous_file, last_archive_checksum) current_archive_checksum = Checksum.text(json_data) date = DateTime.iso8601 chained = Checksum.text("#{current_archive_checksum}#{last_archive_checksum}#{date}") Zip::OutputStream.open(period.archive_file) do |io| io.put_next_entry(period.archive_json_file) io.write(json_data) io.put_next_entry('checksum.sha256') io.write("#{current_archive_checksum}\t#{period.archive_json_file}") io.put_next_entry('chained.sha256') io.write("#{chained}\t#{date}") end NotificationCenter.call type: :notify_admin_archive_complete, receiver: User.find(period.closed_by), attached_object: period end private def to_json_archive(period, invoices, previous_file, last_checksum) code_checksum = Checksum.code ApplicationController.new.view_context.render( partial: 'archive/accounting', locals: { invoices: period.invoices_with_vat(invoices), period_total: period.period_total, perpetual_total: period.perpetual_total, period_footprint: period.footprint, code_checksum: code_checksum, last_archive_checksum: last_checksum, previous_file: previous_file, software_version: Version.current, date: DateTime.current.iso8601 }, formats: [:json], handlers: [:jbuilder] ) end end