diff --git a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py index 0a3584ed2c7a82e0415ce201a60c4d2e58151fe0..b405a91060cdf1c66cbf96ad1652bdd7b4bb1126 100644 --- a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py +++ b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py @@ -16,7 +16,10 @@ class RelationalHyperlinkedModelSerializer(serializers.HyperlinkedModelSerialize def get_field_names(self, declared_fields, info): field_names = super().get_field_names(declared_fields, info) - field_names.remove(self.url_field_name) # is added later, see retun statement + try: + field_names.remove(self.url_field_name) # is added later, see retun statement + except ValueError: + pass if getattr(self.Meta, 'extra_fields', None): field_names += self.Meta.extra_fields @@ -279,6 +282,16 @@ class SchedulingUnitDraftSerializer(RelationalHyperlinkedModelSerializer): fields = '__all__' extra_fields = ['scheduling_unit_blueprints', 'task_drafts', 'duration'] +class SchedulingUnitDraftCopySerializer(SchedulingUnitDraftSerializer): + class Meta(SchedulingUnitDraftSerializer.Meta): + fields = ['copy_reason'] + extra_fields =['scheduling_set_id'] + read_only_fields = ['scheduling_unit_blueprints','task_drafts'] + +class SchedulingUnitDraftCopyFromSchedulingSetSerializer(SchedulingUnitDraftSerializer): + class Meta(SchedulingUnitDraftSerializer.Meta): + fields = ['copy_reason'] + read_only_fields = ['scheduling_unit_blueprints','task_drafts'] class SchedulingUnitBlueprintSerializer(RelationalHyperlinkedModelSerializer): @@ -298,6 +311,13 @@ class SchedulingUnitBlueprintSerializer(RelationalHyperlinkedModelSerializer): fields = '__all__' extra_fields = ['task_blueprints', 'duration', 'start_time', 'stop_time'] +class SchedulingUnitBlueprintCopyToSchedulingUnitDraftSerializer(SchedulingUnitBlueprintSerializer): + class Meta(SchedulingUnitDraftSerializer.Meta): + fields = ['copy_reason'] + extra_fields =['scheduling_set_id'] + read_only_fields = ['scheduling_unit_blueprints','task_drafts'] + + class TaskDraftSerializer(RelationalHyperlinkedModelSerializer): diff --git a/SAS/TMSS/src/tmss/tmssapp/tasks.py b/SAS/TMSS/src/tmss/tmssapp/tasks.py index 0bc760ad2318aab6228232365d78d75f2ef3f9d3..7f7ad51bd577466945b176d334aaeda4feffa880 100644 --- a/SAS/TMSS/src/tmss/tmssapp/tasks.py +++ b/SAS/TMSS/src/tmss/tmssapp/tasks.py @@ -1,16 +1,14 @@ from lofar.sas.tmss.tmss.exceptions import * from lofar.sas.tmss.tmss.tmssapp import models -from lofar.sas.tmss.tmss.tmssapp.models.specification import TaskBlueprint, SchedulingUnitBlueprint, TaskDraft, SchedulingRelationPlacement -from lofar.sas.tmss.tmss.tmssapp.subtasks import create_and_schedule_subtasks_from_task_blueprint -from lofar.sas.tmss.tmss.tmssapp.models.specification import TaskBlueprint, SchedulingUnitBlueprint -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 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 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 from lofar.common.json_utils import add_defaults_to_json_object_for_schema - import logging -logger = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def create_scheduling_unit_blueprint_from_scheduling_unit_draft(scheduling_unit_draft: models.SchedulingUnitDraft) -> models.SchedulingUnitBlueprint: """ @@ -32,6 +30,108 @@ 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, copy_reason: str) -> models.SchedulingUnitDraft: + """ + Copy a SchedulingUnitDraft + :raises Exception if instantiate fails. + """ + task_drafts = list(scheduling_unit_draft.task_drafts.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.scheduling_set=scheduling_set_dst + + task_drafts_copy = [] + scheduling_unit_draft_copy.save() + for td in task_drafts: + task_drafts_copy.append(copy_task_draft(td)) + scheduling_unit_draft_copy.task_drafts.set(task_drafts_copy) + 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 + + +def create_scheduling_unit_draft_from_scheduling_unit_blueprint(scheduling_unit_blueprint: models.SchedulingUnitBlueprint, copy_reason: str) -> models.SchedulingUnitDraft: + """ + Create a SchedulingUnitDraft from the SchedulingUnitBlueprint + :raises Exception if instantiate fails. + """ + logger.debug("create_scheduling_unit_draft_from_scheduling_unit_blueprint(scheduling_unit_blueprint.id=%s)", scheduling_unit_blueprint.pk) + + original_scheduling_unit_draft = scheduling_unit_blueprint.draft + + # TODO: fix the copy reason + scheduling_unit_draft = SchedulingUnitDraft.objects.create( + name="%s (Copied from SchedulingUnitBlueprint)" % (scheduling_unit_blueprint.name,), + description="%s (Copied from %s SchedulingUnitBlueprint)" % (scheduling_unit_blueprint.description or "<no description>",scheduling_unit_blueprint.name,), + requirements_doc=scheduling_unit_blueprint.requirements_doc, + copy_reason=copy_reason, + generator_instance_doc=original_scheduling_unit_draft.generator_instance_doc, + scheduling_set=original_scheduling_unit_draft.scheduling_set, + requirements_template=scheduling_unit_blueprint.requirements_template) + + task_drafts_copy = [] + task_blueprints = list(scheduling_unit_blueprint.task_blueprints.all()) + + for tb in task_blueprints: + task_drafts_copy.append(copy_task_blueprint_to_task_draft(tb)) + scheduling_unit_draft.task_drafts.set(task_drafts_copy) + scheduling_unit_draft.save() + + logger.info("create_scheduling_unit_draft_from_scheduling_unit_blueprint(scheduling_unit_blueprint.id=%s) created scheduling_unit_draft id=%s", scheduling_unit_blueprint.pk, scheduling_unit_draft.pk) + return scheduling_unit_draft + + +def copy_task_draft(task_draft: models.TaskDraft, copy_reason: str) -> models.TaskDraft: + + task_template_name = task_draft.specifications_template + task_template = models.TaskTemplate.objects.get(name=task_template_name) + + task_draft_copy = models.TaskDraft.objects.create( + name=task_draft.name, + description=task_draft.description, + tags=task_draft.tags, + specifications_doc=task_draft.specifications_doc, + copy_reason=copy_reason, + copies=task_draft, + scheduling_unit_draft=task_draft.scheduling_unit_draft, + specifications_template=task_template) + logger.info("task draft with id %s created successfully" % task_draft.id) + logger.info("copy_task_draft(task_draft.id=%s) created copy_task_draft id=%s", task_draft.pk, task_draft_copy.pk) + return task_draft_copy + + +def copy_task_blueprint_to_task_draft(task_blueprint:models.TaskBlueprint ) -> models.TaskDraft: + """ + Create a copy of a task_blueprint to a task_draft + :raises Exception if instantiate fails. + """ + logger.debug("Create Task Draft from Task Blueprint (id=%s)", task_blueprint.pk) + + original_task_draft = task_blueprint.draft + task_template_name = original_task_draft.specifications_template + task_template = models.TaskTemplate.objects.get(name=task_template_name) + + task_draft_copy = models.TaskDraft.objects.create( + name="%s (Copied from Task Blueprint)" % (task_blueprint.name,), + description="%s (Copied from %s Task Blueprint)" % (task_blueprint.description or "<no description>",task_blueprint.name,), + tags=original_task_draft.tags, + specifications_doc=original_task_draft.specifications_doc, + copy_reason=original_task_draft.copy_reason, + copies=original_task_draft, + scheduling_unit_draft=original_task_draft.scheduling_unit_draft, + specifications_template=task_template) + logger.info("copy_task_blueprint_to_task_draft(task_blueprint.id=%s) created task_draft id=%s", task_blueprint.pk, task_draft_copy.pk) + return task_draft_copy + + def create_task_drafts_from_scheduling_unit_draft(scheduling_unit_draft: models.SchedulingUnitDraft) -> models.SchedulingUnitDraft: """ Create all defined task_drafts in the scheduling_unit_draft's requirements_doc, connect them, and return the updated scheduling_unit_draft. 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 f7b2aeeafdd2d57ac65b7da5aa5d1df3e9b3fc2b..169b0188fe3507391d7fee977cf7a5dcd218fa53 100644 --- a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py +++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py @@ -2,7 +2,8 @@ This file contains the viewsets (based on the elsewhere defined data models and serializers) """ -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404,render + from django.http import JsonResponse from django.contrib.auth.models import User from django_filters import rest_framework as filters @@ -17,7 +18,7 @@ from rest_framework.decorators import action from drf_yasg.utils import swagger_auto_schema from drf_yasg.openapi import Parameter -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 @@ -27,8 +28,16 @@ from lofar.common.datetimeutils import formatDatetime from lofar.sas.tmss.tmss.tmssapp.tasks import * from lofar.sas.tmss.tmss.tmssapp.subtasks import * +from django.urls import resolve, get_script_prefix,Resolver404 + +import json +import logging + +from django.core.exceptions import ObjectDoesNotExist +logger = logging.getLogger(__name__) + # This is required for keeping a user reference as ForeignKey in other models # (I think so that the HyperlinkedModelSerializer can generate a URI) @@ -349,7 +358,7 @@ class SchedulingUnitDraftViewSet(LOFARViewSet): return Response(serializers.SchedulingUnitBlueprintSerializer(scheduling_unit_blueprint, context={'request':request}).data, status=status.HTTP_201_CREATED, headers={'Location': scheduling_unit_blueprint_path}) - + @swagger_auto_schema(responses={201: 'The updated scheduling_unit_draft with references to its created task_drafts', 403: 'forbidden'}, @@ -376,7 +385,196 @@ class SchedulingUnitDraftNestedViewSet(LOFARNestedViewSet): else: return models.SchedulingUnitDraft.objects.all() +class TaskDraftCopyViewSet(LOFARCopyViewSet): + queryset = models.TaskDraft.objects.all() + serializer_class = serializers.TaskDraftSerializer + + @swagger_auto_schema(responses={201: 'The new Task Draft', + 403: 'forbidden'}, + operation_description="Copy a Task Draft to a new Task Draft") + def create(self, request, *args, **kwargs): + if 'task_draft_id' in kwargs: + task_draft = get_object_or_404(models.TaskDraft, pk=kwargs["task_draft_id"]) + + 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 + + task_draft_copy = copy_task_draft(task_draft,copy_reason) + + + # url path magic to construct the new task_draft_path url + task_draft_path = request._request.path + base_path = task_draft_path[:task_draft_path.find('/task_draft')] + task_draft_copy_path = '%s/task_draft/%s/' % (base_path, task_draft_copy.id,) + + + # return a response with the new serialized SchedulingUnitBlueprintSerializer, and a Location to the new instance in the header + return Response(serializers.TaskDraftSerializer(task_draft_copy, context={'request':request}).data, + status=status.HTTP_201_CREATED, + headers={'Location': task_draft_copy_path}) + else: + content = {'Error': 'scheduling_unit_draft_id is missing'} + return Response(content, status=status.HTTP_404_NOT_FOUND) + +class SchedulingUnitDraftCopyViewSet(LOFARCopyViewSet): + queryset = models.SchedulingUnitDraft.objects.all() + serializer_class = serializers.SchedulingUnitDraftCopySerializer + + @swagger_auto_schema(responses={201: 'The new scheduling_unit_draft', + 403: 'forbidden'}, + operation_description="Copy a Scheduling Unit Draft to a new Scheduling Unit Draft") + def create(self, request, *args, **kwargs): + if 'scheduling_unit_draft_id' in kwargs: + scheduling_unit_draft = get_object_or_404(models.SchedulingUnitDraft, pk=kwargs['scheduling_unit_draft_id']) + scheduling_set = scheduling_unit_draft.scheduling_set + + 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_set_id = body_data.get('scheduling_set_id', None) + logger.info(scheduling_set_id) + if scheduling_set_id is not None: + try: + scheduling_set = models.SchedulingSet.objects.get(id=scheduling_set_id) + except ObjectDoesNotExist: + logger.info("scheduling Set does not exist.") + + 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_path url + scheduling_unit_draft_path = request._request.path + base_path = scheduling_unit_draft_path[:scheduling_unit_draft_path.find('/scheduling_unit_draft')] + scheduling_unit_draft_copy_path = '%s/scheduling_unit_draft/%s/' % (base_path, scheduling_unit_draft_copy.id,) + + # return a response with the new serialized SchedulingUnitBlueprintSerializer, and a Location to the new instance in the header + return Response(serializers.SchedulingUnitDraftSerializer(scheduling_unit_draft_copy, context={'request':request}).data, + status=status.HTTP_201_CREATED, + headers={'Location': scheduling_unit_draft_copy_path}) + else: + content = {'Error': 'scheduling_unit_draft_id is missing'} + return Response(content, status=status.HTTP_404_NOT_FOUND) + + +class SchedulingUnitDraftCopyFromSchedulingSetViewSet(LOFARCopyViewSet): + queryset = models.SchedulingUnitDraft.objects.all() + serializer_class = serializers.SchedulingUnitDraftCopyFromSchedulingSetSerializer + + 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() + + @swagger_auto_schema(responses={201: "The TaskDrafts copied from the TaskDrafts in this Scheduling Unit Set", + 403: 'forbidden'}, + operation_description="Create a copy of all the TaskDrafts in this Scheduling Unit Set.") + def create(self, request, *args, **kwargs): + 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: + 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_drafts')] + scheduling_unit_draft_copy_path += ['%s/copy_scheduling_unit_drafts/%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 SchedulingUnitBlueprintCopyToSchedulingUnitDraftViewSet(LOFARCopyViewSet): + queryset = models.SchedulingUnitBlueprint.objects.all() + serializer_class = serializers.SchedulingUnitBlueprintCopyToSchedulingUnitDraftSerializer + + @swagger_auto_schema(responses={201: "The copy of the SchedulingUnitDraft", + 403: 'forbidden'}, + operation_description="Create a SchedulingUnitDraft from the SchedulingUnitBlueprint") + def create(self, request, *args, **kwargs): + + if 'scheduling_unit_blueprint_id' in kwargs: + scheduling_unit_blueprint = get_object_or_404(models.SchedulingUnitBlueprint, pk=kwargs['scheduling_unit_blueprint_id']) + + 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 = create_scheduling_unit_draft_from_scheduling_unit_blueprint(scheduling_unit_blueprint,copy_reason) + + # return a response with the new serialized scheduling_unit_blueprint (with references to the created task_blueprint(s) and (scheduled) subtasks) + return Response(serializers.SchedulingUnitDraftSerializer(scheduling_unit_draft, context={'request':request}).data, + status=status.HTTP_201_CREATED) + else: + content = {'Error': 'scheduling_unit_draft_id is missing'} + return Response(content, status=status.HTTP_404_NOT_FOUND) + + +class TaskBlueprintCopyToTaskDraftViewSet(LOFARCopyViewSet): + queryset = models.SchedulingUnitBlueprint.objects.all() + serializer_class = serializers.SchedulingUnitBlueprintCopyToSchedulingUnitDraftSerializer + + @swagger_auto_schema(responses={201: "The TaskDraft created from this TaskBlueprint", + 403: 'forbidden'}, + operation_description="Copy this TaskBlueprint to a new TaskDraft.") + def create(self, request, *args, **kwargs): + if 'task_blueprint_id' in kwargs: + task_blueprint = get_object_or_404(models.TaskBlueprint, pk=kwargs['task_blueprint_id']) + task_draft = copy_task_blueprint_to_task_draft(task_blueprint) + + # return a response with the new serialized scheduling_unit_blueprint (with references to the created task_blueprint(s) and (scheduled) subtasks) + return Response(serializers.TaskDraftSerializer(task_draft, context={'request':request}).data, + status=status.HTTP_201_CREATED) + + else: + content = {'Error': 'task_blueprint_id is missing'} + return Response(content, status=status.HTTP_404_NOT_FOUND) + + class SchedulingUnitBlueprintViewSet(LOFARViewSet): queryset = models.SchedulingUnitBlueprint.objects.all() serializer_class = serializers.SchedulingUnitBlueprintSerializer @@ -417,7 +615,7 @@ class SchedulingUnitBlueprintViewSet(LOFARViewSet): return Response(serializers.SchedulingUnitBlueprintSerializer(scheduling_unit_blueprint, context={'request':request}).data, status=status.HTTP_201_CREATED) - + class SchedulingUnitBlueprintNestedViewSet(LOFARNestedViewSet): queryset = models.SchedulingUnitBlueprint.objects.all() serializer_class = serializers.SchedulingUnitBlueprintSerializer @@ -510,7 +708,7 @@ class TaskDraftViewSet(LOFARViewSet): serializer = self.get_serializer(successors, many=True) return Response(serializer.data) - + class TaskDraftNestedViewSet(LOFARNestedViewSet): queryset = models.TaskDraft.objects.all() serializer_class = serializers.TaskDraftSerializer @@ -585,7 +783,7 @@ class TaskBlueprintViewSet(LOFARViewSet): successors = self.filter_queryset(task_blueprint.successors) serializer = self.get_serializer(successors, many=True) return Response(serializer.data) - + class TaskBlueprintNestedViewSet(LOFARNestedViewSet): queryset = models.TaskBlueprint.objects.all() diff --git a/SAS/TMSS/src/tmss/urls.py b/SAS/TMSS/src/tmss/urls.py index 9b7895326ffebfad99aa9740faa0e649fdc6f608..58ef4ea249203876cbdc99856127a1403edfbdd8 100644 --- a/SAS/TMSS/src/tmss/urls.py +++ b/SAS/TMSS/src/tmss/urls.py @@ -144,6 +144,14 @@ 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'task_draft/(?P<task_draft_id>\d+)/copy', viewsets.TaskDraftCopyViewSet) +router.register(r'task_blueprint/(?P<task_blueprint_id>\d+)/copy_to_task_draft', viewsets.TaskBlueprintCopyToTaskDraftViewSet) +router.register(r'scheduling_set/(?P<scheduling_set_id>\d+)/copy_scheduling_unit_drafts', viewsets.SchedulingUnitDraftCopyFromSchedulingSetViewSet) +router.register(r'scheduling_unit_draft/(?P<scheduling_unit_draft_id>\d+)/copy', viewsets.SchedulingUnitDraftCopyViewSet) +router.register(r'scheduling_unit_blueprint/(?P<scheduling_unit_blueprint_id>\d+)/copy_to_scheduling_unit_draft', viewsets.SchedulingUnitBlueprintCopyToSchedulingUnitDraftViewSet) + + # SCHEDULING # choices