""" Messagerie unifiee - GMAO College Page unique regroupant: - Interpretations a traiter (Outlook + ENT) - 10 derniers messages Outlook - 10 derniers messages ENT - Boutons d'import/sync """ from flask import Blueprint, render_template, jsonify from flask_login import login_required, current_user from app_new.extensions import db messagerie_bp = Blueprint('messagerie', __name__, template_folder='templates') @messagerie_bp.route('/messagerie') @login_required def index(): """Page de messagerie unifiee.""" from datetime import datetime # 1. Interpretations Outlook en attente outlook_interps = [] try: from app_new.outlook.models import OutlookMailInterpretation, OutlookMail pending = OutlookMailInterpretation.query.filter_by( status='pending', user_id=current_user.id ).order_by(OutlookMailInterpretation.created_at.desc()).limit(15).all() for p in pending: outlook_interps.append({ 'id': p.id, 'source': 'outlook', 'date': p.created_at, 'subject': p.mail.subject if p.mail else 'N/A', 'from': p.mail.from_name if p.mail else 'N/A', 'description': p.suggested_description or '', 'equipment': p.suggested_equipment or '', 'action': p.analysis_action or '', 'confidence': getattr(p, 'analysis_confidence', 0.5), 'detail_url': f'/outlook/{p.mail.account_id}/mail/{p.mail_id}' if p.mail else '#', 'create_url': f'/interventions/new?from_interpretation={p.id}&source=outlook', }) except Exception as e: outlook_interps = [] # 2. Interpretations ENT en attente ent_interps = [] try: from app_new.ent.interpretation_models import EntMessageInterpretation pending_ent = EntMessageInterpretation.query.filter_by(status='pending')\ .order_by(EntMessageInterpretation.created_at.desc()).limit(15).all() for p in pending_ent: ent_interps.append({ 'id': p.id, 'source': 'ent', 'date': p.created_at, 'subject': p.message.subject if p.message else 'N/A', 'from': p.message.author if p.message else 'N/A', 'description': p.suggested_description or '', 'equipment': p.suggested_equipment or '', 'action': p.analysis_action or '', 'confidence': getattr(p, 'analysis_confidence', 0.5), 'detail_url': f'/ent/message/{p.message_id}' if p.message else '/ent/interpretations', 'create_url': f'/interventions/new?from_interpretation={p.id}&source=ent', }) except Exception: ent_interps = [] # Combiner et trier par date all_interps = outlook_interps + ent_interps all_interps.sort(key=lambda x: x['date'] if x['date'] else datetime.min, reverse=True) # 3. 10 derniers messages Outlook outlook_mails = [] try: from app_new.outlook.models import OutlookMail mails = OutlookMail.query.order_by(OutlookMail.received_at.desc()).limit(10).all() for m in mails: outlook_mails.append({ 'id': m.id, 'subject': m.subject or '(sans objet)', 'from_name': m.from_name or '', 'from_email': m.from_email or '', 'received_at': m.received_at, 'is_read': m.is_read, 'has_interpretation': m.interpretations.count() > 0 if hasattr(m, 'interpretations') else False, }) except Exception: outlook_mails = [] # 4. 10 derniers messages ENT ent_messages = [] try: from app_new.ent.models import EntMessage msgs = EntMessage.query.order_by(EntMessage.received_at.desc()).limit(10).all() for m in msgs: ent_messages.append({ 'id': m.id, 'subject': m.subject or '(sans objet)', 'author': m.author or '', 'received_at': m.received_at, 'has_interpretation': hasattr(m, 'interpretations') and m.interpretations.count() > 0, }) except Exception: ent_messages = [] return render_template('messagerie/index.html', all_interpretations=all_interps, outlook_mails=outlook_mails, ent_messages=ent_messages, outlook_count=len(outlook_interps), ent_count=len(ent_interps), last_outlook_mail=outlook_mails[0] if outlook_mails else None, last_ent_message=ent_messages[0] if ent_messages else None, last_interpretation=all_interps[0] if all_interps else None) @messagerie_bp.route('/messagerie/api/interpret-now', methods=['POST']) @login_required def interpret_now(): """Lance l'interpretation manuelle des emails Outlook + messages ENT.""" results = {} # Interpretation Outlook try: from app_new.outlook.auto_interpret import run_auto_interpret result = run_auto_interpret() results['outlook'] = { 'success': result.get('success', False), 'processed': result.get('processed', 0), 'created': result.get('created', 0), 'errors': result.get('errors', []) } except Exception as e: results['outlook'] = {'success': False, 'error': str(e)[:200]} # Interpretation ENT try: from app_new.lib_ext.ent_service import _process_credential from app_new.ent.models import EntCredential, EntConfig from flask import current_app creds = EntCredential.query.filter_by(is_active=True).all() config = EntConfig.query.first() app = current_app._get_current_object() ent_created = 0 for cred in creds: try: r = _process_credential(cred, config, app) if isinstance(r, int): ent_created += r except Exception: pass results['ent'] = {'success': True, 'created': ent_created} except Exception as e: results['ent'] = {'success': False, 'error': str(e)[:200]} return jsonify({ 'success': True, 'results': results, 'message': f"Outlook: {results.get('outlook', {}).get('created', 0)} interpretations, ENT: {results.get('ent', {}).get('created', 0)} interpretations" }) @messagerie_bp.route('/messagerie/api/import-outlook', methods=['POST']) @login_required def import_outlook(): """Importe les 10 derniers emails Outlook (sync manuelle).""" try: from app_new.outlook.models import OutlookAccount from app_new.outlook.sync import api_sync_mails accounts = OutlookAccount.query.all() if not accounts: return jsonify({'success': False, 'error': 'Aucun compte Outlook configure'}), 400 total_saved = 0 total_updated = 0 errors = [] for account in accounts: try: # Chercher le dossier inbox pour ce compte from app_new.outlook.models import OutlookFolder inbox = OutlookFolder.query.filter_by(account_id=account.id, folder_type='inbox').first() if not inbox: inbox = OutlookFolder.query.filter( OutlookFolder.account_id == account.id, OutlookFolder.name.like('%ception%') ).first() folder_id = inbox.id if inbox else 'inbox' result = api_sync_mails(account.id, folder_id=folder_id) total_saved += result.get('saved', 0) if isinstance(result, dict) else 0 total_updated += result.get('updated', 0) if isinstance(result, dict) else 0 except Exception as e: errors.append(f'Compte {account.id}: {str(e)[:100]}') return jsonify({ 'success': True, 'saved': total_saved, 'updated': total_updated, 'message': f"{total_saved} nouveaux, {total_updated} mis a jour" + (f" ({len(errors)} erreurs)" if errors else "") }) except Exception as e: return jsonify({'success': False, 'error': str(e)[:200]}), 500 @messagerie_bp.route('/messagerie/api/import-ent', methods=['POST']) @login_required def import_ent(): """Importe les 10 derniers messages ENT (sync manuelle).""" try: from app_new.lib_ext.ent_service import _process_credential, fetch_new_messages, login_ent from app_new.lib_ext.ent_crypto import decrypt_value from app_new.ent.models import EntCredential, EntMessage, EntConfig from app_new.extensions import db from flask import current_app creds = EntCredential.query.filter_by(is_active=True).all() if not creds: return jsonify({'success': False, 'error': 'Aucun credential ENT configure'}), 400 config = EntConfig.query.first() app = current_app._get_current_object() total_new = 0 total_interventions = 0 errors = [] for cred in creds: try: result = _process_credential(cred, config, app) if isinstance(result, int): total_interventions += result elif isinstance(result, dict): total_interventions += result.get('new_messages', 0) except Exception as e: errors.append(str(e)[:100]) # Compter les messages recents en DB recent_count = EntMessage.query.count() return jsonify({ 'success': True, 'saved': recent_count, 'message': f"{recent_count} messages en base, {total_interventions} intervention(s) creee(s)" + (f" ({len(errors)} erreurs)" if errors else "") }) except Exception as e: return jsonify({'success': False, 'error': str(e)[:200]}), 500