From 205a05cb5b8667b88de1cb0cd5b3a66b0207f501 Mon Sep 17 00:00:00 2001 From: kdeterme Date: Fri, 25 Sep 2026 23:20:09 +0200 Subject: [PATCH] feat(interventions): aligner les permissions des notes par statut et historiser le mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Autoriser les modifications/suppressions de notes jusqu'au statut 'traité' pour les externes - Autoriser les modifications/suppressions de notes jusqu'au statut 'validé' pour les internes - Supprimer la contrainte horaire de 1h sur la modification des notes - Brancher l'historisation de la chronologie sur la création et modification de notes mobile - Tracer l'upload des photos de formulaires mobiles dans la chronologie - Ajouter les tests unitaires et d'intégration correspondants --- loko/interventions/permissions.py | 51 +++-- .../interventions/detail/card_notes.html | 6 +- .../detail/card_notes_documents.html | 6 +- .../intervention_detail_mobile.html | 2 +- .../tests/test_timeline_history.py | 187 ++++++++++++++++++ loko/interventions/views/mobile.py | 68 +++++-- 6 files changed, 282 insertions(+), 38 deletions(-) diff --git a/loko/interventions/permissions.py b/loko/interventions/permissions.py index 2ca7b03..7b83232 100644 --- a/loko/interventions/permissions.py +++ b/loko/interventions/permissions.py @@ -1471,10 +1471,14 @@ def get_allowed_transitions(request, intervention): def can_edit_note(user, user_config, note): """ - Règle: - - Admin: peut tout modifier. - - Thématique 'structures': l'auteur OU rôle manager/external_manager (pas de contrainte horaire). - - Sinon: uniquement l'auteur ET la note a été créée il y a < 1h. + Règles de modification et suppression d'une note : + - Admin : peut tout modifier et supprimer sans restriction. + - Externes (non is_intern) : + * Autorisés jusqu'au statut 'traité' (status_order <= STATUS_ORDERS['processed'], soit <= 31). + * Auteur de la note OU rôle 'external_manager' (hors notes rédigées par des internes). + - Internes (is_intern) : + * Autorisés jusqu'au statut 'validé' (status_order <= STATUS_ORDERS['validated'], soit <= 51). + * Auteur de la note OU rôle 'manager'. """ if not user.is_authenticated or user_config is None: return False @@ -1483,29 +1487,42 @@ def can_edit_note(user, user_config, note): if user_config.roles.filter(name='admin').exists(): return True - # 2) Thématique 'structures' intervention = getattr(note, 'intervention', None) - thematic_code = getattr(getattr(intervention, 'thematic', None), 'code', None) - if thematic_code == 'structures': - # Auteur OU rôle manager/external_manager + if intervention is None: + return False + + status_order = getattr(intervention, 'status_order', None) + if status_order is None: + status_order = STATUS_ORDERS.get(intervention.status, 0) + + # 2) Utilisateurs internes (commune / régie / gestionnaires) + if user_config.is_intern: + # Autorisé jusqu'au statut 'validé' (inclus) + if status_order > STATUS_ORDERS.get('validated', 51): + return False + # Auteur OU rôle manager if note.note_author_id == user.id: return True - if user_config.roles.filter(name__in=['manager', 'external_manager']).exists(): + if user_config.roles.filter(name='manager').exists(): return True return False - # 3) Auteur + moins d'une heure (autres thématiques) - if note.note_author_id != user.id: + # 3) Utilisateurs externes (prestataires / soumissionnaires) + # Autorisé jusqu'au statut 'traité' (inclus) + if status_order > STATUS_ORDERS.get('processed', 31): return False - created_at = getattr(note, 'note_time', None) or getattr(note, 'created_at', None) - if created_at is None: - return False + # Auteur + if note.note_author_id == user.id: + return True - if timezone.is_naive(created_at): - created_at = timezone.make_aware(created_at, timezone.get_current_timezone()) + # Rôle external_manager (hors notes rédigées par des agents internes) + if user_config.roles.filter(name='external_manager').exists(): + if note.note_author and hasattr(note.note_author, 'config') and getattr(note.note_author.config, 'is_intern', False): + return False + return True - return (timezone.now() - created_at) <= timedelta(hours=1) + return False diff --git a/loko/interventions/templates/interventions/detail/card_notes.html b/loko/interventions/templates/interventions/detail/card_notes.html index 4de66c4..d09a65e 100644 --- a/loko/interventions/templates/interventions/detail/card_notes.html +++ b/loko/interventions/templates/interventions/detail/card_notes.html @@ -31,7 +31,7 @@ {% for note in notes %}

{{ note.content|safe|linebreaksbr }}

- {% if note.id in editable_note_ids and can_edit_notes %} + {% if note.id in editable_note_ids %}
- {% if note.id in editable_note_ids and can_edit_notes %} + {% if note.id in editable_note_ids %}