add prtial shifts
This commit is contained in:
+136
-2
@@ -3,7 +3,7 @@ from rota_generator.shifts import InvalidShift, MaxShiftsPerWeekConstraint, NoWo
|
||||
from pydantic import ValidationError
|
||||
|
||||
import datetime
|
||||
from rota_generator.workers import NonWorkingDays, NotAvailableToWork, Worker, generate_not_available_to_works
|
||||
from rota_generator.workers import NonWorkingDays, NotAvailableToWork, Worker, generate_not_available_to_works, ShiftStartDate, ShiftEndDate
|
||||
from rota_generator.workers import WorkRequests
|
||||
from rota_generator.shifts import PreShiftConstraint
|
||||
|
||||
@@ -1984,4 +1984,138 @@ def test_shift_group_availability_exclusion():
|
||||
worker_shift_counts[worker.name] += 1
|
||||
|
||||
assert worker_shift_counts["worker1"] == 2
|
||||
assert worker_shift_counts["worker2"] == 0
|
||||
assert worker_shift_counts["worker2"] == 0
|
||||
|
||||
|
||||
def test_shift_dependent_active_dates_constraints():
|
||||
weeks_to_rota = 10
|
||||
start_date = datetime.date(2022, 3, 7) # Mon
|
||||
|
||||
Rota = RotaBuilder(
|
||||
start_date,
|
||||
weeks_to_rota=weeks_to_rota,
|
||||
)
|
||||
worker1 = Worker(name="worker1", site="group1", grade=1, fte=100)
|
||||
worker2 = Worker(
|
||||
name="worker2", site="group1", grade=1, fte=100,
|
||||
shift_start_dates={"a": datetime.date(2022, 3, 28)},
|
||||
shift_end_dates={"a": datetime.date(2022, 4, 25)},
|
||||
)
|
||||
Rota.add_workers([worker1, worker2])
|
||||
Rota.add_shifts(
|
||||
SingleShift(
|
||||
sites=("group1",),
|
||||
name="a",
|
||||
length=12.5,
|
||||
days=("Mon",),
|
||||
workers_required=1,
|
||||
),
|
||||
)
|
||||
Rota.build_and_solve(options={"ratio": 0.0})
|
||||
assert Rota.results.solver.status == "ok"
|
||||
|
||||
# Verify assignments for worker2
|
||||
for week in range(1, weeks_to_rota + 1):
|
||||
val = Rota.model.works[worker2.id, week, "Mon", "a"].value
|
||||
assigned = val is not None and val > 0.5
|
||||
if week < 4 or week >= 8:
|
||||
assert not assigned, f"Worker 2 should not be assigned 'a' in week {week}"
|
||||
|
||||
|
||||
def test_shift_dependent_fte_target_scaling():
|
||||
weeks_to_rota = 10
|
||||
start_date = datetime.date(2022, 3, 7) # Mon
|
||||
|
||||
Rota = RotaBuilder(
|
||||
start_date,
|
||||
weeks_to_rota=weeks_to_rota,
|
||||
)
|
||||
worker1 = Worker(name="worker1", site="group1", grade=1, fte=100)
|
||||
worker2 = Worker(
|
||||
name="worker2", site="group1", grade=1, fte=100,
|
||||
shift_start_dates={"a": datetime.date(2022, 3, 28)},
|
||||
shift_end_dates={"a": datetime.date(2022, 4, 25)},
|
||||
)
|
||||
Rota.add_workers([worker1, worker2])
|
||||
Rota.add_shifts(
|
||||
SingleShift(
|
||||
sites=("group1",),
|
||||
name="a",
|
||||
length=12.5,
|
||||
days=("Mon",),
|
||||
workers_required=1,
|
||||
),
|
||||
)
|
||||
Rota.build_and_solve(options={"ratio": 0.0})
|
||||
assert Rota.results.solver.status == "ok"
|
||||
|
||||
# Targets check
|
||||
assert abs(worker1.shift_target_number["a"] - 7.14) < 0.1
|
||||
assert abs(worker2.shift_target_number["a"] - 2.86) < 0.1
|
||||
|
||||
|
||||
def test_shift_dependent_dates_validation_invalid_shift():
|
||||
weeks_to_rota = 2
|
||||
start_date = datetime.date(2022, 3, 7)
|
||||
|
||||
Rota = RotaBuilder(start_date, weeks_to_rota=weeks_to_rota)
|
||||
worker = Worker(
|
||||
name="worker1", site="group1", grade=1, fte=100,
|
||||
shift_start_dates=[ShiftStartDate(shift="non_existent", start_date=datetime.date(2022, 3, 7))]
|
||||
)
|
||||
Rota.add_worker(worker)
|
||||
Rota.add_shifts(
|
||||
SingleShift(
|
||||
sites=("group1",),
|
||||
name="a",
|
||||
length=12.5,
|
||||
days=("Mon",),
|
||||
workers_required=1,
|
||||
)
|
||||
)
|
||||
with pytest.raises(InvalidShift):
|
||||
Rota.build_workers()
|
||||
|
||||
|
||||
def test_shift_dependent_dates_validation_ineligible_warning():
|
||||
weeks_to_rota = 2
|
||||
start_date = datetime.date(2022, 3, 7)
|
||||
|
||||
Rota = RotaBuilder(start_date, weeks_to_rota=weeks_to_rota)
|
||||
worker = Worker(
|
||||
name="worker1", site="group1", grade=1, fte=100,
|
||||
shift_start_dates=[ShiftStartDate(shift="a", start_date=datetime.date(2022, 3, 7))]
|
||||
)
|
||||
Rota.add_worker(worker)
|
||||
Rota.add_shifts(
|
||||
SingleShift(
|
||||
sites=("group2",),
|
||||
name="a",
|
||||
length=12.5,
|
||||
days=("Mon",),
|
||||
workers_required=1,
|
||||
)
|
||||
)
|
||||
Rota.terminate_on_warning.remove("Worker/no valid shifts")
|
||||
Rota.build_workers()
|
||||
|
||||
warnings = Rota.get_warnings("Worker/ineligible shift date constraint")
|
||||
assert len(warnings) == 1
|
||||
assert "is not eligible to work it" in warnings[0][1]
|
||||
|
||||
|
||||
def test_shift_dependent_dates_model_definition():
|
||||
worker = Worker(
|
||||
name="worker1", site="group1", grade=1, fte=100,
|
||||
shift_start_dates=[{"shift": "a", "start_date": "2022-03-07"}],
|
||||
shift_end_dates=[{"shift": "a", "end_date": "2022-04-07"}]
|
||||
)
|
||||
assert len(worker.shift_start_dates) == 1
|
||||
assert isinstance(worker.shift_start_dates[0], ShiftStartDate)
|
||||
assert worker.shift_start_dates[0].shift == "a"
|
||||
assert worker.shift_start_dates[0].start_date == datetime.date(2022, 3, 7)
|
||||
|
||||
assert len(worker.shift_end_dates) == 1
|
||||
assert isinstance(worker.shift_end_dates[0], ShiftEndDate)
|
||||
assert worker.shift_end_dates[0].shift == "a"
|
||||
assert worker.shift_end_dates[0].end_date == datetime.date(2022, 4, 7)
|
||||
Reference in New Issue
Block a user