fix(interventions): resolve UnboundLocalError contracts_qs for external managers
This commit is contained in:
parent
927c049d02
commit
8df84704dc
2 changed files with 99 additions and 21 deletions
|
|
@ -2195,6 +2195,77 @@ class InterventionRolePersonFilteringTests(TestCase):
|
|||
self.assertIn(self.itv_type_inspection.id, itv_ids_insp)
|
||||
self.assertNotIn(self.itv_controller.id, itv_ids_insp)
|
||||
|
||||
def test_interventions_index_external_manager(self):
|
||||
"""Verify that an external manager (is_intern=False) can access interventions index without 500 error."""
|
||||
ext_manager = self.User.objects.create_user(
|
||||
username='ext_manager_test_user',
|
||||
password='pwd',
|
||||
first_name='Eric',
|
||||
last_name='Gestionnaire'
|
||||
)
|
||||
role_ext_mgr, _ = Role.objects.get_or_create(name='external_manager')
|
||||
ext_config = UserConfig.objects.create(user=ext_manager, is_intern=False)
|
||||
ext_config.roles.add(role_ext_mgr)
|
||||
UserThematics.objects.create(
|
||||
user_config=ext_config,
|
||||
thematic=self.thematic,
|
||||
can_view_interventions=True,
|
||||
can_edit_interventions=True,
|
||||
)
|
||||
|
||||
# Create a contract accessible to this external manager
|
||||
from datetime import date, timedelta
|
||||
contract = Contract.objects.create(
|
||||
contract_number='CONT-EXT-01',
|
||||
company=self.company,
|
||||
start_date=date.today(),
|
||||
end_date=date.today() + timedelta(days=365),
|
||||
uses_intervention_manager=True
|
||||
)
|
||||
contract.thematics.add(self.thematic)
|
||||
from common.models import UserContractAccess
|
||||
UserContractAccess.objects.create(
|
||||
user_config=ext_config,
|
||||
contract=contract,
|
||||
can_view_interventions=True,
|
||||
can_approve=True,
|
||||
)
|
||||
|
||||
self.client.login(username='ext_manager_test_user', password='pwd')
|
||||
url = reverse('interventions:interventions_index')
|
||||
resp = self.client.get(url, follow=True)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn('role_persons_data', resp.context)
|
||||
role_data = resp.context['role_persons_data']
|
||||
self.assertIn('manager', role_data)
|
||||
self.assertIn('controller', role_data)
|
||||
self.assertIn('inspector', role_data)
|
||||
manager_ids = [m['id'] for m in role_data['manager']]
|
||||
self.assertIn(ext_manager.id, manager_ids)
|
||||
|
||||
def test_interventions_index_non_intern_user_without_contracts(self):
|
||||
"""Verify that a non-intern user without any contracts can access interventions index without 500 error."""
|
||||
ext_user = self.User.objects.create_user(
|
||||
username='ext_simple_user',
|
||||
password='pwd'
|
||||
)
|
||||
role_technician, _ = Role.objects.get_or_create(name='technician')
|
||||
ext_config = UserConfig.objects.create(user=ext_user, is_intern=False)
|
||||
ext_config.roles.add(role_technician)
|
||||
UserThematics.objects.create(
|
||||
user_config=ext_config,
|
||||
thematic=self.thematic,
|
||||
can_view_interventions=True,
|
||||
can_edit_interventions=False,
|
||||
)
|
||||
|
||||
self.client.login(username='ext_simple_user', password='pwd')
|
||||
url = reverse('interventions:interventions_index')
|
||||
resp = self.client.get(url, follow=True)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn('role_persons_data', resp.context)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -239,25 +239,26 @@ def index(request):
|
|||
key=lambda t: (t[3] if t[3] is not None else t[0], 1 if t[3] is not None else 0, t[1])
|
||||
)
|
||||
|
||||
# Providers and contracts (intern users only)
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
|
||||
# Providers and contracts
|
||||
is_admin = user_config.roles.filter(name='admin').exists() or request.user.is_superuser
|
||||
contracts_qs = Contract.objects.select_related('company').prefetch_related('thematics')
|
||||
if not is_admin:
|
||||
accessible_contract_ids = UserContractAccess.objects.filter(
|
||||
user_config=user_config,
|
||||
can_view_interventions=True,
|
||||
).values_list('contract_id', flat=True)
|
||||
|
||||
if authorized_thematic_codes:
|
||||
contracts_qs = contracts_qs.filter(thematics__code__in=authorized_thematic_codes)
|
||||
contracts_qs = contracts_qs.filter(id__in=accessible_contract_ids).distinct()
|
||||
|
||||
provider_choices = []
|
||||
contract_choices = []
|
||||
if user_config.is_intern:
|
||||
is_admin = user_config.roles.filter(name='admin').exists() or request.user.is_superuser
|
||||
contracts_qs = Contract.objects.select_related('company').prefetch_related('thematics')
|
||||
if not is_admin:
|
||||
accessible_contract_ids = UserContractAccess.objects.filter(
|
||||
user_config=user_config,
|
||||
can_view_interventions=True,
|
||||
).values_list('contract_id', flat=True)
|
||||
|
||||
if authorized_thematic_codes:
|
||||
contracts_qs = contracts_qs.filter(thematics__code__in=authorized_thematic_codes)
|
||||
contracts_qs = contracts_qs.filter(id__in=accessible_contract_ids).distinct()
|
||||
|
||||
# Build contract choices with thematic codes
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
for contract in contracts_qs:
|
||||
thematic_codes = list(contract.thematics.values_list('code', flat=True))
|
||||
managers_qs = User.objects.filter(
|
||||
|
|
@ -359,18 +360,24 @@ def index(request):
|
|||
# Build role-persons data (Gestionnaire / Contrôleur / Inspecteur)
|
||||
# 1. Managers
|
||||
user_access_map = defaultdict(set)
|
||||
for uca in UserContractAccess.objects.filter(contract__in=contracts_qs, can_approve=True):
|
||||
for uca in UserContractAccess.objects.filter(
|
||||
Q(contract__in=contracts_qs) & (Q(can_approve=True) | Q(user_config__roles__name__in=['manager', 'external_manager']))
|
||||
):
|
||||
user_access_map[uca.user_config.user_id].add(uca.contract_id)
|
||||
managed_itv_map = defaultdict(set)
|
||||
for itv_data in Intervention.objects.filter(contract__in=contracts_qs, intervention_manager__isnull=False).values('intervention_manager_id', 'contract_id').distinct():
|
||||
managed_itv_map[itv_data['intervention_manager_id']].add(itv_data['contract_id'])
|
||||
|
||||
manager_q = (
|
||||
Q(config__usercontractaccess__contract__in=contracts_qs, config__usercontractaccess__can_approve=True) |
|
||||
Q(config__usercontractaccess__contract__in=contracts_qs, config__roles__name__in=['manager', 'external_manager']) |
|
||||
Q(managed_interventions__contract__in=contracts_qs)
|
||||
)
|
||||
if user_config.is_intern:
|
||||
manager_q |= Q(config__roles__name='manager')
|
||||
|
||||
manager_users_qs = (
|
||||
User.objects.filter(
|
||||
Q(config__usercontractaccess__contract__in=contracts_qs, config__usercontractaccess__can_approve=True) |
|
||||
Q(managed_interventions__contract__in=contracts_qs) |
|
||||
Q(config__roles__name='manager')
|
||||
)
|
||||
User.objects.filter(manager_q)
|
||||
.prefetch_related('companymember_set__teams', 'config__company')
|
||||
.distinct()
|
||||
.order_by('first_name', 'last_name', 'username')
|
||||
|
|
|
|||
Loading…
Reference in a new issue