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
|
# When only 1 municipality is accessible, the filter should NOT be shown
|
||||||
self.assertIsNone(muni_filter)
|
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):
|
class NatureLocationDetailViewTest(TestCase):
|
||||||
def setUp(self):
|
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)
|
# Roads / public lighting / sign / artworks: municipality on locations (only if more than 1 option)
|
||||||
if len(municipality_options) > 1:
|
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:
|
if thematic_code in accessible_codes:
|
||||||
config.setdefault(thematic_code, []).append({
|
config.setdefault(thematic_code, []).append({
|
||||||
'key': 'municipality',
|
'key': 'municipality',
|
||||||
|
|
@ -752,16 +752,114 @@ def build_conditional_filter_config(accessible_thematics, user=None):
|
||||||
|
|
||||||
# Nature
|
# Nature
|
||||||
if 'nature' in accessible_codes:
|
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',
|
'key': 'management_type',
|
||||||
'label': _('Gestionnaire'),
|
'label': _('Gestionnaire'),
|
||||||
'type': 'multi',
|
'type': 'multi',
|
||||||
'options': [
|
'options': management_type_options,
|
||||||
{'value': 'municipal', 'label': _('Commune (Watermael-Boitsfort)')},
|
})
|
||||||
{'value': 'regional', 'label': _('Région (Bruxelles Mobilité)')},
|
nature_filters.extend([
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'key': 'location_type',
|
'key': 'location_type',
|
||||||
'label': _('Type de localisation'),
|
'label': _('Type de localisation'),
|
||||||
|
|
@ -777,7 +875,8 @@ def build_conditional_filter_config(accessible_thematics, user=None):
|
||||||
'type': 'checkbox',
|
'type': 'checkbox',
|
||||||
'value': '1',
|
'value': '1',
|
||||||
},
|
},
|
||||||
]
|
])
|
||||||
|
config['nature'] = nature_filters
|
||||||
|
|
||||||
# Water
|
# Water
|
||||||
if 'water' in accessible_codes:
|
if 'water' in accessible_codes:
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,29 @@ def nature_index(request):
|
||||||
category_choices = [(m.id, m.get_name()) for m in categories]
|
category_choices = [(m.id, m.get_name()) for m in categories]
|
||||||
|
|
||||||
selected_management_types = request.GET.getlist('management_type')
|
selected_management_types = request.GET.getlist('management_type')
|
||||||
|
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 = [
|
management_type_choices = [
|
||||||
('municipal', _("Communal (Commune)")),
|
('municipal', _("Communal (Commune)")),
|
||||||
('regional', _("Régional (Bruxelles Mobilité)")),
|
('regional', _("Régional (Région / Bruxelles Mobilité)")),
|
||||||
('community', _("Intercommunal / Communautaire")),
|
('community', _("Intercommunal / Communautaire")),
|
||||||
('private', _("Privé / Conventionné")),
|
('private', _("Privé / Conventionné")),
|
||||||
]
|
]
|
||||||
|
|
@ -462,10 +482,30 @@ def nature_locations_geojson(request):
|
||||||
filter_geom = None
|
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')
|
include_naturelocation = location_type in ('', 'naturelocation')
|
||||||
|
|
||||||
nature_locations = NatureLocation.objects.all() if include_naturelocation else NatureLocation.objects.none()
|
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:
|
if highway:
|
||||||
nature_locations = nature_locations.filter(is_highway=highway)
|
nature_locations = nature_locations.filter(is_highway=highway)
|
||||||
|
|
||||||
|
|
@ -707,6 +747,35 @@ def nature_assets_geojson(request):
|
||||||
NatureBench.objects.all()
|
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')
|
include_naturelocation = location_type in ('', 'naturelocation')
|
||||||
|
|
||||||
if not include_naturelocation:
|
if not include_naturelocation:
|
||||||
|
|
@ -715,7 +784,6 @@ def nature_assets_geojson(request):
|
||||||
natureshrub_qs = natureshrub_qs.none()
|
natureshrub_qs = natureshrub_qs.none()
|
||||||
naturebench_qs = naturebench_qs.none()
|
naturebench_qs = naturebench_qs.none()
|
||||||
|
|
||||||
|
|
||||||
if sections_ids:
|
if sections_ids:
|
||||||
naturegreensurface_qs = naturegreensurface_qs.filter(location__id__in=sections_ids)
|
naturegreensurface_qs = naturegreensurface_qs.filter(location__id__in=sections_ids)
|
||||||
naturetree_qs = naturetree_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)
|
naturebench_qs = naturebench_qs.filter(model__id__in=models)
|
||||||
|
|
||||||
if management_types:
|
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:
|
if categories:
|
||||||
naturegreensurface_qs = naturegreensurface_qs.filter(category__id__in=categories)
|
naturegreensurface_qs = naturegreensurface_qs.filter(category__id__in=categories)
|
||||||
naturetree_qs = naturetree_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:
|
if len(raw_query) < 2:
|
||||||
return JsonResponse([], safe=False)
|
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)
|
# Normalise la requête (équivalent de unaccent+lower côté Python)
|
||||||
qn = strip_accents_lower(raw_query)
|
qn = strip_accents_lower(raw_query)
|
||||||
|
|
||||||
# Prépare des colonnes "recherchables" unaccentées + minuscules
|
# 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 = (
|
qs = (
|
||||||
NatureLocation.objects
|
qs
|
||||||
.annotate(
|
.annotate(
|
||||||
code_u=Lower(Unaccent('code')),
|
code_u=Lower(Unaccent('code')),
|
||||||
name_fr_u=Lower(Unaccent('name_fr')),
|
name_fr_u=Lower(Unaccent('name_fr')),
|
||||||
|
|
@ -954,13 +1070,25 @@ def nature_assets_autocomplete(request):
|
||||||
location_filter = {'location_id': location_id}
|
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):
|
def base_qs(model, extra_filter=None):
|
||||||
ann = {
|
ann = {
|
||||||
'code_u': Lower(Unaccent('code')),
|
'code_u': Lower(Unaccent('code')),
|
||||||
'name_fr_u': Lower(Unaccent('name_fr')),
|
'name_fr_u': Lower(Unaccent('name_fr')),
|
||||||
'name_nl_u': Lower(Unaccent('name_nl')),
|
'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
|
# Si un terme de recherche est fourni, filtrer dessus
|
||||||
if has_search_term:
|
if has_search_term:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue