feat: export organization source records
Some checks failed
CI/CD Pipeline / Quality Gate (push) Failing after 9s
CI/CD Pipeline / Build and Push Images (push) Has been skipped
CI/CD Pipeline / Internal Notify (push) Successful in 1s
CI/CD Pipeline / Deploy Dev via Compose (push) Has been skipped

This commit is contained in:
2026-06-09 12:38:18 +02:00
parent 71eac688f2
commit 7aa67fc192
4 changed files with 613 additions and 1 deletions

View File

@@ -11,12 +11,14 @@ from django.conf import settings
from django.core.cache import cache
from django.db.models import CharField, Q
from django.db.models.functions import Cast
from django.http import HttpResponse
from django_filters import rest_framework as filters
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.permissions import AllowAny, IsAdminUser, IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet
@@ -35,9 +37,11 @@ from organizations.models import (
from organizations.serializers import (
OrganizationSerializer,
OrganizationSourceExtensionSerializer,
OrganizationSourceRecordExportRequestSerializer,
OrganizationSourceRecordListResponseSerializer,
OrganizationSourceRecordSerializer,
)
from organizations.source_record_export import build_source_records_export_archive
ORGANIZATIONS_TAG = swagger_tag("Организации", "Organizations")
FALSE_QUERY_VALUES = {"0", "false", "no", "off"}
@@ -449,6 +453,8 @@ class OrganizationSourceRecordViewSet(ReadOnlyModelViewSet):
ordering = ["-created_at", "-uid"]
def get_permissions(self):
if self.action == "export":
return [IsAdminUser()]
if getattr(settings, "ORGANIZATIONS_V2_ALLOW_ANONYMOUS", False):
return [AllowAny()]
return super().get_permissions()
@@ -553,3 +559,39 @@ class OrganizationSourceRecordViewSet(ReadOnlyModelViewSet):
)
def list(self, request, *args: Any, **kwargs: Any) -> Response:
return super().list(request, *args, **kwargs)
@swagger_auto_schema(
tags=[ORGANIZATIONS_TAG],
operation_id="v2_organization_source_records_export",
operation_summary="Выгрузить записи источников",
operation_description=(
"Формирует ZIP-архив с одним файлом на выбранную группу источников. "
"Финансово-экономические показатели всегда выгружаются в JSON."
),
request_body=OrganizationSourceRecordExportRequestSerializer,
responses={
200: openapi.Response(
description="ZIP-архив записей источников.",
schema=openapi.Schema(type=openapi.TYPE_FILE),
),
400: "Некорректные параметры выгрузки.",
403: "Доступ разрешён только администраторам.",
},
)
@action(detail=False, methods=["post"], url_path="export")
def export(self, request, *args: Any, **kwargs: Any) -> HttpResponse:
serializer = OrganizationSourceRecordExportRequestSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
package = build_source_records_export_archive(
source_groups=serializer.validated_data["sources"],
export_format=serializer.validated_data["format"],
)
response = HttpResponse(package.archive_bytes, content_type="application/zip")
response.status_code = status.HTTP_200_OK
response[
"Content-Disposition"
] = f'attachment; filename="{package.archive_name}"'
response["Content-Length"] = str(len(package.archive_bytes))
response["X-Source-Export-Files"] = str(package.files_count)
return response