feat: migrate parser data to source records
Some checks failed
CI/CD Pipeline / Quality Gate (push) Failing after 14s
CI/CD Pipeline / Build and Push Images (push) Has been skipped
CI/CD Pipeline / Deploy Dev in Dokploy (push) Has been skipped
CI/CD Pipeline / Internal Notify (push) Successful in 0s

This commit is contained in:
2026-05-19 20:21:31 +02:00
parent 1c7c7238be
commit b8a18d6da4
46 changed files with 2689 additions and 6179 deletions

View File

@@ -36,6 +36,7 @@ from organizations.models import (
from organizations.serializers import (
OrganizationSerializer,
OrganizationSourceExtensionSerializer,
OrganizationSourceRecordListResponseSerializer,
OrganizationSourceRecordSerializer,
)
@@ -181,19 +182,15 @@ SOURCE_RECORD_LIST_PARAMS = [
"статусу, датам, URL и исходным данным записи."
),
),
_query_parameter("page", description="Номер страницы.", param_type=openapi.TYPE_INTEGER),
_query_parameter(
"page", description="Номер страницы.", param_type=openapi.TYPE_INTEGER
),
_query_parameter(
"page_size",
description="Размер страницы. Максимум 100.",
param_type=openapi.TYPE_INTEGER,
),
]
ORGANIZATION_LIST_RESPONSE = openapi.Response(
description="Пагинированный список организаций v2 с компактными источниками.",
)
ORGANIZATION_DETAIL_RESPONSE = openapi.Response(
description="Карточка организации v2.",
)
class CachedReadOnlyMixin:
@@ -300,7 +297,12 @@ class OrganizationViewSet(CachedReadOnlyMixin, ReadOnlyModelViewSet):
"записи доступны через endpoints расширений источников."
),
manual_parameters=ORGANIZATION_LIST_PARAMS,
responses={200: ORGANIZATION_LIST_RESPONSE},
responses={
200: openapi.Response(
"Пагинированный список организаций.",
OrganizationSerializer(many=True),
)
},
)
def list(self, request, *args: Any, **kwargs: Any) -> Response:
return self._cached_response(
@@ -317,7 +319,13 @@ class OrganizationViewSet(CachedReadOnlyMixin, ReadOnlyModelViewSet):
"группами источников."
),
manual_parameters=ORGANIZATION_DETAIL_PARAMS,
responses={200: ORGANIZATION_DETAIL_RESPONSE, 404: "Организация не найдена"},
responses={
200: openapi.Response(
"Карточка организации.",
OrganizationSerializer,
),
404: "Организация не найдена",
},
)
def retrieve(self, request, *args: Any, **kwargs: Any) -> Response:
return self._cached_response(
@@ -330,7 +338,10 @@ class OrganizationViewSet(CachedReadOnlyMixin, ReadOnlyModelViewSet):
operation_id="v2_organizations_sources",
operation_summary="Источники организации",
operation_description="Возвращает source extensions одной организации.",
responses={200: "Список source extensions", 404: "Организация не найдена"},
responses={
200: OrganizationSourceExtensionSerializer(many=True),
404: "Организация не найдена",
},
)
@action(detail=True, methods=["get"])
def sources(self, request, *args: Any, **kwargs: Any) -> Response:
@@ -345,7 +356,9 @@ class OrganizationViewSet(CachedReadOnlyMixin, ReadOnlyModelViewSet):
class OrganizationSourceExtensionViewSet(ReadOnlyModelViewSet):
"""Read-only API for source extensions and their records."""
queryset = OrganizationSourceExtension.objects.select_related("organization").order_by(
queryset = OrganizationSourceExtension.objects.select_related(
"organization"
).order_by(
"organization__name",
"source_group",
)
@@ -367,7 +380,10 @@ class OrganizationSourceExtensionViewSet(ReadOnlyModelViewSet):
operation_summary="Записи источника организации",
operation_description="Возвращает записи под конкретным source extension.",
manual_parameters=SOURCE_EXTENSION_PATH_PARAMS,
responses={200: "Пагинированный список записей источника", 404: "Источник не найден"},
responses={
200: OrganizationSourceRecordListResponseSerializer,
404: "Источник не найден",
},
)
@action(detail=True, methods=["get"])
def records(self, request, *args: Any, **kwargs: Any) -> Response:
@@ -388,10 +404,14 @@ class OrganizationSourceExtensionViewSet(ReadOnlyModelViewSet):
class OrganizationSourceRecordViewSet(ReadOnlyModelViewSet):
"""Read-only flat API for source records across source extensions."""
queryset = OrganizationSourceRecord.objects.select_related(
"extension",
"extension__organization",
).prefetch_related("financial_lines").order_by("-created_at", "-uid")
queryset = (
OrganizationSourceRecord.objects.select_related(
"extension",
"extension__organization",
)
.prefetch_related("financial_lines")
.order_by("-created_at", "-uid")
)
serializer_class = OrganizationSourceRecordSerializer
permission_classes = [IsAuthenticated]
lookup_field = "uid"
@@ -465,7 +485,10 @@ class OrganizationSourceRecordViewSet(ReadOnlyModelViewSet):
@staticmethod
def _registry_membership_query():
inn_values, ogrn_values = OrganizationFilter._registry_identity_value_querysets()
(
inn_values,
ogrn_values,
) = OrganizationFilter._registry_identity_value_querysets()
return (
Q(extension__organization__inn__in=inn_values)
@@ -552,7 +575,7 @@ class OrganizationSourceRecordViewSet(ReadOnlyModelViewSet):
"данными организации и финансовыми строками при наличии."
),
manual_parameters=SOURCE_RECORD_LIST_PARAMS,
responses={200: "Пагинированный список записей источников"},
responses={200: OrganizationSourceRecordListResponseSerializer},
)
def list(self, request, *args: Any, **kwargs: Any) -> Response:
return super().list(request, *args, **kwargs)