Séparer les workflows d'intervention et de prévention
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run

This commit is contained in:
root 2026-08-21 10:12:23 +00:00
parent fe7deff504
commit 701a765576
11 changed files with 96 additions and 8 deletions

View file

@ -116,6 +116,20 @@ WORK_TYPES = {
"curative": "Intervention curative", "curative": "Intervention curative",
} }
WORKFLOW_TYPES = {
"corrective": "Corrective",
"preventive": "Préventive",
"travaux": "Travaux",
"prevention": "Prévention",
}
WORKFLOW_STATUS_ORDERS = {
"corrective": ["brouillon", "en_attente", "planifiee", "en_cours", "en_attente_pieces", "en_attente_entreprise", "terminee", "cloturee"],
"preventive": ["brouillon", "planifiee", "en_cours", "en_attente_pieces", "en_attente_entreprise", "terminee", "cloturee"],
"travaux": ["brouillon", "attente_chef", "demande_departement", "attente_devis", "devis_a_valider", "devis_accepte", "entreprise_mandatee", "travaux_planifies", "travaux_en_cours", "travaux_termines", "reception", "cloturee"],
"prevention": ["brouillon", "en_attente", "planifiee", "en_cours", "terminee", "cloturee"],
}
# Rôles utilisateurs # Rôles utilisateurs
ROLES = { ROLES = {
"admin": "Administrateur", "admin": "Administrateur",

View file

@ -24,6 +24,7 @@ class Intervention(db.Model):
# Statut & Workflow # Statut & Workflow
status = db.Column(db.String(30), default="brouillon") status = db.Column(db.String(30), default="brouillon")
workflow_type = db.Column(db.String(20), nullable=False, default="corrective", index=True)
# Responsable actuel (qui doit agir maintenant) # Responsable actuel (qui doit agir maintenant)
assigned_to_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True) assigned_to_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True)
@ -173,6 +174,11 @@ class Intervention(db.Model):
} }
return colors.get(self.status, 'secondary') return colors.get(self.status, 'secondary')
@property
def workflow_label(self):
from app_new.constants import WORKFLOW_TYPES
return WORKFLOW_TYPES.get(self.workflow_type, self.workflow_type or 'Corrective')
@property @property
def status_label(self): def status_label(self):
"""Label du statut.""" """Label du statut."""

View file

@ -139,6 +139,7 @@ def create_intervention_from_task(id, task_id):
equipment_id=id, equipment_id=id,
room_id=request.form.get('room_id') or task.room_id, room_id=request.form.get('room_id') or task.room_id,
type='preventif', type='preventif',
workflow_type='preventive',
status='en_cours', status='en_cours',
scheduled_date=task.scheduled_date, scheduled_date=task.scheduled_date,
scheduled_start=request.form.get('scheduled_start') or task.scheduled_start.strftime('%H:%M') if task.scheduled_start else None, scheduled_start=request.form.get('scheduled_start') or task.scheduled_start.strftime('%H:%M') if task.scheduled_start else None,

View file

