We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Aggregate reward points redemptions in export per user
When exporting the redemptions of an event, all of them are listed in the Excel export. The redemptions of one user should be aggregated into one line.
Also the number of redemptions on the staff page should be replaced by the number of users who redeemed points for an event.

So when a user redeems 1 point and then 2 points for the same event, the export should only state that 3 points have been redeemed in total.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `evap/rewards/exporters.py`
Content:
```
1 from evap.rewards.models import RewardPointRedemption, RewardPointRedemptionEvent
2 
3 from django.utils.translation import ugettext as _
4 
5 from operator import attrgetter
6 
7 from collections import OrderedDict
8 from collections import defaultdict
9 import datetime
10 import xlwt
11 
12 from operator import itemgetter
13 
14 from evap.results.exporters import writen, writec
15 
16 
17 class ExcelExporter(object):
18 
19     def __init__(self, reward_point_redemptions):
20         self.reward_point_redemptions = reward_point_redemptions
21 
22     styles = {
23         'default':       xlwt.Style.default_style,
24         'bold':          xlwt.easyxf('font: bold on'),
25     }
26 
27     def export(self, response):
28         redemptions = self.reward_point_redemptions
29         redemptions = sorted(redemptions, key=attrgetter('user_profile.user.last_name', 'user_profile.user.first_name'))
30 
31         self.workbook = xlwt.Workbook()
32         self.sheet = self.workbook.add_sheet(_(u"Redemptions"))
33         self.row = 0
34         self.col = 0
35 
36         writec(self, _("Last name"), "bold")
37         writec(self, _("First name"), "bold")
38         writec(self, _("Email address"), "bold")
39         writec(self, _("Number of points"), "bold")
40 
41         for redemption in redemptions:
42             user = redemption.user_profile.user
43             writen(self, user.last_name, "default")
44             writec(self, user.first_name, "default")
45             writec(self, user.email, "default")
46             writec(self, redemption.value, "default")
47 
48         self.workbook.save(response)
49
```

