diff --git a/aleksis/apps/kort/api.py b/aleksis/apps/kort/api.py index 1ddeae48ec5b47f7d5af6121b72ded0cab0a3ca5..5179acf9a46240b18110decf532ea94eeee95ab5 100644 --- a/aleksis/apps/kort/api.py +++ b/aleksis/apps/kort/api.py @@ -2,8 +2,11 @@ from django.contrib import admin from django.shortcuts import get_object_or_404 from django.utils import timezone +from celery.result import allow_join_result +from celery.states import SUCCESS from oauth2_provider.contrib.rest_framework import TokenHasScope from rest_framework import generics, permissions, serializers +from rest_framework.exceptions import APIException, ValidationError from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework.views import APIView @@ -79,6 +82,12 @@ class CardPrintJobStatusSerializer(serializers.ModelSerializer): fields = ("id", "status", "status_text") +class CardChipNumberSerializer(serializers.ModelSerializer): + class Meta: + model = Card + fields = ("chip_number",) + + class CardPrinterDetails(generics.RetrieveAPIView): """Show details about the card printer.""" @@ -135,3 +144,39 @@ class CardPrintJobUpdateStatusView(generics.UpdateAPIView): required_scopes = ["card_printer"] serializer_class = CardPrintJobStatusSerializer queryset = CardPrintJob.objects.all() + + +class CardPrintJobSetChipNumberView(generics.UpdateAPIView): + """Update the status of the card printer.""" + + permission_classes = [permissions.IsAuthenticated, TokenHasScope, CorrectJobPrinterPermission] + required_scopes = ["card_printer"] + serializer_class = CardChipNumberSerializer + queryset = CardPrintJob.objects.all() + + def update(self, request, *args, **kwargs): + instance = self.get_object() + card = instance.card + + if card.chip_number: + raise ValidationError + + serializer = self.get_serializer(card, data=request.data) + serializer.is_valid(raise_exception=True) + self.perform_update(serializer) + + result = instance.card.generate_pdf() + + with allow_join_result(): + result.wait() + card.refresh_from_db() + + if result.status == SUCCESS and card.pdf_file: + serializer = CardPrintJobSerializer(instance) + instance.refresh_from_db() + + return Response(serializer.data) + else: + card.chip_number = None + card.save() + raise APIException("Error while generating PDF file") diff --git a/aleksis/apps/kort/models.py b/aleksis/apps/kort/models.py index 7889cb33a6def26a994653b546965377a832244c..eac8c3bf0211296c6f6d34704ace0db9eb3bb505 100644 --- a/aleksis/apps/kort/models.py +++ b/aleksis/apps/kort/models.py @@ -6,6 +6,7 @@ from django.conf import settings from django.core.exceptions import ValidationError from django.core.validators import FileExtensionValidator from django.db import models +from django.db.models import Q from django.template import Context, Template from django.utils import timezone from django.utils.translation import gettext as _ @@ -148,6 +149,21 @@ class CardPrinter(ExtensibleModel): printer.check_online_status() def get_next_print_job(self) -> Optional["CardPrintJob"]: + if not self.generate_number_on_server: + print( + self.jobs.filter(card__pdf_file=""), + self.jobs.filter(card__pdf_file="").exclude(card__chip_number=""), + ) + self.jobs.filter( + (Q(card__pdf_file="") & ~Q(card__chip_number="")) + | Q(status=PrintStatus.IN_PROGRESS) + ).update(status=PrintStatus.FAILED) + Card.objects.filter( + jobs__in=self.jobs.filter(status=PrintStatus.FAILED), chip_number="" + ).update(chip_number="") + else: + self.jobs.filter(status=PrintStatus.IN_PROGRESS).update(status=PrintStatus.FAILED) + jobs = self.jobs.order_by("created").filter(status=PrintStatus.REGISTERED) if self.generate_number_on_server: jobs = jobs.filter(card__pdf_file__isnull=False) @@ -248,7 +264,9 @@ class CardPrintJob(TimeStampedModel, ExtensibleModel): printer = models.ForeignKey( CardPrinter, on_delete=models.CASCADE, verbose_name=_("Printer"), related_name="jobs" ) - card = models.ForeignKey(Card, on_delete=models.CASCADE, verbose_name=_("Card")) + card = models.ForeignKey( + Card, on_delete=models.CASCADE, verbose_name=_("Card"), related_name="jobs" + ) status = models.CharField( max_length=255, diff --git a/aleksis/apps/kort/urls.py b/aleksis/apps/kort/urls.py index a0c9f5de6dd709e91913dc206fa5226c8401092e..1cc3abcde975474cf37c389060e2a7dc1ea0544d 100644 --- a/aleksis/apps/kort/urls.py +++ b/aleksis/apps/kort/urls.py @@ -45,4 +45,9 @@ urlpatterns = [ api.CardPrintJobUpdateStatusView.as_view(), name="api_update_job_status", ), + path( + "api/v1/jobs/<int:pk>/chip_number/", + api.CardPrintJobSetChipNumberView.as_view(), + name="api_set_chip_number", + ), ]