gmao/app_new/wizard/routes.py
2026-08-14 16:02:25 +00:00

281 lines
No EOL
10 KiB
Python

"""
Wizard de création d'équipements par lot - GMAO Collège
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_login import login_required
from app_new.extensions import db
from app_new.core.models.equipment import Equipment, EquipmentCategory
from app_new.core.models.maintenance import Lot
from app_new.core.models.college import Room, Building, Zone, RoomType
wizard_bp = Blueprint('wizard', __name__, url_prefix='/wizard', template_folder='templates')
@wizard_bp.route('/equipments')
@login_required
def equipment_wizard():
"""Page principale du wizard de création d'équipements."""
categories = EquipmentCategory.query.order_by(EquipmentCategory.name).all()
buildings = Building.query.order_by(Building.name).all()
room_types = RoomType.query.order_by(RoomType.name).all()
# Récupérer les lots groupés par catégorie (relation directe)
lots_by_category = {}
for cat in categories:
lots_by_category[cat.id] = [{'id': lot.id, 'name': lot.name} for lot in cat.lots]
# Tous les lots pour fallback
lots = Lot.query.order_by(Lot.name).all()
return render_template('wizard/equipment_wizard.html',
lots=lots,
categories=categories,
buildings=buildings,
room_types=room_types,
lots_by_category=lots_by_category)
@wizard_bp.route('/api/rooms/<int:building_id>')
@login_required
def get_rooms(building_id):
"""Récupère les salles d'un bâtiment."""
rooms = Room.query.filter_by(building_id=building_id).order_by(Room.name).all()
return jsonify([{
'id': r.id,
'name': r.name,
'zone': r.zone.name if r.zone else None
} for r in rooms])
@wizard_bp.route('/api/zones/<int:building_id>')
@login_required
def get_zones(building_id):
"""Récupère les zones d'un bâtiment."""
zones = Zone.query.filter_by(building_id=building_id).order_by(Zone.name).all()
return jsonify([{
'id': z.id,
'name': z.name
} for z in zones])
@wizard_bp.route('/api/lot_tasks/<int:lot_id>')
@login_required
def get_lot_tasks(lot_id):
"""Récupère les tâches préventives d'un lot."""
from app_new.core.models.maintenance import LotTask
tasks = LotTask.query.filter_by(lot_id=lot_id).order_by(LotTask.num_tache).all()
return jsonify([{
'id': t.id,
'num_tache': t.num_tache,
'tache': t.tache,
'periodicite': t.periodicite,
'contrat': t.contrat,
'gestionnaire': t.gestionnaire,
'type_maintenance': t.type_maintenance
} for t in tasks])
@wizard_bp.route('/equipments/create', methods=['POST'])
@login_required
def create_equipments():
"""Crée les équipements selon les paramètres du wizard."""
try:
data = request.get_json()
lot_id = data.get('lot_id')
category_id = data.get('category_id')
equipment_name = data.get('name', '').strip() # Nom personnalisé
parent_name = data.get('parent_name')
create_parent = data.get('create_parent', False)
building_id = data.get('building_id')
zone_id = data.get('zone_id')
rooms_data = data.get('rooms', []) # [{room_id, count}, ...]
tracked_individually = data.get('tracked_individually', False)
# Debug
current_app.logger.info(f"Création équipements: tracked_individually={tracked_individually}, rooms={rooms_data}")
if not lot_id or not category_id:
return jsonify({'error': 'Lot et catégorie requis'}), 400
if not rooms_data:
return jsonify({'error': 'Au moins une salle requise'}), 400
lot = Lot.query.get(lot_id)
category = EquipmentCategory.query.get(category_id)
# Nom de base: personnalisé ou catégorie
base_name = equipment_name if equipment_name else category.name
created_equipments = []
# Étape 1: Créer le parent global (si demandé)
parent = None
if create_parent and parent_name:
parent = Equipment(
name=parent_name,
lot_id=lot_id,
category_id=category_id,
is_group=True,
parent_id=None
)
db.session.add(parent)
db.session.flush() # Pour avoir l'ID
# Étape 2: Pour chaque salle, créer le groupe et les individuels
for room_data in rooms_data:
room_id = room_data.get('room_id')
count = room_data.get('count', 1)
room = Room.query.get(room_id)
if not room:
continue
if tracked_individually:
# Avec suivi individuel: créer un groupe + des individus
room_group = Equipment(
name=f"{base_name} {room.name}",
lot_id=lot_id if not parent else None,
category_id=category_id if not parent else None,
is_group=True,
parent_id=parent.id if parent else None,
room_id=room_id,
quantity=1
)
db.session.add(room_group)
db.session.flush()
created_equipments.append({
'type': 'group',
'name': room_group.name,
'room': room.name,
'quantity': 1
})
# Créer les équipements individuels
if count > 1:
for i in range(1, count + 1):
individual = Equipment(
name=f"{base_name} {i}",
lot_id=lot_id, # Hériter du lot
category_id=category_id, # Hériter de la catégorie
is_group=False,
tracked_individually=True,
parent_id=room_group.id,
room_id=room_id,
position=f"{base_name}{i}"
)
db.session.add(individual)
created_equipments.append({
'type': 'individual',
'name': individual.name,
'room': room.name
})
else:
# Sans suivi individuel: créer un seul équipement avec quantity
equipment = Equipment(
name=f"{base_name} {room.name}",
lot_id=lot_id if not parent else None,
category_id=category_id if not parent else None,
is_group=False,
parent_id=parent.id if parent else None,
room_id=room_id,
quantity=count
)
db.session.add(equipment)
db.session.flush()
created_equipments.append({
'type': 'equipment',
'name': equipment.name,
'room': room.name,
'quantity': count
})
db.session.commit()
# Créer les tâches planifiées pour tous les équipements créés
for eq in created_equipments:
# Récupérer l'équipement depuis la DB pour avoir son ID
equipment = Equipment.query.filter_by(name=eq['name']).first()
if equipment and equipment.effective_lot_id:
equipment.create_scheduled_tasks_from_lot()
return jsonify({
'success': True,
'count': len(created_equipments),
'equipments': created_equipments
})
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500
@wizard_bp.route('/equipments/preview', methods=['POST'])
@login_required
def preview_equipments():
"""Prévisualise les équipements qui seront créés."""
data = request.get_json()
lot_id = data.get('lot_id')
category_id = data.get('category_id')
parent_name = data.get('parent_name')
create_parent = data.get('create_parent', False)
rooms_data = data.get('rooms', [])
tracked_individually = data.get('tracked_individually', False)
lot = Lot.query.get(lot_id) if lot_id else None
category = EquipmentCategory.query.get(category_id) if category_id else None
preview = []
# Parent global
if create_parent and parent_name:
preview.append({
'level': 0,
'name': parent_name,
'type': 'Groupe parent',
'lot': lot.name if lot else '-',
'category': category.name if category else '-',
'room': '-'
})
# Par salle
for room_data in rooms_data:
room_id = room_data.get('room_id')
count = room_data.get('count', 1)
room = Room.query.get(room_id)
if not room:
continue
# Groupe salle
level = 1 if create_parent else 0
preview.append({
'level': level,
'name': f"{category.name} {room.name}",
'type': 'Groupe salle',
'lot': lot.name if lot else '-',
'category': category.name if category else '-',
'room': room.name
})
# Individuels
if tracked_individually:
for i in range(1, count + 1):
preview.append({
'level': level + 1,
'name': f"{category.name} {i}",
'type': 'Individuel',
'lot': '(hérité)',
'category': '(hérité)',
'room': room.name
})
return jsonify({
'preview': preview,
'total': len(preview)
})