class OrganisationsController < ApplicationController before_action :set_organisation, only: [:show, :destroy, :reload] DOC_TYPES = { 0 => { title: 'Бухгалтерский баланс', form_code: '1.1' }, 1 => { title: 'Отчёт о финансовых результатах', form_code: '1.2' }, 2 => { title: 'Отчёт об изменении капитала', form_code: '1.3' }, 3 => { title: 'Отчёт о движении денежных средств', form_code: '1.4' } }.freeze def index @pagy, organizations = pagy(Organization.order(:created_at)) @info_about_organisations = organizations.each_with_object({}) do |org, hash| hash[org.id] = { "ИНН" => org.inn, "Полное наименование юридического лица" => org.full_name, # "КПП" => org.kpp, # "Код по ОКПО" => org.okpo, # "Форма собственности (по ОКФС)" => org.okfs, # "Организационно-правовая форма (по ОКОПФ)" => org.okopf, # "Вид экономической деятельности по ОКВЭД 2" => org.okved2, # "Местонахождение (адрес)" => org.address } end end def show @type_doc = params[:type_doc].present? ? params[:type_doc].to_i : 0 statements_by_year_and_form = build_statements_by_year_and_form years = statements_by_year_and_form.keys.sort.reverse grouped_rows = clean_data(build_grouped_rows(statements_by_year_and_form, years)) @info_about_organisation = build_organization_payload(years) selected_doc = DOC_TYPES.fetch(@type_doc, DOC_TYPES[0]) @doc_name = selected_doc[:title] @current_doc_info1 = grouped_rows[@doc_name] if !@current_doc_info1.values.first.nil? @current_doc_info = @info_about_organisation[@doc_name][0..@current_doc_info1.values.first.size + 1] end end def destroy @org.destroy! redirect_to '/organisations/index', notice: "Организация #{@org.inn} удалена" end def reload report = Report.create!(inn: @org.inn, status: 'processing') FileProcessorJob.perform_async(@org.inn, report.id) redirect_to "/organisations/#{@org.id}", notice: 'Данные обновляются в фоне' end private def set_organisation @org = Organization.find(params[:id]) end def build_organization_payload(years) russian_names = { 'inn' => 'ИНН', 'full_name' => 'Полное наименование юридического лица', 'kpp' => 'КПП', 'okpo' => 'Код по ОКПО', 'okfs' => 'Форма собственности (по ОКФС)', 'okopf' => 'Организационно-правовая форма (по ОКОПФ)', 'okved2' => 'Вид экономической деятельности по ОКВЭД 2', 'address' => 'Местонахождение (адрес)' } payload = { 'Сведения об организации' => @org.attributes.filter_map { |key, value| [russian_names[key], value] \ if !['id', 'created_at', 'updated_at'].include?(key) && !value.nil? }.to_h } DOC_TYPES.each_value do |doc_type| payload[doc_type[:title]] = ['Наименование показателя', 'Код'] + years.map do |year| column_header_for(doc_type[:form_code], year) end end payload end def build_grouped_rows(statements_by_year_and_form, years) data = DOC_TYPES.each_with_object({}) do |(_, doc_type), hash| hash[doc_type[:title]] = {} end years.each do |year| DOC_TYPES.each_value do |doc_type| statement = statements_by_year_and_form.dig(year, doc_type[:form_code]) rows = statement ? extract_rows(statement, doc_type[:form_code]) : [] rows.each do |row| line_name = row['line_name'] || row[:line_name] line_code = row['line_code'] || row[:line_code] next if line_name.blank? && line_code.blank? key = [line_name, line_code] data[doc_type[:title]][key] ||= [] data[doc_type[:title]][key] << (row['value'] || row[:value] || '-') end end end data end def clean_data(data) data.transform_values do |doc_type_data| rows = doc_type_data.reject do |_, values| values.all? { |value| value == "-" || value.nil? || value == ""} end next {} if rows.empty? column_count = rows.values.map(&:size).max columns_to_keep = (0...column_count).select do |i| rows.values.any? { |values| values[i] != "-" && !values[i].nil? && values[i] != ""} end rows.transform_values do |values| columns_to_keep.map { |i| values[i]} end end end def build_statements_by_year_and_form grouped = Hash.new { |hash, key| hash[key] = {} } @org.financial_statements.includes(:yearly_file).each do |statement| year = statement.sheet_number.to_i next unless year.positive? next unless unified_statement?(statement) DOC_TYPES.each_value do |doc_type| form_code = doc_type[:form_code] next if extract_rows(statement, form_code).blank? current = grouped[year][form_code] grouped[year][form_code] = statement if better_statement?(statement, current) end end grouped end def better_statement?(candidate, current) return true if current.nil? candidate_source_year = candidate.yearly_file&.year.to_i current_source_year = current.yearly_file&.year.to_i return true if candidate_source_year > current_source_year return false if candidate_source_year < current_source_year candidate.updated_at > current.updated_at end def unified_statement?(statement) forms = statement.data.is_a?(Hash) ? (statement.data['forms'] || statement.data[:forms]) : nil forms.is_a?(Hash) end def extract_rows(statement, form_code) forms = statement.data['forms'] || statement.data[:forms] || {} form_payload = forms[form_code] || forms[form_code.to_sym] || {} rows = form_payload['rows'] || form_payload[:rows] || [] return rows if rows.is_a?(Array) [] end def column_header_for(form_code, year) return "На 31 декабря #{year} г." if form_code == '1.1' "За #{year} г." end end