diff --git a/tally_ho/apps/tally/templates/super_admin/form_results_duplicates.html b/tally_ho/apps/tally/templates/super_admin/form_results_duplicates.html
index 075ca12cb..a55991048 100644
--- a/tally_ho/apps/tally/templates/super_admin/form_results_duplicates.html
+++ b/tally_ho/apps/tally/templates/super_admin/form_results_duplicates.html
@@ -4,7 +4,7 @@
{% block content %}
-
{% trans 'Results Duplicated List' %}
+{% trans 'Duplicate Result Forms List' %}
diff --git a/tally_ho/apps/tally/templates/super_admin/home.html b/tally_ho/apps/tally/templates/super_admin/home.html
index 819aa7b71..949a79cd3 100644
--- a/tally_ho/apps/tally/templates/super_admin/home.html
+++ b/tally_ho/apps/tally/templates/super_admin/home.html
@@ -62,7 +62,7 @@ {% trans 'Reports' %}
{% trans 'Form Duplicates' %}
{% trans 'Form Clearance' %}
{% trans 'Form Audit' %}
- {% trans 'Form Results Duplicates' %}
+ {% trans 'Duplicate Result Forms List' %}
{% trans 'Download Results' %}
diff --git a/tally_ho/apps/tally/tests/views/test_super_admin.py b/tally_ho/apps/tally/tests/views/test_super_admin.py
index d0fd9fa16..b862fdf7f 100644
--- a/tally_ho/apps/tally/tests/views/test_super_admin.py
+++ b/tally_ho/apps/tally/tests/views/test_super_admin.py
@@ -1160,10 +1160,10 @@ def test_get_result_form_with_duplicate_results(self):
# create duplicate final results
create_result(result_form_4, result.candidate, self.user, votes)
ballot_1_duplicates = views.get_result_form_with_duplicate_results(
- ballot=ballot_1.pk,
+ ballot=ballot_1.number,
tally_id=tally.pk)
ballot_2_duplicates = views.get_result_form_with_duplicate_results(
- ballot=ballot_2.pk,
+ ballot=ballot_2.number,
tally_id=tally.pk)
all_duplicates = views.get_result_form_with_duplicate_results(
tally_id=tally.pk)
@@ -1229,11 +1229,11 @@ def test_duplicate_result_form_view_get(self):
request,
tally_id=tally.pk,
barcode=barcode,
- ballot_id=ballot.pk)
+ ballot_id=ballot.number)
response.render()
self.assertIn(("{}{}").format(
"Duplicate result forms list for ballot: ",
- ballot.pk), str(response.content))
+ ballot.number), str(response.content))
self.assertIn(("{}{}").format("Result form barcode: ",
barcode), str(response.content))
self.assertIn("Send to clearance", str(response.content))
@@ -1277,7 +1277,7 @@ def test_duplicate_result_form_view_duplicate_reviewed_post(self):
request = self.factory.post('/', data=data)
request.user = self.user
configure_messages(request)
- response = view(request, tally_id=tally.pk, ballot_id=ballot.pk)
+ response = view(request, tally_id=tally.pk, ballot_id=ballot.number)
result_form_1.reload()
result_form_2.reload()
@@ -1310,7 +1310,7 @@ def test_duplicate_result_form_view_send_clearance_post(self):
request.user = self.user
configure_messages(request)
request.session = {'result_form': result_form.pk}
- response = view(request, tally_id=tally.pk, ballot_id=ballot.pk)
+ response = view(request, tally_id=tally.pk, ballot_id=ballot.number)
result_form.reload()
self.assertEqual(response.status_code, 302)
@@ -1339,7 +1339,7 @@ def test_duplicate_result_form_view_send_clearance_post(self):
request.user = self.user
configure_messages(request)
request.session = {'result_form': result_form_2.pk}
- response = view(request, tally_id=tally.pk, ballot_id=ballot.pk)
+ response = view(request, tally_id=tally.pk, ballot_id=ballot.number)
result_form_2.reload()
self.assertNotEqual(result_form_2.form_state, FormState.CLEARANCE)
@@ -1384,7 +1384,7 @@ def test_duplicate_result_form_view_send_all_clearance_post(self):
request = self.factory.post('/', data=data)
request.user = self.user
configure_messages(request)
- response = view(request, tally_id=tally.pk, ballot_id=ballot.pk)
+ response = view(request, tally_id=tally.pk, ballot_id=ballot.number)
result_form_1.reload()
result_form_2.reload()
@@ -1432,7 +1432,7 @@ def test_duplicate_archived_result_forms_send_all_clearance_post(self):
request = self.factory.post('/', data=data)
request.user = self.user
configure_messages(request)
- response = view(request, tally_id=tally.pk, ballot_id=ballot.pk)
+ response = view(request, tally_id=tally.pk, ballot_id=ballot.number)
result_form_1.reload()
result_form_2.reload()
diff --git a/tally_ho/apps/tally/views/super_admin.py b/tally_ho/apps/tally/views/super_admin.py
index 794587c95..44bd7c102 100644
--- a/tally_ho/apps/tally/views/super_admin.py
+++ b/tally_ho/apps/tally/views/super_admin.py
@@ -4,7 +4,7 @@
from django.db.models.deletion import ProtectedError
from django.core.exceptions import SuspiciousOperation
from django.contrib.messages.views import SuccessMessageMixin
-from django.db.models import Count, Func, Q, F
+from django.db.models import Count, Q, F
from django.shortcuts import get_object_or_404, redirect
from django.views.generic.edit import UpdateView, DeleteView, CreateView
from django.views.generic import FormView, TemplateView
@@ -180,6 +180,12 @@ def get_results_duplicates(tally_id):
return result_forms_founds
+def all_candidates_have_duplicates(candidate_id_to_votes_array_map):
+ for votes in candidate_id_to_votes_array_map.values():
+ # Check if all items in the list are the same
+ if len(set(votes)) != 1:
+ return False
+ return True
def get_result_form_with_duplicate_results(
ballot=None,
@@ -192,24 +198,55 @@ def get_result_form_with_duplicate_results(
:returns A list of result forms in the system with duplicate results.
"""
- qs = ResultForm.objects.filter(tally_id=tally_id) if not qs else qs
- result_form_ids = qs.exclude(results=None).values(
- 'ballot',
- 'results__votes',
- 'results__candidate') \
- .annotate(ids=ArrayAgg('id')) \
- .annotate(duplicate_count=Count('id')) \
- .annotate(ids=Func('ids', function='unnest')) \
- .filter(
- duplicate_count__gt=1,
- duplicate_reviewed=False
- ).values_list('ids', flat=True).distinct()
+ qs =\
+ ResultForm.objects.filter(
+ tally_id=tally_id,
+ duplicate_reviewed=False) if not qs else qs
+ qs = qs.exclude(results=None)
+ if ballot:
+ qs = qs.filter(ballot__number=ballot)
+ result_forms_barcodes_grouped_by_ballot =\
+ qs.values('ballot').annotate(barcodes=ArrayAgg('barcode'))
+ result_forms_with_ballot =\
+ [
+ b for b in result_forms_barcodes_grouped_by_ballot\
+ if len(b.get('barcodes')) > 1
+ ]
+ result_form_barcodes_with_duplicate_results = []
+ for ballot_result_form_dict in result_forms_with_ballot:
+ candidate_id_to_votes_array_map = {}
+ if ballot_result_form_dict.get('barcodes'):
+ for barcode in ballot_result_form_dict.get('barcodes'):
+ candidate_results_qs =\
+ Result.objects.filter(
+ result_form__tally__id=tally_id,
+ active=True,
+ result_form__barcode=barcode,
+ ).values('candidate_id', 'votes')
+ for candidate_result in candidate_results_qs:
+ candidate_id = candidate_result.get('candidate_id')
+ candidate_votes = candidate_result.get('votes')
+ if candidate_id_to_votes_array_map.get(candidate_id):
+ candidate_id_to_votes_array_map.get(
+ candidate_id).append(candidate_votes)
+ continue
+ candidate_id_to_votes_array_map.setdefault(
+ candidate_id, []).append(candidate_votes)
+
+ if len(candidate_id_to_votes_array_map.values()):
+ # Check for duplicate results
+ duplicates_found =\
+ all_candidates_have_duplicates(
+ candidate_id_to_votes_array_map)
+ if duplicates_found:
+ result_form_barcodes_with_duplicate_results.extend(
+ ballot_result_form_dict.get('barcodes')
+ )
results_form_duplicates = \
- qs.filter(id__in=result_form_ids).order_by('ballot')
-
- if ballot:
- results_form_duplicates = results_form_duplicates.filter(ballot=ballot)
+ qs.filter(
+ barcode__in=result_form_barcodes_with_duplicate_results
+ ).order_by('ballot')
return results_form_duplicates
@@ -494,7 +531,11 @@ def get(self, *args, **kwargs):
ballot_id = kwargs['ballot_id']
result_form = ResultForm.objects.get(
barcode=barcode, tally_id=tally_id)
- results = Result.objects.filter(result_form=result_form.id)
+ results =\
+ Result.objects.filter(
+ result_form=result_form,
+ result_form__tally__id=tally_id,
+ )
return self.render_to_response(self.get_context_data(
results_form_duplicates=get_result_form_with_duplicate_results(