SU2-19 | Парсинг двух форм, пока без понимания того, что делать с расхожениями в данных (обе формы в одном файле)

This commit is contained in:
Dmitry
2026-03-21 15:26:37 +03:00
parent dcba938feb
commit 207e4b45a7
7 changed files with 473 additions and 66 deletions
+42 -65
View File
@@ -1,33 +1,18 @@
require 'roo'
class ReportParser
SHEET_NAME = 'Сведения об организации'
CELL_MAP = {
full_name: { row: 6, col: 13 },
inn: { row: 10, col: 13 },
kpp: { row: 11, col: 13 },
okpo: { row: 12, col: 13 },
okfs: { row: 13, col: 13 },
okopf: { row: 14, col: 13 },
okved2: { row: 15, col: 13 },
address: { row: 16, col: 13 }
}.freeze
AUDITOR_MAP = {
name: { row: 19, col: 13 },
inn: { row: 20, col: 13 },
ogrn: { row: 21, col: 13 }
}.freeze
def initialize(yearly_file)
@yearly_file = yearly_file
end
def call
ActiveRecord::Base.transaction do
parse_organization
parse_auditor
extract_year
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
merge_financial_statements(form_11_data, form_12_data)
end
end
@@ -43,56 +28,48 @@ class ReportParser
end
end
def info_sheet
@info_sheet ||= spreadsheet.sheet(SHEET_NAME)
end
def merge_financial_statements(form_11_data, form_12_data)
document_type = DocumentType.find_or_create_by!(name: 'Финансовые данные')
def read_cell(sheet, row, col)
value = sheet.cell(row, col)
value.is_a?(String) ? value.strip.presence : value
end
all_years = (form_11_data.keys + form_12_data.keys).uniq
def parse_organization
org_data = CELL_MAP.each_with_object({}) do |(attr, pos), hash|
hash[attr] = read_cell(info_sheet, pos[:row], pos[:col])
all_years.each do |year|
statement = find_or_build_statement(document_type, year)
all_rows = []
if form_11_data[year].present?
form_11_rows = form_11_data[year][:rows] || form_11_data[year]['rows'] || []
all_rows.concat(form_11_rows)
end
if form_12_data[year].present?
form_12_rows = form_12_data[year][:rows] || form_12_data[year]['rows'] || []
all_rows.concat(form_12_rows)
end
if all_rows.present?
payload = {
data_year: year,
rows: all_rows
}
statement.assign_attributes(data: payload)
statement.save!
end
end
organization = @yearly_file.organization
organization.update!(org_data)
organization
end
def parse_auditor
auditor_data = AUDITOR_MAP.each_with_object({}) do |(attr, pos), hash|
hash[attr] = read_cell(info_sheet, pos[:row], pos[:col])
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 if auditor_data[:name].blank?
return existing if existing
auditor_inn = auditor_data[:inn].to_s.strip
auditor = if auditor_inn.present?
Auditor.find_or_initialize_by(inn: auditor_inn)
else
Auditor.find_or_initialize_by(name: auditor_data[:name])
end
auditor.assign_attributes(
name: auditor_data[:name],
inn: auditor_inn.presence,
ogrn: auditor_data[:ogrn].to_s.strip.presence
)
auditor.save!
@yearly_file.update!(auditor: auditor)
auditor
end
def extract_year
balance_sheet = spreadsheet.sheet('Бухгалтерский баланс')
period_text = balance_sheet.cell(4, 1).to_s
year = period_text.match(/(\d{4})/)&.captures&.first&.to_i
@yearly_file.update!(year: year) if year
year
@yearly_file.financial_statements.new(document_type: document_type, sheet_number: year)
end
end