140 lines
4.6 KiB
Python
140 lines
4.6 KiB
Python
"""
|
|
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
|