"""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