infrasynth-backend-kit/infrasynth/workflows/views.py
2026-08-28 14:38:47 -05:00

259 lines
8.7 KiB
Python

from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .filters import (
NodeAssignmentFilter,
TransitionFilter,
WorkflowFilter,
WorkflowInstanceFilter,
WorkflowNodeFilter,
WorkflowObserverFilter,
)
from .models import (
NodeAssignment,
Transition,
Workflow,
WorkflowInstance,
WorkflowNode,
WorkflowObserver,
)
from .serializers import (
NodeAssignmentSerializer,
TransitionSerializer,
WorkflowInstanceSerializer,
WorkflowNodeSerializer,
WorkflowObserverSerializer,
WorkflowSerializer,
)
class WorkflowViewSet(viewsets.ModelViewSet):
queryset = Workflow.objects.all()
serializer_class = WorkflowSerializer
permission_classes = [IsAuthenticated]
filterset_class = WorkflowFilter
def initial(self, request, *args, **kwargs):
from infrasynth.features.services import FeatureService
if not FeatureService().is_enabled("workflows", user=request.user):
from django.http import Http404
raise Http404()
super().initial(request, *args, **kwargs)
def get_queryset(self):
return Workflow.objects.select_related("created_by").all()
class WorkflowNodeViewSet(viewsets.ModelViewSet):
queryset = WorkflowNode.objects.all()
serializer_class = WorkflowNodeSerializer
permission_classes = [IsAuthenticated]
filterset_class = WorkflowNodeFilter
def initial(self, request, *args, **kwargs):
from infrasynth.features.services import FeatureService
if not FeatureService().is_enabled("workflows", user=request.user):
from django.http import Http404
raise Http404()
super().initial(request, *args, **kwargs)
def get_queryset(self):
return WorkflowNode.objects.select_related("workflow").all()
class TransitionViewSet(viewsets.ModelViewSet):
queryset = Transition.objects.all()
serializer_class = TransitionSerializer
permission_classes = [IsAuthenticated]
filterset_class = TransitionFilter
def initial(self, request, *args, **kwargs):
from infrasynth.features.services import FeatureService
if not FeatureService().is_enabled("workflows", user=request.user):
from django.http import Http404
raise Http404()
super().initial(request, *args, **kwargs)
def get_queryset(self):
return Transition.objects.select_related("from_node", "to_node").all()
class WorkflowInstanceViewSet(viewsets.ModelViewSet):
queryset = WorkflowInstance.objects.all()
serializer_class = WorkflowInstanceSerializer
permission_classes = [IsAuthenticated]
filterset_class = WorkflowInstanceFilter
def initial(self, request, *args, **kwargs):
from infrasynth.features.services import FeatureService
if not FeatureService().is_enabled("workflows", user=request.user):
from django.http import Http404
raise Http404()
super().initial(request, *args, **kwargs)
def get_queryset(self):
return WorkflowInstance.objects.select_related("workflow", "current_node", "owner").all()
def perform_create(self, serializer):
from .engine import WorkflowEngine
workflow = serializer.validated_data["workflow"]
initial_data = serializer.validated_data.get("metadata")
instance = WorkflowEngine().start(workflow.slug, owner=self.request.user, initial_data=initial_data)
serializer.instance = instance
@action(detail=True, methods=["get"])
def route(self, request, pk=None):
instance = self.get_object()
from .engine import WorkflowEngine
return Response({"route": WorkflowEngine().get_route(instance.pk)})
@action(detail=True, methods=["get"])
def state(self, request, pk=None):
instance = self.get_object()
from .engine import WorkflowEngine
return Response({"state": WorkflowEngine().get_node_states(instance.pk)})
@action(detail=True, methods=["post"])
def submit(self, request, pk=None):
instance = self.get_object()
from .engine import WorkflowEngine
assignment_id = request.data.get("assignment_id")
decision = request.data.get("decision")
if not assignment_id or not decision:
return Response(
{"detail": "assignment_id and decision are required."},
status=status.HTTP_400_BAD_REQUEST,
)
engine = WorkflowEngine()
instance = engine.submit_decision(
assignment_id,
decision,
data=request.data.get("data"),
user=request.user,
comments=request.data.get("comments", ""),
)
return Response(
{
"instance_id": instance.pk,
"status": instance.status,
"current_node": (
{"id": instance.current_node_id, "name": instance.current_node.name}
if instance.current_node_id
else None
),
}
)
@action(detail=True, methods=["post"])
def assign(self, request, pk=None):
instance = self.get_object()
from .engine import WorkflowEngine
node_id = request.data.get("node_id")
user_ids = request.data.get("users", [])
if not node_id or not user_ids:
return Response(
{"detail": "node_id and users are required."},
status=status.HTTP_400_BAD_REQUEST,
)
from django.contrib.auth import get_user_model
user_model = get_user_model()
users = user_model.objects.filter(pk__in=user_ids)
assignments = WorkflowEngine().assign_users(
instance.pk,
node_id,
list(users),
is_required=request.data.get("is_required", True),
)
from .serializers import NodeAssignmentSerializer
return Response(
NodeAssignmentSerializer(assignments, many=True).data,
status=status.HTTP_201_CREATED,
)
@action(detail=True, methods=["post", "delete"])
def observers(self, request, pk=None):
instance = self.get_object()
from .engine import WorkflowEngine
from .models import WorkflowObserver
user_id = request.data.get("user_id")
if not user_id:
return Response(
{"detail": "user_id is required."},
status=status.HTTP_400_BAD_REQUEST,
)
engine = WorkflowEngine()
if request.method == "DELETE":
deleted, _ = WorkflowObserver.objects.filter(instance=instance, user_id=user_id).delete()
if not deleted:
return Response(
{"detail": "Observer not found."},
status=status.HTTP_404_NOT_FOUND,
)
return Response(status=status.HTTP_204_NO_CONTENT)
from django.contrib.auth import get_user_model
user_model = get_user_model()
user = user_model.objects.filter(pk=user_id).first()
if user is None:
return Response({"detail": "User not found."}, status=status.HTTP_404_NOT_FOUND)
observer = engine.add_observer(instance.pk, user)
from .serializers import WorkflowObserverSerializer
return Response(WorkflowObserverSerializer(observer).data, status=status.HTTP_201_CREATED)
class NodeAssignmentViewSet(viewsets.ModelViewSet):
queryset = NodeAssignment.objects.all()
serializer_class = NodeAssignmentSerializer
permission_classes = [IsAuthenticated]
filterset_class = NodeAssignmentFilter
def initial(self, request, *args, **kwargs):
from infrasynth.features.services import FeatureService
if not FeatureService().is_enabled("workflows", user=request.user):
from django.http import Http404
raise Http404()
super().initial(request, *args, **kwargs)
def get_queryset(self):
return NodeAssignment.objects.select_related("instance", "node", "user").all()
class WorkflowObserverViewSet(viewsets.ModelViewSet):
queryset = WorkflowObserver.objects.all()
serializer_class = WorkflowObserverSerializer
permission_classes = [IsAuthenticated]
filterset_class = WorkflowObserverFilter
def initial(self, request, *args, **kwargs):
from infrasynth.features.services import FeatureService
if not FeatureService().is_enabled("workflows", user=request.user):
from django.http import Http404
raise Http404()
super().initial(request, *args, **kwargs)
def get_queryset(self):
return WorkflowObserver.objects.select_related("instance", "user").all()