feat(home): filter controller shortcuts link by assigned controller and remove sub-counters

- Remove 'to_be_corrected' and 'validated' sub-counters from controller shortcuts widget
- Include assigned_controller parameter in widget URL using the new role-person filter
- Update ControllerShortcutsWidgetTests to assert URL parameter and absence of sub-counters
This commit is contained in:
kdeterme 2026-09-30 18:55:56 +02:00
parent 3d9e7c3202
commit 6782959253
3 changed files with 28 additions and 33 deletions

View file

@ -3,7 +3,7 @@
{# ========== Widget raccourcis pour les contrôleurs ========== #}
<div class="card shadow-sm h-100" style="border-color: #00897b !important;">
<div class="card-header d-flex align-items-center justify-content-between text-white" style="background-color: #00897b !important;">
<a href="{% url 'interventions:interventions_index' %}?status=finished&status=processed&status=corrected"
<a href="{{ controller_shortcuts_url }}"
class="text-decoration-none fw-bold text-uppercase text-white d-flex align-items-center" style="letter-spacing:.05em;">
<i class="bi bi-patch-check-fill me-2 fs-5"></i>
<span>{% translate "Interventions à contrôler" %}</span>
@ -13,23 +13,13 @@
</span>
</div>
{# --- Compteur principal et sous-raccourcis --- #}
{# --- Compteur principal --- #}
<div class="text-center py-2 border-bottom bg-light bg-opacity-25">
<a href="{% url 'interventions:interventions_index' %}?status=finished&status=processed&status=corrected"
<a href="{{ controller_shortcuts_url }}"
class="text-decoration-none d-block">
<span class="display-5 fw-bold" style="color: #00897b !important;">{{ controller_interventions_count }}</span>
<div class="small text-muted fw-semibold">{% translate "en attente de contrôle" %}</div>
</a>
<div class="d-flex justify-content-center gap-2 mt-2">
<a href="{% url 'interventions:interventions_index' %}?status=to_be_corrected"
class="badge text-decoration-none bg-warning-subtle text-warning-emphasis border border-warning-subtle">
<i class="bi bi-arrow-repeat me-1"></i>{% translate "À corriger" %} ({{ controller_to_correct_count|default:0 }})
</a>
<a href="{% url 'interventions:interventions_index' %}?status=validated"
class="badge text-decoration-none bg-success-subtle text-success-emphasis border border-success-subtle">
<i class="bi bi-check-all me-1"></i>{% translate "Validées" %} ({{ controller_validated_count|default:0 }})
</a>
</div>
</div>
{# --- Liste des 5 premières interventions --- #}
@ -64,7 +54,7 @@
</ul>
<div class="card-footer text-center text-muted small bg-light">
<a href="{% url 'interventions:interventions_index' %}?status=finished&status=processed&status=corrected"
<a href="{{ controller_shortcuts_url }}"
class="text-decoration-none" style="color: #00897b !important; font-weight: 500;">
<i class="bi bi-arrow-right-circle me-1"></i>{% translate "Voir toutes les interventions à contrôler" %}
</a>

View file

@ -447,7 +447,11 @@ class ControllerShortcutsWidgetTests(TestCase):
self.assertContains(response, 'ITV-CTRL-000')
self.assertContains(response, 'ITV-CTRL-001')
self.assertContains(response, 'ITV-CTRL-002')
self.assertContains(response, 'status=finished&status=processed&status=corrected')
self.assertContains(response, f'assigned_controller={self.member.id}')
self.assertNotContains(response, 'À corriger')
self.assertNotContains(response, 'Validées')
self.assertNotIn('controller_to_correct_count', response.context)
self.assertNotIn('controller_validated_count', response.context)
class StockSummaryWidgetTests(TestCase):

View file

@ -25,7 +25,7 @@ def _t(label, t0, splits):
from interventions.models import Intervention, InterventionTimeLine, STATUS_ORDERS, Symptom
from common.models import UserConfig, UserThematics, UserContractAccess
from contracts.models import CompanyMember, Contract
from contracts.models import CompanyMember, CompanyTeam, Contract
from contracts.permissions import get_allowed_contracts_for_user
from home.models import HomeWidget
from observations.models import Observation
@ -674,14 +674,22 @@ def index(request):
# ========== Données widget controller_shortcuts ==========
user_role_names = set(user_config.roles.values_list('name', flat=True)) if user_config else set()
controller_filter = Q(status__in=['finished', 'processed', 'corrected'])
controller_member = (
CompanyMember.objects.filter(
user=request.user,
teams__operation_types__contains=[CompanyTeam.OPERATION_CONTROLS]
).first()
or CompanyMember.objects.filter(user=request.user).first()
)
controller_member_id = controller_member.id if controller_member else None
if not (user_role_names & {'admin', 'top_manager', 'manager'}):
control_team_ids = list(user_teams.values_list('id', flat=True)) if (user_teams and user_teams.exists()) else []
controller_q = Q(assigned_controller__user=request.user)
if control_team_ids:
controller_q |= Q(assigned_control_team_id__in=control_team_ids)
if controller_member:
controller_q = Q(assigned_controller=controller_member)
else:
controller_q = Q(assigned_controller__user=request.user)
controller_filter &= controller_q
else:
controller_q = None
controller_interventions_qs = interventions.filter(controller_filter)
controller_interventions_count = controller_interventions_qs.count()
@ -691,15 +699,9 @@ def index(request):
.order_by('-code')[:5]
)
controller_to_correct_qs = interventions.filter(status='to_be_corrected')
if controller_q is not None:
controller_to_correct_qs = controller_to_correct_qs.filter(controller_q)
controller_to_correct_count = controller_to_correct_qs.count()
controller_validated_qs = interventions.filter(status='validated')
if controller_q is not None:
controller_validated_qs = controller_validated_qs.filter(controller_q)
controller_validated_count = controller_validated_qs.count()
controller_shortcuts_url = reverse('interventions:interventions_index') + '?status=finished&status=processed&status=corrected'
if controller_member_id:
controller_shortcuts_url += f'&assigned_controller={controller_member_id}'
# ========== Données widget external_interventions ==========
user_company_ids = set()
@ -859,8 +861,7 @@ def index(request):
'external_interventions_list': external_interventions_list,
'controller_interventions_count': controller_interventions_count,
'controller_interventions_list': controller_interventions_list,
'controller_to_correct_count': controller_to_correct_count,
'controller_validated_count': controller_validated_count,
'controller_shortcuts_url': controller_shortcuts_url,
}
# ── Logging de performance (désactivé) ────────────────────────────────