246 lines
No EOL
10 KiB
Python
246 lines
No EOL
10 KiB
Python
"""
|
|
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 |