diff --git a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py index d4378136a3ef31926db28c949426c6809e0fc257..ec6dc54d077ce4a8554e1e43f9cc794ea49fd21a 100644 --- a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py +++ b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py @@ -247,6 +247,11 @@ class SchedulingUnitDraftSerializer(RelationalHyperlinkedModelSerializer): fields = '__all__' extra_fields = ['scheduling_unit_blueprints', 'task_drafts'] +class SchedulingUnitDraftCopySerializer(SchedulingUnitDraftSerializer): + + class Meta(SchedulingUnitDraftSerializer.Meta): + fields = ['copy_reason'] + read_only_fields = ['scheduling_unit_blueprints','task_drafts'] class SchedulingUnitBlueprintSerializer(RelationalHyperlinkedModelSerializer): @@ -342,7 +347,3 @@ class TaskSchedulingRelationBlueprintSerializer(RelationalHyperlinkedModelSerial class Meta: model = models.TaskSchedulingRelationBlueprint fields = '__all__' - - - - diff --git a/SAS/TMSS/src/tmss/tmssapp/tasks.py b/SAS/TMSS/src/tmss/tmssapp/tasks.py index b166c91a8c31f0917766f8b22eed30a8a9d1e138..3f03ac253a0b0e80387bb172684865da0bca7efe 100644 --- a/SAS/TMSS/src/tmss/tmssapp/tasks.py +++ b/SAS/TMSS/src/tmss/tmssapp/tasks.py @@ -3,6 +3,7 @@ from lofar.sas.tmss.tmss.tmssapp.subtasks import create_and_schedule_subtasks_fr from lofar.sas.tmss.tmss.tmssapp.models.specification import TaskBlueprint, SchedulingUnitBlueprint, SchedulingUnitDraft, TaskDraft, SchedulingRelationPlacement from lofar.sas.tmss.tmss.tmssapp.subtasks import create_and_schedule_subtasks_from_task_blueprint, create_subtasks_from_task_blueprint, schedule_independent_subtasks_in_task_blueprint from functools import cmp_to_key +from copy import deepcopy import logging logger = logging.getLogger(__name__) @@ -27,22 +28,27 @@ def create_scheduling_unit_blueprint_from_scheduling_unit_draft(scheduling_unit_ return scheduling_unit_blueprint -def copy_scheduling_unit_draft(scheduling_unit_draft: models.SchedulingUnitDraft, scheduling_set_dst: models.SchedulingSet) -> models.SchedulingUnitDraft: +def copy_scheduling_unit_draft(scheduling_unit_draft: models.SchedulingUnitDraft, scheduling_set_dst: models.SchedulingSet, copy_reason: str) -> models.SchedulingUnitDraft: """ Copy a SchedulingUnitDraft :raises Exception if instantiate fails. """ - logger.debug("copy_scheduling_unit_draft(scheduling_unit_draft.id=%s)", scheduling_unit_draft.pk) - - scheduling_unit_draft_copy = SchedulingUnitDraft.objects.create( - name="%s (Copy)" % (scheduling_unit_draft.name,), - description="%s (Copy from %s)" % (scheduling_unit_draft.description or "<no description>",scheduling_unit_draft.name,), - requirements_doc=scheduling_unit_draft.requirements_doc, - copies=scheduling_unit_draft, - copy_reason=scheduling_unit_draft.copy_reason, - generator_instance_doc=scheduling_unit_draft.generator_instance_doc, - scheduling_set=scheduling_set_dst, - requirements_template=scheduling_unit_draft.requirements_template) + task_drafts = list(scheduling_unit_draft.task_drafts.all()) + scheduling_unit_blueprints = list(scheduling_unit_draft.scheduling_unit_blueprints.all()) + + scheduling_unit_draft_copy = deepcopy(scheduling_unit_draft) + scheduling_unit_draft_copy.id = None + scheduling_unit_draft_copy.copies=scheduling_unit_draft + if copy_reason is not None: + scheduling_unit_draft_copy.copy_reason = models.CopyReason.objects.get(value=copy_reason) + + scheduling_unit_draft_copy.name="%s (Copy)" % (scheduling_unit_draft.name,) + scheduling_unit_draft_copy.description="%s (Copy from %s)" % (scheduling_unit_draft.description or "<no description>",scheduling_unit_draft.name,) + + scheduling_unit_draft_copy.save() + scheduling_unit_draft_copy.task_drafts.set(task_drafts) + scheduling_unit_draft_copy.scheduling_unit_blueprints.set(scheduling_unit_blueprints) + scheduling_unit_draft_copy.save() logger.info("copy_scheduling_unit_draft(scheduling_unit_draft.id=%s) created copy_scheduling_unit_draft id=%s", scheduling_unit_draft.pk, scheduling_unit_draft_copy.pk) return scheduling_unit_draft_copy diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/lofar_viewset.py b/SAS/TMSS/src/tmss/tmssapp/viewsets/lofar_viewset.py index 017d8e13c90b3b6f7e4dce84d8136e1553a38393..c9980cb448ce6c5cb37c30d3b9c6a3065af14f96 100644 --- a/SAS/TMSS/src/tmss/tmssapp/viewsets/lofar_viewset.py +++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/lofar_viewset.py @@ -50,4 +50,16 @@ class LOFARNestedViewSet(mixins.CreateModelMixin, @swagger_auto_schema(responses={400: 'invalid specification', 403: 'forbidden'}) def create(self, request, **kwargs): - return super(LOFARNestedViewSet, self).create(request, **kwargs) \ No newline at end of file + return super(LOFARNestedViewSet, self).create(request, **kwargs) + + +class LOFARCopyViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet): + + """ + @swagger_auto_schema(responses={403: 'forbidden'}) + def list(self, request, **kwargs): + return super(LOFARCopyViewSet, self).list(request, **kwargs) + """ + @swagger_auto_schema(responses={400: 'invalid specification', 403: 'forbidden'}) + def create(self, request, **kwargs): + return super(LOFARCopyViewSet, self).create(request, **kwargs) \ No newline at end of file diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py index 3ca16fc125901ccad87f89bd20f79ac1d6d25c47..fe674df5001d38490f5d5f9b8b443b5d0efe517e 100644 --- a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py +++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py @@ -16,7 +16,7 @@ from rest_framework.decorators import action from drf_yasg.utils import swagger_auto_schema -from lofar.sas.tmss.tmss.tmssapp.viewsets.lofar_viewset import LOFARViewSet, LOFARNestedViewSet +from lofar.sas.tmss.tmss.tmssapp.viewsets.lofar_viewset import LOFARViewSet, LOFARNestedViewSet, LOFARCopyViewSet from lofar.sas.tmss.tmss.tmssapp import models from lofar.sas.tmss.tmss.tmssapp import serializers @@ -26,8 +26,12 @@ from lofar.common.datetimeutils import formatDatetime from lofar.sas.tmss.tmss.tmssapp.tasks import * from lofar.sas.tmss.tmss.tmssapp.subtasks import * - +import json import logging + +from django.core.exceptions import ObjectDoesNotExist + + logger = logging.getLogger(__name__) @@ -246,15 +250,11 @@ class SchedulingUnitDraftViewSet(LOFARViewSet): operation_description="Copy this SchedulingUnitDraft into a new one.") - # @action(methods=['get'], detail=True, url_name="copy_scheduling_unit_draft", url_path="copy_scheduling_unit_draft(?:/(?P<scheduling_set_id>[0-9]+))?", name="Copy Scheduling Unit Draft") - @action(methods=['get'], detail=True, url_name="copy_scheduling_unit_draft", name="Copy Scheduling Unit Draft") + #@action(methods=['get'], detail=True, url_name="copy_scheduling_unit_draft", url_path="copy_scheduling_unit_draft(?:/(?P<scheduling_set_id>[0-9]+))?", name="Copy Scheduling Unit Draft") + @action(methods=['post'], detail=True, url_name="copy_scheduling_unit_draft", name="Copy Scheduling Unit Draft") def copy_scheduling_unit_draft(self, request, scheduling_set = None, pk=None, *args, **kwargs): - scheduling_set_id = request.GET.get('scheduling_set', None) - - logger.info(scheduling_set_id) - logger.info(self.kwargs) - + scheduling_set_id = request.POST.get('scheduling_set', None) scheduling_unit_draft = get_object_or_404(models.SchedulingUnitDraft, pk=pk) #if scheduling_set_id is NONE sopy in to the original scheduling set @@ -304,6 +304,57 @@ class SchedulingUnitDraftNestedViewSet(LOFARNestedViewSet): return models.SchedulingUnitDraft.objects.all() +class SchedulingUnitDraftCopyViewSet(LOFARCopyViewSet): + + queryset = models.SchedulingUnitDraft.objects.all() + serializer_class = serializers.SchedulingUnitDraftCopySerializer + + def get_queryset(self): + if 'scheduling_set_id' in self.kwargs: + scheduling_set = get_object_or_404(models.SchedulingSet, pk=self.kwargs['scheduling_set_id']) + return scheduling_set.scheduling_unit_drafts.all() + else: + return models.SchedulingUnitDraft.objects.all() + + + def create(self, request, *args, **kwargs): + + logger.info(kwargs) + + # return a response with the new serialized SchedulingUnitBlueprintSerializer, and a Location to the new instance in the header + if 'scheduling_set_id' in kwargs: + scheduling_set = get_object_or_404(models.SchedulingSet, pk=kwargs['scheduling_set_id']) + scheduling_unit_drafts = scheduling_set.scheduling_unit_drafts.all() + + body_unicode = request.body.decode('utf-8') + body_data = json.loads(body_unicode) + + + copy_reason = body_data.get('copy_reason', None) + + try: + copy_reason_obj = models.CopyReason.objects.get(value=copy_reason) + except ObjectDoesNotExist: + logger.info("CopyReason matching query does not exist.") + #if a non valid copy_reason is specified, set copy_reason to None + copy_reason = None + + scheduling_unit_draft_copy_path=[] + for scheduling_unit_draft in scheduling_unit_drafts: + logger.info(scheduling_unit_draft.__dict__) + scheduling_unit_draft_copy = copy_scheduling_unit_draft(scheduling_unit_draft,scheduling_set,copy_reason) + # url path magic to construct the new scheduling_unit_draft url + copy_scheduling_unit_draft_path = request._request.path + base_path = copy_scheduling_unit_draft_path[:copy_scheduling_unit_draft_path.find('/copy_scheduling_unit_draft')] + scheduling_unit_draft_copy_path += ['%s/copy_scheduling_unit_draft/%s/' % (base_path, scheduling_unit_draft_copy.id,)] + + # just return as a response the serialized scheduling_set (with references to the created copy_scheduling_unit_draft(s) + return Response(serializers.SchedulingSetSerializer(scheduling_set, context={'request':request}).data,status=status.HTTP_201_CREATED) + else: + content = {'Error': 'scheduling_set_id is missing'} + return Response(content, status=status.HTTP_404_NOT_FOUND) + + class SchedulingUnitBlueprintViewSet(LOFARViewSet): queryset = models.SchedulingUnitBlueprint.objects.all() serializer_class = serializers.SchedulingUnitBlueprintSerializer @@ -467,6 +518,7 @@ class TaskDraftViewSet(LOFARViewSet): status=status.HTTP_201_CREATED, headers={'Location': task_draft_copy_path}) + class TaskDraftNestedViewSet(LOFARNestedViewSet): queryset = models.TaskDraft.objects.all() serializer_class = serializers.TaskDraftSerializer diff --git a/SAS/TMSS/src/tmss/urls.py b/SAS/TMSS/src/tmss/urls.py index 6dda70922b4b63118f7deed3c8e9c9a08b3dea9a..737c5389f3c780b9a89b58ab0dbdbc59a0691997 100644 --- a/SAS/TMSS/src/tmss/urls.py +++ b/SAS/TMSS/src/tmss/urls.py @@ -128,6 +128,10 @@ router.register(r'task_relation_draft/(?P<task_relation_draft_id>\d+)/task_relat router.register(r'task_blueprint/(?P<task_blueprint_id>\d+)/task_relation_blueprint', viewsets.TaskRelationBlueprintNestedViewSet) router.register(r'task_blueprint/(?P<task_blueprint_id>\d+)/subtask', viewsets.SubtaskNestedViewSet) +# copy +router.register(r'scheduling_set/(?P<scheduling_set_id>\d+)/copy_scheduling_unit_draft', viewsets.SchedulingUnitDraftCopyViewSet) + + # SCHEDULING # choices