fix(assets): dynamic nature management_type filter based on visible assets and scope nature endpoints by user accessible municipalities
This commit is contained in:
parent
587f4abf8a
commit
f271d65be2
4 changed files with 351 additions and 19 deletions
14
loko/assets/migrations/0032_merge_20261009_1348.py
Normal file
14
loko/assets/migrations/0032_merge_20261009_1348.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Generated by Django 6.0.7 on 2026-10-09 11:48
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0031_itsgeoasset_extra_data_itsbollardsystem_and_more'),
|
||||
('assets', '0031_naturetree_amenity_value_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
|
|
@ -5441,6 +5441,97 @@ class UserAccessibleMunicipalitiesTest(TestCase):
|
|||
# When only 1 municipality is accessible, the filter should NOT be shown
|
||||
self.assertIsNone(muni_filter)
|
||||
|
||||
def test_nature_assets_geojson_restriction_and_filter(self):
|
||||
from assets.models import NatureLocation, NatureTree
|
||||
from common.models import Thematic, UserThematics
|
||||
from django.urls import reverse
|
||||
import json
|
||||
|
||||
thematic_nature, _ = Thematic.objects.get_or_create(code="nature", defaults={"name_fr": "Nature"})
|
||||
UserThematics.objects.get_or_create(user_config=self.ext_config, thematic=thematic_nature, defaults={"can_view_assets": True})
|
||||
|
||||
loc_a = NatureLocation.objects.create(code="LOC-A", name_fr="Rue A", municipality=self.muni_a)
|
||||
loc_c = NatureLocation.objects.create(code="LOC-C", name_fr="Rue C", municipality=self.muni_c)
|
||||
|
||||
tree_muni = NatureTree.objects.create(code="TR-A-MUNI", name_fr="Arbre Communal", location=loc_a, management_type="municipal")
|
||||
tree_reg = NatureTree.objects.create(code="TR-A-REG", name_fr="Arbre Régional", location=loc_a, management_type="regional")
|
||||
tree_c = NatureTree.objects.create(code="TR-C", name_fr="Arbre Inaccessible", location=loc_c, management_type="municipal")
|
||||
|
||||
self.client.force_login(self.user_ext)
|
||||
|
||||
# 1. Unfiltered request
|
||||
resp = self.client.post(
|
||||
reverse('assets:nature_assets_geojson') + '?unified=1',
|
||||
data=json.dumps({}),
|
||||
content_type='application/json'
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
data = resp.json()
|
||||
ids = [f['id'] for f in data.get('features', [])]
|
||||
self.assertIn(tree_muni.id, ids)
|
||||
self.assertIn(tree_reg.id, ids)
|
||||
self.assertNotIn(tree_c.id, ids)
|
||||
|
||||
# 2. Filter by municipal only
|
||||
resp_muni = self.client.post(
|
||||
reverse('assets:nature_assets_geojson') + '?unified=1',
|
||||
data=json.dumps({'management_type': ['municipal']}),
|
||||
content_type='application/json'
|
||||
)
|
||||
data_muni = resp_muni.json()
|
||||
muni_ids = [f['id'] for f in data_muni.get('features', [])]
|
||||
self.assertIn(tree_muni.id, muni_ids)
|
||||
self.assertNotIn(tree_reg.id, muni_ids)
|
||||
self.assertNotIn(tree_c.id, muni_ids)
|
||||
|
||||
# 3. Filter by regional only
|
||||
resp_reg = self.client.post(
|
||||
reverse('assets:nature_assets_geojson') + '?unified=1',
|
||||
data=json.dumps({'management_type': ['regional']}),
|
||||
content_type='application/json'
|
||||
)
|
||||
data_reg = resp_reg.json()
|
||||
reg_ids = [f['id'] for f in data_reg.get('features', [])]
|
||||
self.assertIn(tree_reg.id, reg_ids)
|
||||
self.assertNotIn(tree_muni.id, reg_ids)
|
||||
|
||||
def test_nature_conditional_filter_config_dynamic_gestionnaire(self):
|
||||
from assets.views.core import build_conditional_filter_config
|
||||
from assets.models import NatureLocation, NatureTree
|
||||
from common.models import Thematic, UserConfig, UserContractAccess
|
||||
from contracts.models import Contract
|
||||
|
||||
thematic_nature, _ = Thematic.objects.get_or_create(code="nature", defaults={"name_fr": "Nature"})
|
||||
|
||||
# Single Walloon municipality user
|
||||
self.muni_a.niscode = '25018' # Court-Saint-Étienne (Wallonia)
|
||||
self.muni_a.name_fr = 'Court-Saint-Étienne'
|
||||
self.muni_a.save()
|
||||
|
||||
user_cse = User.objects.create_user(username="test_cse_user", password="pwd")
|
||||
cfg_cse = UserConfig.objects.create(user=user_cse, is_intern=False, limit_assets_to_contracts=True)
|
||||
ctr_cse = Contract.objects.create(contract_number="CTR-CSE", company=self.company, start_date="2026-01-01", end_date="2026-12-31")
|
||||
ctr_cse.municipalities.add(self.muni_a)
|
||||
UserContractAccess.objects.create(user_config=cfg_cse, contract=ctr_cse, can_view_assets=True)
|
||||
|
||||
loc = NatureLocation.objects.create(code="LOC-CSE", name_fr="Rue CSE", municipality=self.muni_a)
|
||||
NatureTree.objects.create(code="TR-CSE-M", location=loc, management_type="municipal")
|
||||
NatureTree.objects.create(code="TR-CSE-R", location=loc, management_type="regional")
|
||||
|
||||
cfg = build_conditional_filter_config([thematic_nature], user=user_cse)
|
||||
nat_filters = cfg.get('nature', [])
|
||||
mgmt_filter = next((f for f in nat_filters if f['key'] == 'management_type'), None)
|
||||
self.assertIsNotNone(mgmt_filter)
|
||||
|
||||
labels = [opt['label'] for opt in mgmt_filter['options']]
|
||||
values = [opt['value'] for opt in mgmt_filter['options']]
|
||||
self.assertIn('municipal', values)
|
||||
self.assertIn('regional', values)
|
||||
self.assertTrue(any('Court-Saint-Étienne' in lbl for lbl in labels))
|
||||
self.assertTrue(any('Région wallonne' in lbl for lbl in labels))
|
||||
self.assertFalse(any('Boitsfort' in lbl for lbl in labels))
|
||||
self.assertFalse(any('Bruxelles Mobilité' in lbl for lbl in labels))
|
||||
|
||||
|
||||
class NatureLocationDetailViewTest(TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ def build_conditional_filter_config(accessible_thematics, user=None):
|
|||
|
||||
# Roads / public lighting / sign / artworks: municipality on locations (only if more than 1 option)
|
||||
if len(municipality_options) > 1:
|
||||
for thematic_code in ['roads', 'publiclighting', 'sign', 'artworks']:
|
||||
for thematic_code in ['roads', 'publiclighting', 'sign', 'artworks', 'nature']:
|
||||
if thematic_code in accessible_codes:
|
||||
config.setdefault(thematic_code, []).append({
|
||||
'key': 'municipality',
|
||||
|
|
@ -752,16 +752,114 @@ def build_conditional_filter_config(accessible_thematics, user=None):
|
|||
|
||||
# Nature
|
||||
if 'nature' in accessible_codes:
|
||||
config['nature'] = [
|
||||
{
|
||||
from assets.models import NatureTree
|
||||
|
||||
def _get_muni_region(m):
|
||||
if not m:
|
||||
return None
|
||||
code = str(getattr(m, 'niscode', '') or '').strip()
|
||||
if code.startswith('21'):
|
||||
return 'BRU'
|
||||
elif code[:2] in ('25', '51', '52', '53', '55', '56', '57', '61', '62', '63', '81', '82', '83', '84', '85', '91', '92', '93') or (code and code[0] in ('5', '6', '8', '9')):
|
||||
return 'WAL'
|
||||
elif (code and code[0] in ('1', '3', '4', '7')) or code[:2] in ('23', '24'):
|
||||
return 'VLG'
|
||||
name = (getattr(m, 'name_fr', '') or '').lower()
|
||||
if any(b in name for b in ('bruxelles', 'watermael', 'boitsfort', 'berchem', 'ixelles', 'etterbeek', 'uccle', 'woluwe', 'schaerbeek', 'anderlecht', 'forest', 'jette', 'ganshoren', 'evere', 'saint-gilles', 'saint-josse', 'auderghem', 'molenbeek', 'koekelberg')):
|
||||
return 'BRU'
|
||||
return None
|
||||
|
||||
regional_labels = {
|
||||
'BRU': _('Région (Bruxelles Mobilité)'),
|
||||
'WAL': _('Région (Région wallonne)'),
|
||||
'VLG': _('Région (Région flamande)'),
|
||||
}
|
||||
|
||||
user_cfg = getattr(user, 'config', None)
|
||||
user_is_admin = getattr(user, 'is_superuser', False) or (user_cfg and (user_cfg.has_role('admin') or user_cfg.has_role('top_manager')))
|
||||
user_is_ext = (user_cfg is None) or (not user_cfg.is_intern)
|
||||
user_must_limit = user_is_ext or (user_cfg and user_cfg.limit_assets_to_contracts)
|
||||
|
||||
visible_trees_qs = NatureTree.objects.exclude(status='removed')
|
||||
if not user_is_admin and user_must_limit:
|
||||
visible_trees_qs = visible_trees_qs.filter(location__municipality__in=municipalities)
|
||||
|
||||
tree_stats = list(visible_trees_qs.values('management_type', 'location__municipality_id').distinct())
|
||||
has_trees = len(tree_stats) > 0
|
||||
muni_list = list(municipalities)
|
||||
management_type_options = []
|
||||
|
||||
if len(muni_list) == 1:
|
||||
single_muni = muni_list[0]
|
||||
reg = _get_muni_region(single_muni) or 'BRU'
|
||||
reg_label = regional_labels.get(reg, _('Région'))
|
||||
|
||||
has_municipal = any(t['management_type'] == 'municipal' for t in tree_stats) if has_trees else True
|
||||
has_regional = any(t['management_type'] == 'regional' for t in tree_stats) if has_trees else True
|
||||
|
||||
if has_municipal:
|
||||
management_type_options.append({
|
||||
'value': 'municipal',
|
||||
'label': _('Commune (%(name)s)') % {'name': single_muni.name}
|
||||
})
|
||||
if has_regional:
|
||||
management_type_options.append({
|
||||
'value': 'regional',
|
||||
'label': reg_label
|
||||
})
|
||||
elif len(muni_list) > 1:
|
||||
muni_map = {m.id: m for m in muni_list}
|
||||
|
||||
# Municipal options for each municipality with municipal trees
|
||||
for m in muni_list:
|
||||
has_m_trees = any(
|
||||
t['management_type'] == 'municipal' and t['location__municipality_id'] == m.id
|
||||
for t in tree_stats
|
||||
) if has_trees else True
|
||||
if has_m_trees:
|
||||
management_type_options.append({
|
||||
'value': f'municipal_{m.id}',
|
||||
'label': _('Commune (%(name)s)') % {'name': m.name}
|
||||
})
|
||||
|
||||
# Regional options grouped by region
|
||||
regions_with_regional_trees = set()
|
||||
for t in tree_stats:
|
||||
if t['management_type'] == 'regional':
|
||||
mid = t['location__municipality_id']
|
||||
m_obj = muni_map.get(mid)
|
||||
if m_obj:
|
||||
reg = _get_muni_region(m_obj)
|
||||
if reg:
|
||||
regions_with_regional_trees.add(reg)
|
||||
|
||||
if not has_trees:
|
||||
for m in muni_list:
|
||||
reg = _get_muni_region(m)
|
||||
if reg:
|
||||
regions_with_regional_trees.add(reg)
|
||||
|
||||
for reg_code, reg_val in [('BRU', 'regional_bruxelles'), ('WAL', 'regional_wallonie'), ('VLG', 'regional_flandre')]:
|
||||
if reg_code in regions_with_regional_trees:
|
||||
management_type_options.append({
|
||||
'value': reg_val,
|
||||
'label': regional_labels[reg_code]
|
||||
})
|
||||
else:
|
||||
management_type_options = [
|
||||
{'value': 'municipal', 'label': _('Communal')},
|
||||
{'value': 'regional', 'label': _('Régional')},
|
||||
]
|
||||
|
||||
nature_filters = []
|
||||
if management_type_options:
|
||||
nature_filters.append({
|
||||
'key': 'management_type',
|
||||
'label': _('Gestionnaire'),
|
||||
'type': 'multi',
|
||||
'options': [
|
||||
{'value': 'municipal', 'label': _('Commune (Watermael-Boitsfort)')},
|
||||
{'value': 'regional', 'label': _('Région (Bruxelles Mobilité)')},
|
||||
],
|
||||
},
|
||||
'options': management_type_options,
|
||||
})
|
||||
nature_filters.extend([
|
||||
{
|
||||
'key': 'location_type',
|
||||
'label': _('Type de localisation'),
|
||||
|
|
@ -777,7 +875,8 @@ def build_conditional_filter_config(accessible_thematics, user=None):
|
|||
'type': 'checkbox',
|
||||
'value': '1',
|
||||
},
|
||||
]
|
||||
])
|
||||
config['nature'] = nature_filters
|
||||
|
||||
# Water
|
||||
if 'water' in accessible_codes:
|
||||
|
|
|
|||
|
|
@ -72,12 +72,32 @@ def nature_index(request):
|
|||
category_choices = [(m.id, m.get_name()) for m in categories]
|
||||
|
||||
selected_management_types = request.GET.getlist('management_type')
|
||||
management_type_choices = [
|
||||
('municipal', _("Communal (Commune)")),
|
||||
('regional', _("Régional (Bruxelles Mobilité)")),
|
||||
('community', _("Intercommunal / Communautaire")),
|
||||
('private', _("Privé / Conventionné")),
|
||||
]
|
||||
from assets.permissions import get_user_accessible_municipalities
|
||||
_munis = list(get_user_accessible_municipalities(request.user))
|
||||
if len(_munis) == 1:
|
||||
_sm = _munis[0]
|
||||
_code = str(getattr(_sm, 'niscode', '') or '').strip()
|
||||
_is_wal = _code[:2] in ('25', '51', '52', '53', '55', '56', '57', '61', '62', '63', '81', '82', '83', '84', '85', '91', '92', '93') or (_code and _code[0] in ('5', '6', '8', '9')) or 'court-saint' in (_sm.name_fr or '').lower()
|
||||
_is_vlg = (_code and _code[0] in ('1', '3', '4', '7')) or _code[:2] in ('23', '24')
|
||||
if _is_wal:
|
||||
_reg_lbl = _("Régional (Région wallonne)")
|
||||
elif _is_vlg:
|
||||
_reg_lbl = _("Régional (Région flamande)")
|
||||
else:
|
||||
_reg_lbl = _("Régional (Bruxelles Mobilité)")
|
||||
management_type_choices = [
|
||||
('municipal', _("Communal (%(name)s)") % {'name': _sm.name}),
|
||||
('regional', _reg_lbl),
|
||||
('community', _("Intercommunal / Communautaire")),
|
||||
('private', _("Privé / Conventionné")),
|
||||
]
|
||||
else:
|
||||
management_type_choices = [
|
||||
('municipal', _("Communal (Commune)")),
|
||||
('regional', _("Régional (Région / Bruxelles Mobilité)")),
|
||||
('community', _("Intercommunal / Communautaire")),
|
||||
('private', _("Privé / Conventionné")),
|
||||
]
|
||||
|
||||
models = list(NatureAssetModel.objects.all())
|
||||
models.sort(key=lambda m: (m.get_name() or "").lower())
|
||||
|
|
@ -462,10 +482,30 @@ def nature_locations_geojson(request):
|
|||
filter_geom = None
|
||||
|
||||
|
||||
from assets.permissions import get_user_accessible_municipalities
|
||||
user = request.user
|
||||
user_config = getattr(user, 'config', None)
|
||||
is_admin = getattr(user, 'is_superuser', False) or (user_config and (user_config.has_role('admin') or user_config.has_role('top_manager')))
|
||||
is_external = (user_config is None) or (not user_config.is_intern)
|
||||
must_limit = is_external or (user_config and user_config.limit_assets_to_contracts)
|
||||
|
||||
municipalities = ensure_list(data.get('municipality')) if request.method == "POST" else request.GET.getlist('municipality')
|
||||
|
||||
include_naturelocation = location_type in ('', 'naturelocation')
|
||||
|
||||
nature_locations = NatureLocation.objects.all() if include_naturelocation else NatureLocation.objects.none()
|
||||
|
||||
if not is_admin and must_limit:
|
||||
accessible_munis = get_user_accessible_municipalities(user)
|
||||
accessible_muni_ids = list(accessible_munis.values_list('id', flat=True))
|
||||
if municipalities:
|
||||
valid_munis = [mid for mid in municipalities if (int(mid) if str(mid).isdigit() else mid) in accessible_muni_ids]
|
||||
nature_locations = nature_locations.filter(municipality_id__in=valid_munis)
|
||||
else:
|
||||
nature_locations = nature_locations.filter(municipality_id__in=accessible_muni_ids)
|
||||
elif municipalities:
|
||||
nature_locations = nature_locations.filter(municipality_id__in=municipalities)
|
||||
|
||||
if highway:
|
||||
nature_locations = nature_locations.filter(is_highway=highway)
|
||||
|
||||
|
|
@ -707,6 +747,35 @@ def nature_assets_geojson(request):
|
|||
NatureBench.objects.all()
|
||||
)
|
||||
|
||||
from assets.permissions import get_user_accessible_municipalities
|
||||
user = request.user
|
||||
user_config = getattr(user, 'config', None)
|
||||
is_admin = getattr(user, 'is_superuser', False) or (user_config and (user_config.has_role('admin') or user_config.has_role('top_manager')))
|
||||
is_external = (user_config is None) or (not user_config.is_intern)
|
||||
must_limit = is_external or (user_config and user_config.limit_assets_to_contracts)
|
||||
|
||||
municipalities = ensure_list(data.get('municipality')) if request.method == "POST" else request.GET.getlist('municipality')
|
||||
|
||||
if not is_admin and must_limit:
|
||||
accessible_munis = get_user_accessible_municipalities(user)
|
||||
accessible_muni_ids = list(accessible_munis.values_list('id', flat=True))
|
||||
if municipalities:
|
||||
valid_munis = [mid for mid in municipalities if (int(mid) if str(mid).isdigit() else mid) in accessible_muni_ids]
|
||||
naturegreensurface_qs = naturegreensurface_qs.filter(location__municipality_id__in=valid_munis)
|
||||
naturetree_qs = naturetree_qs.filter(location__municipality_id__in=valid_munis)
|
||||
natureshrub_qs = natureshrub_qs.filter(location__municipality_id__in=valid_munis)
|
||||
naturebench_qs = naturebench_qs.filter(location__municipality_id__in=valid_munis)
|
||||
else:
|
||||
naturegreensurface_qs = naturegreensurface_qs.filter(location__municipality_id__in=accessible_muni_ids)
|
||||
naturetree_qs = naturetree_qs.filter(location__municipality_id__in=accessible_muni_ids)
|
||||
natureshrub_qs = natureshrub_qs.filter(location__municipality_id__in=accessible_muni_ids)
|
||||
naturebench_qs = naturebench_qs.filter(location__municipality_id__in=accessible_muni_ids)
|
||||
elif municipalities:
|
||||
naturegreensurface_qs = naturegreensurface_qs.filter(location__municipality_id__in=municipalities)
|
||||
naturetree_qs = naturetree_qs.filter(location__municipality_id__in=municipalities)
|
||||
natureshrub_qs = natureshrub_qs.filter(location__municipality_id__in=municipalities)
|
||||
naturebench_qs = naturebench_qs.filter(location__municipality_id__in=municipalities)
|
||||
|
||||
include_naturelocation = location_type in ('', 'naturelocation')
|
||||
|
||||
if not include_naturelocation:
|
||||
|
|
@ -715,7 +784,6 @@ def nature_assets_geojson(request):
|
|||
natureshrub_qs = natureshrub_qs.none()
|
||||
naturebench_qs = naturebench_qs.none()
|
||||
|
||||
|
||||
if sections_ids:
|
||||
naturegreensurface_qs = naturegreensurface_qs.filter(location__id__in=sections_ids)
|
||||
naturetree_qs = naturetree_qs.filter(location__id__in=sections_ids)
|
||||
|
|
@ -734,7 +802,43 @@ def nature_assets_geojson(request):
|
|||
naturebench_qs = naturebench_qs.filter(model__id__in=models)
|
||||
|
||||
if management_types:
|
||||
naturetree_qs = naturetree_qs.filter(management_type__in=management_types)
|
||||
q_mgmt = Q()
|
||||
for val in management_types:
|
||||
val_str = str(val).strip()
|
||||
if val_str == 'municipal':
|
||||
q_mgmt |= Q(management_type='municipal')
|
||||
elif val_str == 'regional':
|
||||
q_mgmt |= Q(management_type='regional')
|
||||
elif val_str == 'regional_bruxelles':
|
||||
q_mgmt |= Q(management_type='regional') & (
|
||||
Q(location__municipality__niscode__startswith='21') |
|
||||
Q(location__municipality__name_fr__icontains='Bruxelles') |
|
||||
Q(location__municipality__name_fr__icontains='Watermael') |
|
||||
Q(location__municipality__name_fr__icontains='Berchem')
|
||||
)
|
||||
elif val_str == 'regional_wallonie':
|
||||
q_mgmt |= Q(management_type='regional') & (
|
||||
Q(location__municipality__niscode__startswith=('25', '5', '6', '8', '9')) |
|
||||
Q(location__municipality__name_fr__icontains='Court-Saint')
|
||||
)
|
||||
elif val_str == 'regional_flandre':
|
||||
q_mgmt |= Q(management_type='regional') & (
|
||||
Q(location__municipality__niscode__startswith=('1', '3', '4', '7', '23', '24'))
|
||||
)
|
||||
elif val_str.startswith('municipal_'):
|
||||
m_id = val_str.split('_', 1)[1]
|
||||
if m_id.isdigit():
|
||||
q_mgmt |= Q(management_type='municipal', location__municipality_id=int(m_id))
|
||||
elif val_str.startswith('authority:'):
|
||||
auth_name = val_str.split(':', 1)[1]
|
||||
q_mgmt |= Q(managing_authority__iexact=auth_name)
|
||||
else:
|
||||
q_mgmt |= Q(managing_authority__icontains=val_str) | Q(management_type=val_str)
|
||||
|
||||
naturetree_qs = naturetree_qs.filter(q_mgmt)
|
||||
naturegreensurface_qs = naturegreensurface_qs.none()
|
||||
natureshrub_qs = natureshrub_qs.none()
|
||||
naturebench_qs = naturebench_qs.none()
|
||||
if categories:
|
||||
naturegreensurface_qs = naturegreensurface_qs.filter(category__id__in=categories)
|
||||
naturetree_qs = naturetree_qs.filter(category__id__in=categories)
|
||||
|
|
@ -884,12 +988,24 @@ def nature_locations_autocomplete(request):
|
|||
if len(raw_query) < 2:
|
||||
return JsonResponse([], safe=False)
|
||||
|
||||
user = request.user
|
||||
user_config = getattr(user, 'config', None)
|
||||
is_admin = getattr(user, 'is_superuser', False) or (user_config and (user_config.has_role('admin') or user_config.has_role('top_manager')))
|
||||
is_external = (user_config is None) or (not user_config.is_intern)
|
||||
must_limit = is_external or (user_config and user_config.limit_assets_to_contracts)
|
||||
|
||||
# Normalise la requête (équivalent de unaccent+lower côté Python)
|
||||
qn = strip_accents_lower(raw_query)
|
||||
|
||||
# Prépare des colonnes "recherchables" unaccentées + minuscules
|
||||
qs = NatureLocation.objects.all()
|
||||
if not is_admin and must_limit:
|
||||
from assets.permissions import get_user_accessible_municipalities
|
||||
accessible_munis = get_user_accessible_municipalities(user)
|
||||
qs = qs.filter(municipality__in=accessible_munis)
|
||||
|
||||
qs = (
|
||||
NatureLocation.objects
|
||||
qs
|
||||
.annotate(
|
||||
code_u=Lower(Unaccent('code')),
|
||||
name_fr_u=Lower(Unaccent('name_fr')),
|
||||
|
|
@ -954,13 +1070,25 @@ def nature_assets_autocomplete(request):
|
|||
location_filter = {'location_id': location_id}
|
||||
|
||||
|
||||
user = request.user
|
||||
user_config = getattr(user, 'config', None)
|
||||
is_admin = getattr(user, 'is_superuser', False) or (user_config and (user_config.has_role('admin') or user_config.has_role('top_manager')))
|
||||
is_external = (user_config is None) or (not user_config.is_intern)
|
||||
must_limit = is_external or (user_config and user_config.limit_assets_to_contracts)
|
||||
|
||||
def base_qs(model, extra_filter=None):
|
||||
ann = {
|
||||
'code_u': Lower(Unaccent('code')),
|
||||
'name_fr_u': Lower(Unaccent('name_fr')),
|
||||
'name_nl_u': Lower(Unaccent('name_nl')),
|
||||
}
|
||||
q = model.objects.annotate(**ann)
|
||||
q = model.objects.all()
|
||||
if not is_admin and must_limit:
|
||||
from assets.permissions import get_user_accessible_municipalities
|
||||
accessible_munis = get_user_accessible_municipalities(user)
|
||||
q = q.filter(location__municipality__in=accessible_munis)
|
||||
|
||||
q = q.annotate(**ann)
|
||||
|
||||
# Si un terme de recherche est fourni, filtrer dessus
|
||||
if has_search_term:
|
||||
|
|
|
|||
Loading…
Reference in a new issue