""" Views для приложения парсеров. """ import hashlib from pathlib import Path from apps.parsers.models import FinancialReport from apps.parsers.serializers import ( FinancialReportDetailSerializer, FinancialReportSerializer, FNSFileUploadSerializer, ) from apps.parsers.tasks import process_fns_file from django.conf import settings from drf_yasg.utils import swagger_auto_schema from rest_framework import status from rest_framework.parsers import MultiPartParser from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import ReadOnlyModelViewSet FNS_TAG = "ФНС - Бухгалтерская отчетность" class FinancialReportViewSet(ReadOnlyModelViewSet): """ API для просмотра финансовых отчетов ФНС. list: Получить список всех отчетов. Поддерживает фильтрацию по: ogrn, external_id, status. retrieve: Получить детальную информацию об отчете, включая все строки. """ queryset = FinancialReport.objects.all().order_by("-created_at") filterset_fields = ["ogrn", "external_id", "status", "source"] def get_serializer_class(self): if self.action == "retrieve": return FinancialReportDetailSerializer return FinancialReportSerializer @swagger_auto_schema(tags=[FNS_TAG]) def list(self, request, *args, **kwargs): return super().list(request, *args, **kwargs) @swagger_auto_schema(tags=[FNS_TAG]) def retrieve(self, request, *args, **kwargs): return super().retrieve(request, *args, **kwargs) class FNSReportUploadView(APIView): """ API для загрузки файлов бухгалтерской отчетности ФНС. POST: Пакетная загрузка файлов. Файлы сохраняются во временную директорию и ставятся в очередь на обработку через Celery. Request: multipart/form-data с полем 'files' (можно несколько файлов) Response: { "queued": 3, "skipped": 1, "task_ids": ["uuid1", "uuid2", "uuid3"] } """ parser_classes = [MultiPartParser] @swagger_auto_schema(tags=[FNS_TAG], request_body=FNSFileUploadSerializer) def post(self, request): serializer = FNSFileUploadSerializer(data=request.data) serializer.is_valid(raise_exception=True) files = serializer.validated_data["files"] task_ids = [] queued = 0 skipped = 0 # Создаём директорию для загрузки upload_dir = Path(settings.FNS_WATCH_DIRECTORY) upload_dir.mkdir(parents=True, exist_ok=True) from apps.parsers.services import FNSReportService for file in files: # Вычисляем хеш файла file_content = file.read() file_hash = hashlib.sha256(file_content).hexdigest() file.seek(0) # Проверяем дубликат if FNSReportService.exists_by_hash(file_hash): skipped += 1 continue # Сохраняем файл file_path = upload_dir / file.name with open(file_path, "wb") as f: for chunk in file.chunks(): f.write(chunk) # Ставим в очередь task = process_fns_file.delay(str(file_path)) task_ids.append(task.id) queued += 1 return Response( { "queued": queued, "skipped": skipped, "task_ids": task_ids, }, status=status.HTTP_202_ACCEPTED, )