from rest_framework import decorators, mixins, response, status, viewsets from apps.core.errors import ApiError, error_response from apps.orders.models import ProcessingOrder from apps.orders.serializers import ( ConfirmSerializer, OrderCreateSerializer, ProcessingOrderSerializer, StepSelectionSerializer, WeighingSerializer, ) from apps.orders.services import OrderService from apps.rbac.permissions import ActionPermission from apps.reservations.models import Reservation from apps.workflows.models import Workflow class ProcessingOrderViewSet( mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet ): serializer_class = ProcessingOrderSerializer permission_classes = [ActionPermission] code_map = { "list": "processing.view", "retrieve": "processing.view", "create": "reservation.create", "weigh": "weighing.create", "select_steps": "reservation.update", "confirm": "reservation.update", } service = OrderService() def get_queryset(self): user = self.request.user qs = ProcessingOrder.objects.select_related("customer", "workflow_version").all() if user.is_superuser: return qs return qs.filter(customer__user=user) def create(self, request, *args, **kwargs): input_serializer = OrderCreateSerializer(data=request.data) input_serializer.is_valid(raise_exception=True) try: reservation = Reservation.objects.get(pk=input_serializer.validated_data["reservation"]) except Reservation.DoesNotExist: return response.Response( error_response("RESERVATION_NOT_FOUND", "Reservation not found."), status=status.HTTP_404_NOT_FOUND, ) workflow_id = input_serializer.validated_data.get("workflow") workflow = None if workflow_id: try: workflow = Workflow.objects.get(pk=workflow_id) except Workflow.DoesNotExist: return response.Response( error_response("WORKFLOW_NOT_FOUND", "Workflow not found."), status=status.HTTP_404_NOT_FOUND, ) try: order = self.service.create_from_reservation(reservation, workflow) except ApiError as exc: return response.Response(error_response(exc.code, exc.message, exc.details), status=exc.status) return response.Response(ProcessingOrderSerializer(order).data, status=status.HTTP_201_CREATED) @decorators.action(detail=True, methods=["post"]) def weigh(self, request, pk=None): order = self.get_object() input_serializer = WeighingSerializer(data=request.data) input_serializer.is_valid(raise_exception=True) try: order = self.service.record_weighing( order, input_serializer.validated_data["gross"], input_serializer.validated_data["tare"], ) except ApiError as exc: return response.Response(error_response(exc.code, exc.message, exc.details), status=exc.status) return response.Response(ProcessingOrderSerializer(order).data) @decorators.action(detail=True, methods=["post"]) def select_steps(self, request, pk=None): order = self.get_object() input_serializer = StepSelectionSerializer(data=request.data) input_serializer.is_valid(raise_exception=True) try: order = self.service.select_steps(order, input_serializer.validated_data["step_keys"]) except ApiError as exc: return response.Response(error_response(exc.code, exc.message, exc.details), status=exc.status) return response.Response(ProcessingOrderSerializer(order).data) @decorators.action(detail=True, methods=["post"]) def confirm(self, request, pk=None): order = self.get_object() input_serializer = ConfirmSerializer(data=request.data) input_serializer.is_valid(raise_exception=True) try: order = self.service.confirm(order, input_serializer.validated_data["terms_accepted"]) except ApiError as exc: return response.Response(error_response(exc.code, exc.message, exc.details), status=exc.status) return response.Response(ProcessingOrderSerializer(order).data)