(backend) annotate number of accesses on documents

The new UI will display the number of accesses on each document.

/!\ Once team accesses will be used, this will not represent the number
    of people with access anymore and will have to be improved by
    computing the number of people in each team.
This commit is contained in:
Samuel Paccoud - DINUM
2024-11-09 18:33:48 +01:00
committed by Anthony LC
parent 89d9075850
commit 774c2ce248
6 changed files with 25 additions and 6 deletions

View File

@@ -28,6 +28,7 @@ and this project adheres to
## Added
- ✨(backend) annotate number of accesses on documents in list view #411
- ✨(backend) allow users to mark/unmark documents as favorite #411
- 🌐(backend) add German translation #259
- 🌐(frontend) add German translation #255

View File

@@ -141,6 +141,7 @@ class ListDocumentSerializer(BaseResourceSerializer):
"""Serialize documents with limited fields for display in lists."""
is_favorite = serializers.BooleanField(read_only=True)
nb_accesses = serializers.IntegerField(read_only=True)
class Meta:
model = models.Document
@@ -152,6 +153,7 @@ class ListDocumentSerializer(BaseResourceSerializer):
"is_favorite",
"link_role",
"link_reach",
"nb_accesses",
"title",
"updated_at",
]
@@ -162,6 +164,7 @@ class ListDocumentSerializer(BaseResourceSerializer):
"is_favorite",
"link_role",
"link_reach",
"nb_accesses",
"updated_at",
]
@@ -181,6 +184,7 @@ class DocumentSerializer(ListDocumentSerializer):
"is_favorite",
"link_role",
"link_reach",
"nb_accesses",
"title",
"updated_at",
]
@@ -191,6 +195,7 @@ class DocumentSerializer(ListDocumentSerializer):
"is_avorite",
"link_role",
"link_reach",
"nb_accesses",
"updated_at",
]

View File

@@ -1,4 +1,5 @@
"""API endpoints"""
# pylint: disable=too-many-lines
import re
import uuid
@@ -10,6 +11,7 @@ from django.contrib.postgres.search import TrigramSimilarity
from django.core.exceptions import ValidationError
from django.core.files.storage import default_storage
from django.db.models import (
Count,
Exists,
Min,
OuterRef,
@@ -334,6 +336,9 @@ class DocumentViewSet(
queryset = super().get_queryset()
user = self.request.user
# Annotate the number of accesses associated with each document
queryset = queryset.annotate(nb_accesses=Count("accesses", distinct=True))
if not user.is_authenticated:
# If the user is not authenticated, annotate `is_favorite` as False
return queryset.annotate(is_favorite=Value(False))
@@ -360,6 +365,7 @@ class DocumentViewSet(
"""Restrict resources returned by the list endpoint"""
queryset = self.filter_queryset(self.get_queryset())
user = self.request.user
if user.is_authenticated:
queryset = queryset.filter(
Q(accesses__user=user)

View File

@@ -39,9 +39,11 @@ def test_api_documents_list_format():
client = APIClient()
client.force_login(user)
other_users = factories.UserFactory.create_batch(3)
document = factories.DocumentFactory(
users=[user, *factories.UserFactory.create_batch(2)],
favorited_by=[user, *factories.UserFactory.create_batch(2)],
favorited_by=[user, *other_users],
link_traces=other_users,
)
response = client.get("/api/v1.0/documents/")
@@ -63,6 +65,7 @@ def test_api_documents_list_format():
"is_favorite": True,
"link_reach": document.link_reach,
"link_role": document.link_role,
"nb_accesses": 3,
"title": document.title,
"updated_at": document.updated_at.isoformat().replace("+00:00", "Z"),
}
@@ -92,9 +95,7 @@ def test_api_documents_list_authenticated_direct(django_assert_num_queries):
expected_ids = {str(document.id) for document in documents}
with django_assert_num_queries(3):
response = client.get(
"/api/v1.0/documents/",
)
response = client.get("/api/v1.0/documents/")
assert response.status_code == 200
results = response.json()["results"]

View File

@@ -38,6 +38,7 @@ def test_api_documents_retrieve_anonymous_public():
"versions_list": False,
"versions_retrieve": False,
},
"nb_accesses": 0,
"content": document.content,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
"is_favorite": False,
@@ -102,6 +103,7 @@ def test_api_documents_retrieve_authenticated_unrelated_public_or_authenticated(
"is_favorite": False,
"link_reach": reach,
"link_role": document.link_role,
"nb_accesses": 0,
"title": document.title,
"updated_at": document.updated_at.isoformat().replace("+00:00", "Z"),
}
@@ -188,6 +190,7 @@ def test_api_documents_retrieve_authenticated_related_direct():
"is_favorite": False,
"link_reach": document.link_reach,
"link_role": document.link_role,
"nb_accesses": 2,
"title": document.title,
"updated_at": document.updated_at.isoformat().replace("+00:00", "Z"),
}
@@ -272,6 +275,7 @@ def test_api_documents_retrieve_authenticated_related_team_members(
assert response.json() == {
"id": str(document.id),
"abilities": document.get_abilities(user),
"nb_accesses": 5,
"content": document.content,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
"is_favorite": False,
@@ -326,6 +330,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators(
assert response.json() == {
"id": str(document.id),
"abilities": document.get_abilities(user),
"nb_accesses": 5,
"content": document.content,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
"is_favorite": False,
@@ -381,6 +386,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
assert response.json() == {
"id": str(document.id),
"abilities": document.get_abilities(user),
"nb_accesses": 5,
"content": document.content,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
"is_favorite": False,

View File

@@ -216,7 +216,7 @@ def test_api_documents_update_authenticated_editor_administrator_or_owner(
document = models.Document.objects.get(pk=document.pk)
document_values = serializers.DocumentSerializer(instance=document).data
for key, value in document_values.items():
if key in ["id", "created_at", "link_reach", "link_role"]:
if key in ["id", "created_at", "link_reach", "link_role", "nb_accesses"]:
assert value == old_document_values[key]
elif key == "updated_at":
assert value > old_document_values[key]
@@ -255,7 +255,7 @@ def test_api_documents_update_authenticated_owners(via, mock_user_teams):
document = models.Document.objects.get(pk=document.pk)
document_values = serializers.DocumentSerializer(instance=document).data
for key, value in document_values.items():
if key in ["id", "created_at", "link_reach", "link_role"]:
if key in ["id", "created_at", "link_reach", "link_role", "nb_accesses"]:
assert value == old_document_values[key]
elif key == "updated_at":
assert value > old_document_values[key]