Add warning for forced assignments in HardDayDependency
This commit is contained in:
@@ -1702,6 +1702,103 @@ class RotaBuilder(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for week in weeks_to_apply:
|
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 = {}
|
assigned_any_shift = {}
|
||||||
for day in day_group:
|
for day in day_group:
|
||||||
shifts_today = self.get_shift_names_by_week_day(week, day)
|
shifts_today = self.get_shift_names_by_week_day(week, day)
|
||||||
|
|||||||
Reference in New Issue
Block a user