[rentals] Allow reserving lockers for internal makerspace use

This commit is contained in:
Adam Goldsmith 2022-03-15 21:59:48 -04:00
parent 3225f2ff87
commit 87df8d460c
4 changed files with 65 additions and 8 deletions

View File

@ -10,4 +10,5 @@ class LockerInfoForm(forms.ModelForm):
"blind_code",
"bitting_code",
"renter",
"reserved",
]

View File

@ -0,0 +1,30 @@
# Generated by Django 4.0.2 on 2022-03-16 01:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("rentals", "0002_lockerinfo_notes"),
]
operations = [
migrations.AddField(
model_name="lockerinfo",
name="reserved",
field=models.BooleanField(
default=False,
help_text="Locker is reserved for MakerSpace use, and cannot be rented.",
),
),
migrations.AddConstraint(
model_name="lockerinfo",
constraint=models.CheckConstraint(
check=models.Q(
("reserved", False), ("renter__isnull", True), _connector="OR"
),
name="locker_not_reserved_and_rented",
),
),
]

View File

@ -1,7 +1,8 @@
from django.contrib import admin
from django.core import validators
from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.db.models import F
from django.db.models import F, Q
from django.db.models.functions import Chr, Ord, Concat
@ -85,15 +86,31 @@ class LockerInfo(models.Model):
renter = models.ForeignKey(
Member, on_delete=models.CASCADE, null=True, blank=True, db_constraint=False
)
reserved = models.BooleanField(
default=False,
help_text="Locker is reserved for MakerSpace use, and cannot be rented.",
)
notes = models.TextField(blank=True)
def clean(self):
if self.reserved and self.renter is not None:
raise ValidationError("Locker cannot both be reserved and rented!")
class Meta:
constraints = [
models.UniqueConstraint(
fields=["locker_unit", "column", "row"], name="unique_locker_info"
)
),
models.CheckConstraint(
check=Q(reserved=False) | Q(renter__isnull=True),
name="locker_not_reserved_and_rented",
),
]
@property
def available(self) -> bool:
return self.renter is None and not self.reserved
@property
def letter(self) -> str:
return self.locker_unit.letter_for_column(self.column)

View File

@ -39,7 +39,7 @@
justify-content: center;
color: lightgray;
}
.locker .door:not([data-rented="false"]) {
.locker .door[data-available="False"] {
background-color: hsl(24, 15%, 25%);;
}
</style>
@ -60,7 +60,7 @@
data-bs-auto-close="outside"
aria-haspopup="true"
aria-expanded="false"
data-rented="{{ locker_form.instance.renter|yesno:"true,false" }}">
data-available="{{ locker_form.instance.available }}">
<h3 class="locker-address mb-0">{{ locker_form.instance.address }}</h3>
<div class="locker-status text-wrap">
{% if locker_form.instance.renter is not None %}
@ -69,6 +69,8 @@
{% else %}
Occupied
{% endif %}
{% elif locker_form.instance.reserved %}
Reserved
{% else %}
Empty
{% endif %}
@ -83,12 +85,19 @@
{% csrf_token %}
<fieldset {{ perms.rentals.change_lockerinfo|yesno:",disabled" }}>
{% for field in locker_form.visible_fields %}
<div class="form-floating mb-3">
<div class="mb-3">
{% if field.widget_type == 'checkbox' %}
{% render_field field class+="btn-check" %}
{{ field|add_label_class:"btn btn-outline-primary" }}
{% else %}
<div class="form-floating">
{% render_field field class+="form-control" %}
{{ field.label_tag }}
</div>
{% endif %}
{{ field.errors }}
{% if field.help_text %}
<p class="form-text text-nowrap">
<p class="form-text">
{{ field.help_text|safe }}
</p>
{% endif %}