From b1e7f726a241255cb52f41783d5dab6dae60f735 Mon Sep 17 00:00:00 2001 From: Karl Determe Date: Fri, 14 Aug 2026 22:26:41 +0200 Subject: [PATCH] feat: add intervention on pause widget and associated backend logic --- streetup/home/locale/en/LC_MESSAGES/django.mo | Bin 13696 -> 14011 bytes streetup/home/locale/en/LC_MESSAGES/django.po | 16 +++++ streetup/home/locale/fr/LC_MESSAGES/django.mo | Bin 14981 -> 15315 bytes streetup/home/locale/fr/LC_MESSAGES/django.po | 16 +++++ streetup/home/locale/nl/LC_MESSAGES/django.mo | Bin 14096 -> 14407 bytes streetup/home/locale/nl/LC_MESSAGES/django.po | 18 +++++- .../0003_alter_homewidget_widget_code.py | 18 ++++++ streetup/home/models.py | 1 + .../home/widgets/intervention_on_pause.html | 51 ++++++++++++++++ streetup/home/tests.py | 20 ++++++ streetup/home/views.py | 15 +++++ streetup/interventions/tests/test_general.py | 57 ++++++++++++++++++ 12 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 streetup/home/migrations/0003_alter_homewidget_widget_code.py create mode 100644 streetup/home/templates/home/widgets/intervention_on_pause.html diff --git a/streetup/home/locale/en/LC_MESSAGES/django.mo b/streetup/home/locale/en/LC_MESSAGES/django.mo index 4b1176d6bf6409e7843cc32be4c65b727d5e3dbe..e7d15eebac1fa601d4199fc3f98d7462cc3ec262 100644 GIT binary patch delta 4377 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 diff --git a/streetup/home/locale/fr/LC_MESSAGES/django.po b/streetup/home/locale/fr/LC_MESSAGES/django.po index 36c3add..4de794c 100644 --- a/streetup/home/locale/fr/LC_MESSAGES/django.po +++ b/streetup/home/locale/fr/LC_MESSAGES/django.po @@ -69,6 +69,10 @@ msgid "Compteur interventions terminées" msgstr "Compteur interventions terminées" #: streetup/home/models.py:20 +msgid "Compteur interventions en pause" +msgstr "Compteur interventions en pause" + +#: streetup/home/models.py:21 #: streetup/home/templates/home/widgets/stock_actions.html:9 msgid "Actions stock" msgstr "Actions stock" @@ -550,6 +554,18 @@ msgstr "Aucune intervention terminée" msgid "Voir toutes les interventions terminées" msgstr "Voir toutes les interventions terminées" +#: streetup/home/templates/home/widgets/intervention_on_pause.html:8 +msgid "Interventions en pause" +msgstr "Interventions en pause" + +#: streetup/home/templates/home/widgets/intervention_on_pause.html:40 +msgid "Aucune intervention en pause" +msgstr "Aucune intervention en pause" + +#: streetup/home/templates/home/widgets/intervention_on_pause.html:48 +msgid "Voir toutes les interventions en pause" +msgstr "Voir toutes les interventions en pause" + #: streetup/home/templates/home/widgets/intervention_stats.html:13 msgid "Interventions" msgstr "Interventions" diff --git a/streetup/home/locale/nl/LC_MESSAGES/django.mo b/streetup/home/locale/nl/LC_MESSAGES/django.mo index c4c2f9ab22fdf120d61f47d66eb5579120699a56..013885a6ac56b018211c6e15c238c488fc7c88f3 100644 GIT binary patch delta 4314 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 S%{=W3Ov`Q+8Q9->qwhcPFptsz diff --git a/streetup/home/locale/nl/LC_MESSAGES/django.po b/streetup/home/locale/nl/LC_MESSAGES/django.po index af1c261..71d126e 100644 --- a/streetup/home/locale/nl/LC_MESSAGES/django.po +++ b/streetup/home/locale/nl/LC_MESSAGES/django.po @@ -68,7 +68,11 @@ msgstr "Tegengeverifieerde interventies moeten worden goedgekeurd" msgid "Compteur interventions terminées" msgstr "Aantal te behandelen incidenten" -#: home/models.py:20 home/templates/home/widgets/stock_actions.html:9 +#: home/models.py:20 +msgid "Compteur interventions en pause" +msgstr "Teller gepauzeerde interventies" + +#: home/models.py:21 home/templates/home/widgets/stock_actions.html:9 msgid "Actions stock" msgstr "Voorraadacties" @@ -544,6 +548,18 @@ msgstr "Geen incidenten te behandelen" msgid "Voir toutes les interventions terminées" msgstr "Bekijk al mijn observaties" +#: home/templates/home/widgets/intervention_on_pause.html:8 +msgid "Interventions en pause" +msgstr "Gepauzeerde interventies" + +#: home/templates/home/widgets/intervention_on_pause.html:40 +msgid "Aucune intervention en pause" +msgstr "Geen gepauzeerde interventies" + +#: home/templates/home/widgets/intervention_on_pause.html:48 +msgid "Voir toutes les interventions en pause" +msgstr "Bekijk alle gepauzeerde interventies" + #: home/templates/home/widgets/intervention_stats.html:13 msgid "Interventions" msgstr "Interventies" diff --git a/streetup/home/migrations/0003_alter_homewidget_widget_code.py b/streetup/home/migrations/0003_alter_homewidget_widget_code.py new file mode 100644 index 0000000..bee4dfe --- /dev/null +++ b/streetup/home/migrations/0003_alter_homewidget_widget_code.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0.7 on 2026-08-14 20:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0002_delete_teambuildingvote'), + ] + + operations = [ + migrations.AlterField( + model_name='homewidget', + name='widget_code', + field=models.CharField(choices=[('intervention_stats', 'Statistiques interventions'), ('contracts_summary', 'Résumé contrats'), ('map_today', 'Carte du jour'), ('operator_shortcuts', 'Raccourcis opérateur'), ('assets_links', 'Liens assets'), ('stock_summary', 'Résumé stock'), ('observer_shortcuts', 'Raccourcis observateur'), ('incident_counter', 'Compteur incidents à traiter'), ('intervention_to_verify', 'Compteur interventions à vérifier'), ('intervention_to_plan', 'Compteur interventions à planifier'), ('intervention_to_approve', 'Compteur interventions à approuver'), ('intervention_checked_to_approve', 'Compteur interventions vérifiées à approuver'), ('intervention_finished', 'Compteur interventions terminées'), ('intervention_on_pause', 'Compteur interventions en pause'), ('stock_actions', 'Actions stock')], max_length=50, unique=True, verbose_name='Code du widget'), + ), + ] diff --git a/streetup/home/models.py b/streetup/home/models.py index 0e490d8..deed03b 100644 --- a/streetup/home/models.py +++ b/streetup/home/models.py @@ -17,6 +17,7 @@ WIDGET_CODE_CHOICES = [ ('intervention_to_approve', _('Compteur interventions à approuver')), ('intervention_checked_to_approve', _('Compteur interventions vérifiées à approuver')), ('intervention_finished', _('Compteur interventions terminées')), + ('intervention_on_pause', _('Compteur interventions en pause')), ('stock_actions', _('Actions stock')), ] diff --git a/streetup/home/templates/home/widgets/intervention_on_pause.html b/streetup/home/templates/home/widgets/intervention_on_pause.html new file mode 100644 index 0000000..ade2b66 --- /dev/null +++ b/streetup/home/templates/home/widgets/intervention_on_pause.html @@ -0,0 +1,51 @@ +{% load i18n %} + +{# ========== Widget compteur d'interventions en pause ========== #} + diff --git a/streetup/home/tests.py b/streetup/home/tests.py index f857255..60d13a7 100644 --- a/streetup/home/tests.py +++ b/streetup/home/tests.py @@ -231,4 +231,24 @@ class HomeIndexViewTests(TestCase): self.assertContains(response, 'id="home-unread-notifications-alert"') self.assertContains(response, 'Vous avez 1 notification non lue.') + def test_home_index_intervention_on_pause_widget(self): + from django.urls import reverse + from django.contrib.auth import get_user_model + from common.models import UserConfig + from home.models import HomeWidget + + User = get_user_model() + user = User.objects.create_user('pause_widget_user', password='pass') + UserConfig.objects.create(user=user) + self.client.force_login(user) + + # Create the widget + HomeWidget.objects.create(widget_code='intervention_on_pause') + + response = self.client.get(reverse('home:index')) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'Interventions en pause') + self.assertContains(response, 'status=on_pause') + + diff --git a/streetup/home/views.py b/streetup/home/views.py index b183bd6..52d85dd 100644 --- a/streetup/home/views.py +++ b/streetup/home/views.py @@ -631,6 +631,17 @@ def index(request): .order_by('-code')[:5] ) + intervention_on_pause_qs = interventions.filter(status='on_pause').exclude( + Q(contract__uses_intervention_manager=True) & + ~Q(intervention_manager=request.user) + ) + intervention_on_pause_count = intervention_on_pause_qs.count() + intervention_on_pause_list = list( + intervention_on_pause_qs + .select_related('thematic') + .order_by('-code')[:5] + ) + if home_contract_ids is not None: is_manager_filter_applied = user_contracts.filter( id__in=home_contract_ids, uses_intervention_manager=True @@ -641,6 +652,7 @@ def index(request): ).exists() total_finished_count = interventions.filter(status='finished').count() + total_on_pause_count = interventions.filter(status='on_pause').count() is_inspector = 'inspector' in user_roles inspection_configs = [] @@ -710,8 +722,11 @@ def index(request): 'intervention_to_plan_list': intervention_to_plan_list, 'intervention_finished_count': intervention_finished_count, 'intervention_finished_list': intervention_finished_list, + 'intervention_on_pause_count': intervention_on_pause_count, + 'intervention_on_pause_list': intervention_on_pause_list, 'is_manager_filter_applied': is_manager_filter_applied, 'total_finished_count': total_finished_count, + 'total_on_pause_count': total_on_pause_count, 'intervention_to_approve_count': intervention_to_approve_count, 'intervention_to_approve_list': intervention_to_approve_list, 'intervention_checked_to_approve_count': intervention_checked_to_approve_count, diff --git a/streetup/interventions/tests/test_general.py b/streetup/interventions/tests/test_general.py index 418a65d..90c9623 100644 --- a/streetup/interventions/tests/test_general.py +++ b/streetup/interventions/tests/test_general.py @@ -628,6 +628,63 @@ class InterventionManagerTests(TestCase): response2 = self.client.get(reverse('home:index')) self.assertFalse(response2.context['is_manager_filter_applied']) + def test_homepage_on_pause_interventions_filtering(self): + # Create an intervention on_pause, with contract using manager, but manager is None (not this user) + itv_other_mgr = Intervention.objects.create( + title='Other Manager on pause', + status='on_pause', + contract=self.contract, + thematic=self.thematic, + intervention_manager=None, + symptom=self.symptom, + ) + # Create an intervention on_pause, with contract using manager, managed by self.user + itv_self_mgr = Intervention.objects.create( + title='Self Manager on pause', + status='on_pause', + contract=self.contract, + thematic=self.thematic, + intervention_manager=self.user, + symptom=self.symptom, + ) + # Create an intervention on_pause, but contract does not use manager + contract_no_mgr = Contract.objects.create( + company=self.company, + contract_number='C-NOMGR-PAUSE', + start_date=self.contract.start_date, + end_date=self.contract.end_date, + uses_intervention_manager=False + ) + # Grant view permission for the no-manager contract + from common.models import UserContractAccess + UserContractAccess.objects.create( + user_config=self.user_config, + contract=contract_no_mgr, + can_view_interventions=True, + ) + + itv_no_mgr = Intervention.objects.create( + title='No Manager on pause', + status='on_pause', + contract=contract_no_mgr, + thematic=self.thematic, + symptom=self.symptom, + ) + + # Access the homepage + response = self.client.get(reverse('home:index')) + self.assertEqual(response.status_code, 200) + + # On pause list/counter should only contain self-managed and no-manager interventions + on_pause_list = response.context['intervention_on_pause_list'] + self.assertIn(itv_self_mgr, on_pause_list) + self.assertIn(itv_no_mgr, on_pause_list) + self.assertNotIn(itv_other_mgr, on_pause_list) + + self.assertEqual(response.context['intervention_on_pause_count'], 2) + self.assertEqual(response.context['total_on_pause_count'], 3) + self.assertTrue(response.context['is_manager_filter_applied']) + def test_geojson_filtering_by_manager(self): # Create an intervention finished managed by self.user itv_self_mgr = Intervention.objects.create(