281 lines
No EOL
10 KiB
Python
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} n°{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)
|
|
}) |