diff --git a/fet2020/rental/admin.py b/fet2020/rental/admin.py index c8729b05..f209feb9 100644 --- a/fet2020/rental/admin.py +++ b/fet2020/rental/admin.py @@ -14,9 +14,14 @@ class RentalAdmin(admin.ModelAdmin): "firstname", "surname", "status", + "total_disposit", "date_start", "date_end", ] + ordering = ["-id"] + + readonly_fields = ["total_disposit"] + fieldsets = ( ( "Persönliche Daten", @@ -35,6 +40,7 @@ class RentalAdmin(admin.ModelAdmin): ("date_start", "date_end"), "reason", "rentalitems", + "total_disposit", ), }, ), @@ -63,12 +69,22 @@ class RentalAdmin(admin.ModelAdmin): obj.author = request.user super().save_model(request, obj, form, change) + @admin.display(description="Kaution (EUR)") + def total_disposit(self, obj): + total_disposit = 0 + for elem in obj.rentalitems.all(): + total_disposit += elem.deposit + + return f"{total_disposit}" + @admin.register(RentalItem) class RentalItemAdmin(admin.ModelAdmin): form = RentalItemAdminForm model = RentalItem + ordering = ["name"] + def add_view(self, request, form_url="", extra_context=None): extra_context = extra_context or {} extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." diff --git a/fet2020/rental/forms.py b/fet2020/rental/forms.py index 12b90ee6..90f474ff 100644 --- a/fet2020/rental/forms.py +++ b/fet2020/rental/forms.py @@ -12,14 +12,7 @@ class RentalCreateForm(forms.ModelForm): # Conformation conformation = forms.BooleanField( required=True, - label=( - "1. Fachschaft Elektrotechnik (FET) hat stets Vorrecht. 2. Bereits bestätigte Objekte " - "können storniert werden, falls FET sie selber braucht. 3. Sachen dürfen nur über das " - "Verleihsystem verborgt werden. 4. Objekte müssen pünktlich und gereinigt retouniert " - "werden. 5. Verleihpersonen entscheiden über Kaution (lediglich für Pünktlichkeit und " - "Reinheit) 6. Geht was kaputt, muss dies umgehend mitgeteilt werden und finanziell " - "dafür aufgekommen werden. " - ), + label=("Ich habe die Verleihregeln gelesen und akzeptiere sie."), initial=False, ) diff --git a/fet2020/rental/mails.py b/fet2020/rental/mails.py new file mode 100644 index 00000000..621c7c0e --- /dev/null +++ b/fet2020/rental/mails.py @@ -0,0 +1,39 @@ +import logging + +from django.core.mail import send_mail + +RENTAL_EMAIL = "patrick@fet.at" +logger = logging.getLogger(__name__) + + +def send_mail_approved(obj): + subject = f"Verleih #{obj.id}: {obj.get_status_display()}" + + total_deposit = 0 + for rentalitem in obj.rentalitems.all(): + total_deposit += rentalitem.deposit + + message = ( + f"Deine Verleihanfrage mit der Nummer #{obj.id} wurde erfolgreich genehmigt. Die " + f"Gegenstände können am {obj.date_start.strftime('%d.%m.%Y')} während der Beratungszeit " + "(Montag - Donnerstag: 09:00 - 14:00, Freitag: 09:00 - 12:00) abgeholt werden. Bitte bring " + f"den Gesamtpfand in Höhe von {total_deposit} € in bar mit.\nLiebe Grüße,\ndas Verleih-Team" + ) + + try: + send_mail(subject, message, RENTAL_EMAIL, [f"{obj.email}", RENTAL_EMAIL]) + except Exception as exc: + logger.error("Failed to send approval email for rental #%s. Error: %s", obj.id, exc) + + +def send_mail_rejected(obj): + subject = f"Verleih #{obj.id}: {obj.get_status_display()}" + message = ( + f"Deine Verleihanfrage mit der Nummer #{obj.id} wurde abgelehnt.\nLiebe Grüße,\ndas " + "Verleih-Team" + ) + + try: + send_mail(subject, message, RENTAL_EMAIL, [f"{obj.email}", RENTAL_EMAIL]) + except Exception as exc: + logger.error("Failed to send rejection email for rental #%s. Error: %s", obj.id, exc) diff --git a/fet2020/rental/models.py b/fet2020/rental/models.py index b3ec61bb..34e04622 100644 --- a/fet2020/rental/models.py +++ b/fet2020/rental/models.py @@ -1,6 +1,7 @@ from django.db import models from django.forms import ValidationError +from .mails import send_mail_approved, send_mail_rejected from .validators import PhoneNumberValidator @@ -10,6 +11,16 @@ class RentalItem(models.Model): verbose_name="Beschreibung", max_length=128, blank=True, default="" ) + deposit = models.DecimalField( + verbose_name="Kaution (EUR)", max_digits=6, decimal_places=2, default=0 + ) + + image = models.ImageField(verbose_name="Bild", upload_to="rentalitems", blank=True, null=True) + + induction = models.BooleanField(verbose_name="Einschulung notwendig", default=False) + + location = models.CharField(verbose_name="Standort", max_length=128, blank=True, default="") + class Meta: verbose_name = "Verleihgegenstand" verbose_name_plural = "Verleihgegenstände" @@ -63,6 +74,24 @@ class Rental(models.Model): def __str__(self): return f"Verleih #{self.id}: {self.firstname} {self.surname}" + def save(self, *args, **kwargs): + pre_obj = Rental.objects.filter(pk=self.pk).first() + + super().save(*args, **kwargs) + + if ( + pre_obj + and pre_obj.status != self.Status.APPROVED + and self.status == self.Status.APPROVED + ): + send_mail_approved(self) + elif ( + pre_obj + and pre_obj.status != self.Status.REJECTED + and self.status == self.Status.REJECTED + ): + send_mail_rejected(self) + def clean(self): if not self.date_end: self.date_end = self.date_start diff --git a/fet2020/rental/static/rental/Verleihregeln.pdf b/fet2020/rental/static/rental/Verleihregeln.pdf new file mode 100644 index 00000000..93dd65c1 Binary files /dev/null and b/fet2020/rental/static/rental/Verleihregeln.pdf differ diff --git a/fet2020/rental/urls.py b/fet2020/rental/urls.py index f350689e..7703a591 100644 --- a/fet2020/rental/urls.py +++ b/fet2020/rental/urls.py @@ -1,7 +1,7 @@ from django.urls import path from . import apps -from .views import RentalCreateDoneView, RentalCreateView, RentalListView +from .views import RentalCreateDoneView, RentalCreateView, RentalItemDetailView, RentalListView app_name = apps.RentalConfig.name @@ -13,4 +13,5 @@ urlpatterns = [ RentalCreateDoneView.as_view(), name="rental_create_done", ), + path("rentalitems//", RentalItemDetailView.as_view(), name="rentalitem_detail"), ] diff --git a/fet2020/rental/views.py b/fet2020/rental/views.py index c43331c1..0262c9a0 100644 --- a/fet2020/rental/views.py +++ b/fet2020/rental/views.py @@ -4,6 +4,7 @@ import datetime from django.db.models import Q from django.urls import reverse from django.views.generic import ListView, TemplateView +from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView from .forms import RentalCreateForm @@ -150,3 +151,22 @@ class RentalCreateView(CreateView): class RentalCreateDoneView(TemplateView): template_name = "rental/create_done.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + obj = Rental.objects.get(pk=self.kwargs["pk"]) + + total_deposit = 0 + for elem in obj.rentalitems.all(): + total_deposit += elem.deposit + + context["object"] = obj + context["total_deposit"] = total_deposit + + return context + + +class RentalItemDetailView(DetailView): + model = RentalItem + template_name = "rental/rentalitem_detail.html" diff --git a/fet2020/templates/rental/create.html b/fet2020/templates/rental/create.html index b9de3dcc..92f94592 100644 --- a/fet2020/templates/rental/create.html +++ b/fet2020/templates/rental/create.html @@ -1,5 +1,7 @@ {% extends 'base.html' %} +{% load static %} + {% block title %}Verleih Anfrage{% endblock %} {% block content %} @@ -13,7 +15,7 @@

