Files
proc-rota/djangorota/rota/forms.py
T
Ross 3f73316dbf .
2025-12-09 10:32:24 +00:00

102 lines
3.6 KiB
Python

from django import forms
from django.forms import widgets
from .models import Worker, Leave, RotaSchedule
class WorkerForm(forms.ModelForm):
class Meta:
model = Worker
fields = ["name", "email", "site", "grade", "fte", "active"]
class LeaveForm(forms.ModelForm):
class Meta:
model = Leave
fields = ["start_date", "end_date", "reason"]
widgets = {
"start_date": widgets.DateInput(attrs={"class": "datepicker input", "autocomplete": "off"}),
"end_date": widgets.DateInput(attrs={"class": "datepicker input", "autocomplete": "off"}),
}
class RotaScheduleForm(forms.ModelForm):
class Meta:
model = RotaSchedule
# Do not expose end_date as editable: computed from start_date + weeks
fields = ["name", "start_date", "description"]
widgets = {
"start_date": widgets.DateInput(attrs={"class": "datepicker input", "autocomplete": "off"}),
}
weeks = forms.IntegerField(min_value=1, initial=4, help_text="Number of weeks to generate the rota for")
end_date = forms.DateField(required=False, disabled=True, widget=widgets.DateInput(attrs={"class": "datepicker input", "autocomplete": "off"}))
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
if instance and instance.start_date and instance.end_date:
delta = instance.end_date - instance.start_date
weeks = max(1, delta.days // 7)
self.fields["weeks"].initial = weeks
self.fields["end_date"].initial = instance.end_date
def clean_start_date(self):
start = self.cleaned_data.get("start_date")
if start is None:
return start
if start.weekday() != 0:
raise forms.ValidationError("Start date must be a Monday")
return start
def clean(self):
cleaned = super().clean()
start = cleaned.get("start_date")
weeks = cleaned.get("weeks")
if start and weeks:
import datetime
end_date = start + datetime.timedelta(days=weeks * 7)
cleaned["end_date"] = end_date
# update the form data/display
try:
self.data = self.data.copy()
self.data["end_date"] = end_date.isoformat()
except Exception:
pass
self.fields["end_date"].initial = end_date
return cleaned
def save(self, commit=True):
instance = super().save(commit=False)
end_date = self.cleaned_data.get("end_date")
if end_date:
instance.end_date = end_date
if commit:
instance.save()
try:
self.save_m2m()
except Exception:
pass
return instance
class ShiftForm(forms.Form):
name = forms.CharField(max_length=200)
sites = forms.CharField(
help_text="Comma separated list of sites (e.g. exeter,plymouth)",
required=True,
)
length = forms.DecimalField(max_digits=6, decimal_places=2, initial=12.5)
DAYS = [(d, d) for d in ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]]
days = forms.MultipleChoiceField(choices=DAYS, widget=forms.CheckboxSelectMultiple)
workers_required = forms.IntegerField(min_value=1, initial=1)
assign_as_block = forms.BooleanField(required=False, initial=False)
def clean_sites(self):
val = self.cleaned_data["sites"]
sites = [s.strip() for s in val.split(",") if s.strip()]
if not sites:
raise forms.ValidationError("At least one site is required")
return sites