71 lines
2.7 KiB
Python
71 lines
2.7 KiB
Python
"""Règles minimales d'exécution des tâches interrompables/fractionnables."""
|
|
from datetime import datetime, timezone
|
|
|
|
from ...extensions import db
|
|
from ..models.planning import ScheduledTask, TaskExecutionSegment
|
|
|
|
|
|
PAUSE_REASONS = {
|
|
"eleves": "Présence d'élèves",
|
|
"urgence": "Urgence",
|
|
"local": "Local devenu occupé",
|
|
"materiel": "Attente de matériel",
|
|
"entreprise": "Entreprise/personne indisponible",
|
|
"meteo": "Météo",
|
|
"securite": "Sécurité",
|
|
"autre": "Autre",
|
|
}
|
|
|
|
|
|
def _now():
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
def start_task(task, technician_id=None, now=None):
|
|
if not task or task.status in ("completed", "terminée"):
|
|
raise ValueError("Cette tâche est déjà terminée ou introuvable.")
|
|
if task.execution_segments and task.execution_segments[-1].status == "active":
|
|
raise ValueError("Cette tâche est déjà en cours.")
|
|
if task.lot_task and task.lot_task.minimum_segment_minutes and task.remaining_minutes < task.lot_task.minimum_segment_minutes:
|
|
raise ValueError("Le temps restant est inférieur au segment minimum.")
|
|
segment = TaskExecutionSegment(
|
|
scheduled_task=task, technician_id=technician_id,
|
|
started_at=now or _now(), status="active",
|
|
)
|
|
task.status = "in_progress"
|
|
db.session.add(segment)
|
|
return segment
|
|
|
|
|
|
def pause_task(task, reason="autre", now=None, note=None):
|
|
if not task or not task.execution_segments or task.execution_segments[-1].status != "active":
|
|
raise ValueError("Aucun segment actif à mettre en pause.")
|
|
if task.lot_task and not task.lot_task.interruptible:
|
|
raise ValueError("Cette tâche ne peut pas être interrompue.")
|
|
if reason not in PAUSE_REASONS:
|
|
raise ValueError("Motif de pause inconnu.")
|
|
segment = task.execution_segments[-1]
|
|
segment.close(now or _now(), reason=reason)
|
|
segment.note = note
|
|
task.status = "paused"
|
|
return segment
|
|
|
|
|
|
def resume_task(task, technician_id=None, now=None):
|
|
if not task or not task.lot_task or not task.lot_task.interruptible:
|
|
raise ValueError("Cette tâche ne peut pas être reprise après interruption.")
|
|
if task.remaining_minutes <= 0:
|
|
task.status = "completed"
|
|
return None
|
|
return start_task(task, technician_id=technician_id, now=now)
|
|
|
|
|
|
def complete_task(task, now=None):
|
|
if not task or not task.execution_segments or task.execution_segments[-1].status != "active":
|
|
raise ValueError("Aucun segment actif à terminer.")
|
|
segment = task.execution_segments[-1]
|
|
segment.close(now or _now())
|
|
task.actual_duration = task.realized_minutes
|
|
task.completed_at = now or _now()
|
|
task.status = "completed"
|
|
return segment
|