From ac51a9dfbd06a6a6ccb461f5d6dae809460e37eb Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Sat, 19 Mar 2022 21:16:49 +0100
Subject: [PATCH] Add configuration for card printer

---
 aleksis/apps/kort/api.py                      |  1 +
 aleksis/apps/kort/forms.py                    |  9 ++++--
 .../migrations/0008_auto_20220319_2018.py     | 29 +++++++++++++++++++
 aleksis/apps/kort/models.py                   | 19 ++++++++++++
 aleksis/apps/kort/views.py                    | 10 +++++++
 5 files changed, 66 insertions(+), 2 deletions(-)
 create mode 100644 aleksis/apps/kort/migrations/0008_auto_20220319_2018.py

diff --git a/aleksis/apps/kort/api.py b/aleksis/apps/kort/api.py
index 08f403e..cce086a 100644
--- a/aleksis/apps/kort/api.py
+++ b/aleksis/apps/kort/api.py
@@ -34,6 +34,7 @@ class CardPrinterSerializer(serializers.ModelSerializer):
             "status_icon",
             "status_text",
             "last_seen_at",
+            "cups_printer",
         )
 
 
diff --git a/aleksis/apps/kort/forms.py b/aleksis/apps/kort/forms.py
index b8b700e..1bb2c98 100644
--- a/aleksis/apps/kort/forms.py
+++ b/aleksis/apps/kort/forms.py
@@ -2,7 +2,7 @@ from django import forms
 from django.utils.translation import gettext as _
 
 from django_select2.forms import ModelSelect2Widget
-from material import Layout
+from material import Fieldset, Layout
 
 from aleksis.apps.kort.models import Card, CardPrinter
 
@@ -24,9 +24,14 @@ class CardForm(forms.ModelForm):
 
 
 class CardPrinterForm(forms.ModelForm):
+    layout = Layout(
+        Fieldset(_("Generic attributes"), "name", "location", "description"),
+        Fieldset(_("Printer settings"), "cups_printer"),
+    )
+
     class Meta:
         model = CardPrinter
-        fields = ["name", "location", "description"]
+        fields = ["name", "location", "description", "cups_printer"]
 
 
 class PrinterSelectForm(forms.Form):
diff --git a/aleksis/apps/kort/migrations/0008_auto_20220319_2018.py b/aleksis/apps/kort/migrations/0008_auto_20220319_2018.py
new file mode 100644
index 0000000..d350d51
--- /dev/null
+++ b/aleksis/apps/kort/migrations/0008_auto_20220319_2018.py
@@ -0,0 +1,29 @@
+# Generated by Django 3.2.12 on 2022-03-19 19:18
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('kort', '0007_auto_20220315_1957'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='cardprinter',
+            name='cups_printer',
+            field=models.CharField(blank=True, max_length=255, verbose_name='CUPS printer'),
+        ),
+        migrations.AlterField(
+            model_name='cardprintjob',
+            name='printer',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='jobs', to='kort.cardprinter', verbose_name='Printer'),
+        ),
+        migrations.AlterField(
+            model_name='cardprintjob',
+            name='status',
+            field=models.CharField(choices=[('registered', 'Registered'), ('in_progress', 'In progress'), ('finished', 'Finished'), ('failed', 'Failed')], default='registered', max_length=255, verbose_name='Status'),
+        ),
+    ]
diff --git a/aleksis/apps/kort/models.py b/aleksis/apps/kort/models.py
index eb0ed24..c69670e 100644
--- a/aleksis/apps/kort/models.py
+++ b/aleksis/apps/kort/models.py
@@ -1,3 +1,4 @@
+from datetime import timedelta
 from typing import Any, Union
 
 from django.conf import settings
@@ -77,6 +78,9 @@ class CardPrinter(ExtensibleModel):
         related_name="card_printers",
     )
 
+    # Settings
+    cups_printer = models.CharField(max_length=255, verbose_name=_("CUPS printer"), blank=True)
+
     def save(self, *args, **kwargs):
         if not self.oauth2_application:
             application = OAuthApplication(
@@ -122,6 +126,21 @@ class CardPrinter(ExtensibleModel):
         """Return the filename for the printer client configuration."""
         return f"card-printer-config-{self.pk}.json"
 
+    def check_online_status(self):
+        if (
+            self.status
+            not in (CardPrinterStatus.NOT_REGISTERED.value, CardPrinterStatus.OFFLINE.value)
+            and self.last_seen_at
+        ):
+            if self.last_seen_at < timezone.now() - timedelta(minutes=1):
+                self.status = CardPrinterStatus.OFFLINE.value
+                self.save()
+
+    @classmethod
+    def check_online_status_for_all(cls):
+        for printer in cls.objects.all():
+            printer.check_online_status()
+
     class Meta:
         verbose_name = _("Card printer")
         verbose_name_plural = _("Card printers")
diff --git a/aleksis/apps/kort/views.py b/aleksis/apps/kort/views.py
index aadaac6..31a7c42 100644
--- a/aleksis/apps/kort/views.py
+++ b/aleksis/apps/kort/views.py
@@ -163,6 +163,11 @@ class CardPrinterListView(PermissionRequiredMixin, RevisionMixin, SingleTableVie
             )
         )
 
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        CardPrinter.check_online_status_for_all()
+        return context
+
 
 class CardPrinterCreateView(PermissionRequiredMixin, RevisionMixin, AdvancedCreateView):
     """View used to create a card printer."""
@@ -205,6 +210,11 @@ class CardPrinterDetailView(PermissionRequiredMixin, RevisionMixin, DetailView):
     model = CardPrinter
     template_name = "kort/printer/detail.html"
 
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        self.object.check_online_status()
+        return context
+
 
 class CardPrinterConfigView(PermissionRequiredMixin, RevisionMixin, SingleObjectMixin, View):
     permission_required = "core.view_cardprinter_rule"
-- 
GitLab