Persönliche Daten

- Bitte geben Sie Ihre persönlichen Daten ein. + Bitte gib deine persönlichen Daten ein.
@@ -39,7 +41,7 @@

Verleihgegenstände

- Wählen Sie die gewünschten Verleihgegenstände aus. + Wähl deine gewünschten Verleihgegenstände aus.
{% if form.rentalitems.errors %} @@ -59,13 +61,16 @@ name="{{ form.rentalitems.html_name }}" value="{{ elem.data.value }}" class="rounded border-gray-300 dark:border-none text-proprietary shadow-sm focus:border-blue-300 focus:ring focus:ring-offset-0 focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50" - > - {{ elem.choice_label }} + > + {{ elem.choice_label }} {% for item in rentalitems_addinfo %} - {% if item.name == elem.choice_label and item.description %} -

{{ item.description }}

+ {% if item.name == elem.choice_label and item.induction %} +

Einschulung erforderlich!

{% endif %} {% endfor %}
@@ -87,7 +92,7 @@

Zusätzliche Informationen

- Hier können Sie zusätzliche Informationen, Anliegen und Sonstiges angeben. + Hier kannst du zusätzliche Informationen, Anliegen und Sonstiges angeben.
@@ -98,9 +103,13 @@
-
+
{% include "baseform/checkbox.html" with field=form.conformation %}
+ + + Verleihregeln +
diff --git a/fet2020/templates/rental/create_done.html b/fet2020/templates/rental/create_done.html index a90b7c03..bb909c04 100644 --- a/fet2020/templates/rental/create_done.html +++ b/fet2020/templates/rental/create_done.html @@ -4,10 +4,10 @@ {% block content %} -
-
-

- Die Verleihanfrage mit der Nummer #{{ pk }} wurde erfolgreich eingereicht. +

+
+

+ Deine Verleihanfrage mit der Nummer #{{ pk }} wurde erfolgreich eingereicht. Die Gegenstände können am {{ object.date_start }} während der Beratungszeit (Montag - Donnerstag: 09:00 - 14:00, Freitag: 09:00 - 12:00) abgeholt werden. Bitte bring den Gesamtpfand in Höhe von {{ total_deposit }} € in bar mit.

Zur Startseite diff --git a/fet2020/templates/rental/rentalitem_detail.html b/fet2020/templates/rental/rentalitem_detail.html new file mode 100644 index 00000000..9f306f61 --- /dev/null +++ b/fet2020/templates/rental/rentalitem_detail.html @@ -0,0 +1,54 @@ +{% extends 'base.html' %} + +{% block title %}Verleihgegenstand {{ object.name }}{% endblock %} + +{% block content %} + +
+

Verleihgegenstand {{ object.name }}

+ +
+
+ {% if object.description %} +
+ +
+ {% endif %} + {% if object.location %} +
+ +
+ {% endif %} + {% if object.image %} +
+ +
+ {% endif %} + {% if object.deposit %} +
+ +
+ {% endif %} + {% if object.induction %} +
+ +
+ {% endif %} +
+
+
+{% endblock content %}