Merge branch 'fix/SU2-26' of DAAntipenko/finreport-analyzer into develop
This commit is contained in:
@@ -2,6 +2,8 @@ module ReportParsers
|
|||||||
class Form11Parser < BaseParser
|
class Form11Parser < BaseParser
|
||||||
SHEET_NAME = 'Бухгалтерский баланс'
|
SHEET_NAME = 'Бухгалтерский баланс'
|
||||||
FORM_CODE = '1.1'
|
FORM_CODE = '1.1'
|
||||||
|
# Add line codes or names that should be skipped during parsing.
|
||||||
|
IGNORED_KEYS = [2].freeze
|
||||||
|
|
||||||
def call
|
def call
|
||||||
return {} unless sheet_exists?(SHEET_NAME)
|
return {} unless sheet_exists?(SHEET_NAME)
|
||||||
@@ -27,6 +29,7 @@ module ReportParsers
|
|||||||
all_rows = (header_row + 1).upto(sheet.last_row).filter_map do |row|
|
all_rows = (header_row + 1).upto(sheet.last_row).filter_map do |row|
|
||||||
line_name = read_cell(sheet, row, columns[:name_column])
|
line_name = read_cell(sheet, row, columns[:name_column])
|
||||||
line_code = read_cell(sheet, row, columns[:code_column]).to_s.strip.presence
|
line_code = read_cell(sheet, row, columns[:code_column]).to_s.strip.presence
|
||||||
|
next if ignored_row?(line_name, line_code)
|
||||||
|
|
||||||
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
||||||
value = read_cell(sheet, row, col)
|
value = read_cell(sheet, row, col)
|
||||||
@@ -124,5 +127,14 @@ module ReportParsers
|
|||||||
year = period_text[/\d{4}/].to_i
|
year = period_text[/\d{4}/].to_i
|
||||||
yearly_file.update!(year: year) if year.positive?
|
yearly_file.update!(year: year) if year.positive?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ignored_row?(line_name, line_code)
|
||||||
|
keys = [line_code, line_name].compact.map { |value| normalize_label(value) }
|
||||||
|
keys.any? { |key| ignored_keys.include?(key) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignored_keys
|
||||||
|
@ignored_keys ||= IGNORED_KEYS.map { |value| normalize_label(value) }.to_set
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ module ReportParsers
|
|||||||
class Form12Parser < BaseParser
|
class Form12Parser < BaseParser
|
||||||
SHEET_NAME = 'Отчет о финансовых результатах'
|
SHEET_NAME = 'Отчет о финансовых результатах'
|
||||||
FORM_CODE = '1.2'
|
FORM_CODE = '1.2'
|
||||||
|
# Add line codes or names that should be skipped during parsing.
|
||||||
|
IGNORED_KEYS = [2].freeze
|
||||||
|
|
||||||
def call
|
def call
|
||||||
return {} unless sheet_exists?(SHEET_NAME)
|
return {} unless sheet_exists?(SHEET_NAME)
|
||||||
@@ -25,6 +27,7 @@ module ReportParsers
|
|||||||
all_rows = (header_row + 1).upto(sheet.last_row).filter_map do |row|
|
all_rows = (header_row + 1).upto(sheet.last_row).filter_map do |row|
|
||||||
line_name = read_cell(sheet, row, columns[:name_column])
|
line_name = read_cell(sheet, row, columns[:name_column])
|
||||||
line_code = read_cell(sheet, row, columns[:code_column]).to_s.strip.presence
|
line_code = read_cell(sheet, row, columns[:code_column]).to_s.strip.presence
|
||||||
|
next if ignored_row?(line_name, line_code)
|
||||||
|
|
||||||
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
||||||
value = read_cell(sheet, row, col)
|
value = read_cell(sheet, row, col)
|
||||||
@@ -110,5 +113,14 @@ module ReportParsers
|
|||||||
value_columns: value_columns
|
value_columns: value_columns
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ignored_row?(line_name, line_code)
|
||||||
|
keys = [line_code, line_name].compact.map { |value| normalize_label(value) }
|
||||||
|
keys.any? { |key| ignored_keys.include?(key) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignored_keys
|
||||||
|
@ignored_keys ||= IGNORED_KEYS.map { |value| normalize_label(value) }.to_set
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,51 +1,9 @@
|
|||||||
def extract_year_from_header(header_text)
|
|
||||||
year_match = header_text[/\b(20\d{2})\b/]
|
|
||||||
year_match.to_i if year_match
|
|
||||||
end
|
|
||||||
def find_header_row(sheet)
|
|
||||||
1.upto(sheet.last_row) do |row|
|
|
||||||
normalized_cells = 1.upto(sheet.last_column).map { |col| normalize_label(sheet.cell(row, col)) }
|
|
||||||
has_name = normalized_cells.any? { |text| text.include?("наименование показателя") }
|
|
||||||
has_code = normalized_cells.any? { |text| text == "код" || text.start_with?("код ") || text.start_with?("код:") }
|
|
||||||
return row if has_name && has_code
|
|
||||||
end
|
|
||||||
|
|
||||||
1
|
|
||||||
end
|
|
||||||
|
|
||||||
def detect_columns(sheet, header_row)
|
|
||||||
columns = 1.upto(sheet.last_column).each_with_object({}) do |col, hash|
|
|
||||||
hash[col] = normalize_label(sheet.cell(header_row, col))
|
|
||||||
end
|
|
||||||
|
|
||||||
name_column = columns.key(columns.values.find { |text| text.include?("наименование показателя") }) || 1
|
|
||||||
|
|
||||||
code_column = columns.key(columns.values.find { |text|
|
|
||||||
text == "код строки" || text.start_with?("код строки ") ||
|
|
||||||
(text == "код" && columns[name_column + 1] == text)
|
|
||||||
}) || columns.key(columns.values.find { |text| text == "код" || text.start_with?("код ") }) || [name_column + 1, sheet.last_column].min
|
|
||||||
|
|
||||||
value_columns = columns.keys.select do |col|
|
|
||||||
text = columns[col]
|
|
||||||
next false if text.include?("поясн")
|
|
||||||
text.match?(/20\d{2}/) || text.include?("за ") || text.include?("на ")
|
|
||||||
end
|
|
||||||
value_columns = value_columns.sort.last(2)
|
|
||||||
|
|
||||||
{
|
|
||||||
name_column: name_column,
|
|
||||||
code_column: code_column,
|
|
||||||
value_columns: value_columns
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def normalize_label(text)
|
|
||||||
text.to_s.downcase.gsub(/[[:space:]]+/, ' ').strip
|
|
||||||
end
|
|
||||||
module ReportParsers
|
module ReportParsers
|
||||||
class Form14Parser < BaseParser
|
class Form14Parser < BaseParser
|
||||||
SHEET_NAME = 'Отчет о движении денежных средс'
|
SHEET_NAME = 'Отчет о движении денежных средс' # отличное название листа, мне нравится
|
||||||
FORM_CODE = '1.4'
|
FORM_CODE = '1.4'
|
||||||
|
# Add line codes or names that should be skipped during parsing.
|
||||||
|
IGNORED_KEYS = [2].freeze
|
||||||
|
|
||||||
def call
|
def call
|
||||||
return {} unless sheet_exists?(SHEET_NAME)
|
return {} unless sheet_exists?(SHEET_NAME)
|
||||||
@@ -69,6 +27,7 @@ module ReportParsers
|
|||||||
all_rows = (header_row + 1).upto(sheet.last_row).filter_map do |row|
|
all_rows = (header_row + 1).upto(sheet.last_row).filter_map do |row|
|
||||||
line_name = read_cell(sheet, row, columns[:name_column])
|
line_name = read_cell(sheet, row, columns[:name_column])
|
||||||
line_code = read_cell(sheet, row, columns[:code_column]).to_s.strip.presence
|
line_code = read_cell(sheet, row, columns[:code_column]).to_s.strip.presence
|
||||||
|
next if ignored_row?(line_name, line_code)
|
||||||
|
|
||||||
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
||||||
value = read_cell(sheet, row, col)
|
value = read_cell(sheet, row, col)
|
||||||
@@ -86,7 +45,7 @@ module ReportParsers
|
|||||||
end
|
end
|
||||||
|
|
||||||
payloads_by_year = {}
|
payloads_by_year = {}
|
||||||
value_headers.each do |col, year|
|
value_headers.each do |_, year|
|
||||||
next unless year.present?
|
next unless year.present?
|
||||||
|
|
||||||
rows_for_year = all_rows.map do |row|
|
rows_for_year = all_rows.map do |row|
|
||||||
@@ -108,5 +67,57 @@ module ReportParsers
|
|||||||
|
|
||||||
payloads_by_year
|
payloads_by_year
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def extract_year_from_header(header_text)
|
||||||
|
year_match = header_text[/\b(20\d{2})\b/]
|
||||||
|
year_match.to_i if year_match
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_header_row(sheet)
|
||||||
|
1.upto(sheet.last_row) do |row|
|
||||||
|
normalized_cells = 1.upto(sheet.last_column).map { |col| normalize_label(sheet.cell(row, col)) }
|
||||||
|
has_name = normalized_cells.any? { |text| text.include?('наименование показателя') }
|
||||||
|
has_code = normalized_cells.any? { |text| text == 'код' || text.start_with?('код ') || text.start_with?('код:') }
|
||||||
|
return row if has_name && has_code
|
||||||
|
end
|
||||||
|
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
def detect_columns(sheet, header_row)
|
||||||
|
columns = 1.upto(sheet.last_column).each_with_object({}) do |col, hash|
|
||||||
|
hash[col] = normalize_label(sheet.cell(header_row, col))
|
||||||
|
end
|
||||||
|
|
||||||
|
name_column = columns.key(columns.values.find { |text| text.include?('наименование показателя') }) || 1
|
||||||
|
|
||||||
|
code_column = columns.key(columns.values.find { |text|
|
||||||
|
text == 'код строки' || text.start_with?('код строки ') ||
|
||||||
|
(text == 'код' && columns[name_column + 1] == text)
|
||||||
|
}) || columns.key(columns.values.find { |text| text == 'код' || text.start_with?('код ') }) || [name_column + 1, sheet.last_column].min
|
||||||
|
|
||||||
|
value_columns = columns.keys.select do |col|
|
||||||
|
text = columns[col]
|
||||||
|
next false if text.include?('поясн')
|
||||||
|
|
||||||
|
text.match?(/20\d{2}/) || text.include?('за ') || text.include?('на ')
|
||||||
|
end
|
||||||
|
value_columns = value_columns.sort.last(2)
|
||||||
|
|
||||||
|
{
|
||||||
|
name_column: name_column,
|
||||||
|
code_column: code_column,
|
||||||
|
value_columns: value_columns
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignored_row?(line_name, line_code)
|
||||||
|
keys = [line_code, line_name].compact.map { |value| normalize_label(value) }
|
||||||
|
keys.any? { |key| ignored_keys.include?(key) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignored_keys
|
||||||
|
@ignored_keys ||= IGNORED_KEYS.map { |value| normalize_label(value) }.to_set
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user