@ -22,7 +22,7 @@ from ..core.models.planning import ScheduledTask
from ..core.models.equipment import Equipment from ..core.models.equipment import Equipment
from ..core.models.college import Room from ..core.models.college import Room
from ..core.models.company import Service, Company from ..core.models.company import Service, Company
from app_new.constants import INTERVENTION_STATUSES, INTERVENTION_TRANSITIONS, PRIORITIES from app_new.constants import INTERVENTION_STATUSES, INTERVENTION_TRANSITIONS, PRIORITIES, WORKFLOW_TYPES, WORKFLOW_STATUS_ORDERS
interventions_bp = Blueprint('interventions', __name__) interventions_bp = Blueprint('interventions', __name__)
@ -35,6 +35,7 @@ def index():
status = request.args.get('status', '') status = request.args.get('status', '')
priority = request.args.get('priority', '') priority = request.args.get('priority', '')
intervention_type = request.args.get('type', '') intervention_type = request.args.get('type', '')
workflow_type = request.args.get('workflow_type', '')
lot_id = request.args.get('lot', type=int) lot_id = request.args.get('lot', type=int)
assigned_to_id = request.args.get('assigned_to_id', type=int) assigned_to_id = request.args.get('assigned_to_id', type=int)
frequency = request.args.get('frequency', '') frequency = request.args.get('frequency', '')
@ -57,6 +58,8 @@ def index():
query = query.filter_by(priority=priority) query = query.filter_by(priority=priority)
if intervention_type: if intervention_type:
query = query.filter(Intervention.type == intervention_type) query = query.filter(Intervention.type == intervention_type)
if workflow_type in WORKFLOW_TYPES:
query = query.filter_by(workflow_type=workflow_type)
if lot_id: if lot_id:
query = query.filter_by(lot_id=lot_id) query = query.filter_by(lot_id=lot_id)
if assigned_to_id: if assigned_to_id:
@ -106,6 +109,8 @@ def index():
lots=lots, lots=lots,
users=users, users=users,
statuses=INTERVENTION_STATUSES, statuses=INTERVENTION_STATUSES,
workflow_status_order=WORKFLOW_STATUS_ORDERS.get(intervention.workflow_type, WORKFLOW_STATUS_ORDERS['corrective']),
workflow_types=WORKFLOW_TYPES,
priorities=PRIORITIES, priorities=PRIORITIES,
status_counts=status_counts, status_counts=status_counts,
trashed_count=trashed_count, trashed_count=trashed_count,
@ -132,6 +137,11 @@ def create():
# Si pas de demandeur fourni, utiliser le nom de l'utilisateur connecté # Si pas de demandeur fourni, utiliser le nom de l'utilisateur connecté
requester_name = current_user.username if hasattr(current_user, 'username') else 'Inconnu' requester_name = current_user.username if hasattr(current_user, 'username') else 'Inconnu'
selected_type = request.form.get('intervention_type', 'curatif')
workflow_type = request.form.get('workflow_type') or {
'preventif': 'preventive', 'amelioratif': 'travaux',
'prevention': 'prevention', 'administratif': 'prevention',
}.get(selected_type, 'corrective')
intervention = Intervention( intervention = Intervention(
title=request.form.get('title'), title=request.form.get('title'),
description=request.form.get('description') or '', description=request.form.get('description') or '',
@ -142,7 +152,8 @@ def create():
author_id=current_user.id, author_id=current_user.id,
status=request.form.get('status', 'brouillon'), status=request.form.get('status', 'brouillon'),
priority=request.form.get('priority', 'normale'), priority=request.form.get('priority', 'normale'),
type=request.form.get('intervention_type', 'curatif'), type=selected_type,
workflow_type=workflow_type if workflow_type in WORKFLOW_TYPES else 'corrective',
notes=request.form.get('notes') or '', notes=request.form.get('notes') or '',
requester_name=requester_name, requester_name=requester_name,
scheduled_date=datetime.strptime(request.form.get('intervention_date'), '%Y-%m-%d').date() if request.form.get('intervention_date') else None, scheduled_date=datetime.strptime(request.form.get('intervention_date'), '%Y-%m-%d').date() if request.form.get('intervention_date') else None,
@ -211,6 +222,7 @@ def create():
'assignee': '', 'assignee': '',
'date': None, 'date': None,
'requester_name': '' 'requester_name': ''
, 'workflow_type': request.args.get('workflow', 'corrective')
} }
interpretation = None interpretation = None
@ -253,6 +265,7 @@ def create():
'information': 'curatif' 'information': 'curatif'
} }
prefilled['type'] = type_map.get(interpretation.analysis_type, 'curatif') prefilled['type'] = type_map.get(interpretation.analysis_type, 'curatif')
prefilled['workflow_type'] = 'preventive' if interpretation.analysis_type == 'preventive' else prefilled.get('workflow_type', 'corrective')
prefilled['equipment'] = interpretation.suggested_equipment or '' prefilled['equipment'] = interpretation.suggested_equipment or ''
else: else:
json_suggestions = { json_suggestions = {
@ -327,6 +340,7 @@ def create():
users=users, users=users,
statuses=INTERVENTION_STATUSES, statuses=INTERVENTION_STATUSES,
priorities=PRIORITIES, priorities=PRIORITIES,
workflow_types=WORKFLOW_TYPES,
prefilled=prefilled, prefilled=prefilled,
equipment_id=equipment_id, equipment_id=equipment_id,
equipment_match=equipment_match, equipment_match=equipment_match,
@ -453,6 +467,9 @@ def edit(id):
intervention.status = new_status intervention.status = new_status
intervention.priority = request.form.get('priority') intervention.priority = request.form.get('priority')
intervention.type = request.form.get('intervention_type', intervention.type) intervention.type = request.form.get('intervention_type', intervention.type)
workflow_type = request.form.get('workflow_type')
if workflow_type in WORKFLOW_TYPES:
intervention.workflow_type = workflow_type
intervention.scheduled_date = request.form.get('scheduled_date') or None intervention.scheduled_date = request.form.get('scheduled_date') or None
intervention.notes = request.form.get('notes') intervention.notes = request.form.get('notes')
intervention.requester_name = request.form.get('requester_name') or None intervention.requester_name = request.form.get('requester_name') or None
@ -487,6 +504,7 @@ def edit(id):
'assignee': intervention.assigned_to.username if intervention.assigned_to else '', 'assignee': intervention.assigned_to.username if intervention.assigned_to else '',
'date': intervention.scheduled_date, 'date': intervention.scheduled_date,
'requester_name': intervention.requester_name or '' 'requester_name': intervention.requester_name or ''
, 'workflow_type': intervention.workflow_type
} }
return render_template('interventions/new.html', return render_template('interventions/new.html',
@ -497,6 +515,7 @@ def edit(id):
users=users, users=users,
statuses=INTERVENTION_STATUSES, statuses=INTERVENTION_STATUSES,
priorities=PRIORITIES, priorities=PRIORITIES,
workflow_types=WORKFLOW_TYPES,
prefilled=prefilled, prefilled=prefilled,
title="Modifier l'intervention") title="Modifier l'intervention")

