Add PPE sizing and drivers license fields to Worker model
New fields: shoe_size, overall_top_size, pants_size, tshirt_size, has_drivers_license (boolean), drivers_license (file upload). Admin organised into 3 fieldsets. CSV export updated with new columns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
803f8696e7
commit
81009be0c6
@ -37,7 +37,7 @@ staticfiles/ — Collected static assets (Bootstrap, admin)
|
||||
## Key Models
|
||||
- **UserProfile** — extends Django User (OneToOne); minimal, no extra fields in v5
|
||||
- **Project** — work sites with supervisor assignments (M2M User), start/end dates, active flag
|
||||
- **Worker** — profiles with salary, `daily_rate` property (monthly_salary / 20), photo, ID doc
|
||||
- **Worker** — profiles with salary, `daily_rate` property (monthly_salary / 20), photo, ID doc, PPE sizing (shoe, overall top, pants, tshirt), drivers license (boolean + file upload)
|
||||
- **Team** — groups of workers under a supervisor, with optional pay schedule (`pay_frequency`: weekly/fortnightly/monthly, `pay_start_date`: anchor date)
|
||||
- **WorkLog** — daily attendance: date, project, team, workers (M2M), supervisor, overtime, `priced_workers` (M2M)
|
||||
- **PayrollRecord** — completed payments linked to WorkLogs (M2M) and Worker (FK)
|
||||
|
||||
@ -20,9 +20,24 @@ class ProjectAdmin(admin.ModelAdmin):
|
||||
@admin.register(Worker)
|
||||
class WorkerAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'id_number', 'monthly_salary', 'active')
|
||||
list_filter = ('active',)
|
||||
list_filter = ('active', 'has_drivers_license')
|
||||
search_fields = ('name', 'id_number', 'phone_number')
|
||||
|
||||
# === FIELDSETS ===
|
||||
# Organise the worker edit form into clear sections
|
||||
fieldsets = (
|
||||
('Personal Info', {
|
||||
'fields': ('name', 'id_number', 'phone_number', 'monthly_salary',
|
||||
'employment_date', 'active', 'notes'),
|
||||
}),
|
||||
('Sizing', {
|
||||
'fields': ('shoe_size', 'overall_top_size', 'pants_size', 'tshirt_size'),
|
||||
}),
|
||||
('Documents & License', {
|
||||
'fields': ('photo', 'id_document', 'has_drivers_license', 'drivers_license'),
|
||||
}),
|
||||
)
|
||||
|
||||
@admin.register(Team)
|
||||
class TeamAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'supervisor', 'pay_frequency', 'pay_start_date', 'active')
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
# Generated by Django 5.2.7 on 2026-04-20 10:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0005_team_pay_frequency_team_pay_start_date'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='worker',
|
||||
name='drivers_license',
|
||||
field=models.FileField(blank=True, null=True, upload_to='workers/documents/'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='worker',
|
||||
name='has_drivers_license',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='worker',
|
||||
name='overall_top_size',
|
||||
field=models.CharField(blank=True, max_length=10),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='worker',
|
||||
name='pants_size',
|
||||
field=models.CharField(blank=True, max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='worker',
|
||||
name='shoe_size',
|
||||
field=models.CharField(blank=True, max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='worker',
|
||||
name='tshirt_size',
|
||||
field=models.CharField(blank=True, max_length=10),
|
||||
),
|
||||
]
|
||||
@ -44,6 +44,18 @@ class Worker(models.Model):
|
||||
notes = models.TextField(blank=True)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
# === SIZING ===
|
||||
# Clothing and boot sizes for PPE (personal protective equipment) ordering
|
||||
shoe_size = models.CharField(max_length=20, blank=True)
|
||||
overall_top_size = models.CharField(max_length=10, blank=True)
|
||||
pants_size = models.CharField(max_length=20, blank=True)
|
||||
tshirt_size = models.CharField(max_length=10, blank=True)
|
||||
|
||||
# === DRIVERS LICENSE ===
|
||||
# Track which workers have a valid drivers license and store a scanned copy
|
||||
has_drivers_license = models.BooleanField(default=False)
|
||||
drivers_license = models.FileField(upload_to='workers/documents/', blank=True, null=True)
|
||||
|
||||
@property
|
||||
def daily_rate(self):
|
||||
# monthly salary divided by 20 working days
|
||||
|
||||
@ -769,7 +769,9 @@ def export_workers_csv(request):
|
||||
writer = csv.writer(response)
|
||||
writer.writerow([
|
||||
'Name', 'ID Number', 'Phone Number', 'Monthly Salary',
|
||||
'Daily Rate', 'Employment Date', 'Active', 'Notes'
|
||||
'Daily Rate', 'Employment Date', 'Active', 'Notes',
|
||||
'Shoe Size', 'Overall Top Size', 'Pants Size', 'T-Shirt Size',
|
||||
'Has Drivers License',
|
||||
])
|
||||
|
||||
for w in workers:
|
||||
@ -782,6 +784,11 @@ def export_workers_csv(request):
|
||||
w.employment_date.strftime('%Y-%m-%d') if w.employment_date else '',
|
||||
'Yes' if w.active else 'No',
|
||||
w.notes,
|
||||
w.shoe_size,
|
||||
w.overall_top_size,
|
||||
w.pants_size,
|
||||
w.tshirt_size,
|
||||
'Yes' if w.has_drivers_license else 'No',
|
||||
])
|
||||
|
||||
return response
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user