""" API формы Ф-2. Содержит: - FormF2UploadView - загрузка файла - FormF2RecordViewSet - просмотр записей """ import logging from apps.core.upload_contracts import ( build_upload_error_response, build_upload_success_payload, build_upload_validation_response, ) from apps.core.viewsets import ReadOnlyViewSet from apps.form_2.models import FormF2Record from apps.form_2.serializers import ( FormF2ParseResultSerializer, FormF2RecordListSerializer, FormF2RecordSerializer, FormF2UploadSerializer, ) from apps.form_2.services import parse_form_f2_file from apps.form_2.tasks import process_form_f2_file from rest_framework import status from rest_framework.parsers import MultiPartParser from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView logger = logging.getLogger(__name__) # Порог для фоновой обработки (байты) BACKGROUND_THRESHOLD = 1024 * 1024 # 1MB class FormF2UploadView(APIView): """ Загрузка файла формы Ф-2. POST /api/v1/forms/f2/upload/ """ parser_classes = [MultiPartParser] def post(self, request): """Загрузка и обработка файла.""" serializer = FormF2UploadSerializer(data=request.data) if not serializer.is_valid(): return build_upload_validation_response(serializer.errors) file = serializer.validated_data["file"] report_year = serializer.validated_data["report_year"] report_quarter = serializer.validated_data.get("report_quarter") # Для больших файлов - фоновая обработка if file.size > BACKGROUND_THRESHOLD: file_content = file.read() task = process_form_f2_file.delay( file_content, file.name, report_year, report_quarter, ) return Response( build_upload_success_payload( form="f2", report_year=report_year, report_quarter=report_quarter, status="queued", job_id=task.id, ), status=status.HTTP_202_ACCEPTED, ) # Синхронная обработка try: result = parse_form_f2_file( file, report_year=report_year, report_quarter=report_quarter, ) result_serializer = FormF2ParseResultSerializer(result) return Response( build_upload_success_payload( form="f2", report_year=report_year, report_quarter=report_quarter, status="done", result=result_serializer.data, ), status=status.HTTP_200_OK, ) except Exception as e: logger.exception("Ошибка обработки файла Ф-2") return build_upload_error_response( error_code="processing_error", error_message=str(e), status_code=status.HTTP_400_BAD_REQUEST, ) class FormF2RecordViewSet(ReadOnlyViewSet[FormF2Record]): """ ViewSet для записей формы Ф-2. GET /api/v1/forms/f2/records/ - список записей GET /api/v1/forms/f2/records/{id}/ - детали записи """ queryset = FormF2Record.objects.select_related("organization").filter( is_active_version=True ) serializer_class = FormF2RecordSerializer permission_classes = [IsAuthenticated] def get_serializer_class(self): """Выбор сериализатора в зависимости от действия.""" if self.action == "list": return FormF2RecordListSerializer return FormF2RecordSerializer def get_queryset(self): """Фильтрация по batch_id.""" queryset = super().get_queryset() batch_id = self.request.query_params.get("batch_id") report_year = self.request.query_params.get("report_year") report_quarter = self.request.query_params.get("report_quarter") if batch_id: queryset = queryset.filter(load_batch=batch_id) if report_year: queryset = queryset.filter(report_year=report_year) if report_quarter: queryset = queryset.filter(report_quarter=report_quarter) return queryset