Repository: WeblateOrg/weblate

Issue:
Vote for suggestion when adding duplicate
Currently duplicate suggestions are ignored, but it would be better if it would be accepted as upvote in case voting is enabled for given translation.

See also https://github.com/WeblateOrg/weblate/issues/1348#issuecomment-280706768

<bountysource-plugin>

---
Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/42236397-vote-for-suggestion-when-adding-duplicate?utm_campaign=plugin&utm_content=tracker%2F253393&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F253393&utm_medium=issues&utm_source=github).
</bountysource-plugin>


Discussion:

Resolving patch:
diff --git a/weblate/trans/models/suggestion.py b/weblate/trans/models/suggestion.py
--- a/weblate/trans/models/suggestion.py
+++ b/weblate/trans/models/suggestion.py
@@ -35,6 +35,7 @@
 from weblate.utils.fields import JSONField
 from weblate.utils.state import STATE_TRANSLATED
 from weblate.utils.request import get_ip_address
+from django.core.exceptions import ObjectDoesNotExist
 
 
 class SuggestionManager(models.Manager):
@@ -44,15 +45,22 @@ def add(self, unit, target, request, vote=False):
         """Create new suggestion for this unit."""
         user = request.user
 
-        same = self.filter(
-            target=target,
-            content_hash=unit.content_hash,
-            language=unit.translation.language,
-            project=unit.translation.component.project,
-        )
+        try:
+            same = self.get(
+                target=target,
+                content_hash=unit.content_hash,
+                language=unit.translation.language,
+                project=unit.translation.component.project,
+            )
+
+            if same.user == user or not vote:
+                return False
+            else:
+                same.add_vote(unit.translation, request, True)
+                return False
 
-        if same.exists() or (unit.target == target and not unit.fuzzy):
-            return False
+        except ObjectDoesNotExist:
+            pass
 
         # Create the suggestion
         suggestion = self.create(


Test patch:
diff --git a/weblate/trans/tests/test_suggestions.py b/weblate/trans/tests/test_suggestions.py
--- a/weblate/trans/tests/test_suggestions.py
+++ b/weblate/trans/tests/test_suggestions.py
@@ -290,3 +290,34 @@ def test_vote_autoaccept(self):
         self.assertFalse(unit.fuzzy)
         self.assertEqual(unit.target, 'Nazdar svete!\n')
         self.assert_backend(1)
+
+    def test_vote_when_same_suggestion(self):
+        translate_url = reverse('translate', kwargs=self.kw_translation)
+        self.component.suggestion_voting = True
+        self.component.suggestion_autoaccept = 0
+        self.component.save()
+
+        # Add the first suggestion as default test-user
+        response = self.add_suggestion_1()
+        suggestion_id = self.get_unit().suggestions[0].pk
+        suggestion = Suggestion.objects.get(pk=suggestion_id)
+
+        # Suggestion get vote from the user that makes suggestion
+        self.assertEqual(
+            suggestion.get_num_votes(),
+            1
+        )
+
+        # Add suggestion as second user
+        self.log_as_jane()
+        response = self.add_suggestion_1()
+
+        # When adding the same suggestion, we stay on the same page
+        self.assert_redirects_offset(response, translate_url, 1)
+        suggestion = Suggestion.objects.get(pk=suggestion_id)
+
+        # and the suggestion gets an upvote
+        self.assertEqual(
+            suggestion.get_num_votes(),
+            2
+        )
diff --git a/weblate/trans/tests/test_views.py b/weblate/trans/tests/test_views.py
--- a/weblate/trans/tests/test_views.py
+++ b/weblate/trans/tests/test_views.py
@@ -39,7 +39,7 @@
 from weblate.trans.models import ComponentList, WhiteboardMessage, Project
 from weblate.trans.search import Fulltext
 from weblate.trans.tests.test_models import RepoTestCase
-from weblate.trans.tests.utils import create_test_user, wait_for_celery
+from weblate.trans.tests.utils import create_test_user, wait_for_celery, create_another_user
 from weblate.utils.hash import hash_to_checksum
 from weblate.accounts.models import Profile
 
@@ -89,6 +89,9 @@ def setUp(self):
         self.user = create_test_user()
         group = Group.objects.get(name='Users')
         self.user.groups.add(group)
+        # Create another user
+        self.anotheruser = create_another_user()
+        self.user.groups.add(group)
         # Create project to have some test base
         self.component = self.create_component()
         self.project = self.component.project
@@ -242,6 +245,9 @@ def assert_backend(self, expected_translated):
             )
         )
 
+    def log_as_jane(self):
+        self.client.login(username='jane', password='anotherpassword')
+
 
 class FixtureTestCase(ViewTestCase):
     @classmethod
diff --git a/weblate/trans/tests/utils.py b/weblate/trans/tests/utils.py
--- a/weblate/trans/tests/utils.py
+++ b/weblate/trans/tests/utils.py
@@ -70,6 +70,14 @@ def create_test_user():
         full_name='Weblate Test',
     )
 
+def create_another_user():
+    return User.objects.create_user(
+        'jane',
+        'jane.doe@example.org',
+        'anotherpassword',
+        full_name='Jane Doe',
+    )
+
 
 class RepoTestMixin(object):
     """Mixin for testing with test repositories."""