feat: add daily intervention visibility restrictions and mobile filters for technicians with tests
This commit is contained in:
parent
79154085ee
commit
dc6638c4a5
4 changed files with 297 additions and 46 deletions
|
|
@ -17,7 +17,7 @@ from common.models import (
|
|||
UserThematicStatusPermission, UserContractStatusPermission,
|
||||
)
|
||||
from interventions.models import Intervention, InterventionTimeLine, STATUS_ORDERS, STATUS_CHOICES
|
||||
from contracts.models import CompanyMember
|
||||
from contracts.models import CompanyMember, CompanyTeam
|
||||
|
||||
# Ordered list of all status keys (used by get_allowed_statuses_for_user and admin UI)
|
||||
ALL_STATUS_KEYS = list(STATUS_CHOICES.keys())
|
||||
|
|
@ -199,13 +199,15 @@ def get_today_intervention_visibility_q(today):
|
|||
Condition Q pour filtrer les interventions actives le jour 'today' :
|
||||
1. Planifiée pour aujourd'hui (date exacte ou comprise dans la période planifiée [planned_begin, planned_end])
|
||||
2. Démarrée aujourd'hui (begin_time__date == today)
|
||||
3. Travail en cours ou en pause (status in ['in_progress', 'on_pause'])
|
||||
4. Créée aujourd'hui sans planification préalable (urgences du jour)
|
||||
3. Terminée aujourd'hui (end_time__date == today)
|
||||
4. Travail en cours ou en pause (status in ['in_progress', 'on_pause'])
|
||||
5. Créée aujourd'hui sans planification préalable (urgences du jour)
|
||||
"""
|
||||
return (
|
||||
Q(planned_begin_time__date=today) |
|
||||
Q(planned_begin_time__date__lte=today, planned_end_time__date__gte=today) |
|
||||
Q(begin_time__date=today) |
|
||||
Q(end_time__date=today) |
|
||||
Q(status__in=['in_progress', 'on_pause']) |
|
||||
Q(planned_begin_time__isnull=True, begin_time__isnull=True, expected_begin_time__date=today) |
|
||||
Q(planned_begin_time__isnull=True, begin_time__isnull=True, expected_begin_time__isnull=True, creation_time__date=today)
|
||||
|
|
@ -218,7 +220,8 @@ def is_intervention_active_for_today(intervention, today):
|
|||
1. Travail en cours ou en pause
|
||||
2. Planifiée pour aujourd'hui (date exacte ou comprise dans la période planifiée)
|
||||
3. Démarrée aujourd'hui
|
||||
4. Créée aujourd'hui sans planification ni démarrage préalable (urgences du jour)
|
||||
4. Terminée aujourd'hui
|
||||
5. Créée aujourd'hui sans planification ni démarrage préalable (urgences du jour)
|
||||
"""
|
||||
if intervention.status in ('in_progress', 'on_pause'):
|
||||
return True
|
||||
|
|
@ -237,6 +240,11 @@ def is_intervention_active_for_today(intervention, today):
|
|||
if b_date == today:
|
||||
return True
|
||||
|
||||
if intervention.end_time:
|
||||
e_date = timezone.localtime(intervention.end_time).date() if timezone.is_aware(intervention.end_time) else intervention.end_time.date()
|
||||
if e_date == today:
|
||||
return True
|
||||
|
||||
if not intervention.planned_begin_time and not intervention.begin_time:
|
||||
if intervention.expected_begin_time:
|
||||
e_date = timezone.localtime(intervention.expected_begin_time).date() if timezone.is_aware(intervention.expected_begin_time) else intervention.expected_begin_time.date()
|
||||
|
|
@ -250,6 +258,35 @@ def is_intervention_active_for_today(intervention, today):
|
|||
return False
|
||||
|
||||
|
||||
def is_technician_with_daily_team_restriction(user, user_config=None) -> bool:
|
||||
"""
|
||||
Vérifie si l'utilisateur est un technicien (possède le rôle 'technician' et aucun
|
||||
rôle privilégié de gestion/admin) appartenant à au moins une équipe ayant
|
||||
la visibilité restreinte aux interventions du jour ('restrict_today_interventions_visibility'=True).
|
||||
"""
|
||||
if not user or not getattr(user, 'is_authenticated', False):
|
||||
return False
|
||||
|
||||
if user_config is None:
|
||||
try:
|
||||
user_config = UserConfig.objects.prefetch_related('roles').get(user=user)
|
||||
except UserConfig.DoesNotExist:
|
||||
return False
|
||||
|
||||
user_roles = set(user_config.roles.values_list('name', flat=True))
|
||||
privileged_roles = {'admin', 'top_manager', 'manager', 'controller', 'operator', 'external_manager'}
|
||||
if 'technician' not in user_roles or bool(user_roles & privileged_roles):
|
||||
return False
|
||||
|
||||
company_member = CompanyMember.objects.filter(user=user).first()
|
||||
if company_member:
|
||||
from contracts.services_teams import sync_member_current_teams
|
||||
sync_member_current_teams(company_member)
|
||||
return company_member.teams.filter(restrict_today_interventions_visibility=True).exists()
|
||||
|
||||
return CompanyTeam.objects.filter(members__user=user, restrict_today_interventions_visibility=True).exists()
|
||||
|
||||
|
||||
|
||||
def can_view_intervention(user, intervention):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -120,7 +120,9 @@
|
|||
|
||||
<!-- Filtres -->
|
||||
<form method="get" class="d-flex flex-column gap-2 mb-3" data-no-overlay>
|
||||
{% if not hide_filters or can_add_structures_repair or can_add_intervention_mobile %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
{% if not hide_filters %}
|
||||
<div class="form-check m-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
|
@ -135,7 +137,8 @@
|
|||
<i class="bi bi-person"></i> {% translate "Mes interventions" %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
{% endif %}
|
||||
<div class="d-flex align-items-center gap-2{% if hide_filters %} ms-auto{% endif %}">
|
||||
{% if can_add_structures_repair %}
|
||||
<a href="{% url 'mobile:add_repair_intervention_mobile' %}"
|
||||
class="btn btn-primary btn-sm"
|
||||
|
|
@ -150,7 +153,7 @@
|
|||
<i class="bi bi-plus-lg"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if status_filters %}
|
||||
{% if status_filters and not hide_filters %}
|
||||
<button id="toggle-status-filter"
|
||||
class="btn btn-outline-secondary btn-sm"
|
||||
type="button"
|
||||
|
|
@ -163,7 +166,8 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if status_filters %}
|
||||
{% endif %}
|
||||
{% if status_filters and not hide_filters %}
|
||||
<div id="statusFilterPanel" class="collapse mt-2">
|
||||
<p class="mb-1 fw-semibold small text-uppercase text-muted">{% translate "Statuts" %}</p>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
|
|
@ -209,7 +213,9 @@
|
|||
</button>
|
||||
</div>
|
||||
<input type="hidden" name="sort" id="sort-hidden" value="{{ current_sort|default:'' }}">
|
||||
{% if not hide_filters %}
|
||||
<input type="hidden" name="maintain_type" id="maintain-type-hidden" value="{{ selected_maintain_type|default:'' }}">
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% if show_maintain_type_tabs %}
|
||||
|
|
|
|||
|
|
@ -923,6 +923,205 @@ class TeamMultiThematicVisibilityTests(TestCase):
|
|||
self.assertIn('status=to_be_processed', response.url)
|
||||
|
||||
|
||||
class MobileDailyRestrictedTechnicianTests(TestCase):
|
||||
def setUp(self):
|
||||
from common.models import Role, UserConfig, Thematic, UserThematics, UserContractAccess
|
||||
from contracts.models import Company, CompanyTeam, CompanyMember, Contract
|
||||
from datetime import time, timedelta
|
||||
|
||||
self.User = get_user_model()
|
||||
self.tech_role, _ = Role.objects.get_or_create(name='technician')
|
||||
self.admin_role, _ = Role.objects.get_or_create(name='admin')
|
||||
|
||||
self.company = Company.objects.create(name='EquipCo')
|
||||
|
||||
# Restricted team
|
||||
self.team_restricted = CompanyTeam.objects.create(
|
||||
name='Daily Restricted Team',
|
||||
company=self.company,
|
||||
restrict_today_interventions_visibility=True,
|
||||
visibility_start_hour=time(0, 0),
|
||||
)
|
||||
|
||||
# Non-restricted team
|
||||
self.team_unrestricted = CompanyTeam.objects.create(
|
||||
name='Standard Team',
|
||||
company=self.company,
|
||||
restrict_today_interventions_visibility=False,
|
||||
)
|
||||
|
||||
# Restricted technician
|
||||
self.tech_user = self.User.objects.create_user(username='tech-restricted', password='pwd')
|
||||
self.tech_config = UserConfig.objects.create(
|
||||
user=self.tech_user,
|
||||
is_intern=False,
|
||||
)
|
||||
self.tech_config.roles.add(self.tech_role)
|
||||
self.member_restricted = CompanyMember.objects.create(user=self.tech_user, name='Tech Restricted')
|
||||
self.member_restricted.teams.add(self.team_restricted)
|
||||
|
||||
# Unrestricted technician
|
||||
self.tech_unrestricted_user = self.User.objects.create_user(username='tech-unrestricted', password='pwd')
|
||||
self.tech_unrestricted_config = UserConfig.objects.create(
|
||||
user=self.tech_unrestricted_user,
|
||||
is_intern=False,
|
||||
)
|
||||
self.tech_unrestricted_config.roles.add(self.tech_role)
|
||||
self.member_unrestricted = CompanyMember.objects.create(user=self.tech_unrestricted_user, name='Tech Unrestricted')
|
||||
self.member_unrestricted.teams.add(self.team_unrestricted)
|
||||
|
||||
# Admin user
|
||||
self.admin_user = self.User.objects.create_user(username='admin-user', password='pwd')
|
||||
self.admin_config = UserConfig.objects.create(user=self.admin_user, is_intern=True)
|
||||
self.admin_config.roles.add(self.admin_role)
|
||||
|
||||
self.thematic = Thematic.objects.create(code='roads', name_fr='Voirie', name_nl='Wegen')
|
||||
UserThematics.objects.create(user_config=self.tech_config, thematic=self.thematic, can_view_interventions=True, can_edit_interventions=True)
|
||||
UserThematics.objects.create(user_config=self.tech_unrestricted_config, thematic=self.thematic, can_view_interventions=True, can_edit_interventions=True)
|
||||
|
||||
self.contract = Contract.objects.create(
|
||||
contract_number='C-DAILY-TEST',
|
||||
company=self.company,
|
||||
start_date=timezone.now().date() - timedelta(days=10),
|
||||
end_date=timezone.now().date() + timedelta(days=365),
|
||||
is_active=True,
|
||||
)
|
||||
UserContractAccess.objects.create(user_config=self.tech_config, contract=self.contract, can_view_interventions=True)
|
||||
UserContractAccess.objects.create(user_config=self.tech_unrestricted_config, contract=self.contract, can_view_interventions=True)
|
||||
|
||||
def test_is_technician_with_daily_team_restriction(self):
|
||||
from interventions.permissions import is_technician_with_daily_team_restriction
|
||||
|
||||
self.assertTrue(is_technician_with_daily_team_restriction(self.tech_user, self.tech_config))
|
||||
self.assertFalse(is_technician_with_daily_team_restriction(self.tech_unrestricted_user, self.tech_unrestricted_config))
|
||||
self.assertFalse(is_technician_with_daily_team_restriction(self.admin_user, self.admin_config))
|
||||
|
||||
# If restricted technician also has admin role, should return False
|
||||
self.tech_config.roles.add(self.admin_role)
|
||||
self.assertFalse(is_technician_with_daily_team_restriction(self.tech_user, self.tech_config))
|
||||
|
||||
def test_mobile_view_no_redirect_and_hidden_filters(self):
|
||||
self.client.login(username='tech-restricted', password='pwd')
|
||||
url = reverse('mobile:interventions_index_mobile')
|
||||
|
||||
response = self.client.get(url)
|
||||
# Should render 200 directly without 302 redirect
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Context checks
|
||||
self.assertTrue(response.context['hide_filters'])
|
||||
self.assertTrue(response.context['is_daily_restricted_tech'])
|
||||
self.assertTrue(response.context['show_mine_only'])
|
||||
self.assertFalse(response.context['show_maintain_type_tabs'])
|
||||
self.assertEqual(response.context['status_filters'], [])
|
||||
self.assertEqual(
|
||||
response.context['selected_statuses'],
|
||||
['to_be_processed', 'assigned', 'in_progress', 'on_pause', 'finished']
|
||||
)
|
||||
|
||||
# HTML checks: filter controls should be suppressed
|
||||
content = response.content.decode()
|
||||
self.assertNotIn('id="filter-mine"', content)
|
||||
self.assertNotIn('id="toggle-status-filter"', content)
|
||||
self.assertNotIn('id="statusFilterPanel"', content)
|
||||
self.assertNotIn('id="maintainTypeTabs"', content)
|
||||
# Search input should still be present
|
||||
self.assertIn('id="searchInput"', content)
|
||||
|
||||
def test_mobile_view_displays_only_today_and_allowed_statuses(self):
|
||||
from datetime import datetime, timedelta
|
||||
from interventions.models import Intervention
|
||||
today = timezone.localtime(timezone.now()).date()
|
||||
today_dt = timezone.make_aware(datetime.combine(today, datetime.min.time().replace(hour=10)))
|
||||
yesterday_dt = today_dt - timedelta(days=1)
|
||||
|
||||
# 1. Today, assigned to tech, status to_be_processed -> should appear
|
||||
itv_today_to_be_processed = Intervention.objects.create(
|
||||
title='Today to be processed',
|
||||
code='ITV-TBP',
|
||||
status='to_be_processed',
|
||||
contract=self.contract,
|
||||
thematic=self.thematic,
|
||||
assigned_provider=self.company,
|
||||
assigned_team=self.team_restricted,
|
||||
assigned_member=self.member_restricted,
|
||||
planned_begin_time=today_dt,
|
||||
maintain_type='corrective',
|
||||
)
|
||||
|
||||
# 2. Today, assigned to team, status finished -> should appear
|
||||
itv_today_finished = Intervention.objects.create(
|
||||
title='Today finished',
|
||||
code='ITV-FIN',
|
||||
status='finished',
|
||||
contract=self.contract,
|
||||
thematic=self.thematic,
|
||||
assigned_provider=self.company,
|
||||
assigned_team=self.team_restricted,
|
||||
planned_begin_time=today_dt,
|
||||
maintain_type='preventive',
|
||||
)
|
||||
|
||||
# 3. Today, assigned to tech, status closed -> should NOT appear (status closed not in 5 statuses)
|
||||
itv_today_closed = Intervention.objects.create(
|
||||
title='Today closed',
|
||||
code='ITV-CLS',
|
||||
status='closed',
|
||||
contract=self.contract,
|
||||
thematic=self.thematic,
|
||||
assigned_provider=self.company,
|
||||
assigned_team=self.team_restricted,
|
||||
assigned_member=self.member_restricted,
|
||||
planned_begin_time=today_dt,
|
||||
)
|
||||
|
||||
# 4. Yesterday, assigned to tech, status to_be_processed -> should NOT appear (not today)
|
||||
itv_yesterday = Intervention.objects.create(
|
||||
title='Yesterday task',
|
||||
code='ITV-YEST',
|
||||
status='to_be_processed',
|
||||
contract=self.contract,
|
||||
thematic=self.thematic,
|
||||
assigned_provider=self.company,
|
||||
assigned_team=self.team_restricted,
|
||||
assigned_member=self.member_restricted,
|
||||
planned_begin_time=yesterday_dt,
|
||||
)
|
||||
|
||||
# 5. Today, assigned to other team -> should NOT appear (not "mine")
|
||||
itv_other_team = Intervention.objects.create(
|
||||
title='Other team task',
|
||||
code='ITV-OTHER',
|
||||
status='to_be_processed',
|
||||
contract=self.contract,
|
||||
thematic=self.thematic,
|
||||
assigned_provider=self.company,
|
||||
assigned_team=self.team_unrestricted,
|
||||
planned_begin_time=today_dt,
|
||||
)
|
||||
|
||||
self.client.login(username='tech-restricted', password='pwd')
|
||||
url = reverse('mobile:interventions_index_mobile')
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
interventions = list(response.context['interventions'])
|
||||
itv_ids = [itv.id for itv in interventions]
|
||||
|
||||
self.assertIn(itv_today_to_be_processed.id, itv_ids)
|
||||
self.assertIn(itv_today_finished.id, itv_ids)
|
||||
self.assertNotIn(itv_today_closed.id, itv_ids)
|
||||
self.assertNotIn(itv_yesterday.id, itv_ids)
|
||||
self.assertNotIn(itv_other_team.id, itv_ids)
|
||||
|
||||
# Search query check
|
||||
response_search = self.client.get(f"{url}?q=ITV-FIN")
|
||||
self.assertEqual(response_search.status_code, 200)
|
||||
search_ids = [itv.id for itv in response_search.context['interventions']]
|
||||
self.assertEqual(search_ids, [itv_today_finished.id])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ from interventions.permissions import (intervention_permission_required, interve
|
|||
can_add_intervention, can_add_repair_intervention, can_duplicate_intervention,
|
||||
intervention_manage_occupations_required,
|
||||
get_contracts_for_intervention_creation, is_external_manager_with_contract_creation_rights,
|
||||
should_show_created_by_provider_badge, can_view_correction_messages)
|
||||
should_show_created_by_provider_badge, can_view_correction_messages,
|
||||
is_technician_with_daily_team_restriction, get_today_intervention_visibility_q)
|
||||
from interventions.permissions import ALLOWED_TRANSITIONS, get_allowed_transitions, user_allowed_transitions
|
||||
from interventions.views.drafts import InterventionDraftManager
|
||||
from interventions.utils import resolve_intervention_localisations
|
||||
|
|
@ -133,17 +134,29 @@ from interventions.views.helpers import *
|
|||
|
||||
|
||||
def interventions_index_mobile(request):
|
||||
# Synchroniser les équipes du jour du membre avec l'historique planifié
|
||||
company_member_current = CompanyMember.objects.filter(user=request.user).first()
|
||||
if company_member_current:
|
||||
from contracts.services_teams import sync_member_current_teams
|
||||
sync_member_current_teams(company_member_current)
|
||||
|
||||
# Get user config and company member for permissions and maintain type tabs logic
|
||||
user_config = None
|
||||
company_member = None
|
||||
try:
|
||||
user_config = UserConfig.objects.prefetch_related('roles').get(user=request.user)
|
||||
except UserConfig.DoesNotExist:
|
||||
pass
|
||||
|
||||
if user_config and not user_config.is_intern:
|
||||
company_member = CompanyMember.objects.prefetch_related('teams__company', 'visible_maintain_types').filter(user=request.user).first()
|
||||
|
||||
is_daily_restricted_tech = is_technician_with_daily_team_restriction(request.user, user_config=user_config)
|
||||
|
||||
# Redirect if no filter parameters are provided in GET (and it's a standard, non-AJAX request)
|
||||
if not request.GET and request.headers.get('x-requested-with') != 'XMLHttpRequest':
|
||||
# (Uniquement pour les utilisateurs normaux : les techniciens avec restriction quotidienne ont une vue fixe sans filtres)
|
||||
if not is_daily_restricted_tech and not request.GET and request.headers.get('x-requested-with') != 'XMLHttpRequest':
|
||||
query_params = request.GET.copy()
|
||||
|
||||
# Load user config to get saved filters
|
||||
user_config = None
|
||||
try:
|
||||
user_config = UserConfig.objects.get(user=request.user)
|
||||
except UserConfig.DoesNotExist:
|
||||
pass
|
||||
|
||||
saved_filters = user_config.mobile_intervention_list_filters if user_config else {}
|
||||
|
||||
if saved_filters:
|
||||
|
|
@ -169,23 +182,6 @@ def interventions_index_mobile(request):
|
|||
|
||||
return HttpResponseRedirect(f"{request.path}?{query_params.urlencode()}")
|
||||
|
||||
# Synchroniser les équipes du jour du membre avec l'historique planifié
|
||||
company_member_current = CompanyMember.objects.filter(user=request.user).first()
|
||||
if company_member_current:
|
||||
from contracts.services_teams import sync_member_current_teams
|
||||
sync_member_current_teams(company_member_current)
|
||||
|
||||
# Get user config and company member for permissions and maintain type tabs logic
|
||||
user_config = None
|
||||
company_member = None
|
||||
try:
|
||||
user_config = UserConfig.objects.get(user=request.user)
|
||||
except UserConfig.DoesNotExist:
|
||||
pass
|
||||
|
||||
if user_config and not user_config.is_intern:
|
||||
company_member = CompanyMember.objects.prefetch_related('teams__company', 'visible_maintain_types').filter(user=request.user).first()
|
||||
|
||||
# permissions
|
||||
# Les utilisateurs internes avec une thématique par défaut sont restreints à celle-ci.
|
||||
# Pour les prestataires externes (membres d'équipes dont le contrat/métier couvre souvent
|
||||
|
|
@ -194,8 +190,13 @@ def interventions_index_mobile(request):
|
|||
limit_thematic = bool(user_config and user_config.is_intern)
|
||||
interventions = filter_viewable_interventions_for_user(request.user, limit_to_default_thematic=limit_thematic)
|
||||
|
||||
if is_daily_restricted_tech:
|
||||
local_now = timezone.localtime(timezone.now())
|
||||
today = local_now.date()
|
||||
interventions = interventions.filter(get_today_intervention_visibility_q(today))
|
||||
|
||||
# Save the current filters to user config (excluding temporary search query 'q')
|
||||
if user_config and request.GET:
|
||||
if not is_daily_restricted_tech and user_config and request.GET:
|
||||
filters_to_save = {}
|
||||
for key in request.GET:
|
||||
if key == 'q':
|
||||
|
|
@ -238,7 +239,13 @@ def interventions_index_mobile(request):
|
|||
# Save base interventions for counting BEFORE any filtering
|
||||
base_interventions_for_counts = interventions
|
||||
|
||||
if not allowed_statuses:
|
||||
if is_daily_restricted_tech:
|
||||
daily_target_statuses = ['to_be_processed', 'assigned', 'in_progress', 'on_pause', 'finished']
|
||||
selected_statuses = [s for s in daily_target_statuses if s in allowed_statuses]
|
||||
if not selected_statuses:
|
||||
selected_statuses = daily_target_statuses
|
||||
interventions = interventions.filter(status__in=selected_statuses)
|
||||
elif not allowed_statuses:
|
||||
interventions = interventions.none()
|
||||
else:
|
||||
default_statuses = [
|
||||
|
|
@ -265,15 +272,15 @@ def interventions_index_mobile(request):
|
|||
user_teams = CompanyTeam.objects.filter(members__user=request.user)
|
||||
user_team_ids = list(user_teams.values_list('id', flat=True))
|
||||
|
||||
show_mine_only = request.GET.get('mine') == '1'
|
||||
if is_daily_restricted_tech:
|
||||
show_mine_only = True
|
||||
else:
|
||||
show_mine_only = request.GET.get('mine') == '1'
|
||||
|
||||
if show_mine_only:
|
||||
interventions = interventions.filter(
|
||||
Q(assigned_member__user=request.user) | Q(assigned_team_id__in=user_team_ids)
|
||||
)
|
||||
base_interventions_for_counts = base_interventions_for_counts.filter(
|
||||
Q(assigned_member__user=request.user) | Q(assigned_team_id__in=user_team_ids)
|
||||
)
|
||||
mine_filter = Q(assigned_member__user=request.user) | Q(assigned_team_id__in=user_team_ids)
|
||||
interventions = interventions.filter(mine_filter)
|
||||
base_interventions_for_counts = base_interventions_for_counts.filter(mine_filter)
|
||||
|
||||
q = request.GET.get('q')
|
||||
if q:
|
||||
|
|
@ -341,7 +348,7 @@ def interventions_index_mobile(request):
|
|||
visible_maintain_types = None # None means all visible
|
||||
allowed_maintain_types = ['corrective', 'preventive', 'ameliorative'] # Default for internal users
|
||||
|
||||
if user_config:
|
||||
if not is_daily_restricted_tech and user_config:
|
||||
if user_config.is_intern:
|
||||
# Internal users always see tabs
|
||||
show_maintain_type_tabs = True
|
||||
|
|
@ -368,7 +375,7 @@ def interventions_index_mobile(request):
|
|||
maintain_type_counts[item['maintain_type']] = item['count']
|
||||
|
||||
# NOW determine the selected maintain_type (after counting)
|
||||
selected_maintain_type = request.GET.get('maintain_type', '')
|
||||
selected_maintain_type = '' if is_daily_restricted_tech else request.GET.get('maintain_type', '')
|
||||
if show_maintain_type_tabs and not selected_maintain_type:
|
||||
# Set corrective as default
|
||||
selected_maintain_type = 'corrective' if 'corrective' in allowed_maintain_types else allowed_maintain_types[0]
|
||||
|
|
@ -422,7 +429,9 @@ def interventions_index_mobile(request):
|
|||
{
|
||||
'interventions': interventions_list,
|
||||
'show_mine_only': show_mine_only,
|
||||
'status_filters': [
|
||||
'hide_filters': is_daily_restricted_tech,
|
||||
'is_daily_restricted_tech': is_daily_restricted_tech,
|
||||
'status_filters': [] if is_daily_restricted_tech else [
|
||||
{
|
||||
'key': status,
|
||||
'label': STATUS_CHOICES.get(status, status),
|
||||
|
|
|
|||
Loading…
Reference in a new issue