92 lines
3.3 KiB
Python
92 lines
3.3 KiB
Python
|
|
"""
|
||
|
|
Notifications temps réel - GMAO Collège
|
||
|
|
Polling simple via API (pas de WebSocket pour rester leger).
|
||
|
|
"""
|
||
|
|
from flask import Blueprint, jsonify
|
||
|
|
from flask_login import login_required, current_user
|
||
|
|
from app_new.extensions import db
|
||
|
|
|
||
|
|
notifications_bp = Blueprint('notifications', __name__)
|
||
|
|
|
||
|
|
|
||
|
|
@notifications_bp.route('/api/notifications')
|
||
|
|
@login_required
|
||
|
|
def get_notifications():
|
||
|
|
"""Retourne les notifications non lues (alertes, interpretations en attente, watchdog errors)."""
|
||
|
|
notifications = []
|
||
|
|
|
||
|
|
# 1. Alertes non lues
|
||
|
|
try:
|
||
|
|
from app_new.core.models.company import Alert
|
||
|
|
alerts = Alert.query.filter_by(is_read=False).limit(10).all()
|
||
|
|
for a in alerts:
|
||
|
|
notifications.append({
|
||
|
|
'id': f'alert-{a.id}',
|
||
|
|
'type': 'alert',
|
||
|
|
'title': a.title or 'Alerte',
|
||
|
|
'message': (a.message or '')[:100],
|
||
|
|
'level': 'warning',
|
||
|
|
'created_at': a.created_at.isoformat() if a.created_at else None,
|
||
|
|
'url': '/alerts'
|
||
|
|
})
|
||
|
|
except Exception:
|
||
|
|
pass
|
||
|
|
|
||
|
|
# 2. Interpretations Outlook en attente
|
||
|
|
try:
|
||
|
|
from app_new.outlook.models import OutlookMailInterpretation
|
||
|
|
pending = OutlookMailInterpretation.query.filter_by(
|
||
|
|
status='pending', user_id=current_user.id
|
||
|
|
).limit(5).all()
|
||
|
|
for p in pending:
|
||
|
|
notifications.append({
|
||
|
|
'id': f'outlook-{p.id}',
|
||
|
|
'type': 'interpretation',
|
||
|
|
'title': 'Interpretation Outlook en attente',
|
||
|
|
'message': (p.suggested_description or '')[:100],
|
||
|
|
'level': 'info',
|
||
|
|
'created_at': p.created_at.isoformat() if p.created_at else None,
|
||
|
|
'url': '/outlook/'
|
||
|
|
})
|
||
|
|
except Exception:
|
||
|
|
pass
|
||
|
|
|
||
|
|
# 3. Interpretations ENT en attente
|
||
|
|
try:
|
||
|
|
from app_new.ent.interpretation_models import EntMessageInterpretation
|
||
|
|
pending_ent = EntMessageInterpretation.query.filter_by(status='pending').limit(5).all()
|
||
|
|
for p in pending_ent:
|
||
|
|
notifications.append({
|
||
|
|
'id': f'ent-{p.id}',
|
||
|
|
'type': 'interpretation',
|
||
|
|
'title': 'Interpretation ENT en attente',
|
||
|
|
'message': (p.suggested_description or '')[:100],
|
||
|
|
'level': 'info',
|
||
|
|
'created_at': p.created_at.isoformat() if p.created_at else None,
|
||
|
|
'url': '/ent/'
|
||
|
|
})
|
||
|
|
except Exception:
|
||
|
|
pass
|
||
|
|
|
||
|
|
# 4. Watchdog errors recentes
|
||
|
|
try:
|
||
|
|
from app_new.core.models.maintenance import WatchdogLog
|
||
|
|
errors = WatchdogLog.query.filter_by(level='error')\
|
||
|
|
.order_by(WatchdogLog.created_at.desc()).limit(5).all()
|
||
|
|
for e in errors:
|
||
|
|
notifications.append({
|
||
|
|
'id': f'watchdog-{e.id}',
|
||
|
|
'type': 'watchdog_error',
|
||
|
|
'title': f'Erreur {e.watchdog_name}',
|
||
|
|
'message': (e.message or '')[:100],
|
||
|
|
'level': 'error',
|
||
|
|
'created_at': e.created_at.isoformat() if e.created_at else None,
|
||
|
|
'url': '/logs/'
|
||
|
|
})
|
||
|
|
except Exception:
|
||
|
|
pass
|
||
|
|
|
||
|
|
return jsonify({
|
||
|
|
'count': len(notifications),
|
||
|
|
'notifications': notifications
|
||
|
|
})
|