diff --git a/backend/pickupdays/models.py b/backend/pickupdays/models.py index ba87c487..638a9ace 100644 --- a/backend/pickupdays/models.py +++ b/backend/pickupdays/models.py @@ -1,21 +1,24 @@ from django.db import models +class WeekDayEnum(models.TextChoices): + """ + Enum for the days of the week. + """ + MONDAY = "MO", "Monday" + TUESDAY = "TU", "Tuesday" + WEDNESDAY = "WE", "Wednesday" + THURSDAY = "TH", "Thursday" + FRIDAY = "FR", "Friday" + SATURDAY = "SA", "Saturday" + SUNDAY = "SU", "Sunday" + + class PickUpDay(models.Model): """ The pickup day and hours for a TrashContainer. """ - class WeekDayEnum(models.TextChoices): - """ - Enum for the days of the week. - """ - MONDAY = "MO", "Monday" - TUESDAY = "TU", "Tuesday" - WEDNESDAY = "WE", "Wednesday" - THURSDAY = "TH", "Thursday" - FRIDAY = "FR", "Friday" - SATURDAY = "SA", "Saturday" - SUNDAY = "SU", "Sunday" + day = models.CharField( max_length=2, diff --git a/backend/planning/models.py b/backend/planning/models.py index 21c393c4..69e92879 100644 --- a/backend/planning/models.py +++ b/backend/planning/models.py @@ -1,8 +1,9 @@ from django.db import models from django.conf import settings from ronde.models import Ronde -from trashtemplates.models import TrashContainerTemplate +from trashtemplates.models import TrashContainerTemplate, Status from pickupdays.models import PickUpDay +from ronde.models import LocatieEnum class DagPlanning(models.Model): @@ -34,15 +35,21 @@ class DagPlanning(models.Model): class StudentTemplate(models.Model): """ - All the day templates for a certain week + Studenten template die studenten met rondes matcht. Attributes ---------- name : models.TextField - The name of this template + De naam van deze template + + even : models.BooleanField + Bepaalt of de template voor even of oneven weken is. + + location : models.ForeignKey + De locatie van de template. status : models.TextField - Geeft de status van een template aan: actief/tijdelijk/verwijderd/tijdelijk vervangen + Geeft de status van een template aan. year : models.IntegerField Geeft het jaar aan waarin de template gemaakt is. @@ -50,14 +57,24 @@ class StudentTemplate(models.Model): week : models.IntegerField Geeft de week aan waarin de template gemaakt is. + rondes : models.ManyToManyField + Al de rondes die in deze template zitten. + dag_planningen : models.ManyToManyField - The DagPlanning objects of this template + Al de dagplanningen van deze rondes. """ name = models.TextField() - status = models.TextField() # TODO choicefield + even = models.BooleanField() + location = models.ForeignKey(LocatieEnum, on_delete=models.DO_NOTHING) + + status = models.CharField( + max_length=1, + choices=Status.choices + ) year = models.IntegerField() week = models.IntegerField() + rondes = models.ManyToManyField(Ronde, blank=True) dag_planningen = models.ManyToManyField(DagPlanning, blank=True) diff --git a/backend/planning/serializers.py b/backend/planning/serializers.py index c3754ef9..39f76684 100644 --- a/backend/planning/serializers.py +++ b/backend/planning/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import DagPlanning, BuildingPicture, InfoPerBuilding, WeekPlanning +from .models import * from ronde.serializers import RondeRelatedField @@ -13,6 +13,12 @@ class DagPlanningSerializerFull(DagPlanningSerializer): ronde = RondeRelatedField(read_only=True) +class StudentTemplateSerializer(serializers.ModelSerializer): + class Meta: + model = StudentTemplate + fields = '__all__' + + class BuildingPictureSerializer(serializers.ModelSerializer): class Meta: model = BuildingPicture diff --git a/backend/planning/urls.py b/backend/planning/urls.py index e683bcdb..ce48a79f 100644 --- a/backend/planning/urls.py +++ b/backend/planning/urls.py @@ -9,5 +9,8 @@ path("infoperbuilding/", views.InfoPerBuildingCLAPIView.as_view()), path("infoperbuilding//", views.InfoPerBuildingRUDAPIView.as_view()), path("weekplanning/", views.WeekPlanningCLAPIView.as_view()), - path("weekplanning//", views.WeekPlanningRUDAPIView.as_view()) + path("weekplanning//", views.WeekPlanningRUDAPIView.as_view()), + path("studenttemplates/", views.student_templates_view), + path("studenttemplates//rondes/", views.rondes_view) + ] diff --git a/backend/planning/views.py b/backend/planning/views.py index d68326f9..5fb22ae6 100644 --- a/backend/planning/views.py +++ b/backend/planning/views.py @@ -2,6 +2,14 @@ from rest_framework.response import Response from .serializers import * from users.permissions import StudentReadOnly, AdminPermission, SuperstudentPermission, StudentPermission +import datetime +from trashtemplates.models import Status +from ronde.models import LocatieEnum, Ronde +from ronde.serializers import RondeSerializer +from pickupdays.models import WeekDayEnum, PickUpDay + +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny class DagPlanningCreateAndListAPIView(generics.ListCreateAPIView): @@ -148,3 +156,146 @@ class WeekPlanningRUDAPIView(generics.RetrieveUpdateDestroyAPIView): queryset = WeekPlanning.objects.all() serializer_class = WeekPlanningSerializer permission_classes = [StudentReadOnly | AdminPermission | SuperstudentPermission] + + + +def make_copy(template, permanent, current_year, current_week): + """ + Neemt een copy van een template zodat de geschiedenis behouden wordt + """ + + copy = StudentTemplate.objects.create( + name=template.name, + even=template.even, + status=Status.ACTIEF if permanent else Status.EENMALIG, + location=template.location, + year=current_year, + week=current_week + ) + copy.rondes.set(template.rondes.all()) + copy.dag_planningen.set(template.dag_planningen.all()) + + # verander de status van de nu oude template + template.status = Status.INACTIEF if permanent else Status.VERVANGEN + template.week = current_week + template.save() + + return copy + + +@api_view(["GET", "POST"]) +@permission_classes([AllowAny]) +def student_templates_view(request): + + if request.method == "GET": + templates = StudentTemplate.objects.all() + current_year, current_week, _ = datetime.datetime.utcnow().isocalendar() + + for template in templates: + is_current = template.week == current_week or template.year == current_year + # template was tijdelijk veranderd maar de week is voorbij dus nu geldt deze weer + if template.status == Status.VERVANGEN and not is_current: + template.status = Status.ACTIEF + template.save() + # template was tijdelijk maar de week is voorbij dus nu geldt deze niet meer + elif template.status == Status.EENMALIG and not is_current: + template.status = Status.INACTIEF + template.save() + + result = templates.filter(status=Status.ACTIEF) | templates.filter(status=Status.EENMALIG) | templates.filter( + status=Status.VERVANGEN) + data = StudentTemplateSerializer(result, many=True).data + return Response(data) + + if request.method == "POST": + data = request.data + current_year, current_week, _ = datetime.datetime.utcnow().isocalendar() + location = LocatieEnum.objects.get(id=data["location"]) + + new_template = StudentTemplate.objects.create( + name=data["name"], + even=data["even"].lower() == "true", + status=Status.ACTIEF, + location=location, + year=current_year, + week=current_week + ) + + planning, _ = WeekPlanning.objects.get_or_create( + week=current_week, + year=current_year + ) + # voeg nieuwe template toe aan huidige planning + planning.student_templates.add(new_template) + data = StudentTemplateSerializer(new_template).data + return Response(data) + + +@api_view(["GET", "POST"]) +@permission_classes([AllowAny]) +def rondes_view(request, template_id): + template = StudentTemplate.objects.get(id=template_id) + + if request.method == "GET": + data = RondeSerializer(template.rondes.all()).data + return Response(data) + + if request.method == "POST": + data = request.data + method = data["method"] # add of delete + permanent = data["permanent"] + current_year, current_week, _ = datetime.datetime.utcnow().isocalendar() + + ronde = Ronde.objects.get(id=data["ronde"]) + + if template.status == Status.VERVANGEN or template.status == Status.INACTIEF: + # templates met deze status mogen niet aangepast worden + return Response({"error": "Mag niet"}) + + + if method == "delete": + to_remove = template.dag_planningen.filter(ronde=ronde) + + if template.status == Status.EENMALIG or ( + permanent and template.week == current_week and template.year == current_year): + # als de template eenmalig is moet deze niet gekopieerd worden + # ook wanneer het een permanente aanpassing is op een actieve template die deze week is aangemaakt + template.dag_planningen.remove(to_remove) + template.rondes.remove(ronde) + return Response({"message": "Success"}) + + copy = make_copy(template, permanent, current_week, current_year) + copy.dag_planningen.remove(to_remove) + copy.rondes.remove(to_remove) + return Response({"message": "Success"}) + + # method == "add" + dag_planningen = [] + for day in WeekDayEnum: + pickup_day, _ = PickUpDay.objects.get_or_create( + day=day, + start_hour="17:00", + end_hour="20:00" + ) + dag_planning, _ = DagPlanning.objects.get_or_create( + ronde=ronde, + weekday=pickup_day, + students=[] + ) + dag_planningen.append(dag_planning) + + if template.status == Status.EENMALIG or ( + permanent and template.week == current_week and template.year == current_year): + # als de template eenmalig is moet deze niet gekopieerd worden + # ook wanneer het een permanente aanpassing is op een actieve template die deze week is aangemaakt + template.rondes.add(ronde) + template.dag_planningen.add(dag_planningen) + return Response({"message": "Success"}) + + copy = make_copy(template, permanent, current_week, current_year) + copy.rondes.add(ronde) + copy.dag_planningen.add(dag_planningen) + return Response({"message": "Success"}) + + +