gmao/app_new/__init__.py

252 lines
9.4 KiB
Python
Raw Normal View History

2026-08-14 18:02:25 +02:00
"""
GMAO Collège - Application Flask Modulaire
Structure par domaine métier
"""
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_wtf.csrf import CSRFProtect
from datetime import timedelta
import os
import json
# Extensions (définies dans extensions.py)
from .extensions import db, login_manager, migrate, csrf
# Import all models to register them in SQLAlchemy metadata
from .core import models
def create_app(config_name='default'):
"""Factory pour créer l'application Flask."""
# Chemin absolu vers le répertoire app_new
app_dir = os.path.dirname(os.path.abspath(__file__))
# Chemins absolus pour templates et instance
template_dir = os.path.join(app_dir, 'templates')
instance_dir = os.path.join(app_dir, 'instance')
# Créer le dossier instance s'il n'existe pas
os.makedirs(instance_dir, exist_ok=True)
# Charger les variables d'environnement depuis .env AVANT la config
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__,
instance_path=instance_dir,
instance_relative_config=True,
template_folder=template_dir,
static_folder=os.path.join(app_dir, 'static'))
# Tolerer les slashs finaux dans les URLs
app.url_map.strict_slashes = False
# Configuration
from .config import config as config_dict
config_class = config_dict[config_name]
app.config.from_object(config_class)
config_class.init_app(app)
# Initialisation des extensions
db.init_app(app)
login_manager.init_app(app)
migrate.init_app(app, db)
csrf.init_app(app)
# Configuration du login manager
login_manager.login_view = 'auth.login'
login_manager.login_message = 'Veuillez vous connecter pour accéder à cette page.'
login_manager.login_message_category = 'warning'
# Import des modèles AVANT les blueprints
from .core import models as core_models
from .pronote import models as pronote_models
from .ent import models as ent_models
from .outlook import models as outlook_models
from .yeastar import models as yeastar_models
# Enregistrement des blueprints
from .core.routes import auth_bp, admin_bp, dashboard_bp, setup_wizard_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
app.register_blueprint(admin_bp, url_prefix='/admin')
app.register_blueprint(dashboard_bp, url_prefix='/')
app.register_blueprint(setup_wizard_bp, url_prefix='/setup-wizard')
# Blueprints des modules métier
from .equipments.routes import (
equipments_bp, meters_bp, documents_bp, restrictions_bp, scheduled_bp
)
from .equipments.buildings import buildings_bp
from .equipments.zones import zones_bp
from .equipments.rooms import rooms_bp
app.register_blueprint(equipments_bp, url_prefix='/equipments')
app.register_blueprint(buildings_bp, url_prefix='/equipments/buildings')
app.register_blueprint(zones_bp, url_prefix='/equipments/zones')
app.register_blueprint(rooms_bp, url_prefix='/equipments/rooms')
app.register_blueprint(meters_bp, url_prefix='/equipments')
app.register_blueprint(documents_bp, url_prefix='/equipments')
app.register_blueprint(restrictions_bp, url_prefix='/equipments')
app.register_blueprint(scheduled_bp, url_prefix='/equipments')
from .interventions.routes import interventions_bp, interventions_planning_bp
app.register_blueprint(interventions_bp, url_prefix='/interventions')
app.register_blueprint(interventions_planning_bp, url_prefix='/interventions')
from .planning.routes import planning_bp
app.register_blueprint(planning_bp, url_prefix='/planning')
from .companies.routes import companies_bp
app.register_blueprint(companies_bp, url_prefix='/companies')
from .lots.routes import lots_bp
app.register_blueprint(lots_bp, url_prefix='/lots')
from .training.routes import training_bp
app.register_blueprint(training_bp, url_prefix='/training')
from .meters.routes import meters_bp
app.register_blueprint(meters_bp, url_prefix='/meters')
from .parts.routes import parts_bp
app.register_blueprint(parts_bp, url_prefix='/parts')
from .services_module.routes import services_bp
app.register_blueprint(services_bp, url_prefix='/services')
from .room_types.routes import room_types_bp
app.register_blueprint(room_types_bp, url_prefix='/room-types')
from .documents.routes import documents_bp
app.register_blueprint(documents_bp, url_prefix='/documents')
from .gmao_config.routes import gmao_config_bp
app.register_blueprint(gmao_config_bp, url_prefix='/gmao-config')
from .wizard.routes import wizard_bp
app.register_blueprint(wizard_bp)
# Blueprints des intégrations
from .pronote.routes import pronote_bp
csrf.exempt(pronote_bp)
app.register_blueprint(pronote_bp, url_prefix='/pronote')
from .ent.routes import ent_bp
app.register_blueprint(ent_bp, url_prefix='/ent')
from .outlook.routes import outlook_bp, outlook_auth_bp, outlook_sync_bp, outlook_dashboard_bp
app.register_blueprint(outlook_bp, url_prefix='/outlook')
app.register_blueprint(outlook_auth_bp, url_prefix='/outlook')
app.register_blueprint(outlook_sync_bp, url_prefix='/outlook')
app.register_blueprint(outlook_dashboard_bp, url_prefix='/outlook')
from .yeastar.routes import yeastar_bp
app.register_blueprint(yeastar_bp, url_prefix='/yeastar')
from .chatbot.routes import chatbot_bp
app.register_blueprint(chatbot_bp, url_prefix='/chatbot')
# Blueprint status systeme
from .status.routes import status_bp
app.register_blueprint(status_bp)
from .health import health_bp
app.register_blueprint(health_bp)
# Logs centralises des watchdogs
from .logs.routes import logs_bp
app.register_blueprint(logs_bp)
# API REST v1
from .api.routes import api_bp
app.register_blueprint(api_bp)
csrf.exempt(api_bp)
# Notifications temps reel
from .notifications.routes import notifications_bp
app.register_blueprint(notifications_bp)
csrf.exempt(notifications_bp)
# Exports PDF/CSV
from .exports.routes import exports_bp
app.register_blueprint(exports_bp)
# Messagerie unifiee
from .messagerie.routes import messagerie_bp
app.register_blueprint(messagerie_bp)
csrf.exempt(messagerie_bp)
# Contrats d'entreprise
from .contracts.models import Contract
from .contracts.routes import contracts_bp
app.register_blueprint(contracts_bp)
# Configuration IA (OpenRouter)
from .ai_config.routes import ai_config_bp
app.register_blueprint(ai_config_bp)
# Contraintes de zone
from .constraints.routes import constraints_bp
app.register_blueprint(constraints_bp)
# Planificateur automatique
from .scheduler.routes import scheduler_bp
app.register_blueprint(scheduler_bp)
csrf.exempt(scheduler_bp)
# Filtres Jinja2 pour les templates
from .utils import format_status, status_badge_class, priority_badge_class, bootstrap_color_to_hex, bootstrap_text_color
app.jinja_env.filters["date_fmt"] = lambda value: value.strftime("%d/%m/%Y") if value else ""
app.jinja_env.filters["datetime_fmt"] = lambda value: value.strftime("%d/%m/%Y %H:%M") if value else ""
app.jinja_env.filters["format_status"] = format_status
app.jinja_env.filters["status_badge"] = status_badge_class
app.jinja_env.filters["priority_badge"] = priority_badge_class
app.jinja_env.filters["from_json"] = lambda value: json.loads(value) if value else []
app.jinja_env.filters["hex_color"] = bootstrap_color_to_hex
app.jinja_env.filters["text_color"] = bootstrap_text_color
app.jinja_env.globals["timedelta"] = timedelta
# Création des tables (fallback si migrations pas encore appliquees)
with app.app_context():
db.create_all()
# Gestionnaires d'erreurs personnalisées
@app.errorhandler(404)
def not_found_error(e):
return render_template('errors/error.html',
error_code='404',
error_title='Page non trouvée',
error_message='La page demandée nexiste pas ou a été déplacée.'), 404
@app.errorhandler(500)
def internal_error(e):
try:
db.session.rollback()
except Exception:
pass
return render_template('errors/error.html',
error_code='500',
error_title='Erreur serveur',
error_message='Une erreur est survenue. Elle a été signalée automatiquement.'), 500
@app.errorhandler(403)
def forbidden_error(e):
return render_template('errors/error.html',
error_code='403',
error_title='Accès refusé',
error_message='Vous navez pas les droits nécessaires pour accéder à cette page.'), 403
return app
# User loader pour Flask-Login
@login_manager.user_loader
def load_user(user_id):
"""Charge un utilisateur par son ID."""
from .core.models.user import User
return User.query.get(int(user_id))