View file

@ -61,7 +61,8 @@
<button class="btn btn-outline-primary btn-sm" type="submit"><i class="bi bi-arrow-repeat"></i> Appliquer</button> <button class="btn btn-outline-primary btn-sm" type="submit"><i class="bi bi-arrow-repeat"></i> Appliquer</button>
</form> </form>
<div class="d-flex flex-wrap align-items-center gap-1" style="font-size:0.75rem;"> <div class="d-flex flex-wrap align-items-center gap-1" style="font-size:0.75rem;">
{% set workflow_order = ['brouillon', 'attente_chef', 'demande_departement', 'attente_devis', 'devis_a_valider', 'devis_accepte', 'entreprise_mandatee', 'travaux_planifies', 'travaux_en_cours', 'travaux_termines', 'reception', 'cloturee'] if intervention.execution_mode != 'interne' else ['brouillon', 'attente_chef', 'en_cours', 'en_attente_pieces', 'en_attente_entreprise', 'terminee', 'cloturee'] %} {% set workflow_order = workflow_status_order %}
<div class="mb-2"><span class="badge bg-secondary">Workflow {{ intervention.workflow_label }}</span></div>
{% for step in workflow_order %} {% for step in workflow_order %}
{% if step in statuses %} {% if step in statuses %}
{% set is_current = (step == intervention.status) %} {% set is_current = (step == intervention.status) %}

View file

@ -55,6 +55,12 @@
</button> </button>
</div> </div>
<form method="GET" class="row g-2 align-items-end collapse d-md-flex" id="filterCollapse"> <form method="GET" class="row g-2 align-items-end collapse d-md-flex" id="filterCollapse">
<div class="col-6 col-md-2">
<select name="workflow_type" class="form-select form-select-sm">
<option value="">— Workflow —</option>
{% for key, label in workflow_types.items() %}<option value="{{ key }}" {{ 'selected' if request.args.get('workflow_type') == key }}>{{ label }}</option>{% endfor %}
</select>
</div>
<div class="col-6 col-md-2"> <div class="col-6 col-md-2">
<select name="type" class="form-select form-select-sm"> <select name="type" class="form-select form-select-sm">
<option value="">— Type —</option> <option value="">— Type —</option>
@ -107,6 +113,7 @@
<div class="d-flex align-items-center gap-1 mb-1 flex-wrap" style="font-size:0.8rem;"> <div class="d-flex align-items-center gap-1 mb-1 flex-wrap" style="font-size:0.8rem;">
<span class="badge bg-{{ interv.status_color }}">{{ interv.status_label }}</span> <span class="badge bg-{{ interv.status_color }}">{{ interv.status_label }}</span>
<span class="badge bg-{{ interv.priority_color }}">{{ interv.priority_label }}</span> <span class="badge bg-{{ interv.priority_color }}">{{ interv.priority_label }}</span>
<span class="badge bg-secondary">{{ interv.workflow_label }}</span>
{% if interv.type == 'curatif' %} {% if interv.type == 'curatif' %}
<span class="badge bg-danger">Curatif</span> <span class="badge bg-danger">Curatif</span>
{% else %} {% else %}
@ -124,7 +131,7 @@
</div> </div>
<div class="fw-bold text-dark">#{{ interv.id }} — {{ interv.title[:80] }}{% if interv.title|length > 80 %}…{% endif %}</div> <div class="fw-bold text-dark">#{{ interv.id }} — {{ interv.title[:80] }}{% if interv.title|length > 80 %}…{% endif %}</div>
<div class="text-muted" style="font-size:0.8rem;"> <div class="text-muted" style="font-size:0.8rem;">
<i class="bi bi-hdd"></i> {{ interv.equipment.name[:40] }}{% if interv.equipment.name|length > 40 %}…{% endif %} <i class="bi bi-hdd"></i> {{ interv.equipment.name[:40] if interv.equipment else (interv.room.name if interv.room else 'Localisation générale') }}{% if interv.equipment and interv.equipment.name|length > 40 %}…{% endif %}
{% if interv.assigned_to %} {% if interv.assigned_to %}
· <i class="bi bi-person-badge"></i> {{ interv.assigned_to.full_name }} · <i class="bi bi-person-badge"></i> {{ interv.assigned_to.full_name }}
{% endif %} {% endif %}

