gmao/app_new/core/services/task_execution.py

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