Add exclude_dates option to PreShiftConstraint and PostShiftConstraint
This commit is contained in:
+2
-2
@@ -341,7 +341,7 @@ def main(
|
|||||||
constraint_options=RotaConstraintOptions(
|
constraint_options=RotaConstraintOptions(
|
||||||
balance_weekends=True,
|
balance_weekends=True,
|
||||||
max_shifts_per_week=6,
|
max_shifts_per_week=6,
|
||||||
max_days_per_week_block=[(4, 2), (6, 3)],
|
max_days_per_week_block=[(4, 2), (4, 3)],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -356,7 +356,7 @@ def main(
|
|||||||
balance_offset=2,
|
balance_offset=2,
|
||||||
assign_as_block=False,
|
assign_as_block=False,
|
||||||
constraints=[
|
constraints=[
|
||||||
PreShiftConstraint(days=2, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun")),
|
PreShiftConstraint(days=2, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun"), exclude_dates=["2026-04-06", "2026-05-04", "2026-05-25"]),
|
||||||
PostShiftConstraint(days=1, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun"), allow_self=True),
|
PostShiftConstraint(days=1, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun"), allow_self=True),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -93,12 +93,14 @@ class PreShiftConstraint(BaseShiftConstraint):
|
|||||||
days: Optional[int] = None
|
days: Optional[int] = None
|
||||||
ignore_shifts: List[str] = []
|
ignore_shifts: List[str] = []
|
||||||
exclude_days: List[str] = []
|
exclude_days: List[str] = []
|
||||||
|
exclude_dates: List[datetime.date] = []
|
||||||
allow_self: bool = True
|
allow_self: bool = True
|
||||||
|
|
||||||
class PostShiftConstraint(BaseShiftConstraint):
|
class PostShiftConstraint(BaseShiftConstraint):
|
||||||
days: Optional[int] = None
|
days: Optional[int] = None
|
||||||
ignore_shifts: List[str] = []
|
ignore_shifts: List[str] = []
|
||||||
exclude_days: List[str] = []
|
exclude_days: List[str] = []
|
||||||
|
exclude_dates: List[datetime.date] = []
|
||||||
allow_self: bool = True
|
allow_self: bool = True
|
||||||
|
|
||||||
class BalanceAcrossGroupsConstraint(BaseShiftConstraint):
|
class BalanceAcrossGroupsConstraint(BaseShiftConstraint):
|
||||||
@@ -3110,10 +3112,12 @@ class RotaBuilder(object):
|
|||||||
ignore_shifts = constraint.ignore_shifts + [constraint_shift.name]
|
ignore_shifts = constraint.ignore_shifts + [constraint_shift.name]
|
||||||
else:
|
else:
|
||||||
ignore_shifts = constraint.ignore_shifts
|
ignore_shifts = constraint.ignore_shifts
|
||||||
if week not in constraint.weeks:
|
if constraint.weeks is not None and week not in constraint.weeks:
|
||||||
continue
|
continue
|
||||||
|
date_main = self.get_date_by_week_day(week, day)
|
||||||
for n in range(0, constraint.days):
|
for n in range(0, constraint.days):
|
||||||
if day in constraint.exclude_days:
|
# skip if main day excluded by weekday or specific date
|
||||||
|
if day in getattr(constraint, "exclude_days", []) or date_main in getattr(constraint, "exclude_dates", []):
|
||||||
continue
|
continue
|
||||||
if day in constraint_shift.days:
|
if day in constraint_shift.days:
|
||||||
# Only apply if worker can work this shift
|
# Only apply if worker can work this shift
|
||||||
@@ -3125,6 +3129,14 @@ class RotaBuilder(object):
|
|||||||
]
|
]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
# compute the pre date and skip if it's in exclude_dates
|
||||||
|
try:
|
||||||
|
pre_date = self.get_date_by_week_day(pre_map[n][1], pre_map[n][2])
|
||||||
|
except Exception:
|
||||||
|
pre_date = None
|
||||||
|
if pre_date is not None and pre_date in getattr(constraint, "exclude_dates", []):
|
||||||
|
continue
|
||||||
|
|
||||||
self.model.constraints.add(
|
self.model.constraints.add(
|
||||||
1
|
1
|
||||||
>= works
|
>= works
|
||||||
@@ -3150,10 +3162,12 @@ class RotaBuilder(object):
|
|||||||
ignore_shifts = constraint.ignore_shifts + [constraint_shift.name]
|
ignore_shifts = constraint.ignore_shifts + [constraint_shift.name]
|
||||||
else:
|
else:
|
||||||
ignore_shifts = constraint.ignore_shifts
|
ignore_shifts = constraint.ignore_shifts
|
||||||
if week not in constraint.weeks:
|
if constraint.weeks is not None and week not in constraint.weeks:
|
||||||
continue
|
continue
|
||||||
|
date_main = self.get_date_by_week_day(week, day)
|
||||||
for n in range(0, constraint.days):
|
for n in range(0, constraint.days):
|
||||||
if day in constraint.exclude_days:
|
# skip if main day excluded by weekday or specific date
|
||||||
|
if day in getattr(constraint, "exclude_days", []) or date_main in getattr(constraint, "exclude_dates", []):
|
||||||
continue
|
continue
|
||||||
if day in constraint_shift.days:
|
if day in constraint_shift.days:
|
||||||
# Only apply if worker can work this shift
|
# Only apply if worker can work this shift
|
||||||
@@ -3165,6 +3179,14 @@ class RotaBuilder(object):
|
|||||||
]
|
]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
# compute the post date and skip if it's in exclude_dates
|
||||||
|
try:
|
||||||
|
post_date = self.get_date_by_week_day(post_map[n][1], post_map[n][2])
|
||||||
|
except Exception:
|
||||||
|
post_date = None
|
||||||
|
if post_date is not None and post_date in getattr(constraint, "exclude_dates", []):
|
||||||
|
continue
|
||||||
|
|
||||||
self.model.constraints.add(
|
self.model.constraints.add(
|
||||||
1
|
1
|
||||||
>= works
|
>= works
|
||||||
|
|||||||
Reference in New Issue
Block a user