View file

@ -71,6 +71,15 @@
<small class="text-success"><i class="bi bi-lightbulb"></i> Suggestion: {{ json_suggestions.type }}</small> <small class="text-success"><i class="bi bi-lightbulb"></i> Suggestion: {{ json_suggestions.type }}</small>
{% endif %} {% endif %}
</div> </div>
<div class="col-md-6">
<label class="form-label">Parcours de workflow</label>
<select name="workflow_type" class="form-select">
{% for key, label in workflow_types.items() %}
<option value="{{ key }}" {% if (intervention.workflow_type if intervention is defined else (prefilled.workflow_type if prefilled is defined else 'corrective')) == key %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
<small class="text-muted">Le parcours détermine les étapes affichées dans la fiche.</small>
</div>
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label">Lot</label> <label class="form-label">Lot</label>
<select name="lot_id" class="form-select"> <select name="lot_id" class="form-select">

View file

@ -169,6 +169,7 @@ def create_interventions_for_day(date):
estimated_duration=task.estimated_duration or 30, estimated_duration=task.estimated_duration or 30,
status='en_attente', status='en_attente',
type='preventif', type='preventif',
workflow_type='preventive',
assigned_to_id=task.assigned_to_id, assigned_to_id=task.assigned_to_id,
company_id=task.company_id, company_id=task.company_id,
author_id=current_user.id, author_id=current_user.id,

View file

@ -63,6 +63,20 @@ def add_action():
db.session.add(PreventionAction(title=request.form.get("title", "").strip(), source_type=request.form.get("source_type", "observation"), risk_id=request.form.get("risk_id", type=int), priority=request.form.get("priority", "normale"), owner=request.form.get("owner"), due_date=_date(request.form.get("due_date")))) db.session.add(PreventionAction(title=request.form.get("title", "").strip(), source_type=request.form.get("source_type", "observation"), risk_id=request.form.get("risk_id", type=int), priority=request.form.get("priority", "normale"), owner=request.form.get("owner"), due_date=_date(request.form.get("due_date"))))
db.session.commit(); flash("Action créée.", "success"); return redirect(url_for("prevention.index")) db.session.commit(); flash("Action créée.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.post("/action/<int:id>/status")
@login_required
def update_action_status(id):
action = PreventionAction.query.get_or_404(id)
allowed = {"a_faire", "validee", "planifiee", "en_cours", "verifiee", "cloturee", "refusee"}
status = request.form.get("status")
if status not in allowed:
flash("Statut de prévention invalide.", "danger")
else:
action.status = status
db.session.commit()
flash("Action de prévention mise à jour.", "success")
return redirect(url_for("prevention.index"))
@prevention_bp.post("/register") @prevention_bp.post("/register")
@login_required @login_required
def add_register(): def add_register():

View file

@ -4,6 +4,6 @@
<div class="col-lg-6"><div class="card"><div class="card-header">Temps de prévention</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_time') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col-4"><input type="date" name="work_date" class="form-control" required></div><div class="col-3"><input type="number" min="1" name="duration_minutes" class="form-control" placeholder="Minutes" required></div><div class="col"><input name="activity" class="form-control" placeholder="Activité" required></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in logs %}<tr><td>{{ x.work_date|date_fmt }}</td><td>{{ x.activity }}</td><td>{{ x.duration_minutes }} min</td></tr>{% endfor %}</tbody></table></div></div></div> <div class="col-lg-6"><div class="card"><div class="card-header">Temps de prévention</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_time') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col-4"><input type="date" name="work_date" class="form-control" required></div><div class="col-3"><input type="number" min="1" name="duration_minutes" class="form-control" placeholder="Minutes" required></div><div class="col"><input name="activity" class="form-control" placeholder="Activité" required></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in logs %}<tr><td>{{ x.work_date|date_fmt }}</td><td>{{ x.activity }}</td><td>{{ x.duration_minutes }} min</td></tr>{% endfor %}</tbody></table></div></div></div>
<div class="col-lg-6"><div class="card"><div class="card-header">Agents et habilitations ({{ staff|length }})</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_staff') }}" class="row g-2 mb-3"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col"><input name="first_name" class="form-control" placeholder="Prénom" required></div><div class="col"><input name="last_name" class="form-control" placeholder="Nom" required></div><div class="col"><input name="function" class="form-control" placeholder="Fonction"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><form method="post" action="{{ url_for('prevention.add_authorization') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col"><select name="staff_id" class="form-select" required><option value="">Agent…</option>{% for x in staff %}<option value="{{ x.id }}">{{ x.full_name }}</option>{% endfor %}</select></div><div class="col"><input name="name" class="form-control" placeholder="Habilitation / formation" required></div><div class="col"><input type="date" name="expires_on" class="form-control"></div><div class="col-auto"><button class="btn btn-outline-primary">Ajouter</button></div></form></div></div></div> <div class="col-lg-6"><div class="card"><div class="card-header">Agents et habilitations ({{ staff|length }})</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_staff') }}" class="row g-2 mb-3"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col"><input name="first_name" class="form-control" placeholder="Prénom" required></div><div class="col"><input name="last_name" class="form-control" placeholder="Nom" required></div><div class="col"><input name="function" class="form-control" placeholder="Fonction"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><form method="post" action="{{ url_for('prevention.add_authorization') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col"><select name="staff_id" class="form-select" required><option value="">Agent…</option>{% for x in staff %}<option value="{{ x.id }}">{{ x.full_name }}</option>{% endfor %}</select></div><div class="col"><input name="name" class="form-control" placeholder="Habilitation / formation" required></div><div class="col"><input type="date" name="expires_on" class="form-control"></div><div class="col-auto"><button class="btn btn-outline-primary">Ajouter</button></div></form></div></div></div>
<div class="col-lg-6"><div class="card"><div class="card-header">DUERP — risques</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_risk') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col-5"><input name="work_unit" class="form-control" placeholder="Unité de travail" required></div><div class="col-7"><input name="hazard" class="form-control" placeholder="Danger / situation" required></div><div class="col-3"><input type="number" min="1" max="4" name="severity" class="form-control" placeholder="Gravité"></div><div class="col-3"><input type="number" min="1" max="4" name="probability" class="form-control" placeholder="Probabilité"></div><div class="col"><input name="control_measures" class="form-control" placeholder="Mesures existantes"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in risks %}<tr><td>{{ x.work_unit }}</td><td>{{ x.hazard }}</td><td><span class="badge text-bg-{{ 'danger' if x.score >= 9 else 'warning' if x.score >= 4 else 'success' }}">{{ x.score }}</span></td></tr>{% endfor %}</tbody></table></div></div></div> <div class="col-lg-6"><div class="card"><div class="card-header">DUERP — risques</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_risk') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col-5"><input name="work_unit" class="form-control" placeholder="Unité de travail" required></div><div class="col-7"><input name="hazard" class="form-control" placeholder="Danger / situation" required></div><div class="col-3"><input type="number" min="1" max="4" name="severity" class="form-control" placeholder="Gravité"></div><div class="col-3"><input type="number" min="1" max="4" name="probability" class="form-control" placeholder="Probabilité"></div><div class="col"><input name="control_measures" class="form-control" placeholder="Mesures existantes"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in risks %}<tr><td>{{ x.work_unit }}</td><td>{{ x.hazard }}</td><td><span class="badge text-bg-{{ 'danger' if x.score >= 9 else 'warning' if x.score >= 4 else 'success' }}">{{ x.score }}</span></td></tr>{% endfor %}</tbody></table></div></div></div>
<div class="col-lg-6"><div class="card"><div class="card-header">Plan dactions</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_action') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col"><input name="title" class="form-control" placeholder="Action" required></div><div class="col-3"><input name="owner" class="form-control" placeholder="Pilote"></div><div class="col-3"><input type="date" name="due_date" class="form-control"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in actions %}<tr><td>{{ x.title }}</td><td>{{ x.owner or '—' }}</td><td>{{ x.due_date|date_fmt }}</td><td>{{ x.status }}</td></tr>{% endfor %}</tbody></table></div></div></div> <div class="col-lg-6"><div class="card"><div class="card-header">Plan dactions</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_action') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col"><input name="title" class="form-control" placeholder="Action" required></div><div class="col-3"><input name="owner" class="form-control" placeholder="Pilote"></div><div class="col-3"><input type="date" name="due_date" class="form-control"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in actions %}<tr><td>{{ x.title }}</td><td>{{ x.owner or '—' }}</td><td>{{ x.due_date|date_fmt }}</td><td><form method="post" action="{{ url_for('prevention.update_action_status', id=x.id) }}" class="d-flex gap-1"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><select name="status" class="form-select form-select-sm"><option value="a_faire" {% if x.status == 'a_faire' %}selected{% endif %}>À faire</option><option value="validee" {% if x.status == 'validee' %}selected{% endif %}>Validée</option><option value="planifiee" {% if x.status == 'planifiee' %}selected{% endif %}>Planifiée</option><option value="en_cours" {% if x.status == 'en_cours' %}selected{% endif %}>En cours</option><option value="verifiee" {% if x.status == 'verifiee' %}selected{% endif %}>Vérifiée</option><option value="cloturee" {% if x.status == 'cloturee' %}selected{% endif %}>Clôturée</option><option value="refusee" {% if x.status == 'refusee' %}selected{% endif %}>Refusée</option></select><button class="btn btn-sm btn-outline-secondary">OK</button></form></td></tr>{% endfor %}</tbody></table></div></div></div>
<div class="col-12"><div class="card"><div class="card-header">Registre sécurité / incidents / exercices</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_register') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col-2"><input type="date" name="entry_date" class="form-control" required></div><div class="col-2"><select name="entry_type" class="form-select"><option>observation</option><option>incident</option><option>presque_accident</option><option>exercice</option><option>verification</option></select></div><div class="col"><input name="title" class="form-control" placeholder="Objet" required></div><div class="col"><input name="location" class="form-control" placeholder="Lieu"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in entries %}<tr><td>{{ x.entry_date|date_fmt }}</td><td>{{ x.entry_type }}</td><td>{{ x.title }}</td><td>{{ x.location }}</td></tr>{% endfor %}</tbody></table></div></div></div> <div class="col-12"><div class="card"><div class="card-header">Registre sécurité / incidents / exercices</div><div class="card-body"><form method="post" action="{{ url_for('prevention.add_register') }}" class="row g-2"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><div class="col-2"><input type="date" name="entry_date" class="form-control" required></div><div class="col-2"><select name="entry_type" class="form-select"><option>observation</option><option>incident</option><option>presque_accident</option><option>exercice</option><option>verification</option></select></div><div class="col"><input name="title" class="form-control" placeholder="Objet" required></div><div class="col"><input name="location" class="form-control" placeholder="Lieu"></div><div class="col-auto"><button class="btn btn-primary">Ajouter</button></div></form><table class="table table-sm mt-3"><tbody>{% for x in entries %}<tr><td>{{ x.entry_date|date_fmt }}</td><td>{{ x.entry_type }}</td><td>{{ x.title }}</td><td>{{ x.location }}</td></tr>{% endfor %}</tbody></table></div></div></div>
</div>{% endblock %} </div>{% endblock %}

View file

@ -0,0 +1,16 @@
"""Ajoute l'origine fonctionnelle des interventions."""
from alembic import op
import sqlalchemy as sa
revision = "ff6a7b8c9d0e"
down_revision = "fe5f6a7b8c9d"
branch_labels = None
depends_on = None
def upgrade():
op.add_column("interventions", sa.Column("workflow_type", sa.String(20), nullable=False, server_default="corrective"))
op.create_index("ix_interventions_workflow_type", "interventions", ["workflow_type"])
def downgrade():
op.drop_index("ix_interventions_workflow_type", table_name="interventions")
op.drop_column("interventions", "workflow_type")