From 277f14747a0a1140f6b5f8237cb11c4e73a78b72 Mon Sep 17 00:00:00 2001 From: Ross Date: Wed, 7 Jan 2026 21:58:50 +0000 Subject: [PATCH] Increase max_number in LimitGradeNumberConstraint from 1 to 2 for better shift allocation and add internal leave removal functionality --- gen_proc.py | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/gen_proc.py b/gen_proc.py index 1aebcd6..378b22b 100644 --- a/gen_proc.py +++ b/gen_proc.py @@ -243,7 +243,7 @@ def main( PreShiftConstraint(days=2), PostShiftConstraint(days=2), RequireRemoteSitePresenceConstraint(site="plymouth", required_number=1), - LimitGradeNumberConstraint(grade=2, max_number=1), + LimitGradeNumberConstraint(grade=2, max_number=2), MinimumGradeNumberConstraint(grade=4, min_number=1), ], #end_date=datetime.datetime.strptime("2025-06-01", "%Y-%m-%d").date(), @@ -283,6 +283,8 @@ def main( Rota.add_min_summed_grade_by_shifts_per_day_constraint(["weekend_plymouth1", "weekend_plymouth2"], 6) Rota.add_min_summed_grade_by_shifts_per_day_constraint(["plymouth_twilight", "plymouth_bank_holidays"], 6) + Rota.add_min_summed_grade_by_shifts_per_day_constraint(["night_weekday"], 12) + Rota.terminate_on_warning.remove("Worker/no valid shifts") load_leave = True @@ -292,8 +294,43 @@ def main( if load_leave: import leave + # Internal-only option: remove leave requests between two dates. + # Configure by editing the two variables below (not exposed via CLI). + # Use strings in 'YYYY-MM-DD' or datetime.date objects. Set either to None to disable. + REMOVE_LEAVE_FROM = "" + REMOVE_LEAVE_TO = "" + workers = leave.load_leave(Rota) + # If the internal remove range is set, filter out NotAvailableToWork entries + if REMOVE_LEAVE_FROM and REMOVE_LEAVE_TO: + # Coerce to date objects if strings provided + def _to_date(v): + if isinstance(v, str): + for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%d/%m/%y"): + try: + return datetime.datetime.strptime(v, fmt).date() + except Exception: + continue + raise ValueError(f"Cannot parse date: {v}") + if isinstance(v, datetime.datetime): + return v.date() + return v + + _from = _to_date(REMOVE_LEAVE_FROM) + _to = _to_date(REMOVE_LEAVE_TO) + + for name, w in list(workers.items()): + original = w.get("leave", []) + before_count = len(original) + filtered = [lr for lr in original if not (_from <= lr.date <= _to)] + after_count = len(filtered) + if after_count != before_count: + print( + f"Removed {before_count-after_count} leave entries for '{name}' between {_from} and {_to}" + ) + w["leave"] = filtered + n = 0 for worker in workers: worker_name = worker