2026-08-23 18:45:41 +02:00
from flask import Blueprint , render_template
from flask_login import login_required
from app_new . core . models . college import Site , Building , Zone , Room , RoomProfile , RoomSchedule
from app_new . core . models . equipment import Equipment
from app_new . core . models . maintenance import LotTask
from app_new . core . models . user import User
from app_new . core . models . planning import WorkSchedule
from app_new . contracts . models import Contract
configuration_bp = Blueprint ( " configuration " , __name__ , template_folder = " templates " )
def _status ( ok , label , url , detail = None , optional = False , attention = False ) :
if optional and not ok :
state = " Facultatif "
elif attention :
state = " Attention "
elif ok :
state = " Configuré "
else :
state = " À configurer "
return { " label " : label , " state " : state , " ok " : ok , " url " : url , " detail " : detail or " " }
@configuration_bp.route ( " / " )
@login_required
def index ( ) :
from flask import url_for
sites = Site . query . count ( )
buildings = Building . query . count ( )
zones = Zone . query . count ( )
rooms = Room . query . count ( )
profiles = RoomProfile . query . count ( )
unprofiled = Room . query . filter ( Room . room_type_id . is_ ( None ) ) . count ( )
equipment_without_lot = Equipment . query . filter ( Equipment . is_deleted . is_ ( False ) , Equipment . lot_id . is_ ( None ) ) . count ( )
technicians = User . query . filter_by ( is_active = True ) . all ( )
scheduled_users = { row [ 0 ] for row in WorkSchedule . query . filter_by ( is_active = True ) . with_entities ( WorkSchedule . user_id ) . all ( ) }
tasks_without_duration = LotTask . query . filter ( LotTask . is_active . is_ ( True ) , ( LotTask . duree_minutes . is_ ( None ) | ( LotTask . duree_minutes < = 0 ) ) ) . count ( )
2026-08-23 20:10:40 +02:00
contract_table = Contract . __table__ . c
contracts_without_due = Contract . query . filter ( contract_table . status == " actif " , contract_table . end_date . is_ ( None ) ) . count ( )
2026-08-23 18:45:41 +02:00
room_schedules = RoomSchedule . query . count ( )
sections = [
( " ESSENTIEL " , [
_status ( User . query . filter_by ( is_active = True ) . count ( ) > 0 , " Administrateur / utilisateurs " , url_for ( " admin.users " ) ) ,
_status ( sites > 0 , " Établissement / site " , url_for ( " buildings.index " ) , f " { sites } site(s) " ) ,
_status ( buildings > 0 , " Bâtiments " , url_for ( " buildings.index " ) , f " { buildings } bâtiment(s) " ) ,
_status ( zones > 0 , " Zones " , url_for ( " zones.index " ) , f " { zones } zone(s) " ) ,
_status ( rooms > 0 , " Locaux / emplacements " , url_for ( " rooms.index " ) , f " { rooms } local(aux) " ) ,
_status ( len ( scheduled_users ) > = len ( technicians ) and bool ( technicians ) , " Horaires techniciens " , url_for ( " planning.work_schedules " ) , f " { len ( technicians ) - len ( scheduled_users ) } sans horaires " if technicians else " Aucun technicien actif " , attention = bool ( technicians ) and len ( scheduled_users ) < len ( technicians ) ) ,
] ) ,
( " MAINTENANCE " , [
_status ( profiles > 0 , " Profils de locaux " , url_for ( " room_profiles.index " ) , f " { profiles } profil(s) " ) ,
2026-08-23 19:25:32 +02:00
_status ( False , " Équipements sans lot (facultatif) " , url_for ( " equipments.index " ) , f " { equipment_without_lot } équipement(s) sans lot — le lot peut être ajouté plus tard " , optional = True ) ,
2026-08-23 18:45:41 +02:00
_status ( tasks_without_duration == 0 , " Durées préventives " , url_for ( " lots.index " ) , f " { tasks_without_duration } à renseigner " , attention = tasks_without_duration > 0 ) ,
_status ( room_schedules > 0 , " Planning des salles " , url_for ( " planning.room_schedules " ) , f " { room_schedules } créneau(x) " ) ,
] ) ,
( " PATRIMOINE " , [
_status ( unprofiled == 0 , " Locaux avec profil structurel " , url_for ( " rooms.index " ) , f " { unprofiled } sans type " , attention = unprofiled > 0 ) ,
_status ( True , " Logements de fonction " , url_for ( " housing.index " ) , " Facultatif " , optional = True ) ,
] ) ,
( " ENTREPRISES " , [ _status ( contracts_without_due == 0 , " Contrats avec échéance " , url_for ( " companies.index " ) , f " { contracts_without_due } sans échéance " , attention = contracts_without_due > 0 ) ] ) ,
( " COMPTEURS " , [ _status ( False , " Compteurs " , url_for ( " meters.index " ) , " Non configuré " , optional = True ) ] ) ,
( " CARTOGRAPHIE TECHNIQUE " , [ _status ( False , " Relations techniques " , url_for ( " equipments.index " ) , " Facultatif " , optional = True ) ] ) ,
( " INTÉGRATIONS " , [
_status ( False , " Pronote " , url_for ( " pronote.index " ) , " Non configuré " , optional = True ) ,
_status ( False , " ENT / Outlook / Yeastar / IA " , url_for ( " admin.settings " ) , " Facultatif " , optional = True ) ,
] ) ,
]
return render_template ( " configuration/index.html " , sections = sections )