Skip to content

Commit

Permalink
Task chunk series: Clean and schedule on update
Browse files Browse the repository at this point in the history
  • Loading branch information
wichmannpas committed Sep 11, 2018
1 parent 3f39259 commit 6dbaa2d
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 4 deletions.
16 changes: 16 additions & 0 deletions task/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,22 @@ class Meta:
def __str__(self) -> str:
return '{}: {}'.format(self.task, self.rule)

@transaction.atomic
def clean_scheduled(self) -> List[int]:
"""
Clean all scheduled chunks which are no longer valid.
Returns the ids of all chunks that were deleted.
"""
chunks = self.chunks.filter(day__lt=self.start)
if self.end:
chunks |= self.chunks.filter(day__gt=self.end)
ids = [chunk.id for chunk in chunks]
chunks.delete()

self.last_scheduled_day = self.chunks.aggregate(Max('day'))['day__max']
self.save(update_fields=('last_scheduled_day',))
return ids

@transaction.atomic
def schedule(
self,
Expand Down
94 changes: 94 additions & 0 deletions task/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3859,6 +3859,100 @@ def test_create_scheduled_task_duration(self):
Decimal(scheduled['task']['scheduled_duration']),
self.task.scheduled_duration)

@freeze_time('2010-05-03')
def test_update_cleaning(self):
"""
Test the cleaning of task chunks when modifying the end date.
"""
series = TaskChunkSeries.objects.create(
task=self.task,
start=date(2010, 5, 3),
end=date(2010, 5, 24),
rule='interval',
interval_days=7)
series.schedule()

self.assertEqual(
TaskChunkSeries.objects.count(),
1)
self.assertEqual(
TaskChunk.objects.count(),
4)

resp = self.client.put('/task/chunk/series/{}/'.format(series.pk), {
'task_id': self.task.pk,
'duration': '2',
'start': '2010-05-03',
'end': '2010-05-10',
'rule': 'interval',
'interval_days': 7,
})
self.assertEqual(
resp.status_code,
status.HTTP_200_OK)

self.assertSetEqual(
set(resp.data.keys()),
{'series', 'cleaned', 'scheduled'})

self.assertEqual(
len(resp.data['cleaned']),
2)
self.assertEqual(
len(resp.data['scheduled']),
0)

self.assertEqual(
TaskChunk.objects.count(),
2)

@freeze_time('2010-05-03')
def test_update_scheduling(self):
"""
Test the scheduling of task chunks when modifying the end date.
"""
series = TaskChunkSeries.objects.create(
task=self.task,
start=date(2010, 5, 3),
end=date(2010, 5, 24),
rule='interval',
interval_days=7)
series.schedule()

self.assertEqual(
TaskChunkSeries.objects.count(),
1)
self.assertEqual(
TaskChunk.objects.count(),
4)

resp = self.client.put('/task/chunk/series/{}/'.format(series.pk), {
'task_id': self.task.pk,
'duration': '2',
'start': '2010-05-03',
'end': '2010-06-7',
'rule': 'interval',
'interval_days': 7,
})
self.assertEqual(
resp.status_code,
status.HTTP_200_OK)

self.assertSetEqual(
set(resp.data.keys()),
{'series', 'cleaned', 'scheduled'})

self.assertEqual(
len(resp.data['cleaned']),
0)
self.assertEqual(
len(resp.data['scheduled']),
2)

self.assertEqual(
TaskChunk.objects.count(),
6)

def test_partial_update(self):
"""
Test that it is not allowed to partially update a task chunk series.
Expand Down
23 changes: 19 additions & 4 deletions task/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.db.models import F
from rest_framework import mixins, serializers, status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import MethodNotAllowed, ParseError, ValidationError
from rest_framework.exceptions import ParseError, ValidationError
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
Expand Down Expand Up @@ -38,7 +38,7 @@ def merge(self, request, pk: int, other_pk: int):


class TaskChunkSeriesViewSet(viewsets.GenericViewSet, mixins.ListModelMixin,
mixins.RetrieveModelMixin, mixins.UpdateModelMixin):
mixins.RetrieveModelMixin):
permission_classes = IsAuthenticated,
serializer_class = TaskChunkSeriesSerializer

Expand All @@ -60,8 +60,23 @@ def create(self, request, *args, **kwargs):
'scheduled': scheduled_serializer.data,
}, status=status.HTTP_201_CREATED)

def partial_update(self, request, *args, **kwargs):
raise MethodNotAllowed('PATCH')
@transaction.atomic
def update(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()

cleaned = instance.clean_scheduled()

scheduled = instance.schedule()
scheduled_serializer = TaskChunkSerializer(scheduled, many=True)

return Response({
'series': serializer.data,
'scheduled': scheduled_serializer.data,
'cleaned': cleaned,
})


class TaskChunkViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin,
Expand Down

0 comments on commit 6dbaa2d

Please sign in to comment.