gmao/app_new/gmao_config/routes.py
root 8f276b5c47
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
Sécurise et supervise les intégrations externes
2026-08-14 21:46:00 +00:00

153 lines
6.6 KiB
Python

"""
Configuration du contexte GMAO - GMAO Collège
Utilise le modèle GmaoContext existant dans outlook/models.py
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_login import login_required, current_user
from app_new.extensions import db
from app_new.outlook.models import GmaoContext
gmao_config_bp = Blueprint('gmao_config', __name__, template_folder='templates')
@gmao_config_bp.route('/')
@login_required
def index():
"""Page de configuration du contexte GMAO."""
# Récupérer ou créer le contexte pour l'utilisateur actuel
context = GmaoContext.get_for_user(current_user.id)
# Récupérer les comptes Outlook de l'utilisateur (ou tous si admin)
from app_new.outlook.models import OutlookAccount
from app_new.core.models.settings import AppSettings
if current_user.username == 'admin':
outlook_accounts = OutlookAccount.query.all()
else:
outlook_accounts = OutlookAccount.query.filter_by(user_id=current_user.id).all()
# Recuperer la cle API et le modele OpenRouter
openrouter_key = '••••••••' if AppSettings.get('openrouter_api_key') else ''
openrouter_model = AppSettings.get('openrouter_model', 'poolside/laguna-s-2.1:free')
ollama_model = AppSettings.get('ollama_model', 'gemma3:4b-it')
return render_template('gmao_config/index.html', context=context, outlook_accounts=outlook_accounts,
openrouter_key=openrouter_key, openrouter_model=openrouter_model,
ollama_model=ollama_model)
@gmao_config_bp.route('/save', methods=['POST'])
@login_required
def save():
"""Sauvegarde le contexte GMAO."""
context = GmaoContext.get_for_user(current_user.id)
# Informations sur l'établissement
context.establishment_name = request.form.get('establishment_name', '')
context.establishment_type = request.form.get('establishment_type', '')
context.address = request.form.get('address', '')
# Contexte technique
context.technical_context = request.form.get('technical_context', '')
context.equipment_context = request.form.get('equipment_context', '')
context.procedure_context = request.form.get('procedure_context', '')
# Contexte organisationnel
context.staff_info = request.form.get('staff_info', '')
context.contact_info = request.form.get('contact_info', '')
# Instructions pour Hermes
context.hermes_instructions = request.form.get('hermes_instructions', '')
# Expéditeurs exclus
context.excluded_senders = request.form.get('excluded_senders', '')
# Activation du watchdog (interpretation auto Outlook + ENT)
context.auto_interpret_enabled = request.form.get('auto_interpret_enabled') == 'on'
context.auto_interpret_interval = max(1, int(request.form.get('auto_interpret_interval', 10)))
context.auto_interpret_max_emails = max(1, int(request.form.get('auto_interpret_max_emails', 5)))
context.auto_interpret_lookback_hours = max(1, int(request.form.get('auto_interpret_lookback_hours', 24)))
# Activation de la synchronisation PRONOTE
context.pronote_sync_enabled = request.form.get('pronote_sync_enabled') == 'on'
context.pronote_sync_interval = max(60, int(request.form.get('pronote_sync_interval', 360)))
context.pronote_sync_weeks = max(1, int(request.form.get('pronote_sync_weeks', 4)))
# Activation de la synchronisation Outlook
context.outlook_sync_enabled = request.form.get('outlook_sync_enabled') == 'on'
context.outlook_sync_interval = max(1, int(request.form.get('outlook_sync_interval', 10)))
context.outlook_sync_lookback_hours = max(1, int(request.form.get('outlook_sync_lookback_hours', 24)))
# Configuration IA
from app_new.core.models.settings import AppSettings
api_key = request.form.get('openrouter_api_key', '').strip()
if api_key and api_key != '••••••••':
AppSettings.set('openrouter_api_key', api_key, is_encrypted=True)
model = request.form.get('openrouter_model', '').strip()
if model:
AppSettings.set('openrouter_model', model)
# Provider IA : openrouter (cloud) ou ollama (local auto-identification)
context.ai_provider = request.form.get('ai_provider', 'openrouter')
ollama_model = request.form.get('ollama_model', '').strip()
if ollama_model:
context.ollama_model = ollama_model
# Watchdog interne (cron local)
context.watchdog_enabled = request.form.get('watchdog_enabled') == 'on'
context.watchdog_interval = max(1, int(request.form.get('watchdog_interval', 10)))
db.session.commit()
flash('Contexte GMAO mis à jour avec succès.', 'success')
return redirect(url_for('gmao_config.index'))
@gmao_config_bp.route('/test', methods=['POST'])
@login_required
def test():
"""Test l'interpretation avec un email d'exemple."""
from app_new.core.models.settings import AppSettings
from app_new.outlook.auto_interpret import analyze_email_with_hermes
from flask import jsonify
context = GmaoContext.get_for_user(current_user.id)
# Verifier la cle API / connexion Ollama selon le provider
provider = context.ai_provider or 'openrouter'
if provider == 'openrouter':
api_key = AppSettings.get('openrouter_api_key')
if not api_key:
return jsonify({'error': 'Clé API OpenRouter non configurée. Configurez-la dans /gmao-config/.'}), 400
elif provider == 'ollama':
# Vérifier que le service Ollama est accessible
try:
ollama_host = AppSettings.get('ollama_host', 'http://ollama:11434')
requests.get(f'{ollama_host}/api/tags', timeout=5)
except:
return jsonify({'error': 'Service Ollama inaccessible.'}), 400
# Email d'exemple
class FakeMail:
subject = "Fuite d'eau dans la salle B07 - Intervention urgente"
from_name = "M. Dupont"
from_email = "dupont@college.fr"
to_recipients = ""
received_at = None
body_content = "Bonjour,\n\nIl y a une fuite d'eau dans la salle B07, pres de la chaufferie. Cela devrait etre regle en urgence s'il vous plait.\n\nMerci,\nM. Dupont"
body_preview = body_content
attachments = []
fake_mail = FakeMail()
fake_mail.body_preview = fake_mail.body_content
# Lancer l'interpretation
result = analyze_email_with_hermes(fake_mail, context)
if 'error' in result:
return jsonify({'error': result['error']}), 400
return jsonify({
'success': True,
'analysis': result,
'context_summary': context.get_full_context()[:200] + '...' if context.get_full_context() else 'Vide'
})