"""Moteur unique de génération des échéances depuis les tâches de lot.""" from datetime import date, timedelta from app_new.extensions import db from app_new.core.models.planning import Meter, ScheduledTask from app_new.core.models.maintenance import LotTask from app_new.core.services.planning_service import PlanningService def _targets(lot): result = [] for root in lot.equipments.filter_by(is_deleted=False): if root.tracked_individually: result.extend([x for x in root.all_children if not x.is_group and not x.is_deleted]) elif root.is_group and root.children.count(): result.extend([x for x in root.children if not x.is_deleted]) else: result.append(root) return list({item.id: item for item in result}.values()) def _working_day(candidate): for _ in range(370): if PlanningService.get_working_hours(candidate): return candidate candidate += timedelta(days=1) raise ValueError("Aucune journée travaillée disponible dans les 12 prochains mois.") def generate_due_tasks(task: LotTask, event=None, today=None): """Génère les échéances sans doublon et retourne les objets créés.""" today = today or date.today() if not task.is_active: return [] if task.trigger_type in ("event", "weather") and task.trigger_event != event: return [] if task.trigger_type == "season": start, end = task.season_start_month or 1, task.season_end_month or 12 inside = start <= today.month <= end if start <= end else today.month >= start or today.month <= end if not inside: return [] created = [] for equipment in _targets(task.lot): if task.trigger_type == "meter": meter = Meter.query.filter_by(equipment_id=equipment.id, is_active=True).order_by(Meter.current_value.desc()).first() if not meter or task.meter_threshold is None or meter.current_value < task.meter_threshold: continue existing = ScheduledTask.query.filter_by(lot_task_id=task.id, equipment_id=equipment.id, status="planned").first() if existing: continue due = _working_day(today + timedelta(days=max(task.advance_days or 0, 0))) item = ScheduledTask(lot_task_id=task.id, equipment_id=equipment.id, room_id=equipment.effective_room.id if equipment.effective_room else None, scheduled_date=due, estimated_duration=task.effective_duration(), status="planned") db.session.add(item) created.append(item) db.session.commit() return created