Repository: carpentries/amy

Issue:
Removing awards
As per https://github.com/swcarpentry/amy/pull/431#issue-95627056 we don't have a way to remove once assigned awards.



Discussion:

Resolving patch:
diff --git a/workshops/urls.py b/workshops/urls.py
--- a/workshops/urls.py
+++ b/workshops/urls.py
@@ -44,6 +44,9 @@
     url(r'^event/(?P<event_ident>[\w-]+)/task/(?P<task_id>\d+)/delete$', views.task_delete, name='task_delete'),
     url(r'^tasks/add/$', views.TaskCreate.as_view(), name='task_add'),
 
+    url(r'^award/(?P<award_id>\d+)/delete$', views.award_delete, name='award_delete'),
+    url(r'^person/(?P<person_id>[\w\.-]+)/award/(?P<award_id>\d+)/delete$', views.award_delete, name='award_delete'),
+
     url(r'^badges/?$', views.all_badges, name='all_badges'),
     url(r'^badge/(?P<badge_name>[\w\.=-]+)/?$', views.badge_details, name='badge_details'),
 
diff --git a/workshops/views.py b/workshops/views.py
--- a/workshops/views.py
+++ b/workshops/views.py
@@ -971,6 +971,25 @@ class TaskUpdate(LoginRequiredMixin, PermissionRequiredMixin,
     pk_url_kwarg = 'task_id'
     template_name = 'workshops/generic_form.html'
 
+#------------------------------------------------------------
+
+
+@permission_required('workshops.delete_award', raise_exception=True)
+def award_delete(request, award_id, person_id=None):
+    """Delete an award. This is used on the person edit page."""
+    award = get_object_or_404(Award, pk=award_id)
+    badge_name = award.badge.name
+    award.delete()
+
+    messages.success(request, 'Award was deleted successfully.',
+                     extra_tags='awards')
+
+    if person_id:
+        # if a second form of URL, then return back to person edit page
+        return redirect(person_edit, person_id)
+
+    return redirect(reverse(badge_details, args=[badge_name]))
+
 
 #------------------------------------------------------------
 


Test patch:
diff --git a/workshops/test/test_badge.py b/workshops/test/test_badge.py
--- a/workshops/test/test_badge.py
+++ b/workshops/test/test_badge.py
@@ -49,3 +49,29 @@ def test_badge_award(self):
         self._check_status_code_and_parse(response, 200)
 
         assert self.instructor.award_set.count() == 4
+
+    def test_remove_award(self):
+        "Remove a badge from someone (ie. remove corresponding Award object)."
+        person = self.hermione
+        award = person.award_set.all()[0]
+        badge = award.badge
+        # test first URL
+        rv = self.client.get(
+            reverse('award_delete',
+                    kwargs=dict(award_id=award.pk, person_id=person.pk)),
+        )
+        assert rv.status_code == 302
+        assert award not in badge.award_set.all()  # award really removed
+        assert badge not in person.badges.all()  # badge not avail. via Awards
+
+        person = self.ron
+        award = person.award_set.all()[0]
+        badge = award.badge
+        # test second URL
+        rv = self.client.get(
+            reverse('award_delete',
+                    kwargs=dict(award_id=award.pk)),
+        )
+        assert rv.status_code == 302
+        assert award not in badge.award_set.all()  # award really removed
+        assert badge not in person.badges.all()  # badge not avail. via Awards