Path: `evap/rewards/views.py`
Content:
```
1 from django.contrib import messages
2 from django.db import transaction
3 from django.shortcuts import get_object_or_404, redirect, render_to_response
4 from django.template import RequestContext
5 from django.utils.translation import ugettext as _
6 from django.utils.translation import get_language
7 from django.http import HttpResponse
8 from datetime import datetime
9 from operator import attrgetter
10 
11 from evap.evaluation.auth import reward_user_required, fsr_required
12 from evap.evaluation.models import Semester, Course
13 
14 from evap.fsr.views import semester_view
15 
16 from evap.rewards.models import RewardPointGranting, RewardPointRedemption, RewardPointRedemptionEvent, SemesterActivation
17 from evap.rewards.tools import save_redemptions, reward_points_of_user, can_user_use_reward_points
18 from evap.rewards.forms import RewardPointRedemptionEventForm
19 from evap.rewards.exporters import ExcelExporter
20 
21 @reward_user_required
22 def index(request):
23     if request.method == 'POST':
24         redemptions = {}
25         for key, value in request.POST.iteritems():
26             if(key.startswith('points-')):
27                 event_id = int(key.rpartition('-')[2])
28                 redemptions[event_id] = int(value)
29      
30         if save_redemptions(request, redemptions):
31             messages.success(request, _("You successfully redeemed your points."))
32         else:
33             messages.warning(request, _("You don't have enough reward points."))            
34 
35     total_points_available = reward_points_of_user(request.user.userprofile)
36     reward_point_grantings = RewardPointGranting.objects.filter(user_profile=request.user.userprofile)
37     reward_point_redemptions = RewardPointRedemption.objects.filter(user_profile=request.user.userprofile)
38     events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__gte=datetime.now())
39     events = sorted(events, key=lambda event: event.date)
40 
41     reward_point_actions=[]
42     for granting in reward_point_grantings:
43         reward_point_actions.append((granting.granting_time, _('Reward for') + ' ' + granting.semester.name, granting.value, ''))
44     for redemption in reward_point_redemptions:
45         reward_point_actions.append((redemption.redemption_time, redemption.event.name, '', redemption.value))
46 
47     reward_point_actions.sort(key=lambda action: action[0], reverse=True)
48 
49     return render_to_response(
50         "rewards_index.html",
51         dict(
52             reward_point_actions=reward_point_actions,
53             total_points_available=total_points_available,
54             events=events,
55             point_selection=[x for x in range(0,total_points_available+1)]
56         ),
57         context_instance=RequestContext(request))
58 
59 
60 @fsr_required
61 def semester_reward_points(request, semester_id):
62     semester = get_object_or_404(Semester, id=semester_id)
63     courses = Course.objects.filter(semester=semester)
64     participants = set()
65     for course in courses:
66         for participant in course.participants.all():
67             if can_user_use_reward_points(participant.userprofile):
68                 participants.add(participant)
69     participants = sorted(participants, key=attrgetter('last_name', 'first_name'))
70 
71     data = []
72     for participant in participants:
73         number_of_courses = Course.objects.filter(semester=semester, participants=participant).count()
74         number_of_courses_voted_for = Course.objects.filter(semester=semester, voters=participant).count()
75         earned_reward_points = RewardPointGranting.objects.filter(semester=semester, user_profile=participant.userprofile).exists()
76         data.append((participant, number_of_courses_voted_for, number_of_courses, earned_reward_points))
77 
78     return render_to_response("rewards_semester_reward_points_view.html", dict(semester=semester, data=data, disable_breadcrumb_semester=False), context_instance=RequestContext(request))
79 
80 
81 @fsr_required
82 def reward_point_redemption_events(request):
83     upcoming_events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__gte=datetime.now()).order_by('date')
84     past_events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__lt=datetime.now()).order_by('-date')
85     return render_to_response("rewards_reward_point_redemption_events.html", dict(upcoming_events=upcoming_events, past_events=past_events), context_instance=RequestContext(request))
86 
87 
88 @fsr_required
89 def reward_point_redemption_event_create(request):
90     event = RewardPointRedemptionEvent()
91     form = RewardPointRedemptionEventForm(request.POST or None, instance=event)
92 
93     if form.is_valid():
94         form.save()
95         messages.success(request, _("Successfully created event."))
96         return redirect('evap.rewards.views.reward_point_redemption_events')
97     else:
98         return render_to_response("rewards_reward_point_redemption_event_form.html", dict(form=form), context_instance=RequestContext(request))
99 
100 
101 @fsr_required
102 def reward_point_redemption_event_edit(request, event_id):
103     event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)
104     form = RewardPointRedemptionEventForm(request.POST or None, instance=event)
105 
106     if form.is_valid():
107         event = form.save()
108 
109         messages.success(request, _("Successfully updated event."))
110         return redirect('evap.rewards.views.reward_point_redemption_events')
111     else:
112         return render_to_response("rewards_reward_point_redemption_event_form.html", dict(event=event, form=form), context_instance=RequestContext(request))
113 
114 
115 @fsr_required
116 def reward_point_redemption_event_delete(request, event_id):
117     event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)
118 
119     if event.can_delete:
120         if request.method == 'POST':
121             event.delete()
122             return redirect('evap.rewards.views.reward_point_redemption_events')
123         else:
124             return render_to_response("rewards_reward_point_redemption_event_delete.html", dict(event=event), context_instance=RequestContext(request))
125     else:
126         messages.warning(request, _("This event cannot be deleted because some users already redeemed points for it."))
127         return redirect('evap.rewards.views.reward_point_redemption_events')
128 
129 
130 @fsr_required
131 def reward_point_redemption_event_export(request, event_id):
132     event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)
133 
134     filename = _("RewardPoints")+"-%s-%s-%s.xls" % (event.date, event.name, get_language())
135 
136     response = HttpResponse(content_type="application/vnd.ms-excel")
137     response["Content-Disposition"] = "attachment; filename=\"%s\"" % filename
138 
139     ExcelExporter(event.reward_point_redemptions.all()).export(response)
140 
141     return response
142 
143 
144 @fsr_required
145 def semester_activation(request, semester_id, active):
146     if active == 'on':
147         active = True
148     else:
149         active = False
150 
151     try:
152         activation = SemesterActivation.objects.filter(semester=Semester.objects.get(id=semester_id)).get()
153         activation.is_active = active
154     except SemesterActivation.DoesNotExist:
155         activation = SemesterActivation(semester=Semester.objects.get(id=semester_id), is_active=active)
156     activation.save()
157 
158     return semester_view(request=request, semester_id=semester_id)
159
```

Path: `evap/rewards/models.py`
Content:
```
1 from django.utils.translation import ugettext_lazy as _
2 from django.db import models
3 
4 class RewardPointRedemptionEvent(models.Model):
5     name = models.CharField(max_length=1024, verbose_name=_(u"event name"))
6     date = models.DateField(verbose_name=_(u"event date"))
7     redeem_end_date = models.DateField(verbose_name=_(u"redemption end date"))
8 
9     @property
10     def can_delete(self):
11         if RewardPointRedemption.objects.filter(event=self).exists():
12             return False
13         return True
14 
15 class RewardPointGranting(models.Model):
16     user_profile = models.ForeignKey('evaluation.UserProfile', related_name="reward_point_grantings")
17     semester = models.ForeignKey('evaluation.Semester', related_name="reward_point_grantings", blank=True, null=True)
18     granting_time = models.DateTimeField(verbose_name=_(u"granting time"), auto_now_add=True)
19     value = models.IntegerField(verbose_name=_(u"value"), default=0)
20 
21 class RewardPointRedemption(models.Model):
22     user_profile = models.ForeignKey('evaluation.UserProfile', related_name="reward_point_redemptions")
23     redemption_time = models.DateTimeField(verbose_name=_(u"redemption time"), auto_now_add=True)
24     value = models.IntegerField(verbose_name=_(u"value"), default=0)
25     event = models.ForeignKey(RewardPointRedemptionEvent, related_name="reward_point_redemptions")
26 
27 class SemesterActivation(models.Model):
28     semester = models.ForeignKey('evaluation.Semester', related_name='rewards_active', unique=True)
29     is_active = models.BooleanField(default=False)
30
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/evap/rewards/exporters.py b/evap/rewards/exporters.py
--- a/evap/rewards/exporters.py
+++ b/evap/rewards/exporters.py
@@ -2,8 +2,6 @@
 
 from django.utils.translation import ugettext as _
 
-from operator import attrgetter
-
 from collections import OrderedDict
 from collections import defaultdict
 import datetime
@@ -16,8 +14,8 @@
 
 class ExcelExporter(object):
 
-    def __init__(self, reward_point_redemptions):
-        self.reward_point_redemptions = reward_point_redemptions
+    def __init__(self, redemptions_by_user):
+        self.redemptions_by_user = redemptions_by_user
 
     styles = {
         'default':       xlwt.Style.default_style,
@@ -25,9 +23,8 @@
     }
 
     def export(self, response):
-        redemptions = self.reward_point_redemptions
-        redemptions = sorted(redemptions, key=attrgetter('user_profile.user.last_name', 'user_profile.user.first_name'))
-
+        redemptions_dict = self.redemptions_by_user
+        
         self.workbook = xlwt.Workbook()
         self.sheet = self.workbook.add_sheet(_(u"Redemptions"))
         self.row = 0
@@ -38,11 +35,10 @@
         writec(self, _("Email address"), "bold")
         writec(self, _("Number of points"), "bold")
 
-        for redemption in redemptions:
-            user = redemption.user_profile.user
-            writen(self, user.last_name, "default")
-            writec(self, user.first_name, "default")
-            writec(self, user.email, "default")
-            writec(self, redemption.value, "default")
+        for user_profile, value in redemptions_dict.items():
+            writen(self, user_profile.user.last_name, "default")
+            writec(self, user_profile.user.first_name, "default")
+            writec(self, user_profile.user.email, "default")
+            writec(self, value, "default")
 
         self.workbook.save(response)
diff --git a/evap/rewards/models.py b/evap/rewards/models.py
--- a/evap/rewards/models.py
+++ b/evap/rewards/models.py
@@ -1,6 +1,10 @@
 from django.utils.translation import ugettext_lazy as _
 from django.db import models
 
+from collections import OrderedDict
+
+from operator import attrgetter
+
 class RewardPointRedemptionEvent(models.Model):
     name = models.CharField(max_length=1024, verbose_name=_(u"event name"))
     date = models.DateField(verbose_name=_(u"event date"))
@@ -11,6 +15,15 @@
         if RewardPointRedemption.objects.filter(event=self).exists():
             return False
         return True
+    
+    def redemptions_by_user(self):
+        redemptions = self.reward_point_redemptions.order_by('user_profile__user__last_name', 'user_profile__user__first_name')
+        redemptions_dict = OrderedDict()
+        for redemption in redemptions:
+            if not redemption.user_profile in redemptions_dict:
+                redemptions_dict[redemption.user_profile] = 0
+            redemptions_dict[redemption.user_profile] += redemption.value
+        return redemptions_dict
 
 class RewardPointGranting(models.Model):
     user_profile = models.ForeignKey('evaluation.UserProfile', related_name="reward_point_grantings")
diff --git a/evap/rewards/views.py b/evap/rewards/views.py
--- a/evap/rewards/views.py
+++ b/evap/rewards/views.py
@@ -136,7 +136,7 @@
     response = HttpResponse(content_type="application/vnd.ms-excel")
     response["Content-Disposition"] = "attachment; filename=\"%s\"" % filename
 
-    ExcelExporter(event.reward_point_redemptions.all()).export(response)
+    ExcelExporter(event.redemptions_by_user()).export(response)
 
     return response

{"golden_diff": "diff --git a/evap/rewards/exporters.py b/evap/rewards/exporters.py\n--- a/evap/rewards/exporters.py\n+++ b/evap/rewards/exporters.py\n@@ -2,8 +2,6 @@\n \n from django.utils.translation import ugettext as _\n \n-from operator import attrgetter\n-\n from collections import OrderedDict\n from collections import defaultdict\n import datetime\n@@ -16,8 +14,8 @@\n \n class ExcelExporter(object):\n \n-    def __init__(self, reward_point_redemptions):\n-        self.reward_point_redemptions = reward_point_redemptions\n+    def __init__(self, redemptions_by_user):\n+        self.redemptions_by_user = redemptions_by_user\n \n     styles = {\n         'default':       xlwt.Style.default_style,\n@@ -25,9 +23,8 @@\n     }\n \n     def export(self, response):\n-        redemptions = self.reward_point_redemptions\n-        redemptions = sorted(redemptions, key=attrgetter('user_profile.user.last_name', 'user_profile.user.first_name'))\n-\n+        redemptions_dict = self.redemptions_by_user\n+        \n         self.workbook = xlwt.Workbook()\n         self.sheet = self.workbook.add_sheet(_(u\"Redemptions\"))\n         self.row = 0\n@@ -38,11 +35,10 @@\n         writec(self, _(\"Email address\"), \"bold\")\n         writec(self, _(\"Number of points\"), \"bold\")\n \n-        for redemption in redemptions:\n-            user = redemption.user_profile.user\n-            writen(self, user.last_name, \"default\")\n-            writec(self, user.first_name, \"default\")\n-            writec(self, user.email, \"default\")\n-            writec(self, redemption.value, \"default\")\n+        for user_profile, value in redemptions_dict.items():\n+            writen(self, user_profile.user.last_name, \"default\")\n+            writec(self, user_profile.user.first_name, \"default\")\n+            writec(self, user_profile.user.email, \"default\")\n+            writec(self, value, \"default\")\n \n         self.workbook.save(response)\ndiff --git a/evap/rewards/models.py b/evap/rewards/models.py\n--- a/evap/rewards/models.py\n+++ b/evap/rewards/models.py\n@@ -1,6 +1,10 @@\n from django.utils.translation import ugettext_lazy as _\n from django.db import models\n \n+from collections import OrderedDict\n+\n+from operator import attrgetter\n+\n class RewardPointRedemptionEvent(models.Model):\n     name = models.CharField(max_length=1024, verbose_name=_(u\"event name\"))\n     date = models.DateField(verbose_name=_(u\"event date\"))\n@@ -11,6 +15,15 @@\n         if RewardPointRedemption.objects.filter(event=self).exists():\n             return False\n         return True\n+    \n+    def redemptions_by_user(self):\n+        redemptions = self.reward_point_redemptions.order_by('user_profile__user__last_name', 'user_profile__user__first_name')\n+        redemptions_dict = OrderedDict()\n+        for redemption in redemptions:\n+            if not redemption.user_profile in redemptions_dict:\n+                redemptions_dict[redemption.user_profile] = 0\n+            redemptions_dict[redemption.user_profile] += redemption.value\n+        return redemptions_dict\n \n class RewardPointGranting(models.Model):\n     user_profile = models.ForeignKey('evaluation.UserProfile', related_name=\"reward_point_grantings\")\ndiff --git a/evap/rewards/views.py b/evap/rewards/views.py\n--- a/evap/rewards/views.py\n+++ b/evap/rewards/views.py\n@@ -136,7 +136,7 @@\n     response = HttpResponse(content_type=\"application/vnd.ms-excel\")\n     response[\"Content-Disposition\"] = \"attachment; filename=\\\"%s\\\"\" % filename\n \n-    ExcelExporter(event.reward_point_redemptions.all()).export(response)\n+    ExcelExporter(event.redemptions_by_user()).export(response)\n \n     return response\n", "issue": "Aggregate reward points redemptions in export per user\nWhen exporting the redemptions of an event, all of them are listed in the Excel export. The redemptions of one user should be aggregated into one line.\nAlso the number of redemptions on the staff page should be replaced by the number of users who redeemed points for an event.\n\nSo when a user redeems 1 point and then 2 points for the same event, the export should only state that 3 points have been redeemed in total.\n\n", "before_files": [{"content": "from evap.rewards.models import RewardPointRedemption, RewardPointRedemptionEvent\n\nfrom django.utils.translation import ugettext as _\n\nfrom operator import attrgetter\n\nfrom collections import OrderedDict\nfrom collections import defaultdict\nimport datetime\nimport xlwt\n\nfrom operator import itemgetter\n\nfrom evap.results.exporters import writen, writec\n\n\nclass ExcelExporter(object):\n\n    def __init__(self, reward_point_redemptions):\n        self.reward_point_redemptions = reward_point_redemptions\n\n    styles = {\n        'default':       xlwt.Style.default_style,\n        'bold':          xlwt.easyxf('font: bold on'),\n    }\n\n    def export(self, response):\n        redemptions = self.reward_point_redemptions\n        redemptions = sorted(redemptions, key=attrgetter('user_profile.user.last_name', 'user_profile.user.first_name'))\n\n        self.workbook = xlwt.Workbook()\n        self.sheet = self.workbook.add_sheet(_(u\"Redemptions\"))\n        self.row = 0\n        self.col = 0\n\n        writec(self, _(\"Last name\"), \"bold\")\n        writec(self, _(\"First name\"), \"bold\")\n        writec(self, _(\"Email address\"), \"bold\")\n        writec(self, _(\"Number of points\"), \"bold\")\n\n        for redemption in redemptions:\n            user = redemption.user_profile.user\n            writen(self, user.last_name, \"default\")\n            writec(self, user.first_name, \"default\")\n            writec(self, user.email, \"default\")\n            writec(self, redemption.value, \"default\")\n\n        self.workbook.save(response)\n", "path": "evap/rewards/exporters.py"}, {"content": "from django.contrib import messages\nfrom django.db import transaction\nfrom django.shortcuts import get_object_or_404, redirect, render_to_response\nfrom django.template import RequestContext\nfrom django.utils.translation import ugettext as _\nfrom django.utils.translation import get_language\nfrom django.http import HttpResponse\nfrom datetime import datetime\nfrom operator import attrgetter\n\nfrom evap.evaluation.auth import reward_user_required, fsr_required\nfrom evap.evaluation.models import Semester, Course\n\nfrom evap.fsr.views import semester_view\n\nfrom evap.rewards.models import RewardPointGranting, RewardPointRedemption, RewardPointRedemptionEvent, SemesterActivation\nfrom evap.rewards.tools import save_redemptions, reward_points_of_user, can_user_use_reward_points\nfrom evap.rewards.forms import RewardPointRedemptionEventForm\nfrom evap.rewards.exporters import ExcelExporter\n\n@reward_user_required\ndef index(request):\n    if request.method == 'POST':\n        redemptions = {}\n        for key, value in request.POST.iteritems():\n            if(key.startswith('points-')):\n                event_id = int(key.rpartition('-')[2])\n                redemptions[event_id] = int(value)\n     \n        if save_redemptions(request, redemptions):\n            messages.success(request, _(\"You successfully redeemed your points.\"))\n        else:\n            messages.warning(request, _(\"You don't have enough reward points.\"))            \n\n    total_points_available = reward_points_of_user(request.user.userprofile)\n    reward_point_grantings = RewardPointGranting.objects.filter(user_profile=request.user.userprofile)\n    reward_point_redemptions = RewardPointRedemption.objects.filter(user_profile=request.user.userprofile)\n    events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__gte=datetime.now())\n    events = sorted(events, key=lambda event: event.date)\n\n    reward_point_actions=[]\n    for granting in reward_point_grantings:\n        reward_point_actions.append((granting.granting_time, _('Reward for') + ' ' + granting.semester.name, granting.value, ''))\n    for redemption in reward_point_redemptions:\n        reward_point_actions.append((redemption.redemption_time, redemption.event.name, '', redemption.value))\n\n    reward_point_actions.sort(key=lambda action: action[0], reverse=True)\n\n    return render_to_response(\n        \"rewards_index.html\",\n        dict(\n            reward_point_actions=reward_point_actions,\n            total_points_available=total_points_available,\n            events=events,\n            point_selection=[x for x in range(0,total_points_available+1)]\n        ),\n        context_instance=RequestContext(request))\n\n\n@fsr_required\ndef semester_reward_points(request, semester_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    courses = Course.objects.filter(semester=semester)\n    participants = set()\n    for course in courses:\n        for participant in course.participants.all():\n            if can_user_use_reward_points(participant.userprofile):\n                participants.add(participant)\n    participants = sorted(participants, key=attrgetter('last_name', 'first_name'))\n\n    data = []\n    for participant in participants:\n        number_of_courses = Course.objects.filter(semester=semester, participants=participant).count()\n        number_of_courses_voted_for = Course.objects.filter(semester=semester, voters=participant).count()\n        earned_reward_points = RewardPointGranting.objects.filter(semester=semester, user_profile=participant.userprofile).exists()\n        data.append((participant, number_of_courses_voted_for, number_of_courses, earned_reward_points))\n\n    return render_to_response(\"rewards_semester_reward_points_view.html\", dict(semester=semester, data=data, disable_breadcrumb_semester=False), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_events(request):\n    upcoming_events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__gte=datetime.now()).order_by('date')\n    past_events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__lt=datetime.now()).order_by('-date')\n    return render_to_response(\"rewards_reward_point_redemption_events.html\", dict(upcoming_events=upcoming_events, past_events=past_events), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_event_create(request):\n    event = RewardPointRedemptionEvent()\n    form = RewardPointRedemptionEventForm(request.POST or None, instance=event)\n\n    if form.is_valid():\n        form.save()\n        messages.success(request, _(\"Successfully created event.\"))\n        return redirect('evap.rewards.views.reward_point_redemption_events')\n    else:\n        return render_to_response(\"rewards_reward_point_redemption_event_form.html\", dict(form=form), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_event_edit(request, event_id):\n    event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)\n    form = RewardPointRedemptionEventForm(request.POST or None, instance=event)\n\n    if form.is_valid():\n        event = form.save()\n\n        messages.success(request, _(\"Successfully updated event.\"))\n        return redirect('evap.rewards.views.reward_point_redemption_events')\n    else:\n        return render_to_response(\"rewards_reward_point_redemption_event_form.html\", dict(event=event, form=form), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_event_delete(request, event_id):\n    event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)\n\n    if event.can_delete:\n        if request.method == 'POST':\n            event.delete()\n            return redirect('evap.rewards.views.reward_point_redemption_events')\n        else:\n            return render_to_response(\"rewards_reward_point_redemption_event_delete.html\", dict(event=event), context_instance=RequestContext(request))\n    else:\n        messages.warning(request, _(\"This event cannot be deleted because some users already redeemed points for it.\"))\n        return redirect('evap.rewards.views.reward_point_redemption_events')\n\n\n@fsr_required\ndef reward_point_redemption_event_export(request, event_id):\n    event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)\n\n    filename = _(\"RewardPoints\")+\"-%s-%s-%s.xls\" % (event.date, event.name, get_language())\n\n    response = HttpResponse(content_type=\"application/vnd.ms-excel\")\n    response[\"Content-Disposition\"] = \"attachment; filename=\\\"%s\\\"\" % filename\n\n    ExcelExporter(event.reward_point_redemptions.all()).export(response)\n\n    return response\n\n\n@fsr_required\ndef semester_activation(request, semester_id, active):\n    if active == 'on':\n        active = True\n    else:\n        active = False\n\n    try:\n        activation = SemesterActivation.objects.filter(semester=Semester.objects.get(id=semester_id)).get()\n        activation.is_active = active\n    except SemesterActivation.DoesNotExist:\n        activation = SemesterActivation(semester=Semester.objects.get(id=semester_id), is_active=active)\n    activation.save()\n\n    return semester_view(request=request, semester_id=semester_id)\n", "path": "evap/rewards/views.py"}, {"content": "from django.utils.translation import ugettext_lazy as _\nfrom django.db import models\n\nclass RewardPointRedemptionEvent(models.Model):\n    name = models.CharField(max_length=1024, verbose_name=_(u\"event name\"))\n    date = models.DateField(verbose_name=_(u\"event date\"))\n    redeem_end_date = models.DateField(verbose_name=_(u\"redemption end date\"))\n\n    @property\n    def can_delete(self):\n        if RewardPointRedemption.objects.filter(event=self).exists():\n            return False\n        return True\n\nclass RewardPointGranting(models.Model):\n    user_profile = models.ForeignKey('evaluation.UserProfile', related_name=\"reward_point_grantings\")\n    semester = models.ForeignKey('evaluation.Semester', related_name=\"reward_point_grantings\", blank=True, null=True)\n    granting_time = models.DateTimeField(verbose_name=_(u\"granting time\"), auto_now_add=True)\n    value = models.IntegerField(verbose_name=_(u\"value\"), default=0)\n\nclass RewardPointRedemption(models.Model):\n    user_profile = models.ForeignKey('evaluation.UserProfile', related_name=\"reward_point_redemptions\")\n    redemption_time = models.DateTimeField(verbose_name=_(u\"redemption time\"), auto_now_add=True)\n    value = models.IntegerField(verbose_name=_(u\"value\"), default=0)\n    event = models.ForeignKey(RewardPointRedemptionEvent, related_name=\"reward_point_redemptions\")\n\nclass SemesterActivation(models.Model):\n    semester = models.ForeignKey('evaluation.Semester', related_name='rewards_active', unique=True)\n    is_active = models.BooleanField(default=False)\n", "path": "evap/rewards/models.py"}], "after_files": [{"content": "from evap.rewards.models import RewardPointRedemption, RewardPointRedemptionEvent\n\nfrom django.utils.translation import ugettext as _\n\nfrom collections import OrderedDict\nfrom collections import defaultdict\nimport datetime\nimport xlwt\n\nfrom operator import itemgetter\n\nfrom evap.results.exporters import writen, writec\n\n\nclass ExcelExporter(object):\n\n    def __init__(self, redemptions_by_user):\n        self.redemptions_by_user = redemptions_by_user\n\n    styles = {\n        'default':       xlwt.Style.default_style,\n        'bold':          xlwt.easyxf('font: bold on'),\n    }\n\n    def export(self, response):\n        redemptions_dict = self.redemptions_by_user\n        \n        self.workbook = xlwt.Workbook()\n        self.sheet = self.workbook.add_sheet(_(u\"Redemptions\"))\n        self.row = 0\n        self.col = 0\n\n        writec(self, _(\"Last name\"), \"bold\")\n        writec(self, _(\"First name\"), \"bold\")\n        writec(self, _(\"Email address\"), \"bold\")\n        writec(self, _(\"Number of points\"), \"bold\")\n\n        for user_profile, value in redemptions_dict.items():\n            writen(self, user_profile.user.last_name, \"default\")\n            writec(self, user_profile.user.first_name, \"default\")\n            writec(self, user_profile.user.email, \"default\")\n            writec(self, value, \"default\")\n\n        self.workbook.save(response)\n", "path": "evap/rewards/exporters.py"}, {"content": "from django.contrib import messages\nfrom django.db import transaction\nfrom django.shortcuts import get_object_or_404, redirect, render_to_response\nfrom django.template import RequestContext\nfrom django.utils.translation import ugettext as _\nfrom django.utils.translation import get_language\nfrom django.http import HttpResponse\nfrom datetime import datetime\nfrom operator import attrgetter\n\nfrom evap.evaluation.auth import reward_user_required, fsr_required\nfrom evap.evaluation.models import Semester, Course\n\nfrom evap.fsr.views import semester_view\n\nfrom evap.rewards.models import RewardPointGranting, RewardPointRedemption, RewardPointRedemptionEvent, SemesterActivation\nfrom evap.rewards.tools import save_redemptions, reward_points_of_user, can_user_use_reward_points\nfrom evap.rewards.forms import RewardPointRedemptionEventForm\nfrom evap.rewards.exporters import ExcelExporter\n\n@reward_user_required\ndef index(request):\n    if request.method == 'POST':\n        redemptions = {}\n        for key, value in request.POST.iteritems():\n            if(key.startswith('points-')):\n                event_id = int(key.rpartition('-')[2])\n                redemptions[event_id] = int(value)\n     \n        if save_redemptions(request, redemptions):\n            messages.success(request, _(\"You successfully redeemed your points.\"))\n        else:\n            messages.warning(request, _(\"You don't have enough reward points.\"))            \n\n    total_points_available = reward_points_of_user(request.user.userprofile)\n    reward_point_grantings = RewardPointGranting.objects.filter(user_profile=request.user.userprofile)\n    reward_point_redemptions = RewardPointRedemption.objects.filter(user_profile=request.user.userprofile)\n    events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__gte=datetime.now())\n    events = sorted(events, key=lambda event: event.date)\n\n    reward_point_actions=[]\n    for granting in reward_point_grantings:\n        reward_point_actions.append((granting.granting_time, _('Reward for') + ' ' + granting.semester.name, granting.value, ''))\n    for redemption in reward_point_redemptions:\n        reward_point_actions.append((redemption.redemption_time, redemption.event.name, '', redemption.value))\n\n    reward_point_actions.sort(key=lambda action: action[0], reverse=True)\n\n    return render_to_response(\n        \"rewards_index.html\",\n        dict(\n            reward_point_actions=reward_point_actions,\n            total_points_available=total_points_available,\n            events=events,\n            point_selection=[x for x in range(0,total_points_available+1)]\n        ),\n        context_instance=RequestContext(request))\n\n\n@fsr_required\ndef semester_reward_points(request, semester_id):\n    semester = get_object_or_404(Semester, id=semester_id)\n    courses = Course.objects.filter(semester=semester)\n    participants = set()\n    for course in courses:\n        for participant in course.participants.all():\n            if can_user_use_reward_points(participant.userprofile):\n                participants.add(participant)\n    participants = sorted(participants, key=attrgetter('last_name', 'first_name'))\n\n    data = []\n    for participant in participants:\n        number_of_courses = Course.objects.filter(semester=semester, participants=participant).count()\n        number_of_courses_voted_for = Course.objects.filter(semester=semester, voters=participant).count()\n        earned_reward_points = RewardPointGranting.objects.filter(semester=semester, user_profile=participant.userprofile).exists()\n        data.append((participant, number_of_courses_voted_for, number_of_courses, earned_reward_points))\n\n    return render_to_response(\"rewards_semester_reward_points_view.html\", dict(semester=semester, data=data, disable_breadcrumb_semester=False), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_events(request):\n    upcoming_events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__gte=datetime.now()).order_by('date')\n    past_events = RewardPointRedemptionEvent.objects.filter(redeem_end_date__lt=datetime.now()).order_by('-date')\n    return render_to_response(\"rewards_reward_point_redemption_events.html\", dict(upcoming_events=upcoming_events, past_events=past_events), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_event_create(request):\n    event = RewardPointRedemptionEvent()\n    form = RewardPointRedemptionEventForm(request.POST or None, instance=event)\n\n    if form.is_valid():\n        form.save()\n        messages.success(request, _(\"Successfully created event.\"))\n        return redirect('evap.rewards.views.reward_point_redemption_events')\n    else:\n        return render_to_response(\"rewards_reward_point_redemption_event_form.html\", dict(form=form), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_event_edit(request, event_id):\n    event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)\n    form = RewardPointRedemptionEventForm(request.POST or None, instance=event)\n\n    if form.is_valid():\n        event = form.save()\n\n        messages.success(request, _(\"Successfully updated event.\"))\n        return redirect('evap.rewards.views.reward_point_redemption_events')\n    else:\n        return render_to_response(\"rewards_reward_point_redemption_event_form.html\", dict(event=event, form=form), context_instance=RequestContext(request))\n\n\n@fsr_required\ndef reward_point_redemption_event_delete(request, event_id):\n    event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)\n\n    if event.can_delete:\n        if request.method == 'POST':\n            event.delete()\n            return redirect('evap.rewards.views.reward_point_redemption_events')\n        else:\n            return render_to_response(\"rewards_reward_point_redemption_event_delete.html\", dict(event=event), context_instance=RequestContext(request))\n    else:\n        messages.warning(request, _(\"This event cannot be deleted because some users already redeemed points for it.\"))\n        return redirect('evap.rewards.views.reward_point_redemption_events')\n\n\n@fsr_required\ndef reward_point_redemption_event_export(request, event_id):\n    event = get_object_or_404(RewardPointRedemptionEvent, id=event_id)\n\n    filename = _(\"RewardPoints\")+\"-%s-%s-%s.xls\" % (event.date, event.name, get_language())\n\n    response = HttpResponse(content_type=\"application/vnd.ms-excel\")\n    response[\"Content-Disposition\"] = \"attachment; filename=\\\"%s\\\"\" % filename\n\n    ExcelExporter(event.redemptions_by_user()).export(response)\n\n    return response\n\n\n@fsr_required\ndef semester_activation(request, semester_id, active):\n    if active == 'on':\n        active = True\n    else:\n        active = False\n\n    try:\n        activation = SemesterActivation.objects.filter(semester=Semester.objects.get(id=semester_id)).get()\n        activation.is_active = active\n    except SemesterActivation.DoesNotExist:\n        activation = SemesterActivation(semester=Semester.objects.get(id=semester_id), is_active=active)\n    activation.save()\n\n    return semester_view(request=request, semester_id=semester_id)\n", "path": "evap/rewards/views.py"}, {"content": "from django.utils.translation import ugettext_lazy as _\nfrom django.db import models\n\nfrom collections import OrderedDict\n\nfrom operator import attrgetter\n\nclass RewardPointRedemptionEvent(models.Model):\n    name = models.CharField(max_length=1024, verbose_name=_(u\"event name\"))\n    date = models.DateField(verbose_name=_(u\"event date\"))\n    redeem_end_date = models.DateField(verbose_name=_(u\"redemption end date\"))\n\n    @property\n    def can_delete(self):\n        if RewardPointRedemption.objects.filter(event=self).exists():\n            return False\n        return True\n    \n    def redemptions_by_user(self):\n        redemptions = self.reward_point_redemptions.order_by('user_profile__user__last_name', 'user_profile__user__first_name')\n        redemptions_dict = OrderedDict()\n        for redemption in redemptions:\n            if not redemption.user_profile in redemptions_dict:\n                redemptions_dict[redemption.user_profile] = 0\n            redemptions_dict[redemption.user_profile] += redemption.value\n        return redemptions_dict\n\nclass RewardPointGranting(models.Model):\n    user_profile = models.ForeignKey('evaluation.UserProfile', related_name=\"reward_point_grantings\")\n    semester = models.ForeignKey('evaluation.Semester', related_name=\"reward_point_grantings\", blank=True, null=True)\n    granting_time = models.DateTimeField(verbose_name=_(u\"granting time\"), auto_now_add=True)\n    value = models.IntegerField(verbose_name=_(u\"value\"), default=0)\n\nclass RewardPointRedemption(models.Model):\n    user_profile = models.ForeignKey('evaluation.UserProfile', related_name=\"reward_point_redemptions\")\n    redemption_time = models.DateTimeField(verbose_name=_(u\"redemption time\"), auto_now_add=True)\n    value = models.IntegerField(verbose_name=_(u\"value\"), default=0)\n    event = models.ForeignKey(RewardPointRedemptionEvent, related_name=\"reward_point_redemptions\")\n\nclass SemesterActivation(models.Model):\n    semester = models.ForeignKey('evaluation.Semester', related_name='rewards_active', unique=True)\n    is_active = models.BooleanField(default=False)\n", "path": "evap/rewards/models.py"}]}