2026-08-14 18:02:25 +02:00
|
|
|
"""
|
|
|
|
|
Formulaires WTForms pour la GMAO
|
|
|
|
|
"""
|
|
|
|
|
from flask_wtf import FlaskForm
|
|
|
|
|
from wtforms import (StringField, TextAreaField, SelectField, IntegerField,
|
|
|
|
|
FloatField, DateField, BooleanField, PasswordField,
|
|
|
|
|
FieldList, FormField)
|
|
|
|
|
from wtforms.validators import (DataRequired, Optional, Email, Length,
|
|
|
|
|
NumberRange, ValidationError)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def coerce_int_or_none(value):
|
|
|
|
|
"""Convertit en int ou retourne None pour les chaînes vides."""
|
|
|
|
|
if value is None or value == '' or value == 'None':
|
|
|
|
|
return None
|
|
|
|
|
try:
|
|
|
|
|
return int(value)
|
|
|
|
|
except (ValueError, TypeError):
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Authentification ──────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class LoginForm(FlaskForm):
|
|
|
|
|
username = StringField("Nom d'utilisateur", validators=[DataRequired()])
|
|
|
|
|
password = PasswordField("Mot de passe", validators=[DataRequired()])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UserForm(FlaskForm):
|
|
|
|
|
username = StringField("Nom d'utilisateur", validators=[DataRequired(), Length(3, 80)])
|
|
|
|
|
email = StringField("Email", validators=[DataRequired(), Email()])
|
|
|
|
|
full_name = StringField("Nom complet", validators=[DataRequired()])
|
|
|
|
|
password = PasswordField("Mot de passe", validators=[Optional(), Length(min=12)])
|
|
|
|
|
role = SelectField("Rôle", choices=[
|
|
|
|
|
("admin", "Administrateur"),
|
2026-08-14 20:53:03 +02:00
|
|
|
("responsable_gmao", "Responsable GMAO"),
|
|
|
|
|
("technicien", "Technicien"),
|
|
|
|
|
("assistant_prevention", "Assistant de prévention"),
|
|
|
|
|
("demandeur", "Demandeur"),
|
|
|
|
|
("lecture", "Lecture seule"),
|
2026-08-14 18:02:25 +02:00
|
|
|
])
|
|
|
|
|
is_active = BooleanField("Actif")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PasswordForm(FlaskForm):
|
|
|
|
|
current_password = PasswordField("Mot de passe actuel", validators=[DataRequired()])
|
|
|
|
|
new_password = PasswordField("Nouveau mot de passe", validators=[
|
|
|
|
|
DataRequired(), Length(min=12, message="Le mot de passe doit contenir au moins 12 caractères")
|
|
|
|
|
])
|
|
|
|
|
confirm_password = PasswordField("Confirmer le nouveau mot de passe", validators=[
|
|
|
|
|
DataRequired()
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
def validate_confirm_password(form, field):
|
|
|
|
|
if field.data != form.new_password.data:
|
|
|
|
|
raise ValidationError("Les mots de passe ne correspondent pas")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Bâtiments & Salles ────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class BuildingForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom du bâtiment", validators=[DataRequired()])
|
|
|
|
|
description = TextAreaField("Description")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RoomForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom de la salle", validators=[DataRequired()])
|
|
|
|
|
code = StringField("Code", validators=[Optional()])
|
|
|
|
|
floor = IntegerField("Étage", validators=[Optional()], default=0)
|
|
|
|
|
building_id = SelectField("Bâtiment", coerce=int, validators=[DataRequired()])
|
|
|
|
|
room_type_id = SelectField("Type de salle", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RoomTypeForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom du type", validators=[DataRequired()])
|
|
|
|
|
description = TextAreaField("Description")
|
|
|
|
|
is_teaching = BooleanField("Type enseignement (avec planning)", default=False)
|
|
|
|
|
color = SelectField("Couleur", choices=[
|
|
|
|
|
("primary", "Bleu"),
|
|
|
|
|
("secondary", "Gris"),
|
|
|
|
|
("success", "Vert"),
|
|
|
|
|
("danger", "Rouge"),
|
|
|
|
|
("warning", "Orange"),
|
|
|
|
|
("info", "Cyan"),
|
|
|
|
|
("dark", "Noir"),
|
|
|
|
|
], default="primary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Équipements ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class EquipmentCategoryForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom de la catégorie", validators=[DataRequired()])
|
|
|
|
|
description = TextAreaField("Description")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EquipmentForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom de l'équipement", validators=[DataRequired()])
|
|
|
|
|
code = StringField("Code interne", validators=[Optional()])
|
|
|
|
|
description = TextAreaField("Description")
|
|
|
|
|
status = SelectField("Statut", choices=[
|
|
|
|
|
("en_service", "En service"),
|
|
|
|
|
("hors_service", "Hors service"),
|
|
|
|
|
("en_reparation", "En réparation"),
|
|
|
|
|
("remplace", "Remplacé"),
|
|
|
|
|
])
|
|
|
|
|
location = StringField("Emplacement", validators=[Optional()])
|
|
|
|
|
room_id = SelectField("Salle", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
category_id = SelectField("Catégorie", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Interventions ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class InterventionForm(FlaskForm):
|
|
|
|
|
title = StringField("Titre", validators=[DataRequired()])
|
|
|
|
|
description = TextAreaField("Description")
|
|
|
|
|
intervention_type = SelectField("Type", choices=[
|
|
|
|
|
("curatif", "Curatif"),
|
|
|
|
|
("preventif", "Préventif"),
|
|
|
|
|
("amelioratif", "Amélioratif"),
|
|
|
|
|
("administratif", "Administratif"),
|
|
|
|
|
("formation", "Formation"),
|
|
|
|
|
])
|
|
|
|
|
priority = SelectField("Priorité", choices=[
|
|
|
|
|
("basse", "Basse"),
|
|
|
|
|
("normale", "Normale"),
|
|
|
|
|
("haute", "Haute"),
|
|
|
|
|
("urgente", "Urgente"),
|
|
|
|
|
])
|
|
|
|
|
status = SelectField("Statut", choices=[
|
|
|
|
|
("en_attente", "En attente"),
|
|
|
|
|
("en_cours", "En cours"),
|
|
|
|
|
("terminee", "Terminée"),
|
|
|
|
|
("annulee", "Annulée"),
|
|
|
|
|
])
|
|
|
|
|
lot_id = SelectField("Lot", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
equipment_id = SelectField("Équipement", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
room_id = SelectField("Salle", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
assigned_to = SelectField("Technicien assigné", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
scheduled_date = DateField("Date prévue", validators=[Optional()])
|
|
|
|
|
estimated_duration = FloatField("Durée estimée (heures)", validators=[Optional()])
|
|
|
|
|
requester_name = StringField("Demandeur", validators=[Optional()])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Lots ────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class LotForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom du lot", validators=[DataRequired()])
|
|
|
|
|
description = TextAreaField("Description")
|
|
|
|
|
category = StringField("Catégorie", validators=[Optional()])
|
|
|
|
|
company_id = SelectField("Entreprise", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
service_id = SelectField("Service", coerce=coerce_int_or_none, validators=[Optional()])
|
|
|
|
|
is_active = BooleanField("Actif", default=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Entreprises ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class CompanyForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom de l'entreprise", validators=[DataRequired()])
|
|
|
|
|
contact_name = StringField("Nom du contact", validators=[Optional()])
|
|
|
|
|
contact_email = StringField("Email du contact", validators=[Optional(), Email()])
|
|
|
|
|
contact_phone = StringField("Téléphone du contact", validators=[Optional()])
|
|
|
|
|
address = TextAreaField("Adresse")
|
|
|
|
|
is_active = BooleanField("Active", default=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ─── Collège ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
class CollegeForm(FlaskForm):
|
|
|
|
|
name = StringField("Nom du collège", validators=[DataRequired()])
|
|
|
|
|
code = StringField("Code UAI", validators=[Optional()])
|
|
|
|
|
address = StringField("Adresse", validators=[Optional()])
|
|
|
|
|
city = StringField("Ville", validators=[Optional()])
|
|
|
|
|
postal_code = StringField("Code postal", validators=[Optional()])
|
|
|
|
|
phone = StringField("Téléphone", validators=[Optional()])
|
|
|
|
|
email = StringField("Email", validators=[Optional(), Email()])
|
|
|
|
|
principal_name = StringField("Nom du principal", validators=[Optional()])
|