Coverage for backend/django/core/auxiliary/viewsets/FlowsheetTemplateViewSet.py: 90%
95 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-12-18 04:00 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-12-18 04:00 +0000
1from django.db import transaction
2from rest_framework import status, viewsets
3from rest_framework.decorators import action
4from rest_framework.response import Response
5from core.auxiliary.enums.FlowsheetTemplateType import FlowsheetTemplateType
6from core.auxiliary.models.Flowsheet import Flowsheet
7from core.auxiliary.serializers.FlowsheetSerializer import FlowsheetSerializer
8from flowsheetInternals.graphicData.models.groupingModel import Grouping
9from core.auxiliary.methods.CopyFlowsheet import copy_flowsheet_data, create_module_from_template_logic
10from flowsheetInternals.graphicData.serializers.groupingSerializer import GroupingSerializer
11from drf_spectacular.utils import extend_schema
12from rest_framework import serializers
15class CreateFlowsheetTemplateSerializer(serializers.Serializer):
16 flowsheet_id = serializers.IntegerField()
17 flowsheet_template_type = serializers.ChoiceField(choices=FlowsheetTemplateType.choices)
20class CreateModuleFromTemplateSerializer(serializers.Serializer):
21 current_group = serializers.IntegerField(required=False, allow_null=True)
22 flowsheet = serializers.IntegerField()
23 x = serializers.FloatField(required=False, allow_null=True)
24 y = serializers.FloatField(required=False, allow_null=True)
27class FlowsheetTemplateViewSet(viewsets.ReadOnlyModelViewSet):
28 serializer_class = FlowsheetSerializer
30 def get_queryset(self):
31 # Public templates are visible to all users
32 # Private templates only to the owner
33 public_flowsheet_templates = Flowsheet.objects.filter(
34 flowsheet_template_type=FlowsheetTemplateType.PublicTemplate)
35 private_flowsheet_templates = Flowsheet.objects.filter(
36 flowsheet_template_type=FlowsheetTemplateType.PrivateTemplate,
37 owner=self.request.user
38 )
39 return public_flowsheet_templates | private_flowsheet_templates
41 @extend_schema(request=CreateFlowsheetTemplateSerializer, responses=None)
42 @action(detail=False, methods=['post'], url_path='create-flowsheet-template')
43 def create_flowsheet_template(self, request) -> Response:
44 """
45 Convert a flowsheet to a template
46 """
47 serializer = CreateFlowsheetTemplateSerializer(data=request.data)
48 serializer.is_valid(raise_exception=True)
50 flowsheet_id = serializer.validated_data['flowsheet_id']
51 flowsheet_template_type = serializer.validated_data['flowsheet_template_type']
53 # Only allow conversion to public template if user is staff
54 if flowsheet_template_type == FlowsheetTemplateType.PublicTemplate and not request.user.is_staff:
55 return Response({'error': 'You do not have permission to create public templates'},
56 status=status.HTTP_403_FORBIDDEN)
58 try:
59 # get the source flowsheet (only owner can convert to template)
60 source_flowsheet = Flowsheet.objects.get(id=flowsheet_id, owner=request.user)
62 # update the template type
63 source_flowsheet.flowsheet_template_type = flowsheet_template_type
64 source_flowsheet.save(update_fields=['flowsheet_template_type'])
66 return Response(FlowsheetSerializer(source_flowsheet).data, status=status.HTTP_200_OK)
68 except Flowsheet.DoesNotExist:
69 return Response({'error': 'Flowsheet not found or you do not have permission'},
70 status=status.HTTP_404_NOT_FOUND)
72 @extend_schema(responses=None)
73 @action(detail=True, methods=['post'], url_path='create-from-flowsheet-template')
74 def create_from_flowsheet_template(self, request, pk=None) -> Response:
75 """
76 Create a new flowsheet from a template
77 """
78 try:
79 flowsheet_template = self.get_object()
81 # copy the template to create a new flowsheet
82 new_flowsheet = copy_flowsheet_data(flowsheet_template, user=request.user)
84 # reset new flowsheet's template type to regular flowsheet
85 new_flowsheet.flowsheet_template_type = FlowsheetTemplateType.NotTemplate
86 new_flowsheet.save()
88 return Response(FlowsheetSerializer(new_flowsheet).data, status=status.HTTP_201_CREATED)
90 except Flowsheet.DoesNotExist:
91 return Response({'error': 'Template not found'}, status=status.HTTP_404_NOT_FOUND)
92 except Exception as e:
93 return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
95 @extend_schema(request=CreateModuleFromTemplateSerializer, responses=None)
96 @action(detail=True, methods=['post'], url_path='create-module-from-template')
97 def create_module_from_template(self, request, pk=None) -> Response:
98 """
99 Create a new module (grouping) from a template within the current flowsheet
100 """
101 data = request.data.get('createModuleFromTemplate', request.data)
103 serializer = CreateModuleFromTemplateSerializer(data=data)
104 serializer.is_valid(raise_exception=True)
106 current_flowsheet_id = serializer.validated_data['flowsheet']
107 current_group_id = serializer.validated_data.get('current_group')
108 x = serializer.validated_data.get("x")
109 y = serializer.validated_data.get("y")
111 try:
112 with transaction.atomic():
113 flowsheet_template = self.get_object()
114 current_flowsheet = Flowsheet.objects.get(id=current_flowsheet_id)
116 current_group: Grouping | None = None
117 if current_group_id: 117 ↛ 121line 117 didn't jump to line 121 because the condition on line 117 was always true
118 current_group = Grouping.objects.get(id=current_group_id)
120 # Create the module from template
121 new_module = create_module_from_template_logic(
122 flowsheet_template,
123 current_flowsheet,
124 request.user,
125 current_group,
126 x,
127 y
128 )
130 return Response(GroupingSerializer(new_module).data, status=status.HTTP_201_CREATED)
132 except Flowsheet.DoesNotExist:
133 return Response({'error': 'Template or flowsheet not found'}, status=status.HTTP_404_NOT_FOUND)
134 except Exception as e:
135 return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
137 @extend_schema(request=None, responses=FlowsheetSerializer)
138 @action(detail=True, methods=['post'], url_path='revert-flowsheet-template')
139 def revert_flowsheet_template(self, request, pk=None) -> Response:
140 """
141 Revert a template flowsheet back to a regular (not template) flowsheet.
142 """
143 try:
144 flowsheet_template: Flowsheet = self.get_object()
146 # Must currently be a template
147 if flowsheet_template.flowsheet_template_type == FlowsheetTemplateType.NotTemplate: 147 ↛ 148line 147 didn't jump to line 148 because the condition on line 147 was never true
148 return Response({'error': 'Flowsheet is not a template'}, status=status.HTTP_400_BAD_REQUEST)
150 # Permission checks
151 if flowsheet_template.flowsheet_template_type == FlowsheetTemplateType.PublicTemplate:
152 if not request.user.is_staff: 152 ↛ 159line 152 didn't jump to line 159 because the condition on line 152 was always true
153 return Response(
154 {'error': 'You do not have permission to revert public templates'},
155 status=status.HTTP_403_FORBIDDEN
156 )
158 # Revert to regular flowsheet
159 flowsheet_template.flowsheet_template_type = FlowsheetTemplateType.NotTemplate
160 flowsheet_template.save(update_fields=['flowsheet_template_type'])
162 return Response(FlowsheetSerializer(flowsheet_template).data, status=status.HTTP_200_OK)
164 except Flowsheet.DoesNotExist:
165 return Response({'error': 'Template not found or you do not have permission'},
166 status=status.HTTP_404_NOT_FOUND)
167 except Exception as e:
168 return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)