SU2-30 | добавлена фикс таблица для кодов, убрана таблица DocumentTypes, изменена структура jsonb
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
class OrganisationsController < ApplicationController
|
||||
before_action :set_organisation, only: [:show]
|
||||
|
||||
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
|
||||
organizations = Organization.all
|
||||
|
||||
@@ -19,53 +26,18 @@ class OrganisationsController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
doc_types = {
|
||||
0 => 'Бухгалтерский баланс',
|
||||
1 => 'Отчёт о финансовых результатах',
|
||||
2 => 'Отчёт об изменении капитала',
|
||||
3 => 'Отчет о движении денежных средств'
|
||||
}
|
||||
|
||||
@type_doc = params[:type_doc].present? ? params[:type_doc].to_i : 0
|
||||
|
||||
data = doc_types.each_with_object({}) do |(key, value), hash|
|
||||
hash[value] = Hash.new()
|
||||
end
|
||||
statements_by_year_and_form = build_statements_by_year_and_form
|
||||
years = statements_by_year_and_form.keys.sort.reverse
|
||||
grouped_rows = build_grouped_rows(statements_by_year_and_form, years)
|
||||
|
||||
doc_types.keys.each do |key|
|
||||
financial_statements = @org.financial_statements.order(sheet_number: :desc).where(document_type_id: key + 1)
|
||||
financial_statements.each do |financial_statement|
|
||||
financial_statement.data['rows'].each_with_index do |row, index|
|
||||
if index != 0
|
||||
if data[doc_types[key]][[row['line_name'], row['line_code']]].nil?
|
||||
data[doc_types[key]][[row['line_name'], row['line_code']]] = []
|
||||
end
|
||||
data[doc_types[key]][[row['line_name'], row['line_code']]] << row['value']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@info_about_organisation = build_organization_payload(years)
|
||||
|
||||
@info_about_organisation = {
|
||||
"Сведения об организации" => {
|
||||
"ИНН" => @org.inn,
|
||||
"Полное наименование юридического лица" => @org.full_name,
|
||||
"КПП" => @org.kpp,
|
||||
"Код по ОКПО" => @org.okpo,
|
||||
"Форма собственности (по ОКФС)" => @org.okfs,
|
||||
"Организационно-правовая форма (по ОКОПФ)" => @org.okopf,
|
||||
"Вид экономической деятельности по ОКВЭД 2" => @org.okved2,
|
||||
"Местонахождение (адрес)" => @org.address
|
||||
|
||||
},
|
||||
|
||||
"Бухгалтерский баланс" => ["Наименование показателя", "Код", "На 31 декабря 2024 г.", "На 31 декабря 2023 г.", "На 31 декабря 2022 г.", "На 31 декабря 2021 г.", "На 31 декабря 2020 г.", "На 31 декабря 2019 г."],
|
||||
"Отчёт о финансовых результатах" => ["Наименование показателя", "Код", "За 2024 г.", "За 2023 г.", "За 2022 г.", "За 2021 г.", "За 2020 г."]
|
||||
}
|
||||
|
||||
@doc_name = doc_types[@type_doc]
|
||||
selected_doc = DOC_TYPES.fetch(@type_doc, DOC_TYPES[0])
|
||||
@doc_name = selected_doc[:title]
|
||||
@current_doc_info = @info_about_organisation[@doc_name]
|
||||
@current_doc_info1 = data[@doc_name]
|
||||
@current_doc_info1 = grouped_rows[@doc_name]
|
||||
end
|
||||
|
||||
|
||||
@@ -74,4 +46,104 @@ class OrganisationsController < ApplicationController
|
||||
def set_organisation
|
||||
@org = Organization.find(params[:id])
|
||||
end
|
||||
|
||||
def build_organization_payload(years)
|
||||
payload = {
|
||||
'Сведения об организации' => {
|
||||
'ИНН' => @org.inn,
|
||||
'Полное наименование юридического лица' => @org.full_name,
|
||||
'КПП' => @org.kpp,
|
||||
'Код по ОКПО' => @org.okpo,
|
||||
'Форма собственности (по ОКФС)' => @org.okfs,
|
||||
'Организационно-правовая форма (по ОКОПФ)' => @org.okopf,
|
||||
'Вид экономической деятельности по ОКВЭД 2' => @org.okved2,
|
||||
'Местонахождение (адрес)' => @org.address
|
||||
}
|
||||
}
|
||||
|
||||
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 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
|
||||
@@ -1,5 +0,0 @@
|
||||
class DocumentType < ApplicationRecord
|
||||
has_many :financial_statements, dependent: :restrict_with_error
|
||||
|
||||
validates :name, presence: true
|
||||
end
|
||||
@@ -1,6 +1,5 @@
|
||||
class FinancialStatement < ApplicationRecord
|
||||
belongs_to :yearly_file
|
||||
belongs_to :document_type
|
||||
|
||||
validates :data, presence: true
|
||||
end
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
class ReportCode < ApplicationRecord
|
||||
validates :code, presence: true, uniqueness: true
|
||||
validates :name, presence: true
|
||||
end
|
||||
+126
-25
@@ -1,6 +1,27 @@
|
||||
require 'roo'
|
||||
|
||||
class ReportParser
|
||||
FORM_DEFINITIONS = {
|
||||
'1.1' => {
|
||||
parser: ReportParsers::Form11Parser,
|
||||
sheet_name: 'Бухгалтерский баланс'
|
||||
},
|
||||
'1.2' => {
|
||||
parser: ReportParsers::Form12Parser,
|
||||
sheet_name: 'Отчет о финансовых результатах'
|
||||
},
|
||||
'1.3' => {
|
||||
parser: nil,
|
||||
sheet_name: 'Отчет об изменениях капитала'
|
||||
},
|
||||
'1.4' => {
|
||||
parser: ReportParsers::Form14Parser,
|
||||
sheet_name: 'Отчет о движении денежных средств'
|
||||
}
|
||||
}.freeze
|
||||
|
||||
DEFAULT_MISSING_VALUE = '-'
|
||||
|
||||
def initialize(yearly_file)
|
||||
@yearly_file = yearly_file
|
||||
end
|
||||
@@ -9,13 +30,8 @@ class ReportParser
|
||||
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 - Отчет о движении денежных средств
|
||||
parsed_forms = parse_forms
|
||||
save_aggregated_statements(parsed_forms)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,34 +47,119 @@ class ReportParser
|
||||
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!
|
||||
def parse_forms
|
||||
FORM_DEFINITIONS.each_with_object({}) do |(form_code, config), hash|
|
||||
parser_class = config.fetch(:parser)
|
||||
hash[form_code] = parser_class ? parser_class.new(@yearly_file, spreadsheet: spreadsheet).call : {}
|
||||
end
|
||||
end
|
||||
|
||||
def find_or_build_statement(document_type, year)
|
||||
def save_aggregated_statements(parsed_forms)
|
||||
codes = report_codes
|
||||
return if codes.blank?
|
||||
|
||||
target_years = extract_target_years(parsed_forms)
|
||||
return if target_years.blank?
|
||||
|
||||
target_years.each do |year|
|
||||
statement = find_or_build_statement(year)
|
||||
if should_update_statement?(statement)
|
||||
statement.assign_attributes(
|
||||
yearly_file: @yearly_file,
|
||||
sheet_number: year,
|
||||
data: build_payload_for_year(year, parsed_forms, codes)
|
||||
)
|
||||
statement.save!
|
||||
end
|
||||
|
||||
cleanup_duplicate_statements(year, statement.id)
|
||||
end
|
||||
end
|
||||
|
||||
def extract_target_years(parsed_forms)
|
||||
years = parsed_forms.values.flat_map(&:keys).map(&:to_i).select(&:positive?).uniq
|
||||
years = [@yearly_file.year.to_i] if years.blank? && @yearly_file.year.to_i.positive?
|
||||
years.sort.reverse
|
||||
end
|
||||
|
||||
def build_payload_for_year(year, parsed_forms, codes)
|
||||
forms_payload = FORM_DEFINITIONS.each_with_object({}) do |(form_code, config), hash|
|
||||
form_data = parsed_forms.fetch(form_code, {})[year] || {}
|
||||
source_rows = form_data[:rows] || form_data['rows'] || []
|
||||
rows_by_code = index_rows_by_code(source_rows)
|
||||
|
||||
hash[form_code] = {
|
||||
form_code: form_code,
|
||||
sheet_name: form_data[:sheet_name] || form_data['sheet_name'] || config.fetch(:sheet_name),
|
||||
rows: codes.map do |report_code|
|
||||
source_row = rows_by_code[report_code.code]
|
||||
source_value = source_row && (source_row[:value] || source_row['value'])
|
||||
|
||||
{
|
||||
line_name: report_code.name,
|
||||
line_code: report_code.code,
|
||||
value: source_value.presence || DEFAULT_MISSING_VALUE
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
{
|
||||
data_year: year,
|
||||
forms: forms_payload
|
||||
}
|
||||
end
|
||||
|
||||
def index_rows_by_code(rows)
|
||||
rows.each_with_object({}) do |row, hash|
|
||||
normalized_code = normalize_code(row[:line_code] || row['line_code'])
|
||||
next if normalized_code.blank?
|
||||
|
||||
# Keep first non-blank value for duplicated codes inside one form/year.
|
||||
existing = hash[normalized_code]
|
||||
next if existing.present? && (existing[:value] || existing['value']).present?
|
||||
|
||||
hash[normalized_code] = row
|
||||
end
|
||||
end
|
||||
|
||||
def find_or_build_statement(year)
|
||||
existing = FinancialStatement
|
||||
.joins(:yearly_file)
|
||||
.where(document_type: document_type, sheet_number: year)
|
||||
.where(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)
|
||||
@yearly_file.financial_statements.new(sheet_number: year)
|
||||
end
|
||||
|
||||
def should_update_statement?(statement)
|
||||
return true if statement.new_record?
|
||||
|
||||
existing_source_year = statement.yearly_file&.year.to_i
|
||||
current_source_year = @yearly_file.year.to_i
|
||||
|
||||
existing_source_year <= current_source_year
|
||||
end
|
||||
|
||||
def normalize_code(value)
|
||||
value.to_s.scan(/\d+/).join.presence
|
||||
end
|
||||
|
||||
def report_codes
|
||||
@report_codes ||= ReportCode.order(:code).select(:code, :name).to_a
|
||||
end
|
||||
|
||||
def cleanup_duplicate_statements(year, keeper_id)
|
||||
FinancialStatement
|
||||
.joins(:yearly_file)
|
||||
.where(sheet_number: year)
|
||||
.where(yearly_files: { organization_id: @yearly_file.organization_id })
|
||||
.where.not(id: keeper_id)
|
||||
.delete_all
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
class CreateReportCodes < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
create_table :report_codes do |t|
|
||||
t.string :code, null: false
|
||||
t.string :name, null: false
|
||||
t.text :description, null: false, default: ''
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :report_codes, :code, unique: true
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,288 @@
|
||||
class SeedReportCodes < ActiveRecord::Migration[7.1]
|
||||
def up
|
||||
rows = [
|
||||
{ code: "1100", name: "Итого внеоборотных активов", description: "Сумма строк 1110, 1120, 1130, 1140, 1150" },
|
||||
{ code: "1105", name: "Гудвил", description: "-" },
|
||||
{ code: "1110", name: "Нематериальные активы", description: "-" },
|
||||
{ code: "1130", name: "Нематериальные поисковые активы", description: "-" },
|
||||
{ code: "1140", name: "Материальные поисковые активы", description: "-" },
|
||||
{ code: "1150", name: "Основные средства", description: "-" },
|
||||
{ code: "1160", name: "Инвестиционная недвижимость", description: "-" },
|
||||
{ code: "1170", name: "Финансовые вложения", description: "-" },
|
||||
{ code: "1180", name: "Отложенные налоговые активы", description: "-" },
|
||||
{ code: "1190", name: "Прочие внеоборотные активы", description: "-" },
|
||||
{ code: "1200", name: "Итого оборотных активов", description: "-" },
|
||||
{ code: "1210", name: "Запасы", description: "-" },
|
||||
{ code: "1215", name: "Долгосрочные активы к продаже", description: "-" },
|
||||
{ code: "1220", name: "Налог на добавленную стоимость по приобретенным ценностям", description: "-" },
|
||||
{ code: "1230", name: "Дебиторская задолженность", description: "-" },
|
||||
{ code: "1240", name: "Финансовые вложения (за исключением денежных эквивалентов)", description: "-" },
|
||||
{ code: "1250", name: "Денежные средства и денежные эквиваленты", description: "-" },
|
||||
{ code: "1260", name: "Прочие оборотные активы", description: "-" },
|
||||
{ code: "1600", name: "БАЛАНС (актив)", description: "-" },
|
||||
{ code: "1300", name: "Итого капитал/Итого целевое финансирование (в некоммерческой организации)", description: "-" },
|
||||
{ code: "1310", name: "Уставный капитал/Паевой фонд (в некоммерческой организации)", description: "-" },
|
||||
{ code: "1320", name: "Собственные акции, принадлежащие обществу, задолженность акционеров по оплате акций/Целевой капитал (в некоммерческой организации)", description: "-" },
|
||||
{ code: "1330", name: "Целевые средства (в некоммерческой организации)", description: "-" },
|
||||
{ code: "1340", name: "Накопленная дооценка внеоборотных активов", description: "-" },
|
||||
{ code: "1350", name: "Добавочный капитал (без накопленной дооценки)", description: "-" },
|
||||
{ code: "1360", name: "Резервный капитал/Фонд недвижимого и особо ценного движимого имущества (в некоммерческой организации)", description: "-" },
|
||||
{ code: "1370", name: "Нераспределенная прибыль (непокрытый убыток)/Резервный и иные целевые фонды (в некоммерческой организации)", description: "-" },
|
||||
{ code: "1400", name: "Итого долгосрочных обязательств", description: "-" },
|
||||
{ code: "1410", name: "Долгосрочные заемные средства", description: "-" },
|
||||
{ code: "1420", name: "Отложенные налоговые обязательства", description: "-" },
|
||||
{ code: "1430", name: "Долгосрочные оценочные обязательства", description: "-" },
|
||||
{ code: "1450", name: "Прочие долгосрочные обязательства", description: "-" },
|
||||
{ code: "1500", name: "Итого краткосрочных обязательств", description: "-" },
|
||||
{ code: "1510", name: "Краткосрочные заемные средства", description: "-" },
|
||||
{ code: "1520", name: "Краткосрочная кредиторская задолженность", description: "-" },
|
||||
{ code: "1530", name: "Доходы будущих периодов", description: "-" },
|
||||
{ code: "1540", name: "Краткосрочные оценочные обязательства", description: "-" },
|
||||
{ code: "1550", name: "Прочие краткосрочные обязательства", description: "-" },
|
||||
{ code: "2110", name: "Выручка", description: "-" },
|
||||
{ code: "2120", name: "Себестоимость продаж", description: "-" },
|
||||
{ code: "2100", name: "Валовая прибыль (убыток)", description: "-" },
|
||||
{ code: "2210", name: "Коммерческие расходы", description: "-" },
|
||||
{ code: "2220", name: "Управленческие расходы", description: "-" },
|
||||
{ code: "2200", name: "Прибыль (убыток) от продаж", description: "-" },
|
||||
{ code: "2310", name: "Доходы от участия в других организациях", description: "-" },
|
||||
{ code: "2320", name: "Проценты к получению", description: "-" },
|
||||
{ code: "2330", name: "Проценты к уплате", description: "-" },
|
||||
{ code: "2340", name: "Прочие доходы", description: "-" },
|
||||
{ code: "2350", name: "Прочие расходы", description: "-" },
|
||||
{ code: "2300", name: "Прибыль (убыток) от продолжающейся деятельности до налогообложения", description: "-" },
|
||||
{ code: "2410", name: "Налог на прибыль организаций", description: "-" },
|
||||
{ code: "2411", name: "текущий налог на прибыль организаций", description: "в том числе" },
|
||||
{ code: "2412", name: "отложенный налог на прибыль организаций", description: "в том числе" },
|
||||
{ code: "2420", name: "Прибыль (убыток) от прекращаемой деятельности (за вычетом относящегося к ней налога на прибыль организаций)", description: "-" },
|
||||
{ code: "2460", name: "Прочее", description: "-" },
|
||||
{ code: "2400", name: "Чистая прибыль (убыток)", description: "-" },
|
||||
{ code: "2510", name: "Результат от переоценки внеоборотных активов, не включаемый в чистую прибыль (убыток)", description: "-" },
|
||||
{ code: "2520", name: "Результат от прочих операций, не включаемый в чистую прибыль (убыток)", description: "-" },
|
||||
{ code: "2530", name: "Налог на прибыль организаций, относящийся к результатам переоценки внеоборотных активов и прочих операций, не включаемых в чистую прибыль (убыток)", description: "-" },
|
||||
{ code: "2500", name: "Совокупный финансовый результат", description: "-" },
|
||||
{ code: "2900", name: "Базовая прибыль (убыток) на акцию", description: "-" },
|
||||
{ code: "2910", name: "Разводненная прибыль (убыток) на акцию", description: "-" },
|
||||
{ code: "3100", name: "Величина капитала на 31 декабря года, предшествующего предыдущему", description: "-" },
|
||||
{ code: "3110", name: "Корректировка в связи с изменением учетной политики", description: "-" },
|
||||
{ code: "3120", name: "Корректировка в связи с исправлением ошибок", description: "-" },
|
||||
{ code: "3101", name: "Величина капитала на 31 декабря года, предшествующего предыдущему, после корректировки", description: "-" },
|
||||
{ code: "3211", name: "Чистая прибыль (убыток)", description: "-" },
|
||||
{ code: "3212", name: "Переоценка внеоборотных активов", description: "-" },
|
||||
{ code: "3227", name: "Дивиденды", description: "-" },
|
||||
{ code: "3230", name: "Иные изменения за счет операций с собственниками (за исключением дивидендов) - всего", description: "-" },
|
||||
{ code: "3216", name: "Реорганизация юридического лица", description: "-" },
|
||||
{ code: "3240", name: "Иные изменения - всего", description: "-" },
|
||||
{ code: "3250", name: "Величина капитала на дату окончания периода предыдущего года, аналогичного отчетному периоду", description: "-" },
|
||||
{ code: "3200", name: "Величина капитала на 31 декабря предыдущего года", description: "-" },
|
||||
{ code: "3210", name: "Корректировка в связи с изменением учетной политики", description: "-" },
|
||||
{ code: "3220", name: "Корректировка в связи с исправлением ошибок", description: "-" },
|
||||
{ code: "3201", name: "Величина капитала на 31 декабря предыдущего года после корректировки", description: "-" },
|
||||
{ code: "3311", name: "Чистая прибыль (убыток)", description: "-" },
|
||||
{ code: "3312", name: "Переоценка внеоборотных активов", description: "-" },
|
||||
{ code: "3327", name: "Дивиденды", description: "-" },
|
||||
{ code: "3330", name: "Иные изменения за счет операций с собственниками (за исключением дивидендов) - всего", description: "-" },
|
||||
{ code: "3316", name: "Реорганизация юридического лица", description: "-" },
|
||||
{ code: "3340", name: "Иные изменения - всего", description: "-" },
|
||||
{ code: "3300", name: "Величина капитала на отчетную дату", description: "-" },
|
||||
{ code: "4110", name: "Поступления - всего", description: "-" },
|
||||
{ code: "4111", name: "От продажи продукции, товаров, выполнения работ, оказания услуг", description: "-" },
|
||||
{ code: "4112", name: "Арендных платежей, роялти, комиссионных и иных аналогичных платежей", description: "в-" },
|
||||
{ code: "4113", name: "От перепродажи финансовых вложений", description: "-" },
|
||||
{ code: "4114", name: "Процентов по дебиторской задолженности покупателей", description: "-" },
|
||||
{ code: "4119", name: "Прочие поступления", description: "-" },
|
||||
{ code: "4120", name: "Платежи - всего", description: "-" },
|
||||
{ code: "4121", name: "Поставщикам (подрядчикам) за сырье, материалы, выполненные работы, оказанные услуги", description: "в-" },
|
||||
{ code: "4122", name: "В связи с оплатой труда работников", description: "-" },
|
||||
{ code: "4123", name: "Процентов по долговым обязательствам", description: "-" },
|
||||
{ code: "4124", name: "Налога на прибыль организаций", description: "-" },
|
||||
{ code: "4129", name: "Прочие платежи", description: "-" },
|
||||
{ code: "4100", name: "Сальдо денежных потоков от текущих операций", description: "-" },
|
||||
{ code: "4210", name: "Поступления - всего", description: "-" },
|
||||
{ code: "4211", name: "От продажи внеоборотных активов (кроме финансовых вложений)", description: "-" },
|
||||
{ code: "4212", name: "От продажи акций других организаций (долей участия)", description: "-" },
|
||||
{ code: "4213", name: "От возврата предоставленных займов, от продажи долговых ценных бумаг (прав требования денежных средств к другим лицам)", description: "-" },
|
||||
{ code: "4214", name: "Дивидендов, процентов по долговым финансовым вложениям и аналогичных поступлений от долевого участия в других организациях", description: "-" },
|
||||
{ code: "4219", name: "Прочие поступления", description: "-" },
|
||||
{ code: "4220", name: "Платежи - всего", description: "-" },
|
||||
{ code: "4221", name: "В связи с приобретением, созданием, модернизацией, реконструкцией и подготовкой к использованию внеоборотных активов", description: "-" },
|
||||
{ code: "4222", name: "В связи с приобретением акций других организаций (долей участия)", description: "-" },
|
||||
{ code: "4223", name: "В связи с приобретением долговых ценных бумаг (прав требования денежных средств к другим лицам), предоставление займов другим лицам", description: "-" },
|
||||
{ code: "4224", name: "Процентов по долговым обязательствам, включаемым в стоимость инвестиционного актива", description: "-" },
|
||||
{ code: "4229", name: "Прочие платежи", description: "-" },
|
||||
{ code: "4200", name: "Сальдо денежных потоков от инвестиционных операций", description: "-" },
|
||||
{ code: "4310", name: "Поступления - всего", description: "-" },
|
||||
{ code: "4311", name: "Получение кредитов и займов", description: "-" },
|
||||
{ code: "4312", name: "Денежных вкладов собственников (участников)", description: "-" },
|
||||
{ code: "4313", name: "От выпуска акций, увеличения долей участия", description: "-" },
|
||||
{ code: "4314", name: "От выпуска облигаций, векселей и других долговых ценных бумаг", description: "-" },
|
||||
{ code: "4319", name: "Прочие поступления", description: "-" },
|
||||
{ code: "4320", name: "Платежи - всего", description: "-" },
|
||||
{ code: "4321", name: "Собственникам (участникам) в связи с выкупом у них акций (долей участия) организации или их выходом из состава участников", description: "-" },
|
||||
{ code: "4322", name: "На уплату дивидендов и иных платежей по распределению прибыли в пользу собственников (участников)", description: "-" },
|
||||
{ code: "4323", name: "В связи с погашением (выкупом) векселей и других долговых ценных бумаг, возврат кредитов и займов", description: "-" },
|
||||
{ code: "4329", name: "Прочие платежи", description: "-" },
|
||||
{ code: "4300", name: "Сальдо денежных потоков от финансовых операций", description: "-" },
|
||||
{ code: "4400", name: "Сальдо денежных потоков за период", description: "-" },
|
||||
{ code: "4450", name: "Остаток денежных средств и денежных эквивалентов на начало периода", description: "-" },
|
||||
{ code: "4500", name: "Остаток денежных средств и денежных эквивалентов на конец периода", description: "-" },
|
||||
{ code: "4490", name: "Величина влияния изменения курса иностранной валюты по отношению к рублю", description: "-" }
|
||||
]
|
||||
|
||||
return if rows.empty?
|
||||
|
||||
rows.each do |row|
|
||||
execute <<~SQL
|
||||
INSERT INTO report_codes (code, name, description, created_at, updated_at)
|
||||
VALUES (
|
||||
#{connection.quote(row.fetch(:code))},
|
||||
#{connection.quote(row.fetch(:name))},
|
||||
#{connection.quote(row.fetch(:description, ''))},
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (code)
|
||||
DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
description = EXCLUDED.description,
|
||||
updated_at = NOW();
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
codes = [
|
||||
"1100",
|
||||
"1105",
|
||||
"1110",
|
||||
"1130",
|
||||
"1140",
|
||||
"1150",
|
||||
"1160",
|
||||
"1170",
|
||||
"1180",
|
||||
"1190",
|
||||
"1200",
|
||||
"1210",
|
||||
"1215",
|
||||
"1220",
|
||||
"1230",
|
||||
"1240",
|
||||
"1250",
|
||||
"1260",
|
||||
"1600",
|
||||
"1300",
|
||||
"1310",
|
||||
"1320",
|
||||
"1330",
|
||||
"1340",
|
||||
"1350",
|
||||
"1360",
|
||||
"1370",
|
||||
"1400",
|
||||
"1410",
|
||||
"1420",
|
||||
"1430",
|
||||
"1450",
|
||||
"1500",
|
||||
"1510",
|
||||
"1520",
|
||||
"1530",
|
||||
"1540",
|
||||
"1550",
|
||||
"2110",
|
||||
"2120",
|
||||
"2100",
|
||||
"2210",
|
||||
"2220",
|
||||
"2200",
|
||||
"2310",
|
||||
"2320",
|
||||
"2330",
|
||||
"2340",
|
||||
"2350",
|
||||
"2300",
|
||||
"2410",
|
||||
"2411",
|
||||
"2412",
|
||||
"2420",
|
||||
"2460",
|
||||
"2400",
|
||||
"2510",
|
||||
"2520",
|
||||
"2530",
|
||||
"2500",
|
||||
"2900",
|
||||
"2910",
|
||||
"3100",
|
||||
"3110",
|
||||
"3120",
|
||||
"3101",
|
||||
"3211",
|
||||
"3212",
|
||||
"3227",
|
||||
"3230",
|
||||
"3216",
|
||||
"3240",
|
||||
"3250",
|
||||
"3200",
|
||||
"3210",
|
||||
"3220",
|
||||
"3201",
|
||||
"3311",
|
||||
"3312",
|
||||
"3327",
|
||||
"3330",
|
||||
"3316",
|
||||
"3340",
|
||||
"3300",
|
||||
"4110",
|
||||
"4111",
|
||||
"4112",
|
||||
"4113",
|
||||
"4114",
|
||||
"4119",
|
||||
"4120",
|
||||
"4121",
|
||||
"4122",
|
||||
"4123",
|
||||
"4124",
|
||||
"4129",
|
||||
"4100",
|
||||
"4210",
|
||||
"4211",
|
||||
"4212",
|
||||
"4213",
|
||||
"4214",
|
||||
"4219",
|
||||
"4220",
|
||||
"4221",
|
||||
"4222",
|
||||
"4223",
|
||||
"4224",
|
||||
"4229",
|
||||
"4200",
|
||||
"4310",
|
||||
"4311",
|
||||
"4312",
|
||||
"4313",
|
||||
"4314",
|
||||
"4319",
|
||||
"4320",
|
||||
"4321",
|
||||
"4322",
|
||||
"4323",
|
||||
"4329",
|
||||
"4300",
|
||||
"4400",
|
||||
"4450",
|
||||
"4500",
|
||||
"4490"
|
||||
]
|
||||
|
||||
return if codes.empty?
|
||||
|
||||
quoted_codes = codes.map { |code| connection.quote(code) }.join(', ')
|
||||
execute "DELETE FROM report_codes WHERE code IN (#{quoted_codes});"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
class RemoveDocumentTypesFromFinancialStatements < ActiveRecord::Migration[7.1]
|
||||
def up
|
||||
remove_index :financial_statements, name: 'index_fs_on_yearly_file_doc_type_sheet', if_exists: true
|
||||
remove_index :financial_statements, :document_type_id, if_exists: true
|
||||
|
||||
remove_foreign_key :financial_statements, :document_types if foreign_key_exists?(:financial_statements, :document_types)
|
||||
remove_column :financial_statements, :document_type_id if column_exists?(:financial_statements, :document_type_id)
|
||||
|
||||
add_index :financial_statements,
|
||||
[:yearly_file_id, :sheet_number],
|
||||
name: 'index_fs_on_yearly_file_sheet',
|
||||
unique: true,
|
||||
if_not_exists: true
|
||||
|
||||
drop_table :document_types, if_exists: true
|
||||
end
|
||||
|
||||
def down
|
||||
create_table :document_types do |t|
|
||||
t.string :name, null: false
|
||||
|
||||
t.timestamps
|
||||
end unless table_exists?(:document_types)
|
||||
|
||||
add_column :financial_statements, :document_type_id, :bigint unless column_exists?(:financial_statements, :document_type_id)
|
||||
|
||||
add_foreign_key :financial_statements, :document_types unless foreign_key_exists?(:financial_statements, :document_types)
|
||||
|
||||
add_index :financial_statements, :document_type_id, if_not_exists: true
|
||||
|
||||
remove_index :financial_statements, name: 'index_fs_on_yearly_file_sheet', if_exists: true
|
||||
|
||||
add_index :financial_statements,
|
||||
[:yearly_file_id, :document_type_id, :sheet_number],
|
||||
name: 'index_fs_on_yearly_file_doc_type_sheet',
|
||||
unique: true,
|
||||
if_not_exists: true
|
||||
end
|
||||
end
|
||||
Generated
+11
-11
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.1].define(version: 2026_03_25_063000) do
|
||||
ActiveRecord::Schema[7.1].define(version: 2026_04_18_113000) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@@ -51,21 +51,13 @@ ActiveRecord::Schema[7.1].define(version: 2026_03_25_063000) do
|
||||
t.index ["inn"], name: "index_auditors_on_inn"
|
||||
end
|
||||
|
||||
create_table "document_types", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "financial_statements", force: :cascade do |t|
|
||||
t.bigint "yearly_file_id", null: false
|
||||
t.bigint "document_type_id", null: false
|
||||
t.integer "sheet_number"
|
||||
t.jsonb "data", default: {}
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["document_type_id"], name: "index_financial_statements_on_document_type_id"
|
||||
t.index ["yearly_file_id", "document_type_id", "sheet_number"], name: "index_fs_on_yearly_file_doc_type_sheet", unique: true
|
||||
t.index ["yearly_file_id", "sheet_number"], name: "index_fs_on_yearly_file_sheet", unique: true
|
||||
t.index ["yearly_file_id"], name: "index_financial_statements_on_yearly_file_id"
|
||||
end
|
||||
|
||||
@@ -83,6 +75,15 @@ ActiveRecord::Schema[7.1].define(version: 2026_03_25_063000) do
|
||||
t.index ["inn"], name: "index_organizations_on_inn"
|
||||
end
|
||||
|
||||
create_table "report_codes", force: :cascade do |t|
|
||||
t.string "code", null: false
|
||||
t.string "name", null: false
|
||||
t.text "description", default: "", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["code"], name: "index_report_codes_on_code", unique: true
|
||||
end
|
||||
|
||||
create_table "reports", force: :cascade do |t|
|
||||
t.string "inn"
|
||||
t.string "status"
|
||||
@@ -129,7 +130,6 @@ ActiveRecord::Schema[7.1].define(version: 2026_03_25_063000) do
|
||||
|
||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "financial_statements", "document_types"
|
||||
add_foreign_key "financial_statements", "yearly_files"
|
||||
add_foreign_key "yearly_files", "auditors"
|
||||
add_foreign_key "yearly_files", "organizations"
|
||||
|
||||
Reference in New Issue
Block a user