gmao/app_new/prevention/routes.py
root 0b3fff43e5
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
Complète le suivi opérationnel de la GMAO
2026-08-14 23:26:22 +00:00

89 lines
6.1 KiB
Python

from datetime import date, datetime, timedelta
from flask import Blueprint, flash, make_response, redirect, render_template, request, url_for
from flask_login import current_user, login_required
from sqlalchemy import func
from app_new.extensions import db
from app_new.core.models.user import Staff
from app_new.core.models.prevention import PreventionWorkLog, StaffAuthorization, RiskAssessment, PreventionAction, SafetyRegisterEntry
from app_new.core.services.planning_service import PlanningService
prevention_bp = Blueprint("prevention", __name__)
def _date(value): return datetime.strptime(value, "%Y-%m-%d").date() if value else None
@prevention_bp.route("/")
@login_required
def index():
monday = date.today() - timedelta(days=date.today().weekday())
minutes = db.session.query(func.coalesce(func.sum(PreventionWorkLog.duration_minutes), 0)).filter(PreventionWorkLog.user_id == current_user.id, PreventionWorkLog.work_date >= monday).scalar()
available_minutes = 0
for offset in range(7):
hours = PlanningService.get_working_hours(monday + timedelta(days=offset), current_user.id)
if hours:
available_minutes += int((datetime.combine(date.min, hours[1]) - datetime.combine(date.min, hours[0])).total_seconds() / 60)
if hours[2] and hours[3]:
available_minutes -= int((datetime.combine(date.min, hours[3]) - datetime.combine(date.min, hours[2])).total_seconds() / 60)
target = round(available_minutes * 0.10)
logs = PreventionWorkLog.query.filter_by(user_id=current_user.id).order_by(PreventionWorkLog.work_date.desc()).limit(20).all()
return render_template("prevention/index.html", staff=Staff.query.filter_by(is_active=True).order_by(Staff.last_name).all(), logs=logs, risks=RiskAssessment.query.filter_by(is_active=True).all(), actions=PreventionAction.query.order_by(PreventionAction.due_date).all(), entries=SafetyRegisterEntry.query.order_by(SafetyRegisterEntry.entry_date.desc()).limit(20).all(), minutes=minutes, target=target, available_minutes=available_minutes)
@prevention_bp.post("/staff")
@login_required
def add_staff():
db.session.add(Staff(first_name=request.form.get("first_name", "").strip(), last_name=request.form.get("last_name", "").strip(), function=request.form.get("function")))
db.session.commit(); flash("Agent ajouté.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.post("/time")
@login_required
def add_time():
db.session.add(PreventionWorkLog(user_id=current_user.id, work_date=_date(request.form.get("work_date")) or date.today(), duration_minutes=max(1, request.form.get("duration_minutes", type=int) or 1), activity=request.form.get("activity", "").strip(), notes=request.form.get("notes")))
db.session.commit(); flash("Temps de prévention enregistré.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.post("/authorization")
@login_required
def add_authorization():
db.session.add(StaffAuthorization(staff_id=request.form.get("staff_id", type=int), name=request.form.get("name", "").strip(), issued_on=_date(request.form.get("issued_on")), expires_on=_date(request.form.get("expires_on")), issuer=request.form.get("issuer")))
db.session.commit(); flash("Habilitation enregistrée.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.post("/risk")
@login_required
def add_risk():
severity = request.form.get("severity", type=int) or 1
probability = request.form.get("probability", type=int) or 1
work_unit = request.form.get("work_unit", "").strip()
hazard = request.form.get("hazard", "").strip()
if not work_unit or not hazard or severity not in range(1, 5) or probability not in range(1, 5):
flash("Unité, danger et cotations de 1 à 4 sont obligatoires.", "danger")
return redirect(url_for("prevention.index"))
db.session.add(RiskAssessment(work_unit=work_unit, hazard=hazard, exposed_people=request.form.get("exposed_people"), severity=severity, probability=probability, control_measures=request.form.get("control_measures"), reviewed_on=date.today()))
db.session.commit(); flash("Risque ajouté au DUERP.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.post("/action")
@login_required
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.commit(); flash("Action créée.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.post("/register")
@login_required
def add_register():
db.session.add(SafetyRegisterEntry(entry_date=_date(request.form.get("entry_date")) or date.today(), entry_type=request.form.get("entry_type", "observation"), title=request.form.get("title", "").strip(), details=request.form.get("details"), location=request.form.get("location"), created_by_id=current_user.id))
db.session.commit(); flash("Entrée ajoutée au registre.", "success"); return redirect(url_for("prevention.index"))
@prevention_bp.get('/duerp.csv')
@login_required
def export_duerp():
"""Exporte le registre DUERP exploitable dans un tableur."""
import csv
import io
output = io.StringIO()
writer = csv.writer(output, delimiter=';')
writer.writerow(['Unité de travail', 'Danger', 'Personnes exposées', 'Gravité', 'Probabilité', 'Criticité', 'Mesures existantes', 'Dernière revue'])
for risk in RiskAssessment.query.order_by(RiskAssessment.work_unit, RiskAssessment.hazard).all():
writer.writerow([risk.work_unit, risk.hazard, risk.exposed_people or '', risk.severity,
risk.probability, (risk.severity or 0) * (risk.probability or 0),
risk.control_measures or '', risk.reviewed_on.isoformat() if risk.reviewed_on else ''])
response = make_response('\ufeff' + output.getvalue())
response.headers['Content-Type'] = 'text/csv; charset=utf-8'
response.headers['Content-Disposition'] = 'attachment; filename=duerp.csv'
return response