from rest_framework import decorators, mixins, response, status, viewsets from apps.core.errors import ApiError, error_response from apps.processing.models import StepExecution from apps.processing.serializers import StepExecutionSerializer from apps.processing.services import ProcessingService from apps.rbac.permissions import ActionPermission class StepExecutionViewSet( mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet ): serializer_class = StepExecutionSerializer permission_classes = [ActionPermission] code_map = { "list": "processing.view", "retrieve": "processing.view", "start": "processing.start", "pause": "processing.pause", "resume": "processing.start", "complete": "processing.complete", "reject": "processing.complete", "rework": "processing.complete", } service = ProcessingService() def get_queryset(self): user = self.request.user qs = StepExecution.objects.select_related("order", "step", "assigned_to").all() if user.is_superuser: return qs return qs.filter(order__customer__user=user) def _run(self, request, pk, method, **kwargs): execution = self.get_object() try: if method == "start": execution = self.service.start(execution, request.user) elif method == "rework": from apps.workflows.models import WorkflowStep target = WorkflowStep.objects.get(pk=kwargs["target_step"]) execution = self.service.rework(execution, target) else: execution = getattr(self.service, method)(execution) except ApiError as exc: return response.Response(error_response(exc.code, exc.message, exc.details), status=exc.status) return response.Response(StepExecutionSerializer(execution).data) @decorators.action(detail=True, methods=["post"]) def start(self, request, pk=None): return self._run(request, pk, "start") @decorators.action(detail=True, methods=["post"]) def pause(self, request, pk=None): return self._run(request, pk, "pause") @decorators.action(detail=True, methods=["post"]) def resume(self, request, pk=None): return self._run(request, pk, "resume") @decorators.action(detail=True, methods=["post"]) def complete(self, request, pk=None): return self._run(request, pk, "complete") @decorators.action(detail=True, methods=["post"]) def reject(self, request, pk=None): return self._run(request, pk, "reject") @decorators.action(detail=True, methods=["post"]) def rework(self, request, pk=None): target_step = request.data.get("target_step") if not target_step: return response.Response( error_response("TARGET_STEP_REQUIRED", "A target_step id is required."), status=status.HTTP_400_BAD_REQUEST, ) return self._run(request, pk, "rework", target_step=target_step)