add internal rentals with zero deposit

This commit is contained in:
2025-10-30 14:05:53 +01:00
parent 4a7076b120
commit 5d2a052c1e
3 changed files with 192 additions and 191 deletions

View File

@@ -1,124 +1,126 @@
from django.contrib import admin, messages from django.contrib import admin, messages
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from .forms import RentalAdminForm, RentalItemAdminForm from .forms import RentalAdminForm, RentalItemAdminForm
from .models import Rental, RentalItem from .models import Rental, RentalItem
from .utils import generate_rental_pdf from .utils import generate_rental_pdf
@admin.register(Rental) @admin.register(Rental)
class RentalAdmin(admin.ModelAdmin): class RentalAdmin(admin.ModelAdmin):
form = RentalAdminForm form = RentalAdminForm
model = Rental model = Rental
list_display = [ list_display = [
"id", "id",
"firstname", "firstname",
"surname", "surname",
"status", "status",
"total_disposit", "total_disposit",
"date_start", "date_start",
"date_end", "date_end",
] ]
ordering = ["-id"] ordering = ["-id"]
readonly_fields = ["total_disposit"] readonly_fields = ["total_disposit"]
fieldsets = ( fieldsets = (
( (
"Persönliche Daten", "Persönliche Daten",
{ {
"fields": ( "fields": (
("firstname", "surname"), ("firstname", "surname"),
("organization", "matriculation_number"), ("organization", "matriculation_number"),
("email", "phone"), ("email", "phone"),
), ),
}, },
), ),
( (
"Verleih", "Verleih",
{ {
"fields": ( "fields": (
("date_start", "date_end"), ("date_start", "date_end"),
"reason", "reason",
"rentalitems", "rentalitems",
"total_disposit", ("total_disposit", "intern"),
), ),
}, },
), ),
( (
"Sonstiges", "Sonstiges",
{ {
"fields": ( "fields": (
"comment", "comment",
"file_field", "file_field",
"status", "status",
), ),
}, },
), ),
) )
def add_view(self, request, form_url="", extra_context=None): def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {} extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().add_view(request, form_url, extra_context=extra_context) return super().add_view(request, form_url, extra_context=extra_context)
def change_view(self, request, object_id, form_url="", extra_context=None): def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {} extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
extra_context["generate_rental_pdf"] = True extra_context["generate_rental_pdf"] = True
return super().change_view(request, object_id, form_url, extra_context=extra_context) return super().change_view(request, object_id, form_url, extra_context=extra_context)
def response_change(self, request, obj): def response_change(self, request, obj):
if "_generate_rental_pdf" in request.POST: if "_generate_rental_pdf" in request.POST:
if generate_rental_pdf(obj): if generate_rental_pdf(obj):
self.message_user( self.message_user(
request, request,
"Neues Verleihformular wurde generiert.", "Neues Verleihformular wurde generiert.",
messages.SUCCESS, messages.SUCCESS,
) )
else: else:
self.message_user( self.message_user(
request, request,
( (
"Das PDF-Dokument konnte nicht generiert werden, da der Status nicht auf " "Das PDF-Dokument konnte nicht generiert werden, da der Status nicht auf "
"'Verleih genehmigt' gesetzt ist." "'Verleih genehmigt' gesetzt ist."
), ),
messages.WARNING, messages.WARNING,
) )
return HttpResponseRedirect(".") return HttpResponseRedirect(".")
return super().response_change(request, obj) return super().response_change(request, obj)
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
obj.author = request.user obj.author = request.user
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
@admin.display(description="Kaution (EUR)") @admin.display(description="Kaution (EUR)")
def total_disposit(self, obj): def total_disposit(self, obj):
total_disposit = 0 total_disposit = 0
for elem in obj.rentalitems.all():
total_disposit += elem.deposit if not obj.intern:
for elem in obj.rentalitems.all():
return f"{total_disposit}" total_disposit += elem.deposit
return f"{total_disposit}"
@admin.register(RentalItem)
class RentalItemAdmin(admin.ModelAdmin):
form = RentalItemAdminForm @admin.register(RentalItem)
model = RentalItem class RentalItemAdmin(admin.ModelAdmin):
form = RentalItemAdminForm
ordering = ["name"] model = RentalItem
def add_view(self, request, form_url="", extra_context=None): ordering = ["name"]
extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." def add_view(self, request, form_url="", extra_context=None):
return super().add_view(request, form_url, extra_context=extra_context) extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
def change_view(self, request, object_id, form_url="", extra_context=None): return super().add_view(request, form_url, extra_context=extra_context)
extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." def change_view(self, request, object_id, form_url="", extra_context=None):
return super().change_view(request, object_id, form_url, extra_context=extra_context) extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
def save_model(self, request, obj, form, change): return super().change_view(request, object_id, form_url, extra_context=extra_context)
obj.author = request.user
super().save_model(request, obj, form, change) def save_model(self, request, obj, form, change):
obj.author = request.user
super().save_model(request, obj, form, change)

View File

@@ -2,7 +2,7 @@ from django.core.validators import FileExtensionValidator
from django.db import models from django.db import models
from django.forms import ValidationError from django.forms import ValidationError
from .mails import send_mail_approved, send_mail_rejected from .mails import send_mail_approved, send_mail_rejected
from .managers import RentalItemsManager from .managers import RentalItemsManager
from .validators import PhoneNumberValidator from .validators import PhoneNumberValidator
@@ -44,6 +44,7 @@ class Rental(models.Model):
) )
organization = models.CharField(verbose_name="Organisation", max_length=128) organization = models.CharField(verbose_name="Organisation", max_length=128)
intern = models.BooleanField(verbose_name="Interner Verleih", default=False)
date_start = models.DateField(verbose_name="Abholdatum") date_start = models.DateField(verbose_name="Abholdatum")
date_end = models.DateField(verbose_name="Rückgabedatum") date_end = models.DateField(verbose_name="Rückgabedatum")

View File

@@ -1,67 +1,65 @@
import io import io
from django.contrib.staticfiles import finders from django.contrib.staticfiles import finders
from django.core.files import File from django.core.files import File
from pypdf import PdfReader, PdfWriter from pypdf import PdfReader, PdfWriter
from .models import Rental from .models import Rental
def generate_rental_pdf(rental: Rental) -> bool: def generate_rental_pdf(rental: Rental) -> bool:
if not rental or rental.status != Rental.Status.APPROVED: if not rental or rental.status != Rental.Status.APPROVED:
return False return False
# Get data for pdf # Get data for pdf
data = {} data = {}
data.update( data.update(
{ {
"Vorname": rental.firstname, "Vorname": rental.firstname,
"Nachname": rental.surname, "Nachname": rental.surname,
"Orga": rental.organization, "Orga": rental.organization,
"Matrikelnummer": rental.matriculation_number, "Matrikelnummer": rental.matriculation_number,
"E-Mail": rental.email, "E-Mail": rental.email,
"Telefonnummer": rental.phone, "Telefonnummer": rental.phone,
# Change to the correct date format # Change to the correct date format
"Abholdatum": str(rental.date_start.strftime("%d.%m.%Y")), "Abholdatum": str(rental.date_start.strftime("%d.%m.%Y")),
"Rückgabedatum": str(rental.date_end.strftime("%d.%m.%Y")), "Rückgabedatum": str(rental.date_end.strftime("%d.%m.%Y")),
}, },
) )
total_deposit = 0 total_deposit = 0
for i, item in enumerate(rental.rentalitems.all(), start=1): for i, item in enumerate(rental.rentalitems.all(), start=1):
total_deposit += item.deposit if not rental.intern:
data.update( total_deposit += item.deposit
{
f"Produkt Row{i}": item.name, data.update(
f"Menge Row{i}": "1", {
f"Kaution Row{i}": item.deposit, f"Produkt Row{i}": item.name,
}, f"Menge Row{i}": "1",
) f"Kaution Row{i}": (str(item.deposit) if not rental.intern else "0"),
},
data.update( )
{
"Gesamtkaution": total_deposit, data.update({"Gesamtkaution": str(total_deposit)})
},
) # Write data in pdf
pdf_path_str = finders.find("rental/Verleihformular.pdf")
# Write data in pdf reader = PdfReader(pdf_path_str)
pdf_path_str = finders.find("rental/Verleihformular.pdf") writer = PdfWriter()
reader = PdfReader(pdf_path_str) writer.append(reader)
writer = PdfWriter()
writer.append(reader) writer.update_page_form_field_values(
writer.pages[0],
writer.update_page_form_field_values( data,
writer.pages[0], )
data,
) with io.BytesIO() as bytes_stream:
with io.BytesIO() as bytes_stream:
writer.write(bytes_stream) writer.write(bytes_stream)
bytes_stream.seek(0) bytes_stream.seek(0)
# Save pdf in rental # Save pdf in rental
rental_name = f"Verleihformular-{str(rental.pk).zfill(4)}.pdf" rental_name = f"Verleihformular-{str(rental.pk).zfill(4)}.pdf"
rental.file_field.save(rental_name, File(bytes_stream, rental_name)) rental.file_field.save(rental_name, File(bytes_stream, rental_name))
return True return True