start the django
This commit is contained in:
+113
-1
@@ -1,3 +1,115 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class RotaSchedule(models.Model):
|
||||
"""Represents a named rota (collection of shifts over a date range).
|
||||
|
||||
This is the top-level object that groups workers and runs.
|
||||
"""
|
||||
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
start_date = models.DateField()
|
||||
end_date = models.DateField()
|
||||
description = models.TextField(blank=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Worker(models.Model):
|
||||
"""Worker / staff member that can be assigned to one or more rotas."""
|
||||
|
||||
name = models.CharField(max_length=200)
|
||||
email = models.EmailField(blank=True)
|
||||
site = models.CharField(max_length=100, blank=True)
|
||||
grade = models.IntegerField(null=True, blank=True)
|
||||
fte = models.FloatField(default=1.0)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
rotas = models.ManyToManyField(RotaSchedule, through="Assignment", related_name="workers")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Assignment(models.Model):
|
||||
"""Join model assigning a worker to a rota (can hold role / metadata)."""
|
||||
|
||||
worker = models.ForeignKey(Worker, on_delete=models.CASCADE)
|
||||
rota = models.ForeignKey(RotaSchedule, on_delete=models.CASCADE)
|
||||
role = models.CharField(max_length=100, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("worker", "rota")
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.worker} -> {self.rota}"
|
||||
|
||||
|
||||
class Leave(models.Model):
|
||||
"""Leave record for a worker. Stored as inclusive start/end dates."""
|
||||
|
||||
worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name="leaves")
|
||||
start_date = models.DateField()
|
||||
end_date = models.DateField()
|
||||
reason = models.CharField(max_length=255, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ("-start_date",)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.worker}: {self.start_date} → {self.end_date}"
|
||||
|
||||
|
||||
class RotaRun(models.Model):
|
||||
"""Represents an execution of the scheduler for a RotaSchedule.
|
||||
|
||||
The run stores status and (optionally) JSON results. A background
|
||||
runner or management command can update this record as the job progresses.
|
||||
"""
|
||||
|
||||
STATUS_PENDING = "pending"
|
||||
STATUS_RUNNING = "running"
|
||||
STATUS_SUCCESS = "success"
|
||||
STATUS_FAILED = "failed"
|
||||
|
||||
STATUS_CHOICES = [
|
||||
(STATUS_PENDING, "Pending"),
|
||||
(STATUS_RUNNING, "Running"),
|
||||
(STATUS_SUCCESS, "Success"),
|
||||
(STATUS_FAILED, "Failed"),
|
||||
]
|
||||
|
||||
rota = models.ForeignKey(RotaSchedule, on_delete=models.CASCADE, related_name="runs")
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
started_at = models.DateTimeField(null=True, blank=True)
|
||||
finished_at = models.DateTimeField(null=True, blank=True)
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_PENDING)
|
||||
result = models.JSONField(null=True, blank=True)
|
||||
log = models.TextField(blank=True)
|
||||
|
||||
def mark_running(self):
|
||||
self.status = self.STATUS_RUNNING
|
||||
self.started_at = timezone.now()
|
||||
self.save(update_fields=["status", "started_at"])
|
||||
|
||||
def mark_finished(self, result=None):
|
||||
self.status = self.STATUS_SUCCESS
|
||||
self.finished_at = timezone.now()
|
||||
if result is not None:
|
||||
self.result = result
|
||||
self.save(update_fields=["status", "finished_at", "result"])
|
||||
|
||||
def mark_failed(self, message=""):
|
||||
self.status = self.STATUS_FAILED
|
||||
self.finished_at = timezone.now()
|
||||
self.log = (self.log or "") + "\n" + message
|
||||
self.save(update_fields=["status", "finished_at", "log"])
|
||||
|
||||
def __str__(self):
|
||||
return f"RotaRun({self.rota.name} - {self.status} @ {self.created_at.isoformat()})"
|
||||
|
||||
Reference in New Issue
Block a user