From b6fca98c1794bb271ebe77384a40bd6c14de64d9 Mon Sep 17 00:00:00 2001 From: Konrad du Plessis Date: Mon, 23 Feb 2026 00:13:46 +0200 Subject: [PATCH] Fix attendance start date, history worker filter, and add Amount column 1. Attendance form: Force start date to blank by clearing Django 5.x auto-fill from model default (default=timezone.now). Added self.fields['date'].initial=None in AttendanceLogForm.__init__(). 2. History list view: When filtering by a specific worker, show only that worker's name in the Workers column (not all workers on the log). Uses filtered_worker_obj passed from the view. 3. History list view: Added Amount column (admin-only) showing daily cost. When filtering by worker, shows that worker's daily_rate. When unfiltered, shows total via new WorkLog.display_amount property (sum of all workers' daily_rate, uses prefetch cache for efficiency). Co-Authored-By: Claude Opus 4.6 --- core/forms.py | 5 +++++ core/models.py | 6 ++++++ core/templates/core/work_history.html | 29 +++++++++++++++++++++------ core/views.py | 7 +++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/core/forms.py b/core/forms.py index 9c6853c..14702d3 100644 --- a/core/forms.py +++ b/core/forms.py @@ -92,6 +92,11 @@ class AttendanceLogForm(forms.ModelForm): # Make team optional (it already is on the model, but make the form match) self.fields['team'].required = False + # Force start date to be blank — don't pre-fill with today's date. + # Django 5.x auto-fills form fields from model defaults (default=timezone.now), + # but we want the user to consciously pick a date every time. + self.fields['date'].initial = None + def clean(self): """Validate the date range makes sense.""" cleaned_data = super().clean() diff --git a/core/models.py b/core/models.py index e38921a..31b5a5a 100644 --- a/core/models.py +++ b/core/models.py @@ -77,6 +77,12 @@ class WorkLog(models.Model): overtime_amount = models.DecimalField(max_digits=3, decimal_places=2, choices=OVERTIME_CHOICES, default=Decimal('0.00')) priced_workers = models.ManyToManyField(Worker, related_name='priced_overtime_logs', blank=True) + @property + def display_amount(self): + """Total daily cost for all workers on this log (sum of daily_rate). + Works efficiently with prefetch_related('workers').""" + return sum(w.daily_rate for w in self.workers.all()) + def __str__(self): return f"{self.date} - {self.project.name}" diff --git a/core/templates/core/work_history.html b/core/templates/core/work_history.html index f647e28..0122aa1 100644 --- a/core/templates/core/work_history.html +++ b/core/templates/core/work_history.html @@ -592,6 +592,7 @@ Workers Overtime Status + {% if is_admin %}Amount{% endif %} Supervisor @@ -601,11 +602,16 @@ {{ log.date }} {{ log.project.name }} - {# Show worker names as comma-separated list #} - {% for w in log.workers.all %} - {{ w.name }}{% if not forloop.last %}, {% endif %} - {% endfor %} - {{ log.workers.count }} + {# When filtering by a specific worker, show only that worker. + Otherwise show all workers on this log. #} + {% if filtered_worker_obj %} + {{ filtered_worker_obj.name }} + {% else %} + {% for w in log.workers.all %} + {{ w.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} + {{ log.workers.count }} + {% endif %} {% if log.overtime_amount > 0 %} @@ -622,6 +628,17 @@ Unpaid {% endif %} + {% if is_admin %} + + {# Daily cost — when filtering by worker show that worker's rate, + otherwise show the total for all workers on the log #} + {% if filtered_worker_obj %} + R {{ filtered_worker_obj.daily_rate }} + {% else %} + R {{ log.display_amount }} + {% endif %} + + {% endif %} {% if log.supervisor %} {{ log.supervisor.get_full_name|default:log.supervisor.username }} @@ -632,7 +649,7 @@ {% empty %} - + No work history found. {% if selected_worker or selected_project or selected_status %} diff --git a/core/views.py b/core/views.py index 6726dc0..08bd787 100644 --- a/core/views.py +++ b/core/views.py @@ -413,6 +413,12 @@ def work_history(request): # Count filtered results BEFORE adding joins (more efficient SQL) filtered_log_count = logs.count() if has_active_filters else 0 + # If filtering by worker, look up the Worker object so the template can + # show just that worker's name instead of all workers on the log. + filtered_worker_obj = None + if worker_filter: + filtered_worker_obj = Worker.objects.filter(id=worker_filter).first() + # Add related data and order by date (newest first) logs = logs.select_related( 'project', 'supervisor' @@ -458,6 +464,7 @@ def work_history(request): 'has_active_filters': has_active_filters, 'total_log_count': total_log_count, 'filtered_log_count': filtered_log_count, + 'filtered_worker_obj': filtered_worker_obj, } # === CALENDAR MODE ===