Repository: akvo/akvo-rsr

Issue:
Keywords cleanup
## Test plan
1. Run the script as a standard Django managent command: `manage.py merge_keywords`
2. The keywords should be merged (as mentioned in the file @lauraroverts provided)
## Issue description

Going forward the project keywords are to be used to gather the projects shown on an Akvo Site. This replaces the use of sponsor partners for this type of grouping. 

As a step in the removal of sponsor partners, all projects associated with a sponsor partner was given a keyword constructed from the ID and the name of the partner organisation. This ensured that no projects were left out, but also has lead to a number of projects, that were already tagged, e.g. with a consortium keyword, to acquire duplicate keywords.

To fix this we need a data migration that merges duplicate keywords. There are also a number of keywords that aren't used any more. Those should be removed. Finally there are some special cases where a number of Walking for Water keywords should be merged. @lauraroverts has made a [list of changes that need to be made (its extension is .txt to allow uploading, and it's semicolon separated)](https://github.com/akvo/akvo-rsr/files/4667/rsr_keywords_merge.txt).



Discussion:

Resolving patch:
diff --git a/akvo/rsr/management/__init__.py b/akvo/rsr/management/__init__.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/management/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+# Akvo Reporting is covered by the GNU Affero General Public License.
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
diff --git a/akvo/rsr/management/commands/__init__.py b/akvo/rsr/management/commands/__init__.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/management/commands/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+# Akvo Reporting is covered by the GNU Affero General Public License.
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
diff --git a/akvo/rsr/management/commands/merge_keywords.py b/akvo/rsr/management/commands/merge_keywords.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/management/commands/merge_keywords.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+# Akvo Reporting is covered by the GNU Affero General Public License.
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
+from django.core.management.base import BaseCommand
+from ...models import Project, Partnership, Keyword
+
+
+class Command(BaseCommand):
+    help = "Script for merging and purging keywords"
+
+    def handle(self, *args, **options):
+        # This dict holds the old keywords as keys and the new ones as values
+        mergers = {
+            '2150:WvW 2015': 'wvw2015', '912:SRHR Alliance': 'SRHR Alliance',
+            '2151:Walking for Water 2015': 'wfw2015', '1151:WvW 2014': 'wvw2014',
+            '272:Connect4Change': 'Connect4Change', '1684:YEP Water': 'YEP', '444:WvW 2012': 'WvW',
+            '1061:WASH Liberia': 'WASH Liberia', '487:Walking for Water 2012': 'WfW',
+            'wfw2012': 'WfW', 'wfw2013': 'WfW', '829:Walking for Water 2013': 'WfW',
+            '1060:Football for Water': 'Football for Water',
+            '275:Dutch WASH Alliance': 'WASH Alliance', '1443:Walking for Water 2014': 'wfw2014',
+            '815:WvW 2013': 'WvW', '2925:WvW 2016': 'wvw2016', 'wvw2012': 'WvW', 'wvw2013': 'WvW',
+            'ttc': False, 'ttc-c4c': False
+        }
+
+        #setup a dict with all keyword objects
+        keyword_objects = {}
+        for key in mergers.keys():
+            keyword_objects[key], _ = Keyword.objects.get_or_create(label=key)
+            if mergers[key]:
+                keyword_objects[mergers[key]], _ = Keyword.objects.get_or_create(label=mergers[key])
+
+        for project in Project.objects.all().prefetch_related('keywords'):
+            for keyword in project.keywords.all():
+                if mergers.get(keyword.label, False):
+                    self.stdout.write(u"Adding keyword {} to project {}:{}".format(
+                        keyword_objects[mergers[keyword.label]], project.id, project.title
+                    ))
+                    project.keywords.add(keyword_objects[mergers[keyword.label]])
+                    self.stdout.write(u"Removing keyword {} from project {}:{}".format(
+                        keyword.label, project.id, project.title
+                    ))
+                    project.keywords.remove(keyword)
+
+        for key in mergers.keys():
+            self.stdout.write(u"Deleting keyword {}".format(key))
+            Keyword.objects.get(label=key).delete()
+
+


Test patch: