Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
OrganizationRelated,
)
from apps.commons.models import GroupData
from apps.commons.queryset import MultipleIdsQuerySet
from apps.newsfeed.models import Event, Instruction, News
from apps.organizations.models import Organization
from apps.projects.models import AbstractLocation, Project
Expand Down Expand Up @@ -99,6 +100,8 @@ class PeopleGroup(
The visibility setting of the group.
"""

objects = MultipleIdsQuerySet.as_manager()

auto_translated_fields: list[str] = [
"name",
"html:description",
Expand Down
49 changes: 49 additions & 0 deletions apps/commons/queryset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from collections import defaultdict
from typing import Self

from django.contrib.postgres.fields import ArrayField
from django.db import models


class MultipleIdsQuerySet(models.QuerySet):
"""queryset/manager to filter queryset by id or slug"""

def _get_related_field(self, model: models.Model, field: str) -> models.Field:
"""traverse fields query to get real field model"""

acutal_model = model
*traverse, last = field.split("__")
for sub in traverse:
acutal_model = acutal_model._meta.get_field(sub).related_model
return acutal_model._meta.get_field(last)

def build_identifiers_query(self, identifiers: tuple[str | int]) -> models.Q:
query = defaultdict(set)

for identifier in identifiers:
field = self.model.get_id_field_name(identifier)
if field == "slug" and hasattr(self.model, "outdated_slugs"):
fields = (field, "outdated_slugs")
else:
fields = (field,)

for field in fields:
query[field].add(str(identifier))

final_query = models.Q()
for field, values in query.items():
field_cls = self._get_related_field(self.model, field)
if isinstance(field_cls, ArrayField):
lookup = "__contains"
else:
lookup = "__in"

final_query |= models.Q(**{f"{field}{lookup}": list(values)})

return final_query

def slug_or_id(self, identifier: str | int) -> Self:
return self.filter(self.build_identifiers_query((identifier,)))

def slug_or_ids(self, identifiers: tuple[str | int]) -> Self:
return self.filter(self.build_identifiers_query(identifiers))
22 changes: 22 additions & 0 deletions apps/organizations/tests/views/test_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,28 @@ def test_people_groups_hierarchy_params(self):
self.assertEqual(len(data["hierarchy"]), 1)
self.assertEqual(data["hierarchy"][0]["name"], self.root_group.name)

def test_people_groups_hierarchy_slug_or_id(self):
organization = self.organization
user = self.get_parameterized_test_user(TestRoles.SUPERADMIN)
self.client.force_authenticate(user)

url = reverse(
"Organization-people-groups-hierarchy",
args=(organization.code,),
)
parent = self.root_group.children.all().first()
parent.outdated_slugs = [f"{parent.slug}-old"]
parent.save()
response = self.client.get(url, {"depth": 0, "parent": parent.id})
results_id = response.json()
response = self.client.get(url, {"depth": 0, "parent": parent.slug})
results_slug = response.json()
response = self.client.get(url, {"depth": 0, "parent": f"{parent.slug}-old"})
results_outdated_slug = response.json()

self.assertDictEqual(results_id, results_slug)
self.assertDictEqual(results_id, results_outdated_slug)


class ValidateOrganizationTestCase(JwtAPITestCase):
@classmethod
Expand Down
9 changes: 4 additions & 5 deletions apps/organizations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ def remove_member(self, request, *args, **kwargs):
name="parent",
description="people group parents to serializer",
required=False,
type=int,
type=int | str,
),
PeopleGroupModules.ApiParameter(),
],
Expand All @@ -392,10 +392,9 @@ def get_people_groups_hierarchy(self, request, *args, **kwargs):
# get root "organization" group if parent is not set
if request.query_params.get("parent"):
root_group = get_object_or_404(
request.user.get_people_group_queryset().filter(
organization=organization
),
pk=request.query_params.get("parent"),
request.user.get_people_group_queryset()
.filter(organization=organization)
.slug_or_id(request.query_params.get("parent"))
)
else:
root_group = PeopleGroup.update_or_create_root(organization)
Expand Down
4 changes: 2 additions & 2 deletions locale/ca/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -110,7 +110,7 @@ msgstr "No pots assignar aquest rol a un usuari"
msgid "You cannot assign this role to a user : {role}"
msgstr "No pots assignar aquest rol a un usuari: {role}"

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr "visibilitat"

Expand Down
4 changes: 2 additions & 2 deletions locale/de/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -112,7 +112,7 @@ msgstr "Sie können diese Rolle keinem Benutzer zuweisen"
msgid "You cannot assign this role to a user : {role}"
msgstr "Sie können diese Rolle keinem Benutzer zuweisen: {role}"

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr "Sichtbarkeit"

Expand Down
4 changes: 2 additions & 2 deletions locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -108,7 +108,7 @@ msgstr ""
msgid "You cannot assign this role to a user : {role}"
msgstr ""

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr ""

Expand Down
4 changes: 2 additions & 2 deletions locale/es/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -110,7 +110,7 @@ msgstr "No puedes asignar este rol a un usuario"
msgid "You cannot assign this role to a user : {role}"
msgstr "No puedes asignar este rol a un usuario: {role}"

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr "visibilidad"

Expand Down
4 changes: 2 additions & 2 deletions locale/et/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -110,7 +110,7 @@ msgstr "Sa ei saa seda rolli kasutajale määrata"
msgid "You cannot assign this role to a user : {role}"
msgstr "Sa ei saa seda rolli kasutajale määrata: {role}"

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr "nähtavus"

Expand Down
4 changes: 2 additions & 2 deletions locale/fr/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -112,7 +112,7 @@ msgstr "Vous ne pouvez pas assigner ce rôle à un·e utilisateur·ice"
msgid "You cannot assign this role to a user : {role}"
msgstr "Vous ne pouvez pas assigner ce rôle à un·e utilisateur·ice : {role}"

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr "visibilité"

Expand Down
4 changes: 2 additions & 2 deletions locale/nl/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-05 20:01+0100\n"
"POT-Creation-Date: 2026-03-18 10:17+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -112,7 +112,7 @@ msgstr "Je kunt deze rol niet toewijzen aan een gebruiker"
msgid "You cannot assign this role to a user : {role}"
msgstr "Je kunt deze rol niet toewijzen aan een gebruiker: {role}"

#: apps/accounts/models.py:158 apps/projects/models.py:164
#: apps/accounts/models.py:161 apps/projects/models.py:164
msgid "visibility"
msgstr "zichtbaarheid"

Expand Down
Loading