.
This commit is contained in:
@@ -14,10 +14,59 @@ class RotaSchedule(models.Model):
|
||||
description = models.TextField(blank=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
# Store the SingleShift definitions as a list of dicts (pydantic -> dict)
|
||||
shifts = models.JSONField(default=list, blank=True)
|
||||
# Additional builder options / constraints (serialisable)
|
||||
options = models.JSONField(default=dict, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def to_rota_builder(self):
|
||||
"""Construct a `rota.shifts.RotaBuilder` from this schedule and its shifts/workers.
|
||||
|
||||
This will:
|
||||
- instantiate a RotaBuilder with `start_date` and computed `weeks_to_rota`;
|
||||
- convert stored `shifts` (list of dicts) to `SingleShift` pydantic models and add them;
|
||||
- convert assigned Django `Worker` objects to pydantic `Worker` and add them.
|
||||
|
||||
Returns the RotaBuilder instance.
|
||||
"""
|
||||
try:
|
||||
from rota.shifts import RotaBuilder, SingleShift
|
||||
except Exception:
|
||||
raise RuntimeError("Unable to import rota.shifts; ensure the rota package is importable")
|
||||
|
||||
# compute weeks_to_rota (integer number of weeks)
|
||||
delta = self.end_date - self.start_date
|
||||
weeks_to_rota = max(1, int(delta.days // 7))
|
||||
|
||||
# Allow passing options directly if they match RotaBuilder kwargs
|
||||
rb_kwargs = dict(self.options or {})
|
||||
rb = RotaBuilder(start_date=self.start_date, weeks_to_rota=weeks_to_rota, name=self.name, **rb_kwargs)
|
||||
|
||||
# Add shifts (expecting list of dicts compatible with SingleShift)
|
||||
shifts_objs = []
|
||||
for s in self.shifts or []:
|
||||
try:
|
||||
obj = SingleShift(**s)
|
||||
except Exception as exc:
|
||||
raise ValueError(f"Invalid shift data for rota {self.name}: {exc}")
|
||||
shifts_objs.append(obj)
|
||||
|
||||
if shifts_objs:
|
||||
rb.add_shifts(*shifts_objs)
|
||||
|
||||
# Add workers assigned to this rota
|
||||
for w in self.workers.all():
|
||||
try:
|
||||
pyd_worker = w.to_pydantic()
|
||||
except Exception:
|
||||
# skip workers that cannot be converted
|
||||
continue
|
||||
rb.add_worker(pyd_worker)
|
||||
|
||||
return rb
|
||||
|
||||
class Worker(models.Model):
|
||||
"""Worker / staff member that can be assigned to one or more rotas."""
|
||||
@@ -34,6 +83,28 @@ class Worker(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def to_pydantic(self):
|
||||
"""Return a `rota.workers.Worker` pydantic model populated from this Django model.
|
||||
|
||||
Only maps a minimal set of fields required by the scheduler; additional
|
||||
pydantic defaults will fill the rest.
|
||||
"""
|
||||
try:
|
||||
from rota.workers import Worker as PydWorker
|
||||
except Exception:
|
||||
raise RuntimeError("Unable to import rota.workers.Worker; ensure project package is importable")
|
||||
|
||||
# Map fte: Django stores percentage (100) while pydantic Worker expects int
|
||||
pyd_kwargs = {
|
||||
"name": self.name,
|
||||
"site": self.site or "",
|
||||
"grade": self.grade or 1,
|
||||
"id": self.pk,
|
||||
"fte": int(self.fte),
|
||||
}
|
||||
|
||||
return PydWorker(**pyd_kwargs)
|
||||
|
||||
|
||||
class Assignment(models.Model):
|
||||
"""Join model assigning a worker to a rota (can hold role / metadata)."""
|
||||
|
||||
Reference in New Issue
Block a user