# === FORMS === # Django form classes for the attendance logging page. # The AttendanceLogForm handles daily work log creation with support for # date ranges, supervisor filtering, and conflict detection. from django import forms from .models import WorkLog, Project, Team, Worker class AttendanceLogForm(forms.ModelForm): """ Form for logging daily worker attendance. Extra fields (not on the WorkLog model): - end_date: optional end date for logging multiple days at once - include_saturday: whether to include Saturdays in a date range - include_sunday: whether to include Sundays in a date range The supervisor field is NOT shown on the form — it gets set automatically in the view to whoever is logged in. """ # --- Extra fields for date range logging --- # These aren't on the WorkLog model, they're only used by the form end_date = forms.DateField( required=False, widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), label='End Date', help_text='Leave blank to log a single day' ) include_saturday = forms.BooleanField( required=False, initial=False, label='Include Saturdays', widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) ) include_sunday = forms.BooleanField( required=False, initial=False, label='Include Sundays', widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) ) class Meta: model = WorkLog # Supervisor is NOT included — it gets set in the view automatically fields = ['date', 'project', 'team', 'workers', 'overtime_amount', 'notes'] widgets = { 'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'project': forms.Select(attrs={'class': 'form-select'}), 'team': forms.Select(attrs={'class': 'form-select'}), 'workers': forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}), 'overtime_amount': forms.Select(attrs={'class': 'form-select'}), 'notes': forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'Any notes about the day...' }), } def __init__(self, *args, **kwargs): # Pop 'user' from kwargs so we can filter based on who's logged in self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs) # --- Supervisor filtering --- # If the user is NOT an admin, they can only see: # - Projects they're assigned to (via project.supervisors M2M) # - Workers in teams they supervise if self.user and not (self.user.is_staff or self.user.is_superuser): # Only show projects this supervisor is assigned to self.fields['project'].queryset = Project.objects.filter( active=True, supervisors=self.user ) # Only show workers from teams this supervisor manages supervised_teams = Team.objects.filter(supervisor=self.user, active=True) self.fields['workers'].queryset = Worker.objects.filter( active=True, teams__in=supervised_teams ).distinct() # Only show teams this supervisor manages self.fields['team'].queryset = supervised_teams else: # Admins see everything self.fields['workers'].queryset = Worker.objects.filter(active=True) self.fields['project'].queryset = Project.objects.filter(active=True) self.fields['team'].queryset = Team.objects.filter(active=True) # Make team optional (it already is on the model, but make the form match) self.fields['team'].required = False def clean(self): """Validate the date range makes sense.""" cleaned_data = super().clean() start_date = cleaned_data.get('date') end_date = cleaned_data.get('end_date') if start_date and end_date and end_date < start_date: raise forms.ValidationError('End date cannot be before start date.') return cleaned_data