design, rework flow, extend device
This commit is contained in:
parent
673be80284
commit
9c69dba56d
17 changed files with 712 additions and 303 deletions
|
|
@ -63,6 +63,7 @@ Attribute:
|
|||
|
||||
- Datum: Datum der Veranstaltung
|
||||
- Ort: Beschreibung wo das Repair-Café stattfindet
|
||||
- Adresse: Adresse an der das Repair-Café stattfindet
|
||||
|
||||
Annahmen:
|
||||
|
||||
|
|
@ -102,7 +103,6 @@ Attribute:
|
|||
- Telefon: Festnetz oder Mobilnummer des Gastes
|
||||
- Wohnort: Wohnort des Gastes
|
||||
- Mail: eMail-Adresse des Gastes für Benachrichtigungen
|
||||
- Bestätigt: Ein boolesches Flag das anzeigt ob der Gast seine eMail-Adresse bestätigt hat.
|
||||
|
||||
Technische Attribute:
|
||||
|
||||
|
|
@ -115,15 +115,18 @@ Ein Gerät ist ein defekter Gegenstand der im Rahmen eines Repair-Cafés reparie
|
|||
Attribute:
|
||||
|
||||
- Gerät: Bezeichnung des Geräts
|
||||
- Hersteller: Hersteller des Geräts
|
||||
- Fehler: Beschreibung des Defekts
|
||||
- Folgetermin: Boolesches Flag das anzeigt ob es sich um einen Folgetermin handelt.
|
||||
- Bestätigt: Ein boolesches Flag das anzeigt ob der Gast die Greäteanmeldung bestätigt hat.
|
||||
- Foto vom Gerät
|
||||
- Foto vom Typenschild
|
||||
- Bestätigung gesendet?: Ein boolesches Flag das anzeigt ob eine eMail als Anmeldebestätigung gesendet wurde.
|
||||
|
||||
Technische Attribute:
|
||||
|
||||
- Identifier: SHA256 Hash aus Gerät + Gast + Timestamp
|
||||
- Geheimnis: SHA256 Hash aus Gerät + Gast + Timestamp + Zufallszahl
|
||||
- Gast: Referenz zum Gast der das Gerät besitzt
|
||||
- Cafe: Referenz zum Repair-Café für das diese Gerät angemeldet ist
|
||||
|
||||
### Termin
|
||||
|
||||
|
|
@ -192,17 +195,19 @@ URL: cafe/int:cafe/
|
|||
Name: register_device
|
||||
|
||||
Diese Seite zeigt das Formular zum anmelden der Geräte.
|
||||
Das Formular hat die Felder `eMail-Adresse`, `Gerätebezeichnung`, `Fehlerbeschreibung`, eine Kontrollkästchen `Folgetermin` und einen Knopf `Absenden` zum senden des Formulars.
|
||||
Das Formular hat die Felder `eMail-Adresse`, `Art des Geräts`, `Hersteller & Modell/Typ`, `Fehlerbeschreibung`, `Foto vom Gerät`, `Foto vom Typenschild`, ein Kontrollkästchen `Folgetermin`, ein Kontrollkästchen `Informationen zur Reparaturabwicklung`, ein Kontrollkästchen `Datenschutz` und einen Knopf `Absenden` zum senden des Formulars.
|
||||
|
||||
Das Repair-Café zu dem die Anmeldung gehört ist über eine ID in der URL der Seite festgelegt.
|
||||
|
||||
Die eMail-Benachrichtigung and die Organisatoren und die Bestätigung an den Gast wird beim absenden des Formulars gesendet, falls die eMail Adresse zu einem bekannten Gast gehört.
|
||||
|
||||
#### Sicherheit
|
||||
|
||||
Die Seite ist ohne Zugangsbeschränkung oder Anmeldung erreichbar.
|
||||
|
||||
### Gast anmelden (S3)
|
||||
|
||||
URL: cafe/int:cafe/device/str:deviceentifier/str:mail/
|
||||
URL: cafe/int:cafe/device/str:device_identifier/mail/str:mail/
|
||||
|
||||
Name: register_guest
|
||||
|
||||
|
|
@ -211,37 +216,20 @@ Das Formular hat die Felder `Name`, `Telefon`, `Wohnort` und einen Knopf `Absend
|
|||
|
||||
Die eMail-Adresse und das Gerät zu dem die Gast-Kontaktdaten gehören ist über IDs in der URL der Seite festgelegt.
|
||||
|
||||
#### Sicherheit
|
||||
|
||||
Die Seite ist ohne Zugangsbeschränkung oder Anmeldung erreichbar.
|
||||
|
||||
### Bestätigung gesendet (S4)
|
||||
|
||||
URL: cafe/int:cafe/device/str:deviceentifier/guest/str:guestentifier/
|
||||
|
||||
Name: register_device_final
|
||||
|
||||
Die Seite Bestätigung gesendet zeigt einen Hinweis dass eine eMail gesendet wurde und die Anmeldung des Gerätes durch einen Klick auf einen Link in der eMail bestätigt werden muss.
|
||||
|
||||
Die eMail-Bestätigung wird während des Aufrufs dieser Seite gesendet.
|
||||
|
||||
Das Repair-Café, der Gast und das Gerät sind über IDs in der URL der Seite festgelegt.
|
||||
Die eMail-Benachrichtigung and die Organisatoren und die Bestätigung an den Gast wird beim absenden des Formulars gesendet.
|
||||
|
||||
#### Sicherheit
|
||||
|
||||
Die Seite ist ohne Zugangsbeschränkung oder Anmeldung erreichbar.
|
||||
|
||||
|
||||
### Anmeldung bestätigt (S7)
|
||||
|
||||
URL: confirm/str:deviceentifier/code/str:device_secret/
|
||||
URL: cafe/int:cafe/device/str:device_identifier/confirm/
|
||||
|
||||
Name: register_device_confirm
|
||||
Name: register_device_final
|
||||
|
||||
Die Seite Anmeldung bestätigt zeigt einen Hinweis dass die Anmeldung des Gerätes erfolgreich abgeschlossen wurde.
|
||||
|
||||
Die eMail-Benachrichtigung and die Organisatoren wird während des Aufrufs dieser Seite gesendet.
|
||||
|
||||
Die Geräte ID ist in der URL der Seite festgelegt.
|
||||
|
||||
#### Sicherheit
|
||||
|
|
@ -250,11 +238,11 @@ Die Seite ist ohne Zugangsbeschränkung oder Anmeldung erreichbar.
|
|||
|
||||
### Geräte Detailseite (S5)
|
||||
|
||||
URL: device/str:deviceentifier/
|
||||
URL: device/str:device_identifier/
|
||||
|
||||
Name: view_device
|
||||
|
||||
Die Geräte Detailseite zeigt die Informationen `Gerätebezeichnung`, `Fehlerbeschreibung` und `Folgetermin` an.
|
||||
Die Geräte Detailseite zeigt die Informationen `Art des Geräts`, `Hersteller & Modell/Typ`, `Fehlerbeschreibung`, `Foto vom Gerät`, `Foto vom Typenschild` und `Folgetermin` an.
|
||||
|
||||
Das Gerät ist über IDs in der URL der Seite festgelegt.
|
||||
|
||||
|
|
@ -283,16 +271,16 @@ Die Seite enthält persönliche Daten und ist nur nach Anmeldung erreichbar.
|
|||
Als neuer Gast der ein defekten Geräte anmelden möchte,
|
||||
|
||||
- gehe ich auf die Seite (S1) der Repair-Café Termine. Dort klicke ich auf `Gerät anmelden` bei dem richtigen Repair-Café Termin. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S2) enthält ein Formular mit den Feldern `eMail-Adresse`, `Gerätebezeichnung` und `Fehlerbeschreibung` und eine Kontrollkästchen `Folgetermin`. Nachdem ich die Felder ausgefüllt habe klicke auf auf `Absenden`. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S2) enthält ein Formular mit den Feldern `eMail-Adresse`, `Art des Geräts`, `Hersteller & Modell/Typ`, `Fehlerbeschreibung`, `Foto vom Gerät`, `Foto vom Typenschild`, ein Kontrollkästchen `Folgetermin`, ein Kontrollkästchen `Informationen zur Reparaturabwicklung` une ein Kontrollkästchen `Datenschutz`. Nachdem ich die Felder ausgefüllt habe klicke auf auf `Absenden`. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S3) enthält ein Formular mit den Feldern `Name`, `Telefon` und `Wohnort`. Nachdem ich die Felder ausgefüllt habe klicke auf auf `Absenden`. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S4) weißt mich darauf hin dass eine eMail gesendet wurde und ich die Anmeldung über einen Klick in der eMail bestätigen muss.
|
||||
- In meinem eMail Posteingang finde ich eine Bestätigung der Geräteanmeldung die ebenfalls einen Link enthält um die Anmeldung zu bestätigen. Ein Klick auf diesen Link bringt mich auf die Seite Anmeldung bestätigt (S7).
|
||||
- Die nächste Seite (S5) bestätigt mir die Anmeldung meines Gerätes.
|
||||
- In meinem eMail Posteingang finde ich ebenfalls eine Bestätigung der Geräteanmeldung.
|
||||
|
||||
#### Variante: Bekannter Gast (existierende eMail Adresse)
|
||||
|
||||
Als bekannter Gast der ein defekten Geräte anmelden möchte,
|
||||
|
||||
- gehe ich auf die Seite (S1) der Repair-Café Termine. Dort klicke ich auf `Gerät anmelden` bei dem richtigen Repair-Café Termin. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S2) enthält ein Formular mit den Feldern `eMail-Adresse`, `Gerätebezeichnung` und `Fehlerbeschreibung` und eine Kontrollkästchen `Folgetermin`. Nachdem ich die Felder ausgefüllt habe klicke auf auf `Absenden`. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S4) weißt mich darauf hin dass eine eMail gesendet wurde und ich die Anmeldung über einen Klick in der eMail bestätigen muss.
|
||||
- In meinem eMail Posteingang finde ich eine Bestätigung der Geräteanmeldung die ebenfalls einen Link enthält um die Anmeldung zu bestätigen. Ein Klick auf diesen Link bringt mich auf die Seite Anmeldung bestätigt (S7).
|
||||
- Die nächste Seite (S2) enthält ein Formular mit den Feldern `eMail-Adresse`, `Art des Geräts`, `Hersteller & Modell/Typ`, `Fehlerbeschreibung`, `Foto vom Gerät`, `Foto vom Typenschild`, ein Kontrollkästchen `Folgetermin`, ein Kontrollkästchen `Informationen zur Reparaturabwicklung` une ein Kontrollkästchen `Datenschutz`. Nachdem ich die Felder ausgefüllt habe klicke auf auf `Absenden`. Dieser Klick bringt mich auf die nächste Seite.
|
||||
- Die nächste Seite (S5) bestätigt mir die Anmeldung meines Gerätes.
|
||||
- In meinem eMail Posteingang finde ich ebenfalls eine Bestätigung der Geräteanmeldung.
|
||||
|
|
|
|||
|
|
@ -10,4 +10,7 @@ server {
|
|||
location /static {
|
||||
root /opt/app/rc_hip;
|
||||
}
|
||||
location /media {
|
||||
root /opt/app/rc_hip;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ Including another URLconf
|
|||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("", include("repapp.urls")),
|
||||
path('admin/', admin.site.urls),
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ class RegisterDevice(forms.Form):
|
|||
" zur Anfrage verwendet.",
|
||||
max_length=200)
|
||||
device = forms.CharField(
|
||||
label="Gerätebezeichnung",
|
||||
help_text="Bitte geben Sie den Hersteller und die"
|
||||
" Gerätebezeichnung an.",
|
||||
label="Art des Geräts",
|
||||
help_text="z.B. Küchenmaschine, Smartphone, Stehlampe, Drucker, ...",
|
||||
max_length=200
|
||||
)
|
||||
manufacturer = forms.CharField(
|
||||
label="Hersteller & Modell/Typ",
|
||||
max_length=200
|
||||
)
|
||||
error = forms.CharField(
|
||||
|
|
@ -18,12 +21,33 @@ class RegisterDevice(forms.Form):
|
|||
help_text="Beschreiben Sie hier das Problem ihres Gerätes.",
|
||||
widget=forms.Textarea
|
||||
)
|
||||
device_picture = forms.FileField(
|
||||
label="Foto vom Gerät ", required=False
|
||||
)
|
||||
type_plate_picture = forms.FileField(
|
||||
label="Foto vom Typenschild ", required=False
|
||||
)
|
||||
follow_up = forms.BooleanField(
|
||||
label="Folgetermin",
|
||||
help_text="Klicken Sie dieses Kästchen an wenn sie mit diesem"
|
||||
" Gerät bereits bei einem Repair-Café waren.",
|
||||
help_text="Kreuzen Sie diese Kästchen an wenn sie mit diesem Gerät bereits bei einem Repair-Café Termin waren.",
|
||||
required=False
|
||||
)
|
||||
confirm_repair = forms.BooleanField(
|
||||
label="Informationen zur Reparaturabwicklung",
|
||||
help_text="Ich bin mit den <a href="
|
||||
"\"https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/images/"
|
||||
"repaircafe-hilpoltstein.de/docs/Infos_Reparatur-Abwicklung_v2_2023-02.pdf\">"
|
||||
"Allgemeinen Bedingungen zur Reparaturabwicklung</a> einverstanden.",
|
||||
required=True
|
||||
)
|
||||
confirm_data = forms.BooleanField(
|
||||
label="Datenschutz",
|
||||
help_text=" Ich bin mit der Erhebung, Verarbeitung und Speicherung meiner Daten für "
|
||||
"die Bearbeitung meiner Anfrage gemäß der "
|
||||
"<a href=\"https://www.repaircafe-hilpoltstein.de/impressum#c1375\">"
|
||||
"Datenschutzerklärung</a> einverstanden.",
|
||||
required=True
|
||||
)
|
||||
|
||||
|
||||
class RegisterGuest(forms.Form):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
# Generated by Django 4.2 on 2023-04-21 15:21
|
||||
|
||||
from django.db import migrations, models
|
||||
import repapp.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('repapp', '0011_rename_cafe_id_appointment_cafe_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='device',
|
||||
name='secret',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='guest',
|
||||
name='confirmed',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cafe',
|
||||
name='address',
|
||||
field=models.CharField(default='', max_length=200, verbose_name='Ort'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='device_picture',
|
||||
field=models.FileField(null=True, upload_to=repapp.models.device_directory_path, verbose_name='Foto vom Gerät'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='manufacturer',
|
||||
field=models.CharField(default='', max_length=200, verbose_name='Hersteller'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='type_plate_picture',
|
||||
field=models.FileField(null=True, upload_to=repapp.models.device_directory_path, verbose_name='Foto vom Typenschild'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='confirmed',
|
||||
field=models.BooleanField(verbose_name='Bestätigung gesendet?'),
|
||||
),
|
||||
]
|
||||
|
|
@ -11,6 +11,8 @@ class Cafe(models.Model):
|
|||
"""
|
||||
location = models.CharField(
|
||||
max_length=200, verbose_name=_("Ort"))
|
||||
address = models.CharField(
|
||||
max_length=200, verbose_name=_("Adresse"))
|
||||
event_date = models.DateField(verbose_name=_("Datum"))
|
||||
|
||||
class Meta:
|
||||
|
|
@ -60,7 +62,6 @@ class Guest(models.Model):
|
|||
phone = models.CharField(max_length=200, verbose_name=_("Telefonnummer"))
|
||||
residence = models.CharField(max_length=200, verbose_name=_("Wohnort"))
|
||||
mail = models.CharField(max_length=200, verbose_name=_("eMail"))
|
||||
confirmed = models.BooleanField(verbose_name=_("Bestätigt"), default=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Gast')
|
||||
|
|
@ -70,21 +71,29 @@ class Guest(models.Model):
|
|||
return f'Gast {self.name} (eMail: {self.mail})'
|
||||
|
||||
|
||||
def device_directory_path(instance, filename):
|
||||
return f'device_{instance.identifier}/{filename}'
|
||||
|
||||
|
||||
class Device(models.Model):
|
||||
"""
|
||||
A Device is a broken device owned by a guest which shall be repaired during a Repair-Café.
|
||||
"""
|
||||
identifier = models.CharField(max_length=200, verbose_name=_("ID"))
|
||||
secret = models.CharField(
|
||||
max_length=200, verbose_name=_("Bestätigungscode"), default="TEST12345")
|
||||
device = models.CharField(max_length=200, verbose_name=_("Gerät"))
|
||||
error = models.TextField(verbose_name=_("Fehler"))
|
||||
device = models.CharField(max_length=200, verbose_name=_("Art des Geräts"))
|
||||
manufacturer = models.CharField(
|
||||
max_length=200, verbose_name=_("Hersteller & Modell/Typ"))
|
||||
error = models.TextField(verbose_name=_("Fehlerbeschreibung"))
|
||||
follow_up = models.BooleanField(verbose_name=_("Folgetermin"))
|
||||
confirmed = models.BooleanField(verbose_name=_("Bestätigt"), default=False)
|
||||
device_picture = models.FileField(
|
||||
upload_to=device_directory_path, null=True, verbose_name=_("Foto vom Gerät"))
|
||||
type_plate_picture = models.FileField(
|
||||
upload_to=device_directory_path, null=True, verbose_name=_("Foto vom Typenschild"))
|
||||
guest = models.ForeignKey(
|
||||
Guest, on_delete=models.CASCADE, null=True, verbose_name=_("Gast"))
|
||||
cafe = models.ForeignKey(
|
||||
Cafe, on_delete=models.CASCADE, null=False, verbose_name=_("Repair-Café"))
|
||||
confirmed = models.BooleanField(verbose_name=_("Bestätigung gesendet?"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Gerät')
|
||||
|
|
@ -116,25 +125,6 @@ class Appointment(models.Model):
|
|||
return f'Termin {self.cafe.event_date} {self.time} für Gerät {self.device.device}'
|
||||
|
||||
|
||||
class Candidate(models.Model):
|
||||
"""
|
||||
A Candidate is a match of a broken Device and a Repair-Café without a fixed timeslot
|
||||
or pre-assigned Reparateur.
|
||||
"""
|
||||
confirmed = models.BooleanField(verbose_name=_("bestätigt"))
|
||||
cafe = models.ForeignKey(
|
||||
Cafe, on_delete=models.CASCADE, verbose_name=_("Repair-Café"))
|
||||
device = models.ForeignKey(
|
||||
Device, on_delete=models.CASCADE, null=True, verbose_name=_("Gerät"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Kandidat')
|
||||
verbose_name_plural = _('Kandidaten')
|
||||
|
||||
def __str__(self):
|
||||
return f'Kandidat {self.cafe.event_date} für Gerät {self.device.device}'
|
||||
|
||||
|
||||
class Question(models.Model):
|
||||
"""
|
||||
A Question is a request for information form a Organisator or a Reparateur for a Device.
|
||||
|
|
@ -155,3 +145,22 @@ class Question(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return f'Frage vom {self.date} zum Gerät {self.device.device}'
|
||||
|
||||
|
||||
class Candidate(models.Model):
|
||||
"""
|
||||
A Candidate is a match of a broken Device and a Repair-Café without a fixed timeslot
|
||||
or pre-assigned Reparateur.
|
||||
"""
|
||||
confirmed = models.BooleanField(verbose_name=_("bestätigt"))
|
||||
cafe = models.ForeignKey(
|
||||
Cafe, on_delete=models.CASCADE, verbose_name=_("Repair-Café"))
|
||||
device = models.ForeignKey(
|
||||
Device, on_delete=models.CASCADE, null=True, verbose_name=_("Gerät"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Kandidat')
|
||||
verbose_name_plural = _('Kandidaten')
|
||||
|
||||
def __str__(self):
|
||||
return f'Kandidat {self.cafe.event_date} für Gerät {self.device.device}'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description"
|
||||
content="{% block description %} {% endblock description %}" />
|
||||
<meta name="keywords"
|
||||
content="{% block keywords %} {% endblock keywords %}" />
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<link rel="stylesheet"
|
||||
|
|
@ -15,16 +19,15 @@
|
|||
{% block title %}
|
||||
{% endblock title %}
|
||||
</title>
|
||||
{% block head %}
|
||||
{% endblock head %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {% if message.tags %}alert-{{ message.tags }}{% else %}alert-primary{% endif %}"
|
||||
role="alert">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% for message in messages %}<div class="alert alert-primary" role="alert">{{ message }}</div>{% endfor %}
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,56 @@
|
|||
{% block content %}
|
||||
<h1 class="mt-2">Gerät: {{ device.device }}</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<p>Fehler:</p>
|
||||
<p>{{ device.error }}</p>
|
||||
<p>
|
||||
Folgetermin:
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Art des Geräts</th>
|
||||
<td>{{ device.device }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Hersteller & Modell/Typ</th>
|
||||
<td>{{ device.manufacturer }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Fehlerbeschreibung</th>
|
||||
<td>{{ device.error }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Folgetermin</th>
|
||||
<td>
|
||||
{% if device.follow_up %}
|
||||
Ja
|
||||
{% else %}
|
||||
Nein
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Foto vom Gerät</th>
|
||||
<td>
|
||||
{% if device.device_picture %}
|
||||
<img alt="Foto vom Gerät"
|
||||
height="100%"
|
||||
width="50%"
|
||||
src="/media/{{ device.device_picture }}" />
|
||||
{% else %}
|
||||
kein Bild
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Foto vom Typenschild</th>
|
||||
<td>
|
||||
{% if device.device_picture %}
|
||||
<img alt="Foto vom Typenschild"
|
||||
height="100%"
|
||||
width="50%"
|
||||
src="/media/{{ device.type_plate_picture }}" />
|
||||
{% else %}
|
||||
kein Bild
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock content %}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,324 @@
|
|||
{% extends "repapp/base.html" %}
|
||||
{% block title %}
|
||||
- Repair-Cafés
|
||||
{% endblock title %}
|
||||
{% block head %}
|
||||
<style>
|
||||
@font-face {
|
||||
font-family:'Source Sans Pro';
|
||||
font-style:normal;
|
||||
font-weight:300;
|
||||
src:url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-300.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src:local('Source Sans Pro Light'), local('SourceSansPro-Light'),
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-300.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-300.woff') format('woff'), /* Modern Browsers */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-300.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-300.svg#SourceSansPro') format('svg');/* Legacy iOS */;
|
||||
}
|
||||
@font-face {
|
||||
font-family:'Source Sans Pro';
|
||||
font-style:normal;
|
||||
font-weight:400;
|
||||
src:url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-regular.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src:local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-regular.woff') format('woff'), /* Modern Browsers */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-regular.svg#SourceSansPro') format('svg');/* Legacy iOS */;
|
||||
}
|
||||
@font-face {
|
||||
font-family:'Source Sans Pro';
|
||||
font-style:normal;
|
||||
font-weight:700;
|
||||
src:url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-700.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src:local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-700.woff') format('woff'), /* Modern Browsers */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('https://www.repaircafe-hilpoltstein.de/fileadmin/repaircafe-hilpoltstein/default/templates/fonts/source-sans-pro-v11-latin-700.svg#SourceSansPro') format('svg');/* Legacy iOS */;
|
||||
}
|
||||
@media all{
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
{% block title %}- Repair-Cafés{% endblock title %}
|
||||
.frame > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.frame {
|
||||
position: relative;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 576px){
|
||||
.frame {
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px){
|
||||
.frame {
|
||||
padding-top: 3rem;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px){
|
||||
.frame {
|
||||
padding-top: 3.5rem;
|
||||
padding-bottom: 3.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px){
|
||||
.frame {
|
||||
padding-top: 3.5rem;
|
||||
padding-bottom: 3.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media all{
|
||||
.frame-space-before-none {
|
||||
margin-top: 0rem;
|
||||
}
|
||||
|
||||
.frame-space-after-none {
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px){
|
||||
.frame {
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media all{
|
||||
.col-md-8 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px){
|
||||
.col-md-8 {
|
||||
flex: 0 0 66.6666666667%;
|
||||
max-width: 66.6666666667%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 992px){
|
||||
.col-md-8 {
|
||||
padding-right: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all{
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-right: -20px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 576px){
|
||||
.container {
|
||||
max-width: 540px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px){
|
||||
.container {
|
||||
max-width: 720px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px){
|
||||
.container {
|
||||
max-width: 960px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px){
|
||||
.container {
|
||||
max-width: 1140px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all{
|
||||
.section {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px){
|
||||
.section {
|
||||
padding-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all{
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #2b2b2b;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.news-list-view {
|
||||
padding-right: 20px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
*,:before,:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:selection {
|
||||
background-color: darkred;
|
||||
}
|
||||
|
||||
.article {
|
||||
padding: 30px 0;
|
||||
border-bottom: 2px solid #cccccc;
|
||||
}
|
||||
|
||||
.article:last-child {
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.article.event {
|
||||
padding: 0 0 30px 0;
|
||||
}
|
||||
|
||||
.dtdate {
|
||||
font-size: 21px;
|
||||
color: #FFFFFF;
|
||||
background: darkred;
|
||||
padding: 0 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.article.event .ort {
|
||||
margin-top: 5px;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.teaser-text {
|
||||
position: relative;
|
||||
padding-bottom: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.article.event .teaser-text {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
a {
|
||||
color: darkred;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a {
|
||||
color: darkblue;
|
||||
border-bottom: 1px solid;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #FFFFFF;
|
||||
text-decoration: underline;
|
||||
background: darkred;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: darkblue;
|
||||
color: #ffffff!important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock head %}
|
||||
{% block content %}
|
||||
<h1 class="mt-2">Repair-Cafés</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<ul class="list-group">
|
||||
{% for cafe in object_list %}
|
||||
<h1 class="mt-2">Repair-Cafés</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<ul class="list-group">
|
||||
{% for cafe in object_list %}
|
||||
<li class="list-group-item">
|
||||
<a href="{% url 'register_device' cafe.id %}">
|
||||
<button type="button" class="btn btn-primary">Repair-Café am {{ cafe.event_date|date }}, {{ cafe.location }}</button>
|
||||
</a>
|
||||
<div class="news-list-view eventhome snipcss-aSNzE" id="news-container-82">
|
||||
<div class="rc-date">
|
||||
<div class="article event rc-date "
|
||||
itemscope="itemscope"
|
||||
itemtype="http://schema.org/Article">
|
||||
<div class="dtdate">
|
||||
<time itemprop="datePublished" datetime="13.05.2023">
|
||||
{{ cafe.event_date|date:"l" }}, {{ cafe.event_date|date }}, 14.00 - 17.00 Uhr
|
||||
</time>
|
||||
</div>
|
||||
<div class="ort">
|
||||
{{ cafe.location }}
|
||||
<br>
|
||||
{{ cafe.address }}
|
||||
</div>
|
||||
<div class="teaser-text">
|
||||
<div itemprop="description">
|
||||
<p>
|
||||
<strong>
|
||||
Nur per Voranmeldung.
|
||||
<a href="{% url 'register_device' cafe.id %}">Zum Anmeldeformular</a>
|
||||
</strong>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% empty %}
|
||||
{% empty %}
|
||||
<li class="list-group-item">Es gibt keine geplanten Repair-Cafés.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock content %}
|
||||
|
|
@ -1,20 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<body>
|
||||
<p>Hallo {{ guest.name }},</p>
|
||||
<p>Guten Tag,</p>
|
||||
<p>
|
||||
Ihre Anmeldung von {{ device.device }} für das Repair-Café am {{ cafe.event_date|date }}
|
||||
ist bei uns angekommen.
|
||||
dies ist eine automatische Nachricht, die du erhältst, nachdem du unser Anmeldeformular abgesendet hast und deine Angaben in unserer Datenbank gespeichert wurden.
|
||||
</p>
|
||||
<p>
|
||||
Bitte bestätigen sie ihre Anmeldung in dem Sie
|
||||
<a href="https://repapp.rc-hip.de/confirm/{{ device.identifier }}/code/{{ device.secret }}">hier</a>
|
||||
klicken.
|
||||
Vielen Dank für die Anmeldung des Geräts {{ device.device }} - {{ device.manufacturer }} zur Reparatur im Repair-Café am {{ cafe.event_date|date }}.
|
||||
</p>
|
||||
<p>
|
||||
Viele Grüße,
|
||||
<br>
|
||||
Ihr Repair-Café
|
||||
Die Organisation unserer Repair-Cafés beginnt i.a. einige Tage vor dem jeweiligen Termin. Dann erstellen wir anhand der angemeldeten Geräte und der Spezialgebiete der anwesenden Reparateure einen Zeitplan.
|
||||
</p>
|
||||
<p>
|
||||
Sobald dieser Zeitplan fertig gestellt ist, erhältst du von einem Mitglied unseres Organisationsteams eine Mail. Diese beinhaltet im Normalfall den Reparaturtermin inkl. der Uhrzeit, für die die Reparatur vorgesehen ist. In Ausnahmefällen (z.B. wenn kein Spezialist für die Gerätegruppe anwesend sein wird oder überbucht ist) ist es aber auch möglich, dass wir deinen gewünschten Termin absagen und dir einen Alternativtermin vorschlagen müssen.
|
||||
</p>
|
||||
<p>
|
||||
Falls du in der Zwischenzeit Rückfragen hast oder deinen Wunschtermin doch nicht wahrnehmen kannst, antworte bitte einfach auf diese Nachricht.
|
||||
</p>
|
||||
<p>Herzliche Grüße sendet dir das Organisationsteam vom Repair-Café Hilpoltstein!</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Anmeldung von {{ device.device }} für das Repair-Café am {{ cafe.event_date|date }}
|
||||
Repair-Café Hilpoltstein am {{ cafe.event_date|date }} - Geräteanmeldung
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
Hallo {{ guest.name }},
|
||||
Ihre Anmeldung von {{ device.device }} für das Repair-Café am {{ cafe.event_date|date }} ist bei uns angekommen.
|
||||
Bitte bestätigen sie ihre Anmeldung in dem Sie https://repapp.rc-hip.de/confirm/{{ device.identifier }}/code/{{ device.secret }} in ihrem Web-Browser aufrufen.
|
||||
Viele Grüße,
|
||||
Ihr Repair-Café
|
||||
Guten Tag,
|
||||
dies ist eine automatische Nachricht, die du erhältst, nachdem du unser Anmeldeformular abgesendet hast und deine Angaben in unserer Datenbank gespeichert wurden.
|
||||
Vielen Dank für die Anmeldung des Geräts {{ device.device }} - {{ device.manufacturer }} zur Reparatur im Repair-Café am {{ cafe.event_date|date }}.
|
||||
Die Organisation unserer Repair-Cafés beginnt i.a. einige Tage vor dem jeweiligen Termin. Dann erstellen wir anhand der angemeldeten Geräte und der Spezialgebiete der anwesenden Reparateure einen Zeitplan.
|
||||
Sobald dieser Zeitplan fertig gestellt ist, erhältst du von einem Mitglied unseres Organisationsteams eine Mail. Diese beinhaltet im Normalfall den Reparaturtermin inkl. der Uhrzeit, für die die Reparatur vorgesehen ist. In Ausnahmefällen (z.B. wenn kein Spezialist für die Gerätegruppe anwesend sein wird oder überbucht ist) ist es aber auch möglich, dass wir deinen gewünschten Termin absagen und dir einen Alternativtermin vorschlagen müssen.
|
||||
Falls du in der Zwischenzeit Rückfragen hast oder deinen Wunschtermin doch nicht wahrnehmen kannst, antworte bitte einfach auf diese Nachricht.
|
||||
Herzliche Grüße sendet dir das Organisationsteam vom Repair-Café Hilpoltstein!
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
{% extends "repapp/base.html" %}
|
||||
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block title %}- Gerät anmelden{% endblock title %}
|
||||
|
||||
{% block title %}
|
||||
- Gerät anmelden
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<h1 class="mt-2">Gerät anmelden</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<form action="{% url 'register_device' cafe.id %}" method="post">
|
||||
<h1 class="mt-2">Gerät anmelden</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<form action="{% url 'register_device' cafe.id %}"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button type="submit" class="btn btn-primary">Absenden</button>
|
||||
</form>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{% extends "repapp/base.html" %}
|
||||
{% block title %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<h1 class="mt-2">Anmeldung abgeschlossen</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<p>Ihr Gerät ist erfolgreich angemeldet!</p>
|
||||
<p>
|
||||
Wir versuchen für sie einen Termin bei einem geeigneten Reparateur zu finden.
|
||||
Wenn wir einen Termin gefunden haben werden Sie per eMail benachrichtigt.
|
||||
</p>
|
||||
{% endblock content %}
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
{% extends "repapp/base.html" %}
|
||||
|
||||
{% block title %}{% endblock title %}
|
||||
|
||||
{% block title %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<h1 class="mt-2">Bestätigung ihrer Daten</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<p>
|
||||
Wir haben ihnen eine eMail mit ihren Daten gesendet. Bitte bestätigen
|
||||
Sie ihre Anmeldung durch Klick auf den Link in der eMail.
|
||||
</p>
|
||||
<h1 class="mt-2">Anmeldung erfolgreich!</h1>
|
||||
<hr class="mt-0 mb-4">
|
||||
<p>
|
||||
Vielen Dank für die Anmeldung des Geräts {{ device.device }} - {{ device.manufacturer }} zur Reparatur im Repair-Café am {{ cafe.event_date|date }}.
|
||||
</p>
|
||||
<p>
|
||||
Die Organisation unserer Repair-Cafés beginnt i.a. einige Tage vor dem jeweiligen Termin. Dann erstellen wir anhand der angemeldeten Geräte und der Spezialgebiete der anwesenden Reparateure einen Zeitplan.
|
||||
</p>
|
||||
<p>
|
||||
Sobald dieser Zeitplan fertig gestellt ist, erhältst du von einem Mitglied unseres Organisationsteams eine Mail. Diese beinhaltet im Normalfall den Reparaturtermin inkl. der Uhrzeit, für die die Reparatur vorgesehen ist. In Ausnahmefällen (z.B. wenn kein Spezialist für die Gerätegruppe anwesend sein wird oder überbucht ist) ist es aber auch möglich, dass wir deinen gewünschten Termin absagen und dir einen Alternativtermin vorschlagen müssen.
|
||||
</p>
|
||||
{% endblock content %}
|
||||
|
|
@ -13,14 +13,12 @@ urlpatterns = [
|
|||
name="register_device"
|
||||
),
|
||||
path(
|
||||
"cafe/<int:cafe>/device/<str:deviceentifier>/<str:mail>/",
|
||||
"cafe/<int:cafe>/device/<str:device_identifier>/mail/<str:mail>/",
|
||||
views.RegisterGuestFormView.as_view(),
|
||||
name="register_guest"
|
||||
),
|
||||
path("cafe/<int:cafe>/device/<str:deviceentifier>/guest/<str:guestentifier>/",
|
||||
path("cafe/<int:cafe>/device/<str:device_identifier>/confirm/",
|
||||
views.register_device_final, name="register_device_final"),
|
||||
path("confirm/<str:deviceentifier>/code/<str:device_secret>/",
|
||||
views.register_device_confirm, name="register_device_confirm"),
|
||||
path("device/<str:deviceentifier>/",
|
||||
path("device/<str:device_identifier>/",
|
||||
views.device_view, name="view_device"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@ Views of RepApp.
|
|||
"""
|
||||
import datetime
|
||||
import os
|
||||
import random
|
||||
from hashlib import sha256
|
||||
from django.views import generic
|
||||
from django.urls import reverse_lazy
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.http import HttpResponseRedirect, Http404
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib import messages
|
||||
from django.core.mail import send_mail
|
||||
from django.template.loader import render_to_string
|
||||
|
|
@ -28,119 +27,24 @@ class IndexView(generic.ListView):
|
|||
return Cafe.objects.filter(event_date__gte=datetime.date.today())
|
||||
|
||||
|
||||
class RegisterDeviceFormView(generic.edit.FormView):
|
||||
template_name = "repapp/register_device.html"
|
||||
form_class = RegisterDevice
|
||||
def send_confirmation_mails(device, guest, cafe, request):
|
||||
organizers = []
|
||||
for organizer in Organisator.objects.all():
|
||||
organizers.append(organizer.mail)
|
||||
|
||||
def form_valid(self, form):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
text = render_to_string('repapp/mail/notice_new_device.html', {
|
||||
'guest': device.guest,
|
||||
'device': device,
|
||||
'cafe': device.cafe,
|
||||
})
|
||||
|
||||
mail = form.cleaned_data['mail']
|
||||
device = form.cleaned_data['device']
|
||||
identifier = sha256(
|
||||
f'{device}{mail}{datetime.datetime.now()}'.encode('utf-8')
|
||||
).hexdigest()
|
||||
secret = sha256(
|
||||
f'{device}{mail}{datetime.datetime.now()}{random.randint(0, 999999)}'.encode(
|
||||
'utf-8')
|
||||
).hexdigest()
|
||||
device = Device(
|
||||
identifier=identifier,
|
||||
secret=secret,
|
||||
device=device,
|
||||
error=form.cleaned_data['error'],
|
||||
follow_up=form.cleaned_data['follow_up'],
|
||||
cafe=cafe,
|
||||
send_mail(
|
||||
subject=f"Neues Gerät { device.device }",
|
||||
message=text,
|
||||
from_email=os.getenv("DJANGO_SENDER_ADDRESS", ""),
|
||||
recipient_list=organizers,
|
||||
fail_silently=True
|
||||
)
|
||||
device.save()
|
||||
|
||||
guest = Guest.objects.filter(mail=mail).first()
|
||||
|
||||
if guest:
|
||||
device.guest = guest
|
||||
device.save()
|
||||
return HttpResponseRedirect(
|
||||
reverse_lazy('register_device_final', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'deviceentifier': device.identifier,
|
||||
'guestentifier': guest.identifier})
|
||||
)
|
||||
else:
|
||||
return HttpResponseRedirect(
|
||||
reverse_lazy('register_guest', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'deviceentifier': device.identifier,
|
||||
'mail': mail})
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
|
||||
context = super(RegisterDeviceFormView, self).get_context_data(
|
||||
**kwargs
|
||||
)
|
||||
context["cafe"] = cafe
|
||||
return context
|
||||
|
||||
|
||||
class RegisterGuestFormView(generic.edit.FormView):
|
||||
template_name = "repapp/register_guest.html"
|
||||
form_class = RegisterGuest
|
||||
|
||||
def form_valid(self, form):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
|
||||
deviceentifier = self.kwargs['deviceentifier']
|
||||
device = get_object_or_404(Device, identifier=deviceentifier)
|
||||
|
||||
name = form.cleaned_data['name']
|
||||
residence = form.cleaned_data['residence']
|
||||
identifier = sha256(
|
||||
f'{name}{residence}{datetime.datetime.now()}'.encode('utf-8')
|
||||
).hexdigest()
|
||||
guest = Guest(
|
||||
identifier=identifier,
|
||||
name=name,
|
||||
phone=form.cleaned_data['phone'],
|
||||
residence=residence,
|
||||
mail=self.kwargs['mail'],
|
||||
)
|
||||
guest.save()
|
||||
|
||||
device.guest = guest
|
||||
device.save()
|
||||
|
||||
return HttpResponseRedirect(
|
||||
reverse_lazy('register_device_final', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'deviceentifier': device.identifier,
|
||||
'guestentifier': guest.identifier})
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
|
||||
deviceentifier = self.kwargs['deviceentifier']
|
||||
device = get_object_or_404(Device, identifier=deviceentifier)
|
||||
|
||||
context = super(RegisterGuestFormView, self).get_context_data(
|
||||
**kwargs
|
||||
)
|
||||
context["cafe"] = cafe
|
||||
context["device"] = device
|
||||
context["mail"] = self.kwargs['mail']
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def register_device_final(request, cafe, deviceentifier, guestentifier):
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
device = get_object_or_404(Device, identifier=deviceentifier)
|
||||
guest = get_object_or_404(Guest, identifier=guestentifier)
|
||||
|
||||
subject = render_to_string('repapp/mail/mail_register_device_subject.html', {
|
||||
'guest': guest,
|
||||
|
|
@ -168,58 +72,144 @@ def register_device_final(request, cafe, deviceentifier, guestentifier):
|
|||
)
|
||||
|
||||
if ok > 0:
|
||||
messages.add_message(request, messages.INFO,
|
||||
'Die Bestätigungs-eMail wurde erfolgreich gesendet.')
|
||||
device.confirmed = True
|
||||
device.save()
|
||||
else:
|
||||
messages.add_message(request, messages.ERROR,
|
||||
'Fehler beim senden der Bestätigungs-eMail!')
|
||||
|
||||
|
||||
class RegisterDeviceFormView(generic.edit.FormView):
|
||||
template_name = "repapp/register_device.html"
|
||||
form_class = RegisterDevice
|
||||
|
||||
def form_valid(self, form):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
mail = form.cleaned_data['mail']
|
||||
device = form.cleaned_data['device']
|
||||
identifier = sha256(
|
||||
f'{device}{mail}{datetime.datetime.now()}'.encode('utf-8')
|
||||
).hexdigest()
|
||||
device = Device(
|
||||
identifier=identifier,
|
||||
device=device,
|
||||
manufacturer=form.cleaned_data['manufacturer'],
|
||||
error=form.cleaned_data['error'],
|
||||
follow_up=form.cleaned_data['follow_up'],
|
||||
device_picture=self.request.FILES.get("device_picture", None),
|
||||
type_plate_picture=self.request.FILES.get(
|
||||
"type_plate_picture", None),
|
||||
cafe=cafe,
|
||||
confirmed=False,
|
||||
)
|
||||
device.save()
|
||||
|
||||
guest = Guest.objects.filter(mail=mail).first()
|
||||
|
||||
print(f'Register: Dev: {device}, Guest: {guest}')
|
||||
|
||||
if guest:
|
||||
print('Guest already known')
|
||||
device.guest = guest
|
||||
device.save()
|
||||
|
||||
send_confirmation_mails(device, guest, cafe, self.request)
|
||||
|
||||
print('Mails sent')
|
||||
|
||||
resp = HttpResponseRedirect(
|
||||
reverse_lazy('register_device_final', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'device_identifier': device.identifier})
|
||||
)
|
||||
print(resp)
|
||||
return resp
|
||||
else:
|
||||
return HttpResponseRedirect(
|
||||
reverse_lazy('register_guest', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'device_identifier': device.identifier,
|
||||
'mail': mail})
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
|
||||
context = super(RegisterDeviceFormView, self).get_context_data(
|
||||
**kwargs
|
||||
)
|
||||
context["cafe"] = cafe
|
||||
return context
|
||||
|
||||
|
||||
class RegisterGuestFormView(generic.edit.FormView):
|
||||
template_name = "repapp/register_guest.html"
|
||||
form_class = RegisterGuest
|
||||
|
||||
def form_valid(self, form):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
|
||||
device_identifier = self.kwargs['device_identifier']
|
||||
device = get_object_or_404(Device, identifier=device_identifier)
|
||||
|
||||
name = form.cleaned_data['name']
|
||||
residence = form.cleaned_data['residence']
|
||||
identifier = sha256(
|
||||
f'{name}{residence}{datetime.datetime.now()}'.encode('utf-8')
|
||||
).hexdigest()
|
||||
guest = Guest(
|
||||
identifier=identifier,
|
||||
name=name,
|
||||
phone=form.cleaned_data['phone'],
|
||||
residence=residence,
|
||||
mail=self.kwargs['mail'],
|
||||
)
|
||||
guest.save()
|
||||
|
||||
device.guest = guest
|
||||
device.save()
|
||||
|
||||
send_confirmation_mails(device, guest, cafe, self.request)
|
||||
|
||||
return HttpResponseRedirect(
|
||||
reverse_lazy('register_device_final', kwargs={
|
||||
'cafe': cafe.pk,
|
||||
'device_identifier': device.identifier})
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
cafe = self.kwargs['cafe']
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
|
||||
device_identifier = self.kwargs['device_identifier']
|
||||
device = get_object_or_404(Device, identifier=device_identifier)
|
||||
|
||||
context = super(RegisterGuestFormView, self).get_context_data(
|
||||
**kwargs
|
||||
)
|
||||
context["cafe"] = cafe
|
||||
context["device"] = device
|
||||
context["mail"] = self.kwargs['mail']
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def register_device_final(request, cafe, device_identifier):
|
||||
cafe = get_object_or_404(Cafe, pk=cafe)
|
||||
device = get_object_or_404(Device, identifier=device_identifier)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"repapp/register_device_final.html",
|
||||
{},
|
||||
{"device": device, 'cafe': cafe},
|
||||
)
|
||||
|
||||
|
||||
def register_device_confirm(request, deviceentifier, device_secret):
|
||||
device = get_object_or_404(Device, identifier=deviceentifier)
|
||||
if not device.guest:
|
||||
raise Http404('Unknown guest!')
|
||||
|
||||
device.confirmed = True
|
||||
device.save()
|
||||
|
||||
if not device.guest.confirmed:
|
||||
device.guest.confirmed = True
|
||||
device.guest.save()
|
||||
|
||||
text = render_to_string('repapp/mail/notice_new_device.html', {
|
||||
'guest': device.guest,
|
||||
'device': device,
|
||||
'cafe': device.cafe,
|
||||
})
|
||||
|
||||
organizers = []
|
||||
for organizer in Organisator.objects.all():
|
||||
organizers.append(organizer.mail)
|
||||
|
||||
send_mail(
|
||||
subject=f"Neues Gerät { device.device }",
|
||||
message=text,
|
||||
from_email=os.getenv("DJANGO_SENDER_ADDRESS", ""),
|
||||
recipient_list=organizers,
|
||||
fail_silently=True
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"repapp/register_device_confirm.html",
|
||||
{"device": device, "guest": device.guest, "cafe": device.cafe},
|
||||
)
|
||||
|
||||
|
||||
def device_view(request, deviceentifier):
|
||||
device = get_object_or_404(Device, identifier=deviceentifier)
|
||||
def device_view(request, device_identifier):
|
||||
device = get_object_or_404(Device, identifier=device_identifier)
|
||||
|
||||
return render(
|
||||
request,
|
||||
|
|
|
|||
Reference in a new issue