from django.http import HttpResponse from rest_framework import decorators, mixins, response, status, viewsets from apps.core.errors import error_response from apps.orders.models import ProcessingOrder from apps.rbac.permissions import ActionPermission from apps.reports.models import FinalReport, ReportDefinition from apps.reports.serializers import FinalReportSerializer, ReportDefinitionSerializer from apps.reports.services import ReportService class ReportDefinitionViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): queryset = ReportDefinition.objects.prefetch_related("fields").all() serializer_class = ReportDefinitionSerializer permission_classes = [ActionPermission] code_map = {"list": "report.view", "retrieve": "report.view"} class FinalReportViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): queryset = FinalReport.objects.select_related("order").all() serializer_class = FinalReportSerializer permission_classes = [ActionPermission] code_map = { "list": "report.view", "retrieve": "report.view", "generate": "report.create", "pdf": "report.view", } def get_queryset(self): user = self.request.user qs = FinalReport.objects.select_related("order").all() if user.is_superuser: return qs return qs.filter(order__customer__user=user) @decorators.action(detail=False, methods=["post"]) def generate(self, request): order_id = request.data.get("order") if not order_id: return response.Response( error_response("ORDER_REQUIRED", "An order id is required."), status=status.HTTP_400_BAD_REQUEST, ) try: order = ProcessingOrder.objects.select_related("customer").get(pk=order_id) except ProcessingOrder.DoesNotExist: return response.Response( error_response("ORDER_NOT_FOUND", "Order not found."), status=status.HTTP_404_NOT_FOUND, ) if not request.user.is_superuser and order.customer.user_id != request.user.id: return response.Response( error_response("FORBIDDEN", "You do not have access to this order."), status=status.HTTP_403_FORBIDDEN, ) report = ReportService().generate(order) return response.Response(FinalReportSerializer(report).data) @decorators.action(detail=True, methods=["get"]) def pdf(self, request, pk=None): report = self.get_object() pdf_bytes = ReportService().render_pdf(report) filename = f"{report.order.order_number}.pdf" return HttpResponse( pdf_bytes, content_type="application/pdf", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, )