Repository: doccano/doccano
Issue: Wrong progress in collaborative annotation ('Share annotations across all users')

How to reproduce the behaviour
---------
Progress is shown as individual progress instead of total progress when 'Share annotations across all users' is ticked in project setting.

Your Environment
---------
<!-- Include details of your environment.-->
*   Operating System: wsl2+ubuntu20.04
*   Python Version Used: 3.8
*   When you install doccano: 20220403
*   How did you install doccano (Heroku button etc): source


Changed files:
backend/metrics/tests.py, backend/metrics/views.py

diff --git a/backend/metrics/tests.py b/backend/metrics/tests.py
index 82fdd166..eadad24b 100644
--- a/backend/metrics/tests.py
+++ b/backend/metrics/tests.py
@@ -28,6 +28,41 @@ class TestMemberProgress(CRUDMixin):
         self.assertEqual(response.data, {"total": 1, "progress": expected_progress})
 
 
+class TestProgressHelper(CRUDMixin):
+    collaborative_annotation = False
+
+    def setUp(self):
+        self.project = prepare_project(DOCUMENT_CLASSIFICATION, collaborative_annotation=self.collaborative_annotation)
+        self.example = make_doc(self.project.item)
+        mommy.make("ExampleState", example=self.example, confirmed_by=self.project.admin)
+        self.url = reverse(viewname="progress", args=[self.project.item.id])
+
+
+class TestProgress(TestProgressHelper):
+    collaborative_annotation = False
+
+    def test_fetch_progress(self):
+        response = self.assert_fetch(self.project.admin, status.HTTP_200_OK)
+        expected = {"total": 1, "remaining": 0, "complete": 1}
+        self.assertEqual(response.data, expected)
+
+    def test_cannot_affect_others_progress(self):
+        for member in self.project.staffs:
+            response = self.assert_fetch(member, status.HTTP_200_OK)
+            expected = {"total": 1, "remaining": 1, "complete": 0}
+            self.assertEqual(response.data, expected)
+
+
+class TestProgressOnCollaborativeAnnotation(TestProgressHelper):
+    collaborative_annotation = True
+
+    def test_fetch_progress(self):
+        for member in self.project.members:
+            response = self.assert_fetch(member, status.HTTP_200_OK)
+            expected = {"total": 1, "remaining": 0, "complete": 1}
+            self.assertEqual(response.data, expected)
+
+
 class TestCategoryDistribution(CRUDMixin):
     def setUp(self):
         self.project = prepare_project(DOCUMENT_CLASSIFICATION)
diff --git a/backend/metrics/views.py b/backend/metrics/views.py
index ac39fd1a..bca82de1 100644
--- a/backend/metrics/views.py
+++ b/backend/metrics/views.py
@@ -1,5 +1,6 @@
 import abc
 
+from django.shortcuts import get_object_or_404
 from rest_framework import status
 from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
@@ -8,7 +9,7 @@ from rest_framework.views import APIView
 from examples.models import Example, ExampleState
 from label_types.models import CategoryType, LabelType, RelationType, SpanType
 from labels.models import Category, Label, Relation, Span
-from projects.models import Member
+from projects.models import Member, Project
 from projects.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly
 
 
@@ -18,7 +19,11 @@ class ProgressAPI(APIView):
     def get(self, request, *args, **kwargs):
         examples = Example.objects.filter(project=self.kwargs["project_id"]).values("id")
         total = examples.count()
-        complete = ExampleState.objects.count_done(examples, user=self.request.user)
+        project = get_object_or_404(Project, pk=self.kwargs["project_id"])
+        if project.collaborative_annotation:
+            complete = ExampleState.objects.count_done(examples)
+        else:
+            complete = ExampleState.objects.count_done(examples, user=self.request.user)
         data = {"total": total, "remaining": total - complete, "complete": complete}
         return Response(data=data, status=status.HTTP_200_OK)