feat(api): полное API для всех парсеров с документацией
This commit is contained in:
@@ -1,53 +1,296 @@
|
||||
"""
|
||||
Views для приложения парсеров.
|
||||
|
||||
Все ViewSets только для чтения (GET, GET list).
|
||||
Добавление и удаление данных - через парсеры и админку.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
from apps.parsers.models import FinancialReport
|
||||
from apps.parsers.models import (
|
||||
FinancialReport,
|
||||
IndustrialCertificateRecord,
|
||||
InspectionRecord,
|
||||
ManufacturerRecord,
|
||||
ParserLoadLog,
|
||||
ProcurementRecord,
|
||||
Proxy,
|
||||
)
|
||||
from apps.parsers.serializers import (
|
||||
FinancialReportDetailSerializer,
|
||||
FinancialReportSerializer,
|
||||
FNSFileUploadSerializer,
|
||||
IndustrialCertificateSerializer,
|
||||
InspectionSerializer,
|
||||
ManufacturerSerializer,
|
||||
ParserLoadLogSerializer,
|
||||
ProcurementSerializer,
|
||||
ProxySerializer,
|
||||
)
|
||||
from apps.parsers.tasks import process_fns_file
|
||||
from django.conf import settings
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework import status
|
||||
from rest_framework.parsers import MultiPartParser
|
||||
from rest_framework.permissions import IsAdminUser, IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
||||
|
||||
# =============================================================================
|
||||
# Swagger Tags (для группировки в документации)
|
||||
# =============================================================================
|
||||
|
||||
MINPROMTORG_TAG = "Минпромторг"
|
||||
PROVERKI_TAG = "Единый реестр проверок"
|
||||
ZAKUPKI_TAG = "Государственные закупки"
|
||||
FNS_TAG = "ФНС - Бухгалтерская отчетность"
|
||||
SYSTEM_TAG = "Системные"
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Минпромторг - Сертификаты промышленного производства
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class IndustrialCertificateViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра сертификатов промышленного производства.
|
||||
|
||||
Данные загружаются из Минпромторга.
|
||||
Только чтение - добавление через парсер/админку.
|
||||
"""
|
||||
|
||||
queryset = IndustrialCertificateRecord.objects.all().order_by("-created_at")
|
||||
serializer_class = IndustrialCertificateSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
filterset_fields = ["inn", "ogrn", "certificate_number", "load_batch"]
|
||||
search_fields = ["organisation_name", "certificate_number", "inn", "ogrn"]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[MINPROMTORG_TAG],
|
||||
operation_summary="Список сертификатов",
|
||||
operation_description=(
|
||||
"Возвращает список сертификатов промышленного производства.\n"
|
||||
"Поддерживает фильтрацию по: inn, ogrn, certificate_number, load_batch.\n"
|
||||
"Поддерживает поиск по: organisation_name, certificate_number, inn, ogrn."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[MINPROMTORG_TAG],
|
||||
operation_summary="Детали сертификата",
|
||||
operation_description="Возвращает информацию о конкретном сертификате.",
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Минпромторг - Реестр производителей
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class ManufacturerViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра реестра производителей.
|
||||
|
||||
Данные загружаются из Минпромторга.
|
||||
Только чтение - добавление через парсер/админку.
|
||||
"""
|
||||
|
||||
queryset = ManufacturerRecord.objects.all().order_by("-created_at")
|
||||
serializer_class = ManufacturerSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
filterset_fields = ["inn", "ogrn", "load_batch"]
|
||||
search_fields = ["full_legal_name", "inn", "ogrn", "address"]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[MINPROMTORG_TAG],
|
||||
operation_summary="Список производителей",
|
||||
operation_description=(
|
||||
"Возвращает список производителей из реестра Минпромторга.\n"
|
||||
"Поддерживает фильтрацию по: inn, ogrn, load_batch.\n"
|
||||
"Поддерживает поиск по: full_legal_name, inn, ogrn, address."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[MINPROMTORG_TAG],
|
||||
operation_summary="Детали производителя",
|
||||
operation_description="Возвращает информацию о конкретном производителе.",
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Единый реестр проверок (proverki.gov.ru)
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class InspectionViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра проверок из Единого реестра проверок.
|
||||
|
||||
Данные из ФГИС "Единый реестр проверок" (Генпрокуратура РФ).
|
||||
Поддерживает ФЗ-294 (традиционные) и ФЗ-248 (новые с 2021).
|
||||
Только чтение - добавление через парсер/админку.
|
||||
"""
|
||||
|
||||
queryset = InspectionRecord.objects.all().order_by("-created_at")
|
||||
serializer_class = InspectionSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
filterset_fields = [
|
||||
"inn",
|
||||
"ogrn",
|
||||
"registration_number",
|
||||
"is_federal_law_248",
|
||||
"data_year",
|
||||
"data_month",
|
||||
"load_batch",
|
||||
]
|
||||
search_fields = [
|
||||
"organisation_name",
|
||||
"registration_number",
|
||||
"inn",
|
||||
"ogrn",
|
||||
"control_authority",
|
||||
]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[PROVERKI_TAG],
|
||||
operation_summary="Список проверок",
|
||||
operation_description=(
|
||||
"Возвращает список проверок из Единого реестра.\n"
|
||||
"Поддерживает фильтрацию по: inn, ogrn, registration_number, "
|
||||
"is_federal_law_248, data_year, data_month, load_batch.\n"
|
||||
"Поддерживает поиск по: organisation_name, registration_number, "
|
||||
"inn, ogrn, control_authority."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[PROVERKI_TAG],
|
||||
operation_summary="Детали проверки",
|
||||
operation_description="Возвращает информацию о конкретной проверке.",
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Государственные закупки (zakupki.gov.ru)
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class ProcurementViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра государственных закупок.
|
||||
|
||||
Данные из ЕИС zakupki.gov.ru.
|
||||
Поддерживает 44-ФЗ и 223-ФЗ.
|
||||
Только чтение - добавление через парсер/админку.
|
||||
"""
|
||||
|
||||
queryset = ProcurementRecord.objects.all().order_by("-created_at")
|
||||
serializer_class = ProcurementSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
filterset_fields = [
|
||||
"customer_inn",
|
||||
"customer_ogrn",
|
||||
"purchase_number",
|
||||
"law_type",
|
||||
"status",
|
||||
"region_code",
|
||||
"data_year",
|
||||
"data_month",
|
||||
"load_batch",
|
||||
]
|
||||
search_fields = [
|
||||
"purchase_name",
|
||||
"purchase_number",
|
||||
"customer_name",
|
||||
"customer_inn",
|
||||
"customer_ogrn",
|
||||
]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[ZAKUPKI_TAG],
|
||||
operation_summary="Список закупок",
|
||||
operation_description=(
|
||||
"Возвращает список государственных закупок.\n"
|
||||
"Поддерживает фильтрацию по: customer_inn, customer_ogrn, "
|
||||
"purchase_number, law_type, status, region_code, "
|
||||
"data_year, data_month, load_batch.\n"
|
||||
"Поддерживает поиск по: purchase_name, purchase_number, "
|
||||
"customer_name, customer_inn, customer_ogrn."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[ZAKUPKI_TAG],
|
||||
operation_summary="Детали закупки",
|
||||
operation_description="Возвращает информацию о конкретной закупке.",
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# ФНС - Бухгалтерская отчетность
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class FinancialReportViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра финансовых отчетов ФНС.
|
||||
|
||||
list:
|
||||
Получить список всех отчетов.
|
||||
Поддерживает фильтрацию по: ogrn, external_id, status.
|
||||
|
||||
retrieve:
|
||||
Получить детальную информацию об отчете, включая все строки.
|
||||
Данные загружаются из Excel файлов (fin_{id}_{ogrn}.xlsx).
|
||||
Только чтение - добавление через загрузку файлов.
|
||||
"""
|
||||
|
||||
queryset = FinancialReport.objects.all().order_by("-created_at")
|
||||
filterset_fields = ["ogrn", "external_id", "status", "source"]
|
||||
permission_classes = [IsAuthenticated]
|
||||
filterset_fields = ["ogrn", "external_id", "status", "source", "load_batch"]
|
||||
search_fields = ["ogrn", "external_id", "file_name"]
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == "retrieve":
|
||||
return FinancialReportDetailSerializer
|
||||
return FinancialReportSerializer
|
||||
|
||||
@swagger_auto_schema(tags=[FNS_TAG])
|
||||
@swagger_auto_schema(
|
||||
tags=[FNS_TAG],
|
||||
operation_summary="Список отчетов",
|
||||
operation_description=(
|
||||
"Возвращает список финансовых отчетов ФНС.\n"
|
||||
"Поддерживает фильтрацию по: ogrn, external_id, status, "
|
||||
"source, load_batch.\n"
|
||||
"Поддерживает поиск по: ogrn, external_id, file_name."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(tags=[FNS_TAG])
|
||||
@swagger_auto_schema(
|
||||
tags=[FNS_TAG],
|
||||
operation_summary="Детали отчета",
|
||||
operation_description=(
|
||||
"Возвращает детальную информацию об отчете, "
|
||||
"включая все строки бухгалтерской отчетности."
|
||||
),
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
@@ -56,25 +299,59 @@ class FNSReportUploadView(APIView):
|
||||
"""
|
||||
API для загрузки файлов бухгалтерской отчетности ФНС.
|
||||
|
||||
POST:
|
||||
Пакетная загрузка файлов.
|
||||
Файлы сохраняются во временную директорию и ставятся в очередь
|
||||
на обработку через Celery.
|
||||
|
||||
Request:
|
||||
multipart/form-data с полем 'files' (можно несколько файлов)
|
||||
|
||||
Response:
|
||||
{
|
||||
"queued": 3,
|
||||
"skipped": 1,
|
||||
"task_ids": ["uuid1", "uuid2", "uuid3"]
|
||||
}
|
||||
Файлы сохраняются во временную директорию и ставятся в очередь
|
||||
на обработку через Celery.
|
||||
"""
|
||||
|
||||
parser_classes = [MultiPartParser]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(tags=[FNS_TAG], request_body=FNSFileUploadSerializer)
|
||||
@swagger_auto_schema(
|
||||
tags=[FNS_TAG],
|
||||
operation_summary="Загрузка файлов",
|
||||
operation_description=(
|
||||
"Пакетная загрузка файлов бухгалтерской отчетности.\n\n"
|
||||
"**Формат файла:** fin_{id}_{ogrn}.xlsx\n\n"
|
||||
"**Ответ:**\n"
|
||||
"- queued: количество файлов в очереди\n"
|
||||
"- skipped: количество пропущенных (дубликаты)\n"
|
||||
"- task_ids: ID задач для отслеживания статуса"
|
||||
),
|
||||
manual_parameters=[
|
||||
openapi.Parameter(
|
||||
name="files",
|
||||
in_=openapi.IN_FORM,
|
||||
type=openapi.TYPE_FILE,
|
||||
required=True,
|
||||
description="Файл(ы) для загрузки (fin_*.xlsx)",
|
||||
),
|
||||
],
|
||||
consumes=["multipart/form-data"],
|
||||
responses={
|
||||
202: openapi.Response(
|
||||
description="Файлы приняты в обработку",
|
||||
schema=openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
"queued": openapi.Schema(
|
||||
type=openapi.TYPE_INTEGER,
|
||||
description="Количество файлов в очереди",
|
||||
),
|
||||
"skipped": openapi.Schema(
|
||||
type=openapi.TYPE_INTEGER,
|
||||
description="Количество пропущенных",
|
||||
),
|
||||
"task_ids": openapi.Schema(
|
||||
type=openapi.TYPE_ARRAY,
|
||||
items=openapi.Schema(type=openapi.TYPE_STRING),
|
||||
description="ID задач Celery",
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
400: "Ошибка валидации файлов",
|
||||
},
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = FNSFileUploadSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
@@ -120,3 +397,76 @@ class FNSReportUploadView(APIView):
|
||||
},
|
||||
status=status.HTTP_202_ACCEPTED,
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Системные (логи загрузок, прокси)
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class ParserLoadLogViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра логов загрузок парсеров.
|
||||
|
||||
Информация о каждой загрузке данных из внешних источников.
|
||||
Только для администраторов.
|
||||
"""
|
||||
|
||||
queryset = ParserLoadLog.objects.all().order_by("-created_at")
|
||||
serializer_class = ParserLoadLogSerializer
|
||||
permission_classes = [IsAdminUser]
|
||||
filterset_fields = ["source", "status", "batch_id"]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[SYSTEM_TAG],
|
||||
operation_summary="Список логов загрузок",
|
||||
operation_description=(
|
||||
"Возвращает историю загрузок данных парсерами.\n"
|
||||
"Доступно только администраторам.\n"
|
||||
"Поддерживает фильтрацию по: source, status, batch_id."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[SYSTEM_TAG],
|
||||
operation_summary="Детали загрузки",
|
||||
operation_description="Возвращает информацию о конкретной загрузке.",
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ProxyViewSet(ReadOnlyModelViewSet):
|
||||
"""
|
||||
API для просмотра списка прокси-серверов.
|
||||
|
||||
Используется для отладки и мониторинга парсеров.
|
||||
Только для администраторов.
|
||||
"""
|
||||
|
||||
queryset = Proxy.objects.all().order_by("-last_used_at")
|
||||
serializer_class = ProxySerializer
|
||||
permission_classes = [IsAdminUser]
|
||||
filterset_fields = ["is_active"]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[SYSTEM_TAG],
|
||||
operation_summary="Список прокси",
|
||||
operation_description=(
|
||||
"Возвращает список прокси-серверов для парсеров.\n"
|
||||
"Доступно только администраторам.\n"
|
||||
"Поддерживает фильтрацию по: is_active."
|
||||
),
|
||||
)
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[SYSTEM_TAG],
|
||||
operation_summary="Детали прокси",
|
||||
operation_description="Возвращает информацию о конкретном прокси.",
|
||||
)
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return super().retrieve(request, *args, **kwargs)
|
||||
|
||||
Reference in New Issue
Block a user