Add warning for forced assignments in HardDayDependency

This commit is contained in:
Ross
2025-12-16 22:35:21 +00:00
parent 8e580440e0
commit 51ed25d04c
+97
View File
@@ -1702,6 +1702,103 @@ class RotaBuilder(object):
)
for week in weeks_to_apply:
# If the worker has any forced assignment in the dependency group,
# emit a concise warning. For visibility include every day in the
# group showing the worker's forced shifts (if any) and other
# workers' forced shifts on those days so blocking days are visible.
worker_has_forced_in_group = False
for (fw, fd, fs) in getattr(worker, "forced_assignments", []):
if fw == week and fd in day_group:
worker_has_forced_in_group = True
break
if not worker_has_forced_in_group:
try:
for (d_date, d_shift) in getattr(worker, "forced_assignments_by_date", []):
ww, dd = self.date_week_day_map.get(d_date, (None, None))
if ww == week and dd in day_group:
worker_has_forced_in_group = True
break
except Exception:
pass
if worker_has_forced_in_group:
forced_day_details = []
try:
date_map_for_week = {self.get_date_by_week_day(week, d): d for d in day_group}
except Exception:
date_map_for_week = {}
for day in day_group:
worker_forced_shifts = set()
# week-based forced assignments
for (fw, fd, fs) in getattr(worker, "forced_assignments", []):
if fw == week and fd == day:
worker_forced_shifts.add(fs)
# date-based forced assignments
try:
date = self.get_date_by_week_day(week, day)
for (d_date, d_shift) in getattr(worker, "forced_assignments_by_date", []):
try:
ww, dd = self.date_week_day_map.get(d_date, (None, None))
except Exception:
ww = dd = None
if ww == week and dd == day:
worker_forced_shifts.add(d_shift)
else:
try:
if str(d_date) == str(date):
worker_forced_shifts.add(d_shift)
except Exception:
pass
except Exception:
pass
# collect other workers' forced shifts on this day
others_forced = {}
try:
date_for_day = self.get_date_by_week_day(week, day)
except Exception:
date_for_day = None
for other in self.workers:
if other is worker:
continue
other_shifts = set()
# week-based forced assignments
for (ofw, ofd, ofs) in getattr(other, "forced_assignments", []):
if ofw == week and ofd == day:
other_shifts.add(ofs)
# date-based forced assignments: try mapping then fallback
for (odate, oshift) in getattr(other, "forced_assignments_by_date", []):
try:
oww, odd = self.date_week_day_map.get(odate, (None, None))
except Exception:
oww = odd = None
if oww == week and odd == day:
other_shifts.add(oshift)
continue
try:
if date_for_day is not None and str(odate) == str(date_for_day):
other_shifts.add(oshift)
except Exception:
pass
if other_shifts:
others_forced[other.name] = sorted(list(other_shifts))
forced_day_details.append((day, sorted(list(worker_forced_shifts)), others_forced))
parts = []
for d, wfs, others in forced_day_details:
olist = ", ".join([f"{n}: {', '.join(s)}" for n, s in others.items()]) or "none"
wfs_str = ", ".join(wfs) or "none"
parts.append(f"{d} - worker forced: {wfs_str}; others forced: {olist}")
details = "; ".join(parts)
logger.warning(f"HardDayDependency forced-assignment warning for worker={worker.name} week={week}: {details}")
self.add_warning(
"HardDayDependency forced assignment",
f"Worker '{worker.name}' has hard_day_dependency {set(day_group)} in week {week}; forced assignments on dependency days: {details}. If the rota is not infeasible this is unlikely to be an issue.",
)
assigned_any_shift = {}
for day in day_group:
shifts_today = self.get_shift_names_by_week_day(week, day)