diff --git a/app_new/core/routes/dashboard.py b/app_new/core/routes/dashboard.py index c2bda46..b3a052c 100644 --- a/app_new/core/routes/dashboard.py +++ b/app_new/core/routes/dashboard.py @@ -12,6 +12,7 @@ from ..models.company import Company from ..models.college import Building, Room from ..models.company import Part from app_new.constants import INTERVENTION_STATUSES, EQUIPMENT_STATUSES +from sqlalchemy import func dashboard_bp = Blueprint('dashboard', __name__) @@ -23,6 +24,7 @@ def index(): from datetime import date from ..services.planning_service import PlanningService from ..models.planning import ScheduledTask, AdminTask + from ..models.maintenance import Lot # Statistiques stats = { @@ -38,6 +40,41 @@ def index(): 'companies_total': Company.query.count(), 'parts_low_stock': Part.query.filter(Part.quantity <= Part.min_quantity).count(), } + + # Contrôle des lots : un lot présent doit être rattaché à au moins un + # équipement, sauf s'il a été explicitement marqué « non présent ». + equipment_counts = dict( + db.session.query(Equipment.lot_id, func.count(Equipment.id)) + .filter( + Equipment.lot_id.isnot(None), + Equipment.is_deleted.is_(False), + db.or_(Equipment.status.is_(None), Equipment.status != 'jete'), + ) + .group_by(Equipment.lot_id) + .all() + ) + lots = Lot.query.order_by(Lot.name).all() + lots_without_equipment = [ + lot for lot in lots + if lot.is_present and equipment_counts.get(lot.id, 0) == 0 + ] + lots_missing_duration = [] + for lot in lots: + if not lot.is_present or equipment_counts.get(lot.id, 0) == 0: + continue + active_tasks = [task for task in lot.tasks if task.is_active] + missing_tasks = [ + task for task in lot.tasks + if task.is_active and not task.duree_minutes + ] + if missing_tasks or not active_tasks: + lots_missing_duration.append({ + 'lot': lot, + 'tasks': missing_tasks, + 'no_task': not active_tasks, + }) + stats['lots_without_equipment'] = len(lots_without_equipment) + stats['lots_missing_duration'] = len(lots_missing_duration) # Dernières interventions recent_interventions = Intervention.query.order_by(Intervention.created_at.desc()).limit(10).all() @@ -108,6 +145,8 @@ def index(): urgent_interventions=urgent_interventions, pending_interpretations=pending_interpretations, day_schedule=day_schedule, + lots_without_equipment=lots_without_equipment, + lots_missing_duration=lots_missing_duration, today=today, statuses=INTERVENTION_STATUSES) diff --git a/app_new/templates/dashboard/index.html b/app_new/templates/dashboard/index.html index e3822be..f5ffda3 100644 --- a/app_new/templates/dashboard/index.html +++ b/app_new/templates/dashboard/index.html @@ -119,6 +119,66 @@ + +
+
+
+
+ Lots présents sans équipement + {{ stats.lots_without_equipment }} +
+
+ {% if lots_without_equipment %} +
+ {% for lot in lots_without_equipment[:8] %} + + {{ lot.name }} + + {% endfor %} +
+ {% if lots_without_equipment|length > 8 %}{{ lots_without_equipment|length - 8 }} autre(s){% endif %} + {% else %} + Tous les lots présents ont un équipement. + {% endif %} +
+
+
+
+
+
+ Lots équipés avec durée manquante + {{ stats.lots_missing_duration }} +
+
+ {% if lots_missing_duration %} +
+ {% for item in lots_missing_duration[:8] %} +
+
+ {{ item.lot.name }} + {% if item.no_task %}Aucune tâche{% else %}{{ item.tasks|length }} tâche(s){% endif %} +
+ {% if item.no_task %} + + Ajouter une tâche et définir sa durée + + {% endif %} + {% for task in item.tasks[:3] %} + + {{ task.tache or 'Tâche sans nom' }} — définir la durée + + {% endfor %} +
+ {% endfor %} +
+ {% else %} + Toutes les tâches actives ont une durée définie. + {% endif %} +
+
+
+
+ {% if alerts %}
@@ -652,4 +712,4 @@ fetch('/scheduler/api/overdue-count').then(r => r.json()).then(d => { } }).catch(() => {}); -{% endblock %} \ No newline at end of file +{% endblock %}