49 lines
2.5 KiB
Python
49 lines
2.5 KiB
Python
from datetime import date, time
|
|
|
|
from app_new.core.services.day_planner import DayPlanner, PlanningCandidate, WorkWindow
|
|
|
|
|
|
def test_proposal_respects_pause_and_is_deterministic(monkeypatch):
|
|
monkeypatch.setattr(
|
|
DayPlanner,
|
|
"work_windows",
|
|
staticmethod(lambda day, user_id=None: [WorkWindow(time(8), time(12)), WorkWindow(time(13, 30), time(17))]),
|
|
)
|
|
candidates = [
|
|
PlanningCandidate("scheduled_task", 2, "Contrôle B", duration_minutes=45),
|
|
PlanningCandidate("scheduled_task", 1, "Contrôle A", duration_minutes=45),
|
|
]
|
|
first = DayPlanner.propose(date(2026, 8, 24), candidates)
|
|
assert [(item.proposed_start, item.proposed_end) for item in first] == [
|
|
(time(8), time(8, 45)), (time(8, 45), time(9, 30))
|
|
]
|
|
assert all(item.proposed_end <= time(12) for item in first)
|
|
second = DayPlanner.propose(date(2026, 8, 24), [
|
|
PlanningCandidate("scheduled_task", 2, "Contrôle B", duration_minutes=45),
|
|
PlanningCandidate("scheduled_task", 1, "Contrôle A", duration_minutes=45),
|
|
])
|
|
assert [(item.proposed_start, item.proposed_end) for item in first] == [
|
|
(item.proposed_start, item.proposed_end) for item in second
|
|
]
|
|
|
|
|
|
def test_fixed_event_is_preserved(monkeypatch):
|
|
monkeypatch.setattr(DayPlanner, "work_windows", staticmethod(lambda day, user_id=None: [WorkWindow(time(8), time(17))]))
|
|
fixed = PlanningCandidate("company", 1, "Entreprise", constraint="fixed", fixed_start=time(9), fixed_end=time(10))
|
|
flexible = PlanningCandidate("admin", 2, "Commande", duration_minutes=30)
|
|
result = DayPlanner.propose(date(2026, 8, 24), [flexible, fixed])
|
|
assert next(item for item in result if item.source_id == 1).proposed_start == time(9)
|
|
assert next(item for item in result if item.source_id == 2).proposed_end <= time(9)
|
|
|
|
|
|
def test_task_too_long_is_marked_to_reschedule(monkeypatch):
|
|
monkeypatch.setattr(DayPlanner, "work_windows", staticmethod(lambda day, user_id=None: [WorkWindow(time(8), time(9))]))
|
|
result = DayPlanner.propose(date(2026, 8, 24), [PlanningCandidate("admin", 1, "Tâche", duration_minutes=90)])
|
|
assert result[0].status == "à replanifier"
|
|
assert result[0].proposed_start is None
|
|
|
|
|
|
def test_no_work_window_explains_missing_schedule(monkeypatch):
|
|
monkeypatch.setattr(DayPlanner, "work_windows", staticmethod(lambda day, user_id=None: []))
|
|
result = DayPlanner.propose(date(2026, 8, 24), [PlanningCandidate("admin", 1, "Tâche")])
|
|
assert "horaire de travail" in result[0].explanation
|