Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77382c918c | ||
|
|
e64dfb767b | ||
|
|
4483aba8ce | ||
|
|
17508519f2 | ||
|
|
cbc83c0caf | ||
|
|
5425a95219 | ||
|
|
fabc2df38c | ||
|
|
e47ec8afcc | ||
|
|
e682897dce | ||
|
|
37e7d25976 | ||
|
|
3f889b5b9a | ||
|
|
1134732a32 | ||
|
|
aea8b7975e | ||
|
|
136de5f238 | ||
|
|
a1cbddf4e2 |
@@ -35,3 +35,4 @@
|
|||||||
|
|
||||||
/node_modules
|
/node_modules
|
||||||
.idea/
|
.idea/
|
||||||
|
TZ.xlsx
|
||||||
|
|||||||
@@ -1,38 +1,15 @@
|
|||||||
# Load DSL and set up stages
|
|
||||||
require "capistrano/setup"
|
require "capistrano/setup"
|
||||||
|
|
||||||
# Include default deployment tasks
|
|
||||||
require "capistrano/deploy"
|
require "capistrano/deploy"
|
||||||
|
|
||||||
# Load the SCM plugin appropriate to your project:
|
|
||||||
#
|
|
||||||
# require "capistrano/scm/hg"
|
|
||||||
# install_plugin Capistrano::SCM::Hg
|
|
||||||
# or
|
|
||||||
# require "capistrano/scm/svn"
|
|
||||||
# install_plugin Capistrano::SCM::Svn
|
|
||||||
# or
|
|
||||||
require "capistrano/scm/git"
|
require "capistrano/scm/git"
|
||||||
install_plugin Capistrano::SCM::Git
|
install_plugin Capistrano::SCM::Git
|
||||||
|
|
||||||
# Include tasks from other gems included in your Gemfile
|
require "capistrano/master_key"
|
||||||
#
|
require "capistrano/rvm"
|
||||||
# For documentation on these, see for example:
|
require "capistrano/bundler"
|
||||||
#
|
require "capistrano/rails/assets"
|
||||||
# https://github.com/capistrano/rvm
|
require "capistrano/rails/migrations"
|
||||||
# https://github.com/capistrano/rbenv
|
require "capistrano/puma"
|
||||||
# https://github.com/capistrano/chruby
|
install_plugin Capistrano::Puma
|
||||||
# https://github.com/capistrano/bundler
|
install_plugin Capistrano::Puma::Systemd
|
||||||
# https://github.com/capistrano/rails
|
|
||||||
# https://github.com/capistrano/passenger
|
|
||||||
#
|
|
||||||
# require "capistrano/rvm"
|
|
||||||
# require "capistrano/rbenv"
|
|
||||||
# require "capistrano/chruby"
|
|
||||||
# require "capistrano/bundler"
|
|
||||||
# require "capistrano/rails/assets"
|
|
||||||
# require "capistrano/rails/migrations"
|
|
||||||
# require "capistrano/passenger"
|
|
||||||
|
|
||||||
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
|
|
||||||
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
|
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
|
||||||
|
<rect width="32" height="32" rx="6" fill="#1a1a1a"/>
|
||||||
|
<rect x="5" y="22" width="5" height="6" rx="1" fill="white"/>
|
||||||
|
<rect x="13" y="16" width="5" height="12" rx="1" fill="white"/>
|
||||||
|
<rect x="21" y="10" width="5" height="18" rx="1" fill="white"/>
|
||||||
|
<polyline points="7.5,18 15.5,12 23.5,6" stroke="#4ade80" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<circle cx="7.5" cy="18" r="1.5" fill="#4ade80"/>
|
||||||
|
<circle cx="15.5" cy="12" r="1.5" fill="#4ade80"/>
|
||||||
|
<circle cx="23.5" cy="6" r="1.5" fill="#4ade80"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 614 B |
@@ -34,9 +34,9 @@ a.link:hover {
|
|||||||
.informations-data {
|
.informations-data {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 90%;
|
width: 95%;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
max-width: 1400px;
|
max-width: 1500px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-bottom: inherit;
|
padding-bottom: inherit;
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,11 @@ a.link:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.information-table tr :is(td, th):first-child {
|
.information-table tr :is(td, th):first-child {
|
||||||
width: 35%;
|
width: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
width: 15%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.type_doc_header#tabs {
|
.type_doc_header#tabs {
|
||||||
@@ -104,3 +108,55 @@ a.link:hover {
|
|||||||
a.link:has(.active__button) {
|
a.link:has(.active__button) {
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nav.pagy {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-block: 20px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid black;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
|
&.current { font-weight: 700; }
|
||||||
|
&[aria-disabled="true"] { opacity: 0.4; }
|
||||||
|
&:not([aria-disabled="true"]):hover { background-color: black; color: white; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.organisation-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-block: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.link-action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: black;
|
||||||
|
color: var(--white-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.link-action--danger {
|
||||||
|
border-color: #c0392b;
|
||||||
|
color: #c0392b;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #c0392b;
|
||||||
|
color: var(--white-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,18 +28,13 @@ module Authorization
|
|||||||
session['cas'] && session['cas']['user']
|
session['cas'] && session['cas']['user']
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_current_user(options = {})
|
|
||||||
return nil if current_login.blank?
|
|
||||||
load_current_user
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_current_user
|
def load_current_user
|
||||||
@current_user ||= User.where('lower(login) = lower(?)', current_login).first
|
@current_user ||= User.where('lower(login) = lower(?)', current_login).first
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_authentication
|
def check_authentication
|
||||||
if session.blank? || session['cas'].blank? || session['cas']['user'].blank? ||
|
if session.blank? || session['cas'].blank? || session['cas']['user'].blank? ||
|
||||||
(request.get? && !request.xhr? && request.xhr? != 0 && (session['cas']['last_validated_at'].blank? || session['cas']['last_validated_at'] < 15.minutes.ago))
|
(request.get? && !request.xhr? && (session['cas']['last_validated_at'].blank? || session['cas']['last_validated_at'] < 15.minutes.ago))
|
||||||
render plain: 'Требуется авторизация', status: 401
|
render plain: 'Требуется авторизация', status: 401
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class OrganisationsController < ApplicationController
|
class OrganisationsController < ApplicationController
|
||||||
before_action :set_organisation, only: [:show]
|
before_action :set_organisation, :set_report_codes, only: [:show, :destroy, :reload]
|
||||||
|
|
||||||
DOC_TYPES = {
|
DOC_TYPES = {
|
||||||
0 => { title: 'Бухгалтерский баланс', form_code: '1.1' },
|
0 => { title: 'Бухгалтерский баланс', form_code: '1.1' },
|
||||||
@@ -9,7 +9,7 @@ class OrganisationsController < ApplicationController
|
|||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def index
|
def index
|
||||||
organizations = Organization.all
|
@pagy, organizations = pagy(Organization.order(:created_at))
|
||||||
|
|
||||||
@info_about_organisations = organizations.each_with_object({}) do |org, hash|
|
@info_about_organisations = organizations.each_with_object({}) do |org, hash|
|
||||||
hash[org.id] = {
|
hash[org.id] = {
|
||||||
@@ -37,33 +37,55 @@ class OrganisationsController < ApplicationController
|
|||||||
@doc_name = selected_doc[:title]
|
@doc_name = selected_doc[:title]
|
||||||
@current_doc_info1 = grouped_rows[@doc_name]
|
@current_doc_info1 = grouped_rows[@doc_name]
|
||||||
if !@current_doc_info1.values.first.nil?
|
if !@current_doc_info1.values.first.nil?
|
||||||
@current_doc_info = @info_about_organisation[@doc_name][0..@current_doc_info1.values.first.size + 1]
|
number_of_columns = @current_doc_info1.values.first.size + 1
|
||||||
|
number_of_columns += 1 if @type_doc < 2
|
||||||
|
@current_doc_info = @info_about_organisation[@doc_name][0..number_of_columns]
|
||||||
end
|
end
|
||||||
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
|
private
|
||||||
|
|
||||||
def set_organisation
|
def set_organisation
|
||||||
@org = Organization.find(params[:id])
|
@org = Organization.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_report_codes
|
||||||
|
@report_codes = ReportCode.all.filter_map { |report_code| [report_code.code, report_code.description] if report_code.code.match?(/\A[12]/) }.to_h
|
||||||
|
end
|
||||||
|
|
||||||
def build_organization_payload(years)
|
def build_organization_payload(years)
|
||||||
payload = {
|
russian_names = {
|
||||||
'Сведения об организации' => {
|
'inn' => 'ИНН',
|
||||||
'ИНН' => @org.inn,
|
'full_name' => 'Полное наименование юридического лица',
|
||||||
'Полное наименование юридического лица' => @org.full_name,
|
'kpp' => 'КПП',
|
||||||
'КПП' => @org.kpp,
|
'okpo' => 'Код по ОКПО',
|
||||||
'Код по ОКПО' => @org.okpo,
|
'okfs' => 'Форма собственности (по ОКФС)',
|
||||||
'Форма собственности (по ОКФС)' => @org.okfs,
|
'okopf' => 'Организационно-правовая форма (по ОКОПФ)',
|
||||||
'Организационно-правовая форма (по ОКОПФ)' => @org.okopf,
|
'okved2' => 'Вид экономической деятельности по ОКВЭД 2',
|
||||||
'Вид экономической деятельности по ОКВЭД 2' => @org.okved2,
|
'address' => 'Местонахождение (адрес)'
|
||||||
'Местонахождение (адрес)' => @org.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|
|
DOC_TYPES.each_value do |doc_type|
|
||||||
payload[doc_type[:title]] = ['Наименование показателя', 'Код'] + years.map do |year|
|
first_headers = ['Наименование показателя', 'Код']
|
||||||
|
first_headers << 'Пояснения' if ['Бухгалтерский баланс', 'Отчёт о финансовых результатах'].include?(doc_type[:title])
|
||||||
|
payload[doc_type[:title]] = first_headers + years.map do |year|
|
||||||
column_header_for(doc_type[:form_code], year)
|
column_header_for(doc_type[:form_code], year)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ class ReportsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
inn = params[:inn]
|
inn = params[:inn].to_s.strip
|
||||||
report = Report.create!(inn: inn, status: 'processing')
|
unless inn.match?(/\A\d{10}(\d{2})?\z/)
|
||||||
|
redirect_to reports_path, alert: 'Некорректный ИНН (должен содержать 10 или 12 цифр)'
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
report = Report.create!(inn: inn, status: 'processing')
|
||||||
FileProcessorJob.perform_async(inn, report.id)
|
FileProcessorJob.perform_async(inn, report.id)
|
||||||
|
|
||||||
redirect_to reports_path, notice: 'Отчёт загружается в фоне'
|
redirect_to reports_path, notice: 'Отчёт загружается в фоне'
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ module OrganisationsHelper
|
|||||||
return nil if code.nil? || code.size < 2
|
return nil if code.nil? || code.size < 2
|
||||||
prefix = code[0, 2]
|
prefix = code[0, 2]
|
||||||
case prefix
|
case prefix
|
||||||
when '21', '22', '23', '24'
|
when '21', '22', '23', '24', '25'
|
||||||
'21-24'
|
'21-25'
|
||||||
else
|
else
|
||||||
prefix
|
prefix
|
||||||
end
|
end
|
||||||
@@ -16,8 +16,8 @@ module OrganisationsHelper
|
|||||||
prefix = code[0, 2]
|
prefix = code[0, 2]
|
||||||
return false unless prefix.match?(/\A\d{2}\z/)
|
return false unless prefix.match?(/\A\d{2}\z/)
|
||||||
if type_data == 'min_max'
|
if type_data == 'min_max'
|
||||||
return false if %w[16 17].include?(prefix)
|
return false if %w[16 17 29].include?(prefix) || prefix.start_with?("3")
|
||||||
return true if %w[21 22 23 24 25 29].include?(prefix)
|
return true if %w[21 22 23 24 25].include?(prefix)
|
||||||
return !code.end_with?('00')
|
return !code.end_with?('00')
|
||||||
elsif type_data == 'comparsion'
|
elsif type_data == 'comparsion'
|
||||||
return code.end_with?('00')
|
return code.end_with?('00')
|
||||||
@@ -25,7 +25,7 @@ module OrganisationsHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse_number(value)
|
def parse_number(value)
|
||||||
return 0 if value.empty? || ['-', '(-)', 'X'].include?(value)
|
return 0 if value.nil? || value.empty? || ['-', '(-)', 'X'].include?(value)
|
||||||
negative = value.start_with?('(') && value.end_with?(')')
|
negative = value.start_with?('(') && value.end_with?(')')
|
||||||
value = value.tr('()', '') if negative
|
value = value.tr('()', '') if negative
|
||||||
value = value.delete(' ')
|
value = value.delete(' ')
|
||||||
@@ -43,19 +43,15 @@ module OrganisationsHelper
|
|||||||
prepared_data = filtered_data.each_with_object({}) do |((_, code), values), result|
|
prepared_data = filtered_data.each_with_object({}) do |((_, code), values), result|
|
||||||
next if code.nil? || !keep_code?(code)
|
next if code.nil? || !keep_code?(code)
|
||||||
group = group_key(code)
|
group = group_key(code)
|
||||||
result[group] ||= Hash.new { |h, k| h[k] = [] }
|
result[group] ||= []
|
||||||
values.each_with_index do |value, index|
|
result[group] += values.map { |value| parse_number(value)}
|
||||||
result[group][index + 1] << parse_number(value)
|
|
||||||
end
|
end
|
||||||
end
|
min_max_data = prepared_data.transform_values do |values|
|
||||||
min_max_data = prepared_data.transform_values do |columns|
|
|
||||||
columns.transform_values do |values|
|
|
||||||
sorted = values.sort
|
sorted = values.sort
|
||||||
size = sorted.size
|
size = sorted.size
|
||||||
p50 = size.odd? ? sorted[size / 2] : (sorted[size / 2 - 1] + sorted[size / 2]) / 2.0
|
p50 = size.odd? ? sorted[size / 2] : (sorted[size / 2 - 1] + sorted[size / 2]) / 2.0
|
||||||
{ min: sorted.first, p50: p50, max: sorted.last }
|
{ min: sorted.first, p50: p50, max: sorted.last }
|
||||||
end
|
end
|
||||||
end
|
|
||||||
elsif type_data == 'comparsion'
|
elsif type_data == 'comparsion'
|
||||||
prepared_data = filtered_data.each_with_object({}) do |((_, code), values), result|
|
prepared_data = filtered_data.each_with_object({}) do |((_, code), values), result|
|
||||||
next if code.nil? || !keep_code?(code, type_data: 'comparsion')
|
next if code.nil? || !keep_code?(code, type_data: 'comparsion')
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class ReportParser
|
|||||||
sheet_name: 'Отчет о финансовых результатах'
|
sheet_name: 'Отчет о финансовых результатах'
|
||||||
},
|
},
|
||||||
'1.3' => {
|
'1.3' => {
|
||||||
parser: nil,
|
parser: ReportParsers::Form13Parser,
|
||||||
sheet_name: 'Отчет об изменениях капитала'
|
sheet_name: 'Отчет об изменениях капитала'
|
||||||
},
|
},
|
||||||
'1.4' => {
|
'1.4' => {
|
||||||
@@ -33,17 +33,19 @@ class ReportParser
|
|||||||
parsed_forms = parse_forms
|
parsed_forms = parse_forms
|
||||||
save_aggregated_statements(parsed_forms)
|
save_aggregated_statements(parsed_forms)
|
||||||
end
|
end
|
||||||
|
ensure
|
||||||
|
@tempfile&.close!
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def spreadsheet
|
def spreadsheet
|
||||||
@spreadsheet ||= begin
|
@spreadsheet ||= begin
|
||||||
tempfile = Tempfile.new(['report', '.xlsx'])
|
@tempfile = Tempfile.new(['report', '.xlsx'])
|
||||||
tempfile.binmode
|
@tempfile.binmode
|
||||||
@yearly_file.file.download { |chunk| tempfile.write(chunk) }
|
@yearly_file.file.download { |chunk| @tempfile.write(chunk) }
|
||||||
tempfile.rewind
|
@tempfile.rewind
|
||||||
Roo::Excelx.new(tempfile.path)
|
Roo::Excelx.new(@tempfile.path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -202,7 +204,7 @@ class ReportParser
|
|||||||
end
|
end
|
||||||
|
|
||||||
def report_codes
|
def report_codes
|
||||||
@report_codes ||= ReportCode.order(:code).select(:code, :name).to_a
|
@report_codes ||= ReportCode.select(:code, :name).order(:id).to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
def report_codes_for_form(form_code, codes)
|
def report_codes_for_form(form_code, codes)
|
||||||
@@ -229,7 +231,7 @@ class ReportParser
|
|||||||
.where(sheet_number: year)
|
.where(sheet_number: year)
|
||||||
.where(yearly_files: { organization_id: @yearly_file.organization_id })
|
.where(yearly_files: { organization_id: @yearly_file.organization_id })
|
||||||
.where.not(id: keeper_id)
|
.where.not(id: keeper_id)
|
||||||
.delete_all
|
.destroy_all
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ module ReportParsers
|
|||||||
columns = detect_columns(sheet, header_row)
|
columns = detect_columns(sheet, header_row)
|
||||||
|
|
||||||
|
|
||||||
value_headers = columns[:value_columns].each_with_object({}) do |col, hash|
|
# year читается по оригинальному col заголовка, данные — по откалиброванному
|
||||||
header_text = read_cell(sheet, header_row, col).to_s
|
value_headers = columns[:value_columns].zip(columns[:data_value_columns]).each_with_object({}) do |(header_col, data_col), hash|
|
||||||
|
header_text = read_cell(sheet, header_row, header_col).to_s
|
||||||
year = extract_year_from_header(header_text)
|
year = extract_year_from_header(header_text)
|
||||||
hash[col] = year
|
hash[data_col] = year
|
||||||
end
|
end
|
||||||
|
|
||||||
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|
|
||||||
@@ -30,7 +31,7 @@ module ReportParsers
|
|||||||
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)
|
next if ignored_row?(line_name, line_code)
|
||||||
|
|
||||||
values = columns[:value_columns].each_with_object({}) do |col, hash|
|
values = columns[:data_value_columns].each_with_object({}) do |col, hash|
|
||||||
value = read_cell(sheet, row, col)
|
value = read_cell(sheet, row, col)
|
||||||
year = value_headers[col]
|
year = value_headers[col]
|
||||||
hash[year.to_s] = value if value.present? && year.present?
|
hash[year.to_s] = value if value.present? && year.present?
|
||||||
@@ -46,7 +47,7 @@ module ReportParsers
|
|||||||
end
|
end
|
||||||
|
|
||||||
payloads_by_year = {}
|
payloads_by_year = {}
|
||||||
value_headers.each do |col, year|
|
value_headers.each do |_data_col, 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|
|
||||||
@@ -114,13 +115,29 @@ module ReportParsers
|
|||||||
value_columns = columns.keys.select { |col| col > code_column && columns[col].present? }
|
value_columns = columns.keys.select { |col| col > code_column && columns[col].present? }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
original_cols = value_columns.sort.first(3)
|
||||||
{
|
{
|
||||||
name_column: name_column,
|
name_column: name_column,
|
||||||
code_column: code_column,
|
code_column: code_column,
|
||||||
value_columns: value_columns.sort.first(3)
|
value_columns: original_cols,
|
||||||
|
data_value_columns: calibrate_value_columns(sheet, header_row, original_cols, code_column)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def calibrate_value_columns(sheet, header_row, value_columns, code_column)
|
||||||
|
data_row = (header_row + 2).upto(sheet.last_row).find do |row|
|
||||||
|
sheet.cell(row, code_column).to_s.strip.match?(/\A\d{4}\z/)
|
||||||
|
end
|
||||||
|
return value_columns unless data_row
|
||||||
|
|
||||||
|
value_columns.map do |col|
|
||||||
|
next col unless sheet.cell(data_row, col).nil? || sheet.cell(data_row, col).to_s.strip.empty?
|
||||||
|
|
||||||
|
shifted = col + 1
|
||||||
|
shifted <= sheet.last_column && !sheet.cell(data_row, shifted).to_s.strip.empty? ? shifted : col
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def extract_year(sheet)
|
def extract_year(sheet)
|
||||||
period_text = sheet.cell(4, 1).to_s
|
period_text = sheet.cell(4, 1).to_s
|
||||||
year = period_text[/\d{4}/].to_i
|
year = period_text[/\d{4}/].to_i
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
module ReportParsers
|
||||||
|
class Form13Parser < BaseParser
|
||||||
|
SHEET_NAME = 'Отчет об изменениях капитала'
|
||||||
|
FORM_CODE = '1.3'
|
||||||
|
|
||||||
|
def call
|
||||||
|
return {} unless sheet_exists?(SHEET_NAME)
|
||||||
|
|
||||||
|
sheet = spreadsheet.sheet(SHEET_NAME)
|
||||||
|
build_payloads(sheet)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build_payloads(sheet)
|
||||||
|
header_row = find_section1_header_row(sheet)
|
||||||
|
return {} unless header_row
|
||||||
|
|
||||||
|
report_year = extract_report_year(sheet)
|
||||||
|
return {} unless report_year
|
||||||
|
|
||||||
|
name_col = find_name_column(sheet, header_row)
|
||||||
|
code_col = find_code_column(sheet, header_row)
|
||||||
|
total_col = find_total_column(sheet, header_row)
|
||||||
|
return {} unless code_col && total_col
|
||||||
|
|
||||||
|
end_row = section1_end_row(sheet, header_row)
|
||||||
|
payloads_by_year = {}
|
||||||
|
|
||||||
|
(header_row + 2).upto(end_row) do |row|
|
||||||
|
line_code = read_cell(sheet, row, code_col).to_s.strip.presence
|
||||||
|
next unless line_code&.match?(/\A3[123]\d{2}\z/)
|
||||||
|
|
||||||
|
row_year = year_from_code(line_code, report_year)
|
||||||
|
next unless row_year
|
||||||
|
|
||||||
|
name_cell = read_cell(sheet, row, name_col).to_s.strip
|
||||||
|
name_cell = read_cell(sheet, row, 1).to_s.strip if name_cell.blank?
|
||||||
|
value = read_cell(sheet, row, total_col)
|
||||||
|
|
||||||
|
payloads_by_year[row_year] ||= { form_code: FORM_CODE, sheet_name: SHEET_NAME, rows: [] }
|
||||||
|
payloads_by_year[row_year][:rows] << {
|
||||||
|
line_name: normalize_line_name(name_cell),
|
||||||
|
line_code: line_code,
|
||||||
|
value: value
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
payloads_by_year
|
||||||
|
end
|
||||||
|
|
||||||
|
def year_from_code(code, report_year)
|
||||||
|
case code[1]
|
||||||
|
when '1' then report_year - 2
|
||||||
|
when '2' then report_year - 1
|
||||||
|
when '3' then report_year
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def extract_report_year(sheet)
|
||||||
|
1.upto([sheet.last_row, 10].min) do |row|
|
||||||
|
1.upto(sheet.last_column) do |col|
|
||||||
|
m = sheet.cell(row, col).to_s.match(/\bза\s+(20\d{2})\s*г/i)
|
||||||
|
return m[1].to_i if m
|
||||||
|
end
|
||||||
|
end
|
||||||
|
year = yearly_file&.year.to_i
|
||||||
|
year.positive? ? year : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_section1_header_row(sheet)
|
||||||
|
1.upto(sheet.last_row) do |row|
|
||||||
|
cells = 1.upto(sheet.last_column).map { |col| normalize_label(sheet.cell(row, col)) }
|
||||||
|
next unless cells.any? { |c| c.include?('наименование показателя') }
|
||||||
|
next unless cells.any? { |c| c.include?('код строки') || c == 'код' }
|
||||||
|
|
||||||
|
return row
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_name_column(sheet, header_row)
|
||||||
|
1.upto(sheet.last_column) do |col|
|
||||||
|
return col if normalize_label(sheet.cell(header_row, col)).include?('наименование показателя')
|
||||||
|
end
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_code_column(sheet, header_row)
|
||||||
|
1.upto(sheet.last_column) do |col|
|
||||||
|
text = normalize_label(sheet.cell(header_row, col))
|
||||||
|
return col if text.include?('код строки') || text == 'код'
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_total_column(sheet, header_row)
|
||||||
|
result = nil
|
||||||
|
[header_row, header_row + 1].each do |row|
|
||||||
|
1.upto(sheet.last_column) do |col|
|
||||||
|
result = col if normalize_label(sheet.cell(row, col)) == 'итого'
|
||||||
|
end
|
||||||
|
return result if result
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def section1_end_row(sheet, from_row)
|
||||||
|
(from_row + 1).upto(sheet.last_row) do |row|
|
||||||
|
return row - 1 if normalize_label(sheet.cell(row, 1)).match?(/\A2\.\s*корректировки/i)
|
||||||
|
end
|
||||||
|
sheet.last_row
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -6,11 +6,12 @@ class FileProcessorJob
|
|||||||
include Sidekiq::Job
|
include Sidekiq::Job
|
||||||
|
|
||||||
def perform(inn, report_id)
|
def perform(inn, report_id)
|
||||||
|
raise ArgumentError, "Некорректный ИНН: #{inn}" unless inn.to_s.match?(/\A\d{10}(\d{2})?\z/)
|
||||||
|
|
||||||
report = Report.find(report_id)
|
report = Report.find(report_id)
|
||||||
Rails.logger.info "=== Начало загрузки для ИНН: #{inn} ==="
|
Rails.logger.info "=== Начало загрузки для ИНН: #{inn} ==="
|
||||||
|
|
||||||
# Временная папка
|
temp_dir = Rails.root.join('tmp', 'reports', inn.to_s.gsub(/[^0-9]/, ''))
|
||||||
temp_dir = Rails.root.join('tmp', 'reports', inn)
|
|
||||||
FileUtils.mkdir_p(temp_dir)
|
FileUtils.mkdir_p(temp_dir)
|
||||||
|
|
||||||
download_inn(inn, temp_dir.to_s)
|
download_inn(inn, temp_dir.to_s)
|
||||||
@@ -26,7 +27,9 @@ class FileProcessorJob
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Создаём YearlyFile и прикрепляем xlsx
|
# Создаём YearlyFile и прикрепляем xlsx
|
||||||
yearly_file = organization.yearly_files.build(year: 0)
|
year_from_filename = File.basename(file_path, '.*').split('_')[2].to_i
|
||||||
|
year_from_filename = 0 unless (2000..2099).cover?(year_from_filename)
|
||||||
|
yearly_file = organization.yearly_files.build(year: year_from_filename)
|
||||||
yearly_file.file.attach(
|
yearly_file.file.attach(
|
||||||
io: File.open(file_path),
|
io: File.open(file_path),
|
||||||
filename: File.basename(file_path)
|
filename: File.basename(file_path)
|
||||||
@@ -57,18 +60,28 @@ class FileProcessorJob
|
|||||||
'Accept-Language' => 'en-US,en;q=0.9',
|
'Accept-Language' => 'en-US,en;q=0.9',
|
||||||
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
|
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
|
||||||
}
|
}
|
||||||
content = HTTParty.get(url, headers: headers).body
|
response = HTTParty.get(url, headers: headers, timeout: 30)
|
||||||
json_need ? JSON.parse(content) : content
|
raise "HTTP #{response.code} при запросе #{url}" unless response.success?
|
||||||
|
|
||||||
|
json_need ? JSON.parse(response.body) : response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_inn(inn, output)
|
def download_inn(inn, output)
|
||||||
url = "https://bo.nalog.gov.ru/advanced-search/organizations/search?query=#{inn}&page=0&size=20"
|
url = "https://bo.nalog.gov.ru/advanced-search/organizations/search?query=#{inn}&page=0&size=20"
|
||||||
content = get_content(url, true)
|
content = get_content(url, true)
|
||||||
id = content['content'][0]['id']
|
org_entry = content.dig('content', 0) or raise "Организация с ИНН #{inn} не найдена"
|
||||||
|
id = org_entry['id']
|
||||||
|
|
||||||
url = "https://bo.nalog.gov.ru/nbo/organizations/#{id}/bfo/"
|
url = "https://bo.nalog.gov.ru/nbo/organizations/#{id}/bfo/"
|
||||||
content = get_content(url, true)
|
content = get_content(url, true)
|
||||||
periods_and_details_ids = content.map { |item| [item['period'], item['typeCorrections'][0]['correction']['id']] }
|
raise "Нет отчётности для организации #{id}" if content.blank?
|
||||||
|
|
||||||
|
periods_and_details_ids = content.filter_map do |item|
|
||||||
|
details_id = item.dig('typeCorrections', 0, 'correction', 'id')
|
||||||
|
next if details_id.nil?
|
||||||
|
|
||||||
|
[item['period'], details_id]
|
||||||
|
end
|
||||||
|
|
||||||
periods_and_details_ids.each do |period, details_id|
|
periods_and_details_ids.each do |period, details_id|
|
||||||
url = "https://bo.nalog.gov.ru/download/bfo/#{id}?auditReport=false&balance=true"\
|
url = "https://bo.nalog.gov.ru/download/bfo/#{id}?auditReport=false&balance=true"\
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ html
|
|||||||
meta name="turbo-refresh-method" content="morph"
|
meta name="turbo-refresh-method" content="morph"
|
||||||
= csrf_meta_tags
|
= csrf_meta_tags
|
||||||
= csp_meta_tag
|
= csp_meta_tag
|
||||||
/ = favicon_link_tag 'favicon.ico'
|
= favicon_link_tag 'favicon.svg', type: 'image/svg+xml'
|
||||||
/ = favicon_link_tag 'favicon-32x32.png', sizes: '32x32'
|
|
||||||
/ = favicon_link_tag 'apple-icon.png', rel: 'apple-touch-icon'
|
|
||||||
= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload"
|
= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload"
|
||||||
= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload"
|
= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload"
|
||||||
script[async src="https://ga.jspm.io/npm:es-module-shims@1.8.2/dist/es-module-shims.js" data-turbo-track="reload"]
|
script[async src="https://ga.jspm.io/npm:es-module-shims@1.8.2/dist/es-module-shims.js" data-turbo-track="reload"]
|
||||||
|
|||||||
@@ -17,3 +17,4 @@
|
|||||||
.information-button
|
.information-button
|
||||||
a.link[href="/organisations/#{organisation}"]
|
a.link[href="/organisations/#{organisation}"]
|
||||||
= "Подробнее"
|
= "Подробнее"
|
||||||
|
== pagy_nav(@pagy)
|
||||||
|
|||||||
@@ -14,6 +14,17 @@
|
|||||||
- @info_about_organisation["Сведения об организации"].each do |key, value|
|
- @info_about_organisation["Сведения об организации"].each do |key, value|
|
||||||
.information-elem
|
.information-elem
|
||||||
= "#{key}: #{value}"
|
= "#{key}: #{value}"
|
||||||
|
.organisation-actions
|
||||||
|
= link_to "/organisations/#{@org.id}/reload",
|
||||||
|
class: 'link-action',
|
||||||
|
data: { turbo_method: :post, turbo_confirm: 'Перекачать данные с nalog.gov.ru?' } do
|
||||||
|
i.bi.bi-arrow-clockwise
|
||||||
|
| Обновить данные
|
||||||
|
= link_to "/organisations/#{@org.id}",
|
||||||
|
class: 'link-action link-action--danger',
|
||||||
|
data: { turbo_method: :delete, turbo_confirm: 'Удалить организацию и все её данные? Это действие необратимо.' } do
|
||||||
|
i.bi.bi-trash
|
||||||
|
| Удалить
|
||||||
= render 'organisations/templates/type_doc', target: "type_doc_#{@type_doc}", org_id: "#{@org.id}"
|
= render 'organisations/templates/type_doc', target: "type_doc_#{@type_doc}", org_id: "#{@org.id}"
|
||||||
h2
|
h2
|
||||||
= "#{@doc_name}"
|
= "#{@doc_name}"
|
||||||
@@ -29,12 +40,14 @@
|
|||||||
tr
|
tr
|
||||||
td = key[0]
|
td = key[0]
|
||||||
td = key[1]
|
td = key[1]
|
||||||
|
-if @report_codes.has_key?(key[1])
|
||||||
|
td.description = @report_codes[key[1]]
|
||||||
- @current_doc_info1[key].each_with_index do |value, index|
|
- @current_doc_info1[key].each_with_index do |value, index|
|
||||||
- key_group = key[1].nil? ? nil : group_key(key[1])
|
- key_group = key[1].nil? ? nil : group_key(key[1])
|
||||||
- if min_max_data.has_key?(key_group) && keep_code?(key[1])
|
- if min_max_data.has_key?(key_group) && keep_code?(key[1])
|
||||||
- min_value = min_max_data[key_group][index + 1][:min]
|
- min_value = min_max_data[key_group][:min]
|
||||||
- max_value = min_max_data[key_group][index + 1][:max]
|
- max_value = min_max_data[key_group][:max]
|
||||||
- p50 = min_max_data[key_group][index + 1][:p50]
|
- p50 = min_max_data[key_group][:p50]
|
||||||
- color = get_color_for_cell(value, min: min_value, median: p50, max: max_value)
|
- color = get_color_for_cell(value, min: min_value, median: p50, max: max_value)
|
||||||
td style="background-color: #{color}" = value
|
td style="background-color: #{color}" = value
|
||||||
- elsif comparsion_data.has_key?(key[1]) && keep_code?(key[1], type_data: 'comparsion')
|
- elsif comparsion_data.has_key?(key[1]) && keep_code?(key[1], type_data: 'comparsion')
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Nc1hSplQ0MqAyalUwEkhP4MHvgHWBdQ1asGv87citiRh0CbxU5jWK0Lue0mz1IgZfkeHK/Tk1hMRgvBraTADvRbQNW1F49wW6KM/A3JSbviimeFMhwpNeX4Td4gqGNCdynu6etedjxDNjmDVvL9ADgq2ekVJR4ILXiJOarH1Ke9xF1Ep/4NAo3ce8Ec7h9Rphk16V8sLzIQ1J+dR1gJEVAPuGElftRXxRrWx8Q6pM+iAjd/7XdqpDhhmqNZwl2b/2w0pmy1MDeAuSoEFK8VtTqKW+e8MfR7iSMX8p6FCBr0BIqlrnthmzr/et3o03X9ZxAnrWrWk+hECMPLri2hW+w0r/JuGZjBahCr3PF/MHggtx0GJNmbnxb18TRPje3hQjDZ1ro0WorO6EdoH6Tsaby+IAwIknx7WLd5N--H3c/XDWT/kou9ABR--loDWauLHnUsVDLFdegRueA==
|
vzvJyboAlEsDCJYPDUPlvQefU89OZO14EHm+KkZc/SXKOKak0o0h6eMpA50DWzlMqgLppOuZqg2Y4lLCSIicLEjenP9N5fhmRDDGZmMe2OtUUYo8KOOAggbV93xL/He1GbFv0g0FPljIgn3dZvesQDQeU+/Hvmip4t9d7xSIq5ztA1ljraPmT4fasc8NvPElY6HN5YuuivvDZEXrb9Ck+5o5gmLS+KHKWqEygVpnLCgXVbVFVhuNbmAJ+C/pLvPDpzDgtkbEMhMr+1B8HGyBauan5CK5afW6AUPl5hVVr1LoefHL1ZY3pl1f/4JGJijfS1Fl3E0HgGyD7etwW4s1nn5IsVhF1QzHkULAtCGTvTBMTcdrhtxvrrDu4cYUuTZ8/FnghLbw1rNdEGR4Ic00lY7Nbkzg--6FKykVUCPO92dm87--85MEOy/jUeU6+C7IezR8hQ==
|
||||||
+40
-29
@@ -1,39 +1,50 @@
|
|||||||
# config valid for current version and patch releases of Capistrano
|
|
||||||
lock "~> 3.19.2"
|
lock "~> 3.19.2"
|
||||||
|
|
||||||
set :application, "my_app_name"
|
set :application, "finreport-analyzer"
|
||||||
set :repo_url, "git@example.com:me/my_repo.git"
|
set :repo_url, "https://git.ada-dev.ru/ada/finreport-analyzer.git"
|
||||||
|
|
||||||
# Default branch is :master
|
set :deploy_to, "/var/www/finreport-analyzer"
|
||||||
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
|
set :branch, "develop"
|
||||||
|
|
||||||
# Default deploy_to directory is /var/www/my_app_name
|
set :rvm_type, :user
|
||||||
# set :deploy_to, "/var/www/my_app_name"
|
set :rvm_ruby_version, "3.3.0"
|
||||||
|
|
||||||
# Default value for :format is :airbrussh.
|
append :linked_files, "config/database.yml"
|
||||||
# set :format, :airbrussh
|
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets",
|
||||||
|
"public/system", "storage"
|
||||||
|
|
||||||
# You can configure the Airbrussh format using :format_options.
|
set :keep_releases, 5
|
||||||
# These are the defaults.
|
|
||||||
# set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto
|
|
||||||
|
|
||||||
# Default value for :pty is false
|
set :puma_threads, [2, 4]
|
||||||
# set :pty, true
|
set :puma_workers, 2
|
||||||
|
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
|
||||||
|
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
|
||||||
|
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
|
||||||
|
set :puma_access_log, "#{release_path}/log/puma.access.log"
|
||||||
|
set :puma_error_log, "#{release_path}/log/puma.error.log"
|
||||||
|
set :puma_preload_app, true
|
||||||
|
set :puma_systemctl_user, :system
|
||||||
|
set :puma_service_unit_name, "puma-finreport"
|
||||||
|
|
||||||
# Default value for :linked_files is []
|
namespace :sidekiq do
|
||||||
# append :linked_files, "config/database.yml", 'config/master.key'
|
task :restart do
|
||||||
|
on roles(:app) do
|
||||||
|
execute :sudo, "systemctl restart sidekiq-finreport", raise_on_non_zero_exit: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Default value for linked_dirs is []
|
after "deploy:finished", "sidekiq:restart"
|
||||||
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system", "vendor", "storage"
|
after "deploy:migrate", "deploy:seed"
|
||||||
|
|
||||||
# Default value for default_env is {}
|
namespace :deploy do
|
||||||
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
|
task :seed do
|
||||||
|
on roles(:db) do
|
||||||
# Default value for local_user is ENV['USER']
|
within release_path do
|
||||||
# set :local_user, -> { `git config user.name`.chomp }
|
with rails_env: fetch(:rails_env, "production") do
|
||||||
|
execute :bundle, "exec rake db:seed"
|
||||||
# Default value for keep_releases is 5
|
end
|
||||||
# set :keep_releases, 5
|
end
|
||||||
|
end
|
||||||
# Uncomment the following to require manually verifying the host key before first deploy.
|
end
|
||||||
# set :ssh_options, verify_host_key: :secure
|
end
|
||||||
|
|||||||
@@ -1,61 +1,8 @@
|
|||||||
# server-based syntax
|
server "finreport-prod",
|
||||||
# ======================
|
user: "deploy",
|
||||||
# Defines a single server with a list of roles and multiple properties.
|
roles: %w[app db web]
|
||||||
# You can define all roles on a single server, or split them:
|
|
||||||
|
|
||||||
# server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
|
set :ssh_options, {
|
||||||
# server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value
|
forward_agent: true,
|
||||||
# server "db.example.com", user: "deploy", roles: %w{db}
|
auth_methods: %w[publickey]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# role-based syntax
|
|
||||||
# ==================
|
|
||||||
|
|
||||||
# Defines a role with one or multiple servers. The primary server in each
|
|
||||||
# group is considered to be the first unless any hosts have the primary
|
|
||||||
# property set. Specify the username and a domain or IP for the server.
|
|
||||||
# Don't use `:all`, it's a meta role.
|
|
||||||
|
|
||||||
# role :app, %w{deploy@example.com}, my_property: :my_value
|
|
||||||
# role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value
|
|
||||||
# role :db, %w{deploy@example.com}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
# =============
|
|
||||||
# You can set any configuration variable like in config/deploy.rb
|
|
||||||
# These variables are then only loaded and set in this stage.
|
|
||||||
# For available Capistrano configuration variables see the documentation page.
|
|
||||||
# http://capistranorb.com/documentation/getting-started/configuration/
|
|
||||||
# Feel free to add new variables to customise your setup.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Custom SSH Options
|
|
||||||
# ==================
|
|
||||||
# You may pass any option but keep in mind that net/ssh understands a
|
|
||||||
# limited set of options, consult the Net::SSH documentation.
|
|
||||||
# http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
|
|
||||||
#
|
|
||||||
# Global options
|
|
||||||
# --------------
|
|
||||||
# set :ssh_options, {
|
|
||||||
# keys: %w(/home/user_name/.ssh/id_rsa),
|
|
||||||
# forward_agent: false,
|
|
||||||
# auth_methods: %w(password)
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# The server-based syntax can be used to override options:
|
|
||||||
# ------------------------------------
|
|
||||||
# server "example.com",
|
|
||||||
# user: "user_name",
|
|
||||||
# roles: %w{web app},
|
|
||||||
# ssh_options: {
|
|
||||||
# user: "user_name", # overrides user setting above
|
|
||||||
# keys: %w(/home/user_name/.ssh/id_rsa),
|
|
||||||
# forward_agent: false,
|
|
||||||
# auth_methods: %w(publickey password)
|
|
||||||
# # password: "please use keys"
|
|
||||||
# }
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ Rails.application.routes.draw do
|
|||||||
get '/auth/login', to: 'auth#login', as: :login
|
get '/auth/login', to: 'auth#login', as: :login
|
||||||
get '/organisations/index'
|
get '/organisations/index'
|
||||||
get '/organisations/:id', to: 'organisations#show'
|
get '/organisations/:id', to: 'organisations#show'
|
||||||
|
delete '/organisations/:id', to: 'organisations#destroy'
|
||||||
|
post '/organisations/:id/reload', to: 'organisations#reload'
|
||||||
get '/auditors/index'
|
get '/auditors/index'
|
||||||
get '/reports/create'
|
get '/reports/create'
|
||||||
get '/reports', to: 'reports#index'
|
get '/reports', to: 'reports#index'
|
||||||
|
|||||||
@@ -1,68 +1,70 @@
|
|||||||
class SeedReportCodes < ActiveRecord::Migration[7.1]
|
class SeedReportCodes < ActiveRecord::Migration[7.1]
|
||||||
def up
|
def up
|
||||||
rows = [
|
rows = [
|
||||||
{ code: "1100", name: "Итого внеоборотных активов", description: "Сумма строк 1110, 1120, 1130, 1140, 1150" },
|
|
||||||
{ code: "1105", name: "Гудвил", description: "-" },
|
{ code: "1105", name: "Гудвил", description: "-" },
|
||||||
{ code: "1110", name: "Нематериальные активы", description: "-" },
|
{ code: "1110", name: "Нематериальные активы", description: "Ценности, которые не имеют вещественной формы (товарные знаки, патенты, программы, авторские права)" },
|
||||||
{ code: "1130", name: "Нематериальные поисковые активы", description: "-" },
|
{ code: "1120", name: "Результаты исследований и разработок", description: "Затраты на незавершенные исследования и разработки" },
|
||||||
{ code: "1140", name: "Материальные поисковые активы", description: "-" },
|
{ code: "1130", name: "Нематериальные поисковые активы", description: "Затраты на поиск полезных ископаемых в виде исследований, лицензий, геологических изысканий" },
|
||||||
{ code: "1150", name: "Основные средства", description: "-" },
|
{ code: "1140", name: "Материальные поисковые активы", description: "Оборудование и сооружения, используемые для поиска и разведки месторождений" },
|
||||||
{ code: "1160", name: "Инвестиционная недвижимость", description: "-" },
|
{ code: "1150", name: "Основные средства", description: "Имущество, используемое длительно в ходе обычной деятельности (недвижимость, земля, оборудование, транспорт)" },
|
||||||
{ code: "1170", name: "Финансовые вложения", description: "-" },
|
{ code: "1160", name: "Инвестиционная недвижимость", description: "Долгосрочное имущество, переданное в аренду, лизинг" },
|
||||||
{ code: "1180", name: "Отложенные налоговые активы", description: "-" },
|
{ code: "1170", name: "Финансовые вложения", description: "Долгосрочные доходные инвестиции (ценные бумаги, вклады, выданные займы)" },
|
||||||
{ code: "1190", name: "Прочие внеоборотные активы", description: "-" },
|
{ code: "1180", name: "Отложенные налоговые активы", description: "Сумма налога на прибыль, которую компания сможет уменьшить в будущем" },
|
||||||
{ code: "1200", name: "Итого оборотных активов", description: "-" },
|
{ code: "1190", name: "Прочие внеоборотные активы", description: "Долгосрочное имущество, не включенное в другие строки раздела I" },
|
||||||
{ code: "1210", name: "Запасы", description: "-" },
|
{ code: "1100", name: "Итого внеоборотных активов", description: "Сумма всего долгосрочного имущества (> 12 мес.)" },
|
||||||
|
{ code: "1210", name: "Запасы", description: "Материальные ресурсы, которые используются в ходе текущей деятельности (сырьё, материалы, товары, готовая продукция)" },
|
||||||
{ code: "1215", name: "Долгосрочные активы к продаже", description: "-" },
|
{ code: "1215", name: "Долгосрочные активы к продаже", description: "-" },
|
||||||
{ code: "1220", name: "Налог на добавленную стоимость по приобретенным ценностям", description: "-" },
|
{ code: "1220", name: "Налог на добавленную стоимость по приобретенным ценностям", description: "Сумма входящего НДС, не принятая на отчетную дату к вычету" },
|
||||||
{ code: "1230", name: "Дебиторская задолженность", description: "-" },
|
{ code: "1230", name: "Дебиторская задолженность", description: "Неисполненные обязательства контрагентов перед организацией" },
|
||||||
{ code: "1240", name: "Финансовые вложения (за исключением денежных эквивалентов)", description: "-" },
|
{ code: "1240", name: "Финансовые вложения (за исключением денежных эквивалентов)", description: "Краткосрочные доходные инвестиции (ценные бумаги, вклады)" },
|
||||||
{ code: "1250", name: "Денежные средства и денежные эквиваленты", description: "-" },
|
{ code: "1250", name: "Денежные средства и денежные эквиваленты", description: "Деньги и вклады до востребования" },
|
||||||
{ code: "1260", name: "Прочие оборотные активы", description: "-" },
|
{ code: "1260", name: "Прочие оборотные активы", description: "Краткосрочное имущество, не включенное в другие строки раздела I" },
|
||||||
{ code: "1600", name: "БАЛАНС (актив)", description: "-" },
|
{ code: "1200", name: "Итого оборотных активов", description: "Сумма всего краткосрочного имущества (< 12 мес.)" },
|
||||||
{ code: "1300", name: "Итого капитал/Итого целевое финансирование (в некоммерческой организации)", description: "-" },
|
{ code: "1600", name: "БАЛАНС (актив)", description: "Общая стоимость имущества организации" },
|
||||||
{ code: "1310", name: "Уставный капитал/Паевой фонд (в некоммерческой организации)", description: "-" },
|
{ code: "1310", name: "Уставный капитал/Паевой фонд (в некоммерческой организации)", description: "Зафиксированная в учредительных документах сумма, образованная из вкладов учредителей (участников)" },
|
||||||
{ code: "1320", name: "Собственные акции, принадлежащие обществу, задолженность акционеров по оплате акций/Целевой капитал (в некоммерческой организации)", description: "-" },
|
{ code: "1320", name: "Собственные акции, принадлежащие обществу, задолженность акционеров по оплате акций/Целевой капитал (в некоммерческой организации)", description: "Стоимость выкупленных акций для перепродажи или аннулирования" },
|
||||||
{ code: "1330", name: "Целевые средства (в некоммерческой организации)", description: "-" },
|
{ code: "1330", name: "Целевые средства (в некоммерческой организации)", description: "Дооценка основных средств, нематериальных активов до справедливой стоимости" },
|
||||||
{ code: "1340", name: "Накопленная дооценка внеоборотных активов", description: "-" },
|
{ code: "1340", name: "Накопленная дооценка внеоборотных активов", description: "-" },
|
||||||
{ code: "1350", name: "Добавочный капитал (без накопленной дооценки)", description: "-" },
|
{ code: "1350", name: "Добавочный капитал (без накопленной дооценки)", description: "Дополнительные взносы учредителей (участников), эмиссионный доход" },
|
||||||
{ code: "1360", name: "Резервный капитал/Фонд недвижимого и особо ценного движимого имущества (в некоммерческой организации)", description: "-" },
|
{ code: "1360", name: "Резервный капитал/Фонд недвижимого и особо ценного движимого имущества (в некоммерческой организации)", description: "Часть чистой прибыли, используемая для покрытия возможных убытков" },
|
||||||
{ code: "1370", name: "Нераспределенная прибыль (непокрытый убыток)/Резервный и иные целевые фонды (в некоммерческой организации)", description: "-" },
|
{ code: "1370", name: "Нераспределенная прибыль (непокрытый убыток)/Резервный и иные целевые фонды (в некоммерческой организации)", description: "Чистая прибыль, которая не была распределена между участниками/акционерами" },
|
||||||
{ code: "1400", name: "Итого долгосрочных обязательств", description: "-" },
|
{ code: "1300", name: "Итого капитал/Итого целевое финансирование (в некоммерческой организации)", description: "Сумма собственного капитала" },
|
||||||
{ code: "1410", name: "Долгосрочные заемные средства", description: "-" },
|
{ code: "1410", name: "Долгосрочные заемные средства", description: "Кредиты и займы, привлеченные организацией на срок > 12 мес." },
|
||||||
{ code: "1420", name: "Отложенные налоговые обязательства", description: "-" },
|
{ code: "1420", name: "Отложенные налоговые обязательства", description: "Сумма налога на прибыль, которую компания заплатит в будущем" },
|
||||||
{ code: "1430", name: "Долгосрочные оценочные обязательства", description: "-" },
|
{ code: "1430", name: "Долгосрочные оценочные обязательства", description: "Обязательства с неопределенной суммой или сроком исполнения (> 12 мес.)" },
|
||||||
{ code: "1450", name: "Прочие долгосрочные обязательства", description: "-" },
|
{ code: "1450", name: "Прочие долгосрочные обязательства", description: "Долгосрочные обязательства, не включенные в другие строки раздела IV" },
|
||||||
{ code: "1500", name: "Итого краткосрочных обязательств", description: "-" },
|
{ code: "1400", name: "Итого долгосрочных обязательств", description: "Сумма всех долгосрочных обязательств" },
|
||||||
{ code: "1510", name: "Краткосрочные заемные средства", description: "-" },
|
{ code: "1510", name: "Краткосрочные заемные средства", description: "Кредиты и займы, привлеченные организацией на срок < 12 мес." },
|
||||||
{ code: "1520", name: "Краткосрочная кредиторская задолженность", description: "-" },
|
{ code: "1520", name: "Краткосрочная кредиторская задолженность", description: "Неисполненные обязательства организации перед контрагентами" },
|
||||||
{ code: "1530", name: "Доходы будущих периодов", description: "-" },
|
{ code: "1530", name: "Доходы будущих периодов", description: "-" },
|
||||||
{ code: "1540", name: "Краткосрочные оценочные обязательства", description: "-" },
|
{ code: "1540", name: "Краткосрочные оценочные обязательства", description: "Обязательства с неопределенной суммой или сроком исполнения (< 12 мес.)" },
|
||||||
{ code: "1550", name: "Прочие краткосрочные обязательства", description: "-" },
|
{ code: "1550", name: "Прочие краткосрочные обязательства", description: "Краткосрочные обязательства, не включенные в другие строки раздела V" },
|
||||||
{ code: "2110", name: "Выручка", description: "-" },
|
{ code: "1500", name: "Итого краткосрочных обязательств", description: "Сумма всех краткосрочных обязательств" },
|
||||||
{ code: "2120", name: "Себестоимость продаж", description: "-" },
|
{ code: "1700", name: "БАЛАНС (пассив)", description: "Общая стоимость источников формирования имущества организации" },
|
||||||
{ code: "2100", name: "Валовая прибыль (убыток)", description: "-" },
|
{ code: "2110", name: "Выручка", description: "Доходы от продажи товаров (оказания услуг, выполнения работ)" },
|
||||||
{ code: "2210", name: "Коммерческие расходы", description: "-" },
|
{ code: "2120", name: "Себестоимость продаж", description: "Прямые расходы, направленные на получение выручки" },
|
||||||
{ code: "2220", name: "Управленческие расходы", description: "-" },
|
{ code: "2100", name: "Валовая прибыль (убыток)", description: "Разница между выручкой и себестоимостью" },
|
||||||
{ code: "2200", name: "Прибыль (убыток) от продаж", description: "-" },
|
{ code: "2210", name: "Коммерческие расходы", description: "Расходы на сбыт, рекламу и маркетинг" },
|
||||||
{ code: "2310", name: "Доходы от участия в других организациях", description: "-" },
|
{ code: "2220", name: "Управленческие расходы", description: "Расходы на содержание аппарата управления" },
|
||||||
{ code: "2320", name: "Проценты к получению", description: "-" },
|
{ code: "2200", name: "Прибыль (убыток) от продаж", description: "Валовая прибыль за вычетом коммерческих и управленческих расходов" },
|
||||||
{ code: "2330", name: "Проценты к уплате", description: "-" },
|
{ code: "2310", name: "Доходы от участия в других организациях", description: "Дивиденды от дочерних компаний" },
|
||||||
{ code: "2340", name: "Прочие доходы", description: "-" },
|
{ code: "2320", name: "Проценты к получению", description: "Процентные доходы от финансовых вложений (акций, вкладов, выданных займов)" },
|
||||||
{ code: "2350", name: "Прочие расходы", description: "-" },
|
{ code: "2330", name: "Проценты к уплате", description: "Процентные расходы по полученным кредитам и займам" },
|
||||||
{ code: "2300", name: "Прибыль (убыток) от продолжающейся деятельности до налогообложения", description: "-" },
|
{ code: "2340", name: "Прочие доходы", description: "Прочие нерегулярные доходы" },
|
||||||
{ code: "2410", name: "Налог на прибыль организаций", description: "-" },
|
{ code: "2350", name: "Прочие расходы", description: "Прочие нерегулярные расходы" },
|
||||||
{ code: "2411", name: "текущий налог на прибыль организаций", description: "в том числе" },
|
{ code: "2300", name: "Прибыль (убыток) от продолжающейся деятельности до налогообложения", description: "Прибыль (убыток) до налогообложения за вычетом доходоы и расходов по прочим видам деятельности" },
|
||||||
{ code: "2412", name: "отложенный налог на прибыль организаций", description: "в том числе" },
|
{ code: "2410", name: "Налог на прибыль организаций", description: "Сумма текущего и отложенного налога" },
|
||||||
|
{ code: "2411", name: "текущий налог на прибыль организаций", description: "Налог к уплате в текущем периоде" },
|
||||||
|
{ code: "2412", name: "отложенный налог на прибыль организаций", description: "Налог к уплате в будущих периодах" },
|
||||||
{ code: "2420", name: "Прибыль (убыток) от прекращаемой деятельности (за вычетом относящегося к ней налога на прибыль организаций)", description: "-" },
|
{ code: "2420", name: "Прибыль (убыток) от прекращаемой деятельности (за вычетом относящегося к ней налога на прибыль организаций)", description: "-" },
|
||||||
{ code: "2460", name: "Прочее", description: "-" },
|
{ code: "2460", name: "Прочее", description: "Корректировчки чистой прибыли" },
|
||||||
{ code: "2400", name: "Чистая прибыль (убыток)", description: "-" },
|
{ code: "2400", name: "Чистая прибыль (убыток)", description: "Финансовый результат, доступный к распределению акционерами (участниками) или накоплению" },
|
||||||
{ code: "2510", name: "Результат от переоценки внеоборотных активов, не включаемый в чистую прибыль (убыток)", description: "-" },
|
{ code: "2510", name: "Результат от переоценки внеоборотных активов, не включаемый в чистую прибыль (убыток)", description: "Изменение стоимости основных средств и нематериальных активов" },
|
||||||
{ code: "2520", name: "Результат от прочих операций, не включаемый в чистую прибыль (убыток)", description: "-" },
|
{ code: "2520", name: "Результат от прочих операций, не включаемый в чистую прибыль (убыток)", description: "Курсовые разницы по деятельности за рубежом" },
|
||||||
{ code: "2530", name: "Налог на прибыль организаций, относящийся к результатам переоценки внеоборотных активов и прочих операций, не включаемых в чистую прибыль (убыток)", description: "-" },
|
{ code: "2530", name: "Налог на прибыль организаций, относящийся к результатам переоценки внеоборотных активов и прочих операций, не включаемых в чистую прибыль (убыток)", description: "Налог с операций вне чистой прибыли" },
|
||||||
{ code: "2500", name: "Совокупный финансовый результат", description: "-" },
|
{ code: "2500", name: "Совокупный финансовый результат", description: "Сумма чистой прибыли (убытка) и прочего финансового результата" },
|
||||||
{ code: "2900", name: "Базовая прибыль (убыток) на акцию", description: "-" },
|
{ code: "2900", name: "Базовая прибыль (убыток) на акцию", description: "Чистая прибыль, поделенная на одну обыкновенную акцию" },
|
||||||
{ code: "2910", name: "Разводненная прибыль (убыток) на акцию", description: "-" },
|
{ code: "2910", name: "Разводненная прибыль (убыток) на акцию", description: "Прибыль на акцию в случае конвертации привилегированных акций в обыкновенные" },
|
||||||
{ code: "3100", name: "Величина капитала на 31 декабря года, предшествующего предыдущему", description: "-" },
|
{ code: "3100", name: "Величина капитала на 31 декабря года, предшествующего предыдущему", description: "-" },
|
||||||
{ code: "3110", name: "Корректировка в связи с изменением учетной политики", description: "-" },
|
{ code: "3110", name: "Корректировка в связи с изменением учетной политики", description: "-" },
|
||||||
{ code: "3120", name: "Корректировка в связи с исправлением ошибок", description: "-" },
|
{ code: "3120", name: "Корректировка в связи с исправлением ошибок", description: "-" },
|
||||||
|
|||||||
Reference in New Issue
Block a user