require 'roo' class ReportParser def initialize(yearly_file) @yearly_file = yearly_file end def call ActiveRecord::Base.transaction do ReportParsers::OrganizationInfoParser.new(@yearly_file, spreadsheet: spreadsheet).call form_11_data = ReportParsers::Form11Parser.new(@yearly_file, spreadsheet: spreadsheet).call form_12_data = ReportParsers::Form12Parser.new(@yearly_file, spreadsheet: spreadsheet).call form_14_data = ReportParsers::Form14Parser.new(@yearly_file, spreadsheet: spreadsheet).call save_form_statements(form_11_data, 1) # 1 - Бух. баланс save_form_statements(form_12_data, 2) # 2 - Отчет о фин. результатах save_form_statements(form_14_data, 4) # 4 - Отчет о движении денежных средств end end private def spreadsheet @spreadsheet ||= begin tempfile = Tempfile.new(['report', '.xlsx']) tempfile.binmode @yearly_file.file.download { |chunk| tempfile.write(chunk) } tempfile.rewind Roo::Excelx.new(tempfile.path) end end def save_form_statements(form_data, form_id) document_type = DocumentType.find_by(id: form_id) raise "DocumentType with id=#{form_id} not found!" unless document_type form_data.each do |year, data| rows = data[:rows] || data['rows'] || [] next if rows.blank? statement = find_or_build_statement(document_type, year) payload = { data_year: year, rows: rows } statement.assign_attributes(data: payload) statement.save! end end def find_or_build_statement(document_type, year) existing = FinancialStatement .joins(:yearly_file) .where(document_type: document_type, sheet_number: year) .where(yearly_files: { organization_id: @yearly_file.organization_id }) .order('yearly_files.year DESC NULLS LAST, financial_statements.updated_at DESC') .first return existing if existing @yearly_file.financial_statements.new(document_type: document_type, sheet_number: year) end end