Add initial implementations for forms and organization apps with serializers, factories, and admin configurations
Some checks failed
CI/CD Pipeline / Run Tests (push) Failing after 45s
CI/CD Pipeline / Code Quality Checks (push) Failing after 48s
CI/CD Pipeline / Build Docker Images (push) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (push) Has been skipped
CI/CD Pipeline / Deploy to Server (push) Has been skipped
Some checks failed
CI/CD Pipeline / Run Tests (push) Failing after 45s
CI/CD Pipeline / Code Quality Checks (push) Failing after 48s
CI/CD Pipeline / Build Docker Images (push) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (push) Has been skipped
CI/CD Pipeline / Deploy to Server (push) Has been skipped
This commit is contained in:
@@ -15,6 +15,7 @@ from apps.core.excel import (
|
||||
ParseResult,
|
||||
RowData,
|
||||
)
|
||||
from apps.core.reporting import ReportingPeriodParserMixin, VersionedReportServiceMixin
|
||||
from apps.core.services import BaseService, BulkOperationsMixin
|
||||
from apps.form_2.models import FormF2Record
|
||||
from apps.organization.services import OrganizationService
|
||||
@@ -24,7 +25,11 @@ from django.db.models import Count, Max
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FormF2Service(BulkOperationsMixin, BaseService[FormF2Record]):
|
||||
class FormF2Service(
|
||||
BulkOperationsMixin,
|
||||
VersionedReportServiceMixin[FormF2Record],
|
||||
BaseService[FormF2Record],
|
||||
):
|
||||
"""
|
||||
Сервис для работы с записями формы Ф-2.
|
||||
|
||||
@@ -36,11 +41,27 @@ class FormF2Service(BulkOperationsMixin, BaseService[FormF2Record]):
|
||||
|
||||
model = FormF2Record
|
||||
|
||||
@classmethod
|
||||
def get_by_organization(cls, organization_id):
|
||||
"""Получить записи организации."""
|
||||
return cls.get_queryset().filter(organization_id=organization_id)
|
||||
|
||||
@classmethod
|
||||
def get_by_batch(cls, batch_id: int):
|
||||
"""Получить записи по номеру загрузки."""
|
||||
return cls.get_queryset().filter(load_batch=batch_id)
|
||||
|
||||
@classmethod
|
||||
def get_by_load_batch(cls, batch_id: int):
|
||||
"""Совместимость со старым API сервиса."""
|
||||
return cls.get_by_batch(batch_id)
|
||||
|
||||
@classmethod
|
||||
def delete_by_load_batch(cls, batch_id: int) -> int:
|
||||
"""Удалить записи по номеру загрузки."""
|
||||
deleted_count, _ = cls.get_queryset().filter(load_batch=batch_id).delete()
|
||||
return deleted_count
|
||||
|
||||
@classmethod
|
||||
def get_next_batch_id(cls) -> int:
|
||||
"""Получить следующий номер загрузки."""
|
||||
@@ -60,7 +81,7 @@ class FormF2Service(BulkOperationsMixin, BaseService[FormF2Record]):
|
||||
)
|
||||
|
||||
|
||||
class FormF2Parser(BaseExcelParser[FormF2Record]):
|
||||
class FormF2Parser(ReportingPeriodParserMixin, BaseExcelParser[FormF2Record]):
|
||||
"""
|
||||
Парсер Excel файла формы Ф-2 (Бухгалтерский баланс).
|
||||
|
||||
@@ -81,71 +102,255 @@ class FormF2Parser(BaseExcelParser[FormF2Record]):
|
||||
"""Маппинг колонок Excel на поля модели."""
|
||||
return [
|
||||
# I. Внеоборотные активы
|
||||
ColumnMapping(4, "Нематериальные активы", "intangible_assets", field_type="decimal"),
|
||||
ColumnMapping(5, "Результаты исследований и разработок", "rd_results", field_type="decimal"),
|
||||
ColumnMapping(6, "Нематериальные поисковые активы", "intangible_search_assets", field_type="decimal"),
|
||||
ColumnMapping(7, "Материальные поисковые активы", "tangible_search_assets", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
4, "Нематериальные активы", "intangible_assets", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
5,
|
||||
"Результаты исследований и разработок",
|
||||
"rd_results",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
6,
|
||||
"Нематериальные поисковые активы",
|
||||
"intangible_search_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
7,
|
||||
"Материальные поисковые активы",
|
||||
"tangible_search_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(8, "Основные средства", "fixed_assets", field_type="decimal"),
|
||||
ColumnMapping(9, "Доходные вложения в материальные ценности", "profitable_investments", field_type="decimal"),
|
||||
ColumnMapping(10, "Финансовые вложения (внеоборотные)", "financial_investments_non_current", field_type="decimal"),
|
||||
ColumnMapping(11, "Отложенные налоговые активы", "deferred_tax_assets", field_type="decimal"),
|
||||
ColumnMapping(12, "Прочие внеоборотные активы", "other_non_current_assets", field_type="decimal"),
|
||||
ColumnMapping(13, "Итого внеоборотные активы", "total_non_current_assets", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
9,
|
||||
"Доходные вложения в материальные ценности",
|
||||
"profitable_investments",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
10,
|
||||
"Финансовые вложения (внеоборотные)",
|
||||
"financial_investments_non_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
11,
|
||||
"Отложенные налоговые активы",
|
||||
"deferred_tax_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
12,
|
||||
"Прочие внеоборотные активы",
|
||||
"other_non_current_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
13,
|
||||
"Итого внеоборотные активы",
|
||||
"total_non_current_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
# II. Оборотные активы
|
||||
ColumnMapping(14, "Запасы", "inventories", field_type="decimal"),
|
||||
ColumnMapping(15, "НДС по приобретённым ценностям", "vat_on_acquired_assets", field_type="decimal"),
|
||||
ColumnMapping(16, "Дебиторская задолженность", "receivables", field_type="decimal"),
|
||||
ColumnMapping(17, "Финансовые вложения (оборотные)", "financial_investments_current", field_type="decimal"),
|
||||
ColumnMapping(18, "Денежные средства и эквиваленты", "cash_and_equivalents", field_type="decimal"),
|
||||
ColumnMapping(19, "Прочие оборотные активы", "other_current_assets", field_type="decimal"),
|
||||
ColumnMapping(20, "Итого оборотные активы", "total_current_assets", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
15,
|
||||
"НДС по приобретённым ценностям",
|
||||
"vat_on_acquired_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
16, "Дебиторская задолженность", "receivables", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
17,
|
||||
"Финансовые вложения (оборотные)",
|
||||
"financial_investments_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
18,
|
||||
"Денежные средства и эквиваленты",
|
||||
"cash_and_equivalents",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
19,
|
||||
"Прочие оборотные активы",
|
||||
"other_current_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
20,
|
||||
"Итого оборотные активы",
|
||||
"total_current_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(21, "Баланс (актив)", "total_assets", field_type="decimal"),
|
||||
# III. Капитал и резервы
|
||||
ColumnMapping(22, "Уставный капитал", "authorized_capital", field_type="decimal"),
|
||||
ColumnMapping(23, "Собственные акции, выкупленные у акционеров", "own_shares_bought_back", field_type="decimal"),
|
||||
ColumnMapping(24, "Переоценка внеоборотных активов", "revaluation_of_non_current_assets", field_type="decimal"),
|
||||
ColumnMapping(25, "Добавочный капитал", "additional_capital", field_type="decimal"),
|
||||
ColumnMapping(26, "Резервный капитал", "reserve_capital", field_type="decimal"),
|
||||
ColumnMapping(27, "Нераспределённая прибыль", "retained_earnings", field_type="decimal"),
|
||||
ColumnMapping(28, "Итого капитал и резервы", "total_equity", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
22, "Уставный капитал", "authorized_capital", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
23,
|
||||
"Собственные акции, выкупленные у акционеров",
|
||||
"own_shares_bought_back",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
24,
|
||||
"Переоценка внеоборотных активов",
|
||||
"revaluation_of_non_current_assets",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
25, "Добавочный капитал", "additional_capital", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
26, "Резервный капитал", "reserve_capital", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
27,
|
||||
"Нераспределённая прибыль",
|
||||
"retained_earnings",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
28, "Итого капитал и резервы", "total_equity", field_type="decimal"
|
||||
),
|
||||
# IV. Долгосрочные обязательства
|
||||
ColumnMapping(29, "Заёмные средства (долгосрочные)", "borrowings_non_current", field_type="decimal"),
|
||||
ColumnMapping(30, "Отложенные налоговые обязательства", "deferred_tax_liabilities", field_type="decimal"),
|
||||
ColumnMapping(31, "Оценочные обязательства (долгосрочные)", "estimated_liabilities_non_current", field_type="decimal"),
|
||||
ColumnMapping(32, "Прочие обязательства (долгосрочные)", "other_liabilities_non_current", field_type="decimal"),
|
||||
ColumnMapping(33, "Итого долгосрочные обязательства", "total_non_current_liabilities", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
29,
|
||||
"Заёмные средства (долгосрочные)",
|
||||
"borrowings_non_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
30,
|
||||
"Отложенные налоговые обязательства",
|
||||
"deferred_tax_liabilities",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
31,
|
||||
"Оценочные обязательства (долгосрочные)",
|
||||
"estimated_liabilities_non_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
32,
|
||||
"Прочие обязательства (долгосрочные)",
|
||||
"other_liabilities_non_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
33,
|
||||
"Итого долгосрочные обязательства",
|
||||
"total_non_current_liabilities",
|
||||
field_type="decimal",
|
||||
),
|
||||
# V. Краткосрочные обязательства
|
||||
ColumnMapping(34, "Заёмные средства (краткосрочные)", "borrowings_current", field_type="decimal"),
|
||||
ColumnMapping(35, "Кредиторская задолженность", "payables", field_type="decimal"),
|
||||
ColumnMapping(36, "Доходы будущих периодов", "deferred_income", field_type="decimal"),
|
||||
ColumnMapping(37, "Оценочные обязательства (краткосрочные)", "estimated_liabilities_current", field_type="decimal"),
|
||||
ColumnMapping(38, "Прочие обязательства (краткосрочные)", "other_liabilities_current", field_type="decimal"),
|
||||
ColumnMapping(39, "Итого краткосрочные обязательства", "total_current_liabilities", field_type="decimal"),
|
||||
ColumnMapping(40, "Баланс (пассив)", "total_liabilities", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
34,
|
||||
"Заёмные средства (краткосрочные)",
|
||||
"borrowings_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
35, "Кредиторская задолженность", "payables", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
36, "Доходы будущих периодов", "deferred_income", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
37,
|
||||
"Оценочные обязательства (краткосрочные)",
|
||||
"estimated_liabilities_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
38,
|
||||
"Прочие обязательства (краткосрочные)",
|
||||
"other_liabilities_current",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
39,
|
||||
"Итого краткосрочные обязательства",
|
||||
"total_current_liabilities",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
40, "Баланс (пассив)", "total_liabilities", field_type="decimal"
|
||||
),
|
||||
# Отчёт о финансовых результатах
|
||||
ColumnMapping(41, "Выручка", "revenue", field_type="decimal"),
|
||||
ColumnMapping(42, "Себестоимость продаж", "cost_of_sales", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
42, "Себестоимость продаж", "cost_of_sales", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(43, "Валовая прибыль", "gross_profit", field_type="decimal"),
|
||||
ColumnMapping(44, "Коммерческие расходы", "selling_expenses", field_type="decimal"),
|
||||
ColumnMapping(45, "Управленческие расходы", "administrative_expenses", field_type="decimal"),
|
||||
ColumnMapping(46, "Прибыль от продаж", "profit_from_sales", field_type="decimal"),
|
||||
ColumnMapping(47, "Проценты к получению", "interest_receivable", field_type="decimal"),
|
||||
ColumnMapping(48, "Проценты к уплате", "interest_payable", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
44, "Коммерческие расходы", "selling_expenses", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
45,
|
||||
"Управленческие расходы",
|
||||
"administrative_expenses",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
46, "Прибыль от продаж", "profit_from_sales", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
47, "Проценты к получению", "interest_receivable", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
48, "Проценты к уплате", "interest_payable", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(49, "Прочие доходы", "other_income", field_type="decimal"),
|
||||
ColumnMapping(50, "Прочие расходы", "other_expenses", field_type="decimal"),
|
||||
ColumnMapping(51, "Прибыль до налогообложения", "profit_before_tax", field_type="decimal"),
|
||||
ColumnMapping(52, "Текущий налог на прибыль", "income_tax", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
51,
|
||||
"Прибыль до налогообложения",
|
||||
"profit_before_tax",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
52, "Текущий налог на прибыль", "income_tax", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(53, "Чистая прибыль", "net_profit", field_type="decimal"),
|
||||
# Дополнительные показатели
|
||||
ColumnMapping(54, "EBITDA", "ebitda", field_type="decimal"),
|
||||
ColumnMapping(55, "Амортизация", "depreciation", field_type="decimal"),
|
||||
ColumnMapping(56, "Оборотный капитал", "working_capital", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
56, "Оборотный капитал", "working_capital", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(57, "Чистый долг", "net_debt", field_type="decimal"),
|
||||
# Прошлый период
|
||||
ColumnMapping(58, "Баланс (актив) - прошлый период", "total_assets_prev", field_type="decimal"),
|
||||
ColumnMapping(59, "Баланс (пассив) - прошлый период", "total_liabilities_prev", field_type="decimal"),
|
||||
ColumnMapping(60, "Выручка - прошлый период", "revenue_prev", field_type="decimal"),
|
||||
ColumnMapping(61, "Чистая прибыль - прошлый период", "net_profit_prev", field_type="decimal"),
|
||||
ColumnMapping(
|
||||
58,
|
||||
"Баланс (актив) - прошлый период",
|
||||
"total_assets_prev",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
59,
|
||||
"Баланс (пассив) - прошлый период",
|
||||
"total_liabilities_prev",
|
||||
field_type="decimal",
|
||||
),
|
||||
ColumnMapping(
|
||||
60, "Выручка - прошлый период", "revenue_prev", field_type="decimal"
|
||||
),
|
||||
ColumnMapping(
|
||||
61,
|
||||
"Чистая прибыль - прошлый период",
|
||||
"net_profit_prev",
|
||||
field_type="decimal",
|
||||
),
|
||||
]
|
||||
|
||||
def get_next_batch_id(self) -> int:
|
||||
@@ -153,8 +358,14 @@ class FormF2Parser(BaseExcelParser[FormF2Record]):
|
||||
return FormF2Service.get_next_batch_id()
|
||||
|
||||
@transaction.atomic
|
||||
def create_record(self, row_data: RowData, batch_id: int) -> FormF2Record:
|
||||
def create_record(
|
||||
self,
|
||||
row_data: RowData | dict[str, Any],
|
||||
batch_id: int | None = None,
|
||||
) -> FormF2Record:
|
||||
"""Создать запись формы Ф-2."""
|
||||
row_data = self._normalize_row_data(row_data)
|
||||
batch_id = batch_id or getattr(self, "load_batch", self.get_next_batch_id())
|
||||
org, _ = OrganizationService.get_or_create_by_inn(
|
||||
inn=row_data.inn,
|
||||
defaults={
|
||||
@@ -165,16 +376,23 @@ class FormF2Parser(BaseExcelParser[FormF2Record]):
|
||||
},
|
||||
)
|
||||
|
||||
record = FormF2Record.objects.create(
|
||||
record = FormF2Service.create_versioned_record(
|
||||
organization=org,
|
||||
load_batch=batch_id,
|
||||
report_year=self.report_year,
|
||||
report_quarter=self.report_quarter,
|
||||
**row_data.fields,
|
||||
)
|
||||
|
||||
return record
|
||||
|
||||
|
||||
def parse_form_f2_file(file) -> ParseResult:
|
||||
def parse_form_f2_file(
|
||||
file,
|
||||
*,
|
||||
report_year: int,
|
||||
report_quarter: int | None = None,
|
||||
) -> ParseResult:
|
||||
"""
|
||||
Парсит Excel файл формы Ф-2.
|
||||
|
||||
@@ -184,5 +402,5 @@ def parse_form_f2_file(file) -> ParseResult:
|
||||
Returns:
|
||||
ParseResult с результатами парсинга
|
||||
"""
|
||||
parser = FormF2Parser()
|
||||
parser = FormF2Parser(report_year=report_year, report_quarter=report_quarter)
|
||||
return parser.parse(file)
|
||||
|
||||
Reference in New Issue
Block a user