add detailview, mail sending and new db values

This commit is contained in:
2025-03-05 21:11:03 +01:00
parent dc263ee28c
commit 77d18cf58c
10 changed files with 182 additions and 21 deletions

View File

@@ -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."

View File

@@ -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,
)

39
fet2020/rental/mails.py Normal file
View File

@@ -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)

View File

@@ -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

Binary file not shown.

View File

@@ -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/<int:pk>/", RentalItemDetailView.as_view(), name="rentalitem_detail"),
]

View File

@@ -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"