We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Proxied evaluations shouldn't show as delegated
Evaluations where a proxy user is responsible shouldn't be shown as "delegated courses" for the delegates of this proxy user. The delegates should see this course in the list of their own courses like those they are directly responsible for and they shouldn't be hidden when the option to hide delegated courses is active.

--- 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/contributor/views.py`
Content:
```
1 from django.contrib import messages
2 from django.core.exceptions import PermissionDenied, SuspiciousOperation
3 from django.db import IntegrityError, transaction
4 from django.db.models import Max, Q
5 from django.forms.models import inlineformset_factory
6 from django.shortcuts import get_object_or_404, redirect, render
7 from django.utils.translation import gettext as _
8 from django.views.decorators.http import require_POST
9 
10 from evap.contributor.forms import EvaluationForm, DelegatesForm, EditorContributionForm, DelegateSelectionForm
11 from evap.evaluation.auth import responsible_or_contributor_or_delegate_required, editor_or_delegate_required, editor_required
12 from evap.evaluation.models import Contribution, Course, CourseType, Degree, Evaluation, Semester, UserProfile, EmailTemplate
13 from evap.evaluation.tools import get_parameter_from_url_or_session, sort_formset, FileResponse
14 from evap.results.exporters import ResultsExporter
15 from evap.results.tools import (calculate_average_distribution, distribution_to_grade,
16                                 get_evaluations_with_course_result_attributes, get_single_result_rating_result,
17                                 normalized_distribution)
18 from evap.staff.forms import ContributionFormSet
19 from evap.student.views import get_valid_form_groups_or_render_vote_page
20 
21 
22 @responsible_or_contributor_or_delegate_required
23 def index(request):
24     user = request.user
25     show_delegated = get_parameter_from_url_or_session(request, "show_delegated", True)
26 
27     contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']
28     own_courses = Course.objects.filter(
29         Q(evaluations__state__in=contributor_visible_states) & (
30             Q(responsibles=user) |
31             Q(evaluations__contributions__contributor=user)
32         )
33     )
34     own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]
35     for evaluation in own_evaluations:
36         evaluation.contributes_to = evaluation.contributions.filter(contributor=user).exists()
37 
38     displayed_evaluations = set(own_evaluations)
39     if show_delegated:
40         represented_users = user.represented_users.all()
41         delegated_courses = Course.objects.filter(
42             Q(evaluations__state__in=contributor_visible_states) & (
43                 Q(responsibles__in=represented_users) |
44                 Q(
45                     evaluations__contributions__role=Contribution.Role.EDITOR,
46                     evaluations__contributions__contributor__in=represented_users,
47                 )
48             )
49         )
50         delegated_evaluations = set(evaluation for course in delegated_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user))
51         for evaluation in delegated_evaluations:
52             evaluation.delegated_evaluation = True
53         displayed_evaluations |= delegated_evaluations - displayed_evaluations
54     displayed_evaluations = list(displayed_evaluations)
55     displayed_evaluations.sort(key=lambda evaluation: (evaluation.course.name, evaluation.name))  # evaluations must be sorted for regrouping them in the template
56 
57     for evaluation in displayed_evaluations:
58         if evaluation.state == "published":
59             if not evaluation.is_single_result:
60                 evaluation.distribution = calculate_average_distribution(evaluation)
61             else:
62                 evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
63                 evaluation.distribution = normalized_distribution(evaluation.single_result_rating_result.counts)
64             evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
65     displayed_evaluations = get_evaluations_with_course_result_attributes(displayed_evaluations)
66 
67     semesters = Semester.objects.all()
68     semester_list = [dict(
69         semester_name=semester.name,
70         id=semester.id,
71         is_active=semester.is_active,
72         evaluations=[evaluation for evaluation in displayed_evaluations if evaluation.course.semester_id == semester.id]
73     ) for semester in semesters]
74 
75     template_data = dict(
76         semester_list=semester_list,
77         show_delegated=show_delegated,
78         delegate_selection_form=DelegateSelectionForm(),
79     )
80     return render(request, "contributor_index.html", template_data)
81 
82 
83 @editor_required
84 def settings_edit(request):
85     user = request.user
86     form = DelegatesForm(request.POST or None, request.FILES or None, instance=user)
87 
88     if form.is_valid():
89         form.save()
90 
91         messages.success(request, _("Successfully updated your settings."))
92         return redirect('contributor:settings_edit')
93 
94     return render(request, "contributor_settings.html", dict(
95         form=form,
96         delegate_of=user.represented_users.all(),
97         cc_users=user.cc_users.all(),
98         ccing_users=user.ccing_users.all(),
99     ))
100 
101 
102 @editor_or_delegate_required
103 def evaluation_view(request, evaluation_id):
104     user = request.user
105     evaluation = get_object_or_404(Evaluation, id=evaluation_id)
106 
107     # check rights
108     if not evaluation.is_user_editor_or_delegate(user) or evaluation.state not in ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed']:
109         raise PermissionDenied
110 
111     InlineContributionFormset = inlineformset_factory(Evaluation, Contribution, formset=ContributionFormSet, form=EditorContributionForm, extra=0)
112 
113     form = EvaluationForm(request.POST or None, instance=evaluation)
114     formset = InlineContributionFormset(request.POST or None, instance=evaluation)
115 
116     # make everything read-only
117     for cform in formset.forms + [form]:
118         for field in cform.fields.values():
119             field.disabled = True
120 
121     template_data = dict(form=form, formset=formset, evaluation=evaluation, editable=False)
122     return render(request, "contributor_evaluation_form.html", template_data)
123 
124 
125 def render_preview(request, formset, evaluation_form, evaluation):
126     # open transaction to not let any other requests see anything of what we're doing here
127     try:
128         with transaction.atomic():
129             evaluation = evaluation_form.save()
130             evaluation.set_last_modified(request.user)
131             evaluation.save()
132             formset.save()
133             request.POST = None  # this prevents errors rendered in the vote form
134 
135             preview_response = get_valid_form_groups_or_render_vote_page(request, evaluation, preview=True, for_rendering_in_modal=True)[1].content.decode()
136             raise IntegrityError  # rollback transaction to discard the database writes
137     except IntegrityError:
138         pass
139 
140     return preview_response
141 
142 
143 @editor_or_delegate_required
144 def evaluation_edit(request, evaluation_id):
145     evaluation = get_object_or_404(Evaluation, id=evaluation_id)
146 
147     # check rights
148     if not (evaluation.is_user_editor_or_delegate(request.user) and evaluation.state == 'prepared'):
149         raise PermissionDenied
150 
151     post_operation = request.POST.get('operation') if request.POST else None
152     preview = post_operation == 'preview'
153 
154     InlineContributionFormset = inlineformset_factory(Evaluation, Contribution, formset=ContributionFormSet, form=EditorContributionForm, extra=1)
155     evaluation_form = EvaluationForm(request.POST or None, instance=evaluation)
156     formset = InlineContributionFormset(request.POST or None, instance=evaluation, form_kwargs={'evaluation': evaluation})
157 
158     forms_are_valid = evaluation_form.is_valid() and formset.is_valid()
159     if forms_are_valid and not preview:
160         if post_operation not in ('save', 'approve'):
161             raise SuspiciousOperation("Invalid POST operation")
162 
163         form_has_changed = evaluation_form.has_changed() or formset.has_changed()
164 
165         if form_has_changed:
166             evaluation.set_last_modified(request.user)
167         evaluation_form.save()
168         formset.save()
169 
170         if post_operation == 'approve':
171             evaluation.editor_approve()
172             evaluation.save()
173             if form_has_changed:
174                 messages.success(request, _("Successfully updated and approved evaluation."))
175             else:
176                 messages.success(request, _("Successfully approved evaluation."))
177         else:
178             messages.success(request, _("Successfully updated evaluation."))
179 
180         return redirect('contributor:index')
181 
182     preview_html = None
183     if preview and forms_are_valid:
184         preview_html = render_preview(request, formset, evaluation_form, evaluation)
185 
186     if not forms_are_valid and (evaluation_form.errors or formset.errors):
187         if preview:
188             messages.error(request, _("The preview could not be rendered. Please resolve the errors shown below."))
189         else:
190             messages.error(request, _("The form was not saved. Please resolve the errors shown below."))
191 
192     sort_formset(request, formset)
193     template_data = dict(form=evaluation_form, formset=formset, evaluation=evaluation, editable=True, preview_html=preview_html)
194     return render(request, "contributor_evaluation_form.html", template_data)
195 
196 
197 @responsible_or_contributor_or_delegate_required
198 def evaluation_preview(request, evaluation_id):
199     user = request.user
200     evaluation = get_object_or_404(Evaluation, id=evaluation_id)
201 
202     # check rights
203     if not (evaluation.is_user_responsible_or_contributor_or_delegate(user) and evaluation.state in ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed']):
204         raise PermissionDenied
205 
206     return get_valid_form_groups_or_render_vote_page(request, evaluation, preview=True)[1]
207 
208 
209 @require_POST
210 @editor_or_delegate_required
211 def evaluation_direct_delegation(request, evaluation_id):
212     delegate_user_id = request.POST.get("delegate_to")
213 
214     evaluation = get_object_or_404(Evaluation, id=evaluation_id)
215     delegate_user = get_object_or_404(UserProfile, id=delegate_user_id)
216 
217     contribution, created = Contribution.objects.update_or_create(
218         evaluation=evaluation,
219         contributor=delegate_user,
220         defaults={'role': Contribution.Role.EDITOR},
221     )
222     if created:
223         contribution.order = evaluation.contributions.all().aggregate(Max('order'))['order__max'] + 1
224         contribution.save()
225 
226     template = EmailTemplate.objects.get(name=EmailTemplate.DIRECT_DELEGATION)
227     subject_params = {"evaluation": evaluation, "user": request.user, "delegate_user": delegate_user}
228     body_params = subject_params
229 
230     # we don't provide the request here since send_to_user only uses it to display a warning message in case the user does not have
231     # an email address. In this special case, we don't want that warning. Instead, we want a mail to the admins.
232     template.send_to_user(delegate_user, subject_params, body_params, use_cc=True, additional_cc_users=[request.user])
233 
234     messages.add_message(
235         request,
236         messages.SUCCESS,
237         _('{} was added as a contributor for evaluation "{}" and was sent an email with further information.').format(str(delegate_user), str(evaluation))
238     )
239 
240     return redirect('contributor:index')
241 
242 
243 def export_contributor_results(contributor):
244     filename = "Evaluation_{}.xls".format(contributor.full_name)
245     response = FileResponse(filename, content_type="application/vnd.ms-excel")
246     ResultsExporter().export(
247         response,
248         Semester.objects.all(),
249         [(Degree.objects.all(), CourseType.objects.all())],
250         include_not_enough_voters=True,
251         include_unpublished=False,
252         contributor=contributor
253     )
254     return response
255 
256 
257 @responsible_or_contributor_or_delegate_required
258 def export(request):
259     return export_contributor_results(request.user)
260
```
--- 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/contributor/views.py b/evap/contributor/views.py
--- a/evap/contributor/views.py
+++ b/evap/contributor/views.py
@@ -24,11 +24,14 @@
     user = request.user
     show_delegated = get_parameter_from_url_or_session(request, "show_delegated", True)
 
+    represented_proxy_users = user.represented_users.filter(is_proxy_user=True)
     contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']
     own_courses = Course.objects.filter(
         Q(evaluations__state__in=contributor_visible_states) & (
             Q(responsibles=user) |
-            Q(evaluations__contributions__contributor=user)
+            Q(evaluations__contributions__contributor=user) |
+            Q(evaluations__contributions__contributor__in=represented_proxy_users) |
+            Q(responsibles__in=represented_proxy_users)
         )
     )
     own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]
@@ -37,7 +40,7 @@
 
     displayed_evaluations = set(own_evaluations)
     if show_delegated:
-        represented_users = user.represented_users.all()
+        represented_users = user.represented_users.exclude(is_proxy_user=True)
         delegated_courses = Course.objects.filter(
             Q(evaluations__state__in=contributor_visible_states) & (
                 Q(responsibles__in=represented_users) |

{"golden_diff": "diff --git a/evap/contributor/views.py b/evap/contributor/views.py\n--- a/evap/contributor/views.py\n+++ b/evap/contributor/views.py\n@@ -24,11 +24,14 @@\n     user = request.user\n     show_delegated = get_parameter_from_url_or_session(request, \"show_delegated\", True)\n \n+    represented_proxy_users = user.represented_users.filter(is_proxy_user=True)\n     contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']\n     own_courses = Course.objects.filter(\n         Q(evaluations__state__in=contributor_visible_states) & (\n             Q(responsibles=user) |\n-            Q(evaluations__contributions__contributor=user)\n+            Q(evaluations__contributions__contributor=user) |\n+            Q(evaluations__contributions__contributor__in=represented_proxy_users) |\n+            Q(responsibles__in=represented_proxy_users)\n         )\n     )\n     own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]\n@@ -37,7 +40,7 @@\n \n     displayed_evaluations = set(own_evaluations)\n     if show_delegated:\n-        represented_users = user.represented_users.all()\n+        represented_users = user.represented_users.exclude(is_proxy_user=True)\n         delegated_courses = Course.objects.filter(\n             Q(evaluations__state__in=contributor_visible_states) & (\n                 Q(responsibles__in=represented_users) |\n", "issue": "Proxied evaluations shouldn't show as delegated\nEvaluations where a proxy user is responsible shouldn't be shown as \"delegated courses\" for the delegates of this proxy user. The delegates should see this course in the list of their own courses like those they are directly responsible for and they shouldn't be hidden when the option to hide delegated courses is active.\n", "before_files": [{"content": "from django.contrib import messages\nfrom django.core.exceptions import PermissionDenied, SuspiciousOperation\nfrom django.db import IntegrityError, transaction\nfrom django.db.models import Max, Q\nfrom django.forms.models import inlineformset_factory\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils.translation import gettext as _\nfrom django.views.decorators.http import require_POST\n\nfrom evap.contributor.forms import EvaluationForm, DelegatesForm, EditorContributionForm, DelegateSelectionForm\nfrom evap.evaluation.auth import responsible_or_contributor_or_delegate_required, editor_or_delegate_required, editor_required\nfrom evap.evaluation.models import Contribution, Course, CourseType, Degree, Evaluation, Semester, UserProfile, EmailTemplate\nfrom evap.evaluation.tools import get_parameter_from_url_or_session, sort_formset, FileResponse\nfrom evap.results.exporters import ResultsExporter\nfrom evap.results.tools import (calculate_average_distribution, distribution_to_grade,\n                                get_evaluations_with_course_result_attributes, get_single_result_rating_result,\n                                normalized_distribution)\nfrom evap.staff.forms import ContributionFormSet\nfrom evap.student.views import get_valid_form_groups_or_render_vote_page\n\n\n@responsible_or_contributor_or_delegate_required\ndef index(request):\n    user = request.user\n    show_delegated = get_parameter_from_url_or_session(request, \"show_delegated\", True)\n\n    contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']\n    own_courses = Course.objects.filter(\n        Q(evaluations__state__in=contributor_visible_states) & (\n            Q(responsibles=user) |\n            Q(evaluations__contributions__contributor=user)\n        )\n    )\n    own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]\n    for evaluation in own_evaluations:\n        evaluation.contributes_to = evaluation.contributions.filter(contributor=user).exists()\n\n    displayed_evaluations = set(own_evaluations)\n    if show_delegated:\n        represented_users = user.represented_users.all()\n        delegated_courses = Course.objects.filter(\n            Q(evaluations__state__in=contributor_visible_states) & (\n                Q(responsibles__in=represented_users) |\n                Q(\n                    evaluations__contributions__role=Contribution.Role.EDITOR,\n                    evaluations__contributions__contributor__in=represented_users,\n                )\n            )\n        )\n        delegated_evaluations = set(evaluation for course in delegated_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user))\n        for evaluation in delegated_evaluations:\n            evaluation.delegated_evaluation = True\n        displayed_evaluations |= delegated_evaluations - displayed_evaluations\n    displayed_evaluations = list(displayed_evaluations)\n    displayed_evaluations.sort(key=lambda evaluation: (evaluation.course.name, evaluation.name))  # evaluations must be sorted for regrouping them in the template\n\n    for evaluation in displayed_evaluations:\n        if evaluation.state == \"published\":\n            if not evaluation.is_single_result:\n                evaluation.distribution = calculate_average_distribution(evaluation)\n            else:\n                evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)\n                evaluation.distribution = normalized_distribution(evaluation.single_result_rating_result.counts)\n            evaluation.avg_grade = distribution_to_grade(evaluation.distribution)\n    displayed_evaluations = get_evaluations_with_course_result_attributes(displayed_evaluations)\n\n    semesters = Semester.objects.all()\n    semester_list = [dict(\n        semester_name=semester.name,\n        id=semester.id,\n        is_active=semester.is_active,\n        evaluations=[evaluation for evaluation in displayed_evaluations if evaluation.course.semester_id == semester.id]\n    ) for semester in semesters]\n\n    template_data = dict(\n        semester_list=semester_list,\n        show_delegated=show_delegated,\n        delegate_selection_form=DelegateSelectionForm(),\n    )\n    return render(request, \"contributor_index.html\", template_data)\n\n\n@editor_required\ndef settings_edit(request):\n    user = request.user\n    form = DelegatesForm(request.POST or None, request.FILES or None, instance=user)\n\n    if form.is_valid():\n        form.save()\n\n        messages.success(request, _(\"Successfully updated your settings.\"))\n        return redirect('contributor:settings_edit')\n\n    return render(request, \"contributor_settings.html\", dict(\n        form=form,\n        delegate_of=user.represented_users.all(),\n        cc_users=user.cc_users.all(),\n        ccing_users=user.ccing_users.all(),\n    ))\n\n\n@editor_or_delegate_required\ndef evaluation_view(request, evaluation_id):\n    user = request.user\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n\n    # check rights\n    if not evaluation.is_user_editor_or_delegate(user) or evaluation.state not in ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed']:\n        raise PermissionDenied\n\n    InlineContributionFormset = inlineformset_factory(Evaluation, Contribution, formset=ContributionFormSet, form=EditorContributionForm, extra=0)\n\n    form = EvaluationForm(request.POST or None, instance=evaluation)\n    formset = InlineContributionFormset(request.POST or None, instance=evaluation)\n\n    # make everything read-only\n    for cform in formset.forms + [form]:\n        for field in cform.fields.values():\n            field.disabled = True\n\n    template_data = dict(form=form, formset=formset, evaluation=evaluation, editable=False)\n    return render(request, \"contributor_evaluation_form.html\", template_data)\n\n\ndef render_preview(request, formset, evaluation_form, evaluation):\n    # open transaction to not let any other requests see anything of what we're doing here\n    try:\n        with transaction.atomic():\n            evaluation = evaluation_form.save()\n            evaluation.set_last_modified(request.user)\n            evaluation.save()\n            formset.save()\n            request.POST = None  # this prevents errors rendered in the vote form\n\n            preview_response = get_valid_form_groups_or_render_vote_page(request, evaluation, preview=True, for_rendering_in_modal=True)[1].content.decode()\n            raise IntegrityError  # rollback transaction to discard the database writes\n    except IntegrityError:\n        pass\n\n    return preview_response\n\n\n@editor_or_delegate_required\ndef evaluation_edit(request, evaluation_id):\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n\n    # check rights\n    if not (evaluation.is_user_editor_or_delegate(request.user) and evaluation.state == 'prepared'):\n        raise PermissionDenied\n\n    post_operation = request.POST.get('operation') if request.POST else None\n    preview = post_operation == 'preview'\n\n    InlineContributionFormset = inlineformset_factory(Evaluation, Contribution, formset=ContributionFormSet, form=EditorContributionForm, extra=1)\n    evaluation_form = EvaluationForm(request.POST or None, instance=evaluation)\n    formset = InlineContributionFormset(request.POST or None, instance=evaluation, form_kwargs={'evaluation': evaluation})\n\n    forms_are_valid = evaluation_form.is_valid() and formset.is_valid()\n    if forms_are_valid and not preview:\n        if post_operation not in ('save', 'approve'):\n            raise SuspiciousOperation(\"Invalid POST operation\")\n\n        form_has_changed = evaluation_form.has_changed() or formset.has_changed()\n\n        if form_has_changed:\n            evaluation.set_last_modified(request.user)\n        evaluation_form.save()\n        formset.save()\n\n        if post_operation == 'approve':\n            evaluation.editor_approve()\n            evaluation.save()\n            if form_has_changed:\n                messages.success(request, _(\"Successfully updated and approved evaluation.\"))\n            else:\n                messages.success(request, _(\"Successfully approved evaluation.\"))\n        else:\n            messages.success(request, _(\"Successfully updated evaluation.\"))\n\n        return redirect('contributor:index')\n\n    preview_html = None\n    if preview and forms_are_valid:\n        preview_html = render_preview(request, formset, evaluation_form, evaluation)\n\n    if not forms_are_valid and (evaluation_form.errors or formset.errors):\n        if preview:\n            messages.error(request, _(\"The preview could not be rendered. Please resolve the errors shown below.\"))\n        else:\n            messages.error(request, _(\"The form was not saved. Please resolve the errors shown below.\"))\n\n    sort_formset(request, formset)\n    template_data = dict(form=evaluation_form, formset=formset, evaluation=evaluation, editable=True, preview_html=preview_html)\n    return render(request, \"contributor_evaluation_form.html\", template_data)\n\n\n@responsible_or_contributor_or_delegate_required\ndef evaluation_preview(request, evaluation_id):\n    user = request.user\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n\n    # check rights\n    if not (evaluation.is_user_responsible_or_contributor_or_delegate(user) and evaluation.state in ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed']):\n        raise PermissionDenied\n\n    return get_valid_form_groups_or_render_vote_page(request, evaluation, preview=True)[1]\n\n\n@require_POST\n@editor_or_delegate_required\ndef evaluation_direct_delegation(request, evaluation_id):\n    delegate_user_id = request.POST.get(\"delegate_to\")\n\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n    delegate_user = get_object_or_404(UserProfile, id=delegate_user_id)\n\n    contribution, created = Contribution.objects.update_or_create(\n        evaluation=evaluation,\n        contributor=delegate_user,\n        defaults={'role': Contribution.Role.EDITOR},\n    )\n    if created:\n        contribution.order = evaluation.contributions.all().aggregate(Max('order'))['order__max'] + 1\n        contribution.save()\n\n    template = EmailTemplate.objects.get(name=EmailTemplate.DIRECT_DELEGATION)\n    subject_params = {\"evaluation\": evaluation, \"user\": request.user, \"delegate_user\": delegate_user}\n    body_params = subject_params\n\n    # we don't provide the request here since send_to_user only uses it to display a warning message in case the user does not have\n    # an email address. In this special case, we don't want that warning. Instead, we want a mail to the admins.\n    template.send_to_user(delegate_user, subject_params, body_params, use_cc=True, additional_cc_users=[request.user])\n\n    messages.add_message(\n        request,\n        messages.SUCCESS,\n        _('{} was added as a contributor for evaluation \"{}\" and was sent an email with further information.').format(str(delegate_user), str(evaluation))\n    )\n\n    return redirect('contributor:index')\n\n\ndef export_contributor_results(contributor):\n    filename = \"Evaluation_{}.xls\".format(contributor.full_name)\n    response = FileResponse(filename, content_type=\"application/vnd.ms-excel\")\n    ResultsExporter().export(\n        response,\n        Semester.objects.all(),\n        [(Degree.objects.all(), CourseType.objects.all())],\n        include_not_enough_voters=True,\n        include_unpublished=False,\n        contributor=contributor\n    )\n    return response\n\n\n@responsible_or_contributor_or_delegate_required\ndef export(request):\n    return export_contributor_results(request.user)\n", "path": "evap/contributor/views.py"}], "after_files": [{"content": "from django.contrib import messages\nfrom django.core.exceptions import PermissionDenied, SuspiciousOperation\nfrom django.db import IntegrityError, transaction\nfrom django.db.models import Max, Q\nfrom django.forms.models import inlineformset_factory\nfrom django.shortcuts import get_object_or_404, redirect, render\nfrom django.utils.translation import gettext as _\nfrom django.views.decorators.http import require_POST\n\nfrom evap.contributor.forms import EvaluationForm, DelegatesForm, EditorContributionForm, DelegateSelectionForm\nfrom evap.evaluation.auth import responsible_or_contributor_or_delegate_required, editor_or_delegate_required, editor_required\nfrom evap.evaluation.models import Contribution, Course, CourseType, Degree, Evaluation, Semester, UserProfile, EmailTemplate\nfrom evap.evaluation.tools import get_parameter_from_url_or_session, sort_formset, FileResponse\nfrom evap.results.exporters import ResultsExporter\nfrom evap.results.tools import (calculate_average_distribution, distribution_to_grade,\n                                get_evaluations_with_course_result_attributes, get_single_result_rating_result,\n                                normalized_distribution)\nfrom evap.staff.forms import ContributionFormSet\nfrom evap.student.views import get_valid_form_groups_or_render_vote_page\n\n\n@responsible_or_contributor_or_delegate_required\ndef index(request):\n    user = request.user\n    show_delegated = get_parameter_from_url_or_session(request, \"show_delegated\", True)\n\n    represented_proxy_users = user.represented_users.filter(is_proxy_user=True)\n    contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']\n    own_courses = Course.objects.filter(\n        Q(evaluations__state__in=contributor_visible_states) & (\n            Q(responsibles=user) |\n            Q(evaluations__contributions__contributor=user) |\n            Q(evaluations__contributions__contributor__in=represented_proxy_users) |\n            Q(responsibles__in=represented_proxy_users)\n        )\n    )\n    own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]\n    for evaluation in own_evaluations:\n        evaluation.contributes_to = evaluation.contributions.filter(contributor=user).exists()\n\n    displayed_evaluations = set(own_evaluations)\n    if show_delegated:\n        represented_users = user.represented_users.exclude(is_proxy_user=True)\n        delegated_courses = Course.objects.filter(\n            Q(evaluations__state__in=contributor_visible_states) & (\n                Q(responsibles__in=represented_users) |\n                Q(\n                    evaluations__contributions__role=Contribution.Role.EDITOR,\n                    evaluations__contributions__contributor__in=represented_users,\n                )\n            )\n        )\n        delegated_evaluations = set(evaluation for course in delegated_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user))\n        for evaluation in delegated_evaluations:\n            evaluation.delegated_evaluation = True\n        displayed_evaluations |= delegated_evaluations - displayed_evaluations\n    displayed_evaluations = list(displayed_evaluations)\n    displayed_evaluations.sort(key=lambda evaluation: (evaluation.course.name, evaluation.name))  # evaluations must be sorted for regrouping them in the template\n\n    for evaluation in displayed_evaluations:\n        if evaluation.state == \"published\":\n            if not evaluation.is_single_result:\n                evaluation.distribution = calculate_average_distribution(evaluation)\n            else:\n                evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)\n                evaluation.distribution = normalized_distribution(evaluation.single_result_rating_result.counts)\n            evaluation.avg_grade = distribution_to_grade(evaluation.distribution)\n    displayed_evaluations = get_evaluations_with_course_result_attributes(displayed_evaluations)\n\n    semesters = Semester.objects.all()\n    semester_list = [dict(\n        semester_name=semester.name,\n        id=semester.id,\n        is_active=semester.is_active,\n        evaluations=[evaluation for evaluation in displayed_evaluations if evaluation.course.semester_id == semester.id]\n    ) for semester in semesters]\n\n    template_data = dict(\n        semester_list=semester_list,\n        show_delegated=show_delegated,\n        delegate_selection_form=DelegateSelectionForm(),\n    )\n    return render(request, \"contributor_index.html\", template_data)\n\n\n@editor_required\ndef settings_edit(request):\n    user = request.user\n    form = DelegatesForm(request.POST or None, request.FILES or None, instance=user)\n\n    if form.is_valid():\n        form.save()\n\n        messages.success(request, _(\"Successfully updated your settings.\"))\n        return redirect('contributor:settings_edit')\n\n    return render(request, \"contributor_settings.html\", dict(\n        form=form,\n        delegate_of=user.represented_users.all(),\n        cc_users=user.cc_users.all(),\n        ccing_users=user.ccing_users.all(),\n    ))\n\n\n@editor_or_delegate_required\ndef evaluation_view(request, evaluation_id):\n    user = request.user\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n\n    # check rights\n    if not evaluation.is_user_editor_or_delegate(user) or evaluation.state not in ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed']:\n        raise PermissionDenied\n\n    InlineContributionFormset = inlineformset_factory(Evaluation, Contribution, formset=ContributionFormSet, form=EditorContributionForm, extra=0)\n\n    form = EvaluationForm(request.POST or None, instance=evaluation)\n    formset = InlineContributionFormset(request.POST or None, instance=evaluation)\n\n    # make everything read-only\n    for cform in formset.forms + [form]:\n        for field in cform.fields.values():\n            field.disabled = True\n\n    template_data = dict(form=form, formset=formset, evaluation=evaluation, editable=False)\n    return render(request, \"contributor_evaluation_form.html\", template_data)\n\n\ndef render_preview(request, formset, evaluation_form, evaluation):\n    # open transaction to not let any other requests see anything of what we're doing here\n    try:\n        with transaction.atomic():\n            evaluation = evaluation_form.save()\n            evaluation.set_last_modified(request.user)\n            evaluation.save()\n            formset.save()\n            request.POST = None  # this prevents errors rendered in the vote form\n\n            preview_response = get_valid_form_groups_or_render_vote_page(request, evaluation, preview=True, for_rendering_in_modal=True)[1].content.decode()\n            raise IntegrityError  # rollback transaction to discard the database writes\n    except IntegrityError:\n        pass\n\n    return preview_response\n\n\n@editor_or_delegate_required\ndef evaluation_edit(request, evaluation_id):\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n\n    # check rights\n    if not (evaluation.is_user_editor_or_delegate(request.user) and evaluation.state == 'prepared'):\n        raise PermissionDenied\n\n    post_operation = request.POST.get('operation') if request.POST else None\n    preview = post_operation == 'preview'\n\n    InlineContributionFormset = inlineformset_factory(Evaluation, Contribution, formset=ContributionFormSet, form=EditorContributionForm, extra=1)\n    evaluation_form = EvaluationForm(request.POST or None, instance=evaluation)\n    formset = InlineContributionFormset(request.POST or None, instance=evaluation, form_kwargs={'evaluation': evaluation})\n\n    forms_are_valid = evaluation_form.is_valid() and formset.is_valid()\n    if forms_are_valid and not preview:\n        if post_operation not in ('save', 'approve'):\n            raise SuspiciousOperation(\"Invalid POST operation\")\n\n        form_has_changed = evaluation_form.has_changed() or formset.has_changed()\n\n        if form_has_changed:\n            evaluation.set_last_modified(request.user)\n        evaluation_form.save()\n        formset.save()\n\n        if post_operation == 'approve':\n            evaluation.editor_approve()\n            evaluation.save()\n            if form_has_changed:\n                messages.success(request, _(\"Successfully updated and approved evaluation.\"))\n            else:\n                messages.success(request, _(\"Successfully approved evaluation.\"))\n        else:\n            messages.success(request, _(\"Successfully updated evaluation.\"))\n\n        return redirect('contributor:index')\n\n    preview_html = None\n    if preview and forms_are_valid:\n        preview_html = render_preview(request, formset, evaluation_form, evaluation)\n\n    if not forms_are_valid and (evaluation_form.errors or formset.errors):\n        if preview:\n            messages.error(request, _(\"The preview could not be rendered. Please resolve the errors shown below.\"))\n        else:\n            messages.error(request, _(\"The form was not saved. Please resolve the errors shown below.\"))\n\n    sort_formset(request, formset)\n    template_data = dict(form=evaluation_form, formset=formset, evaluation=evaluation, editable=True, preview_html=preview_html)\n    return render(request, \"contributor_evaluation_form.html\", template_data)\n\n\n@responsible_or_contributor_or_delegate_required\ndef evaluation_preview(request, evaluation_id):\n    user = request.user\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n\n    # check rights\n    if not (evaluation.is_user_responsible_or_contributor_or_delegate(user) and evaluation.state in ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed']):\n        raise PermissionDenied\n\n    return get_valid_form_groups_or_render_vote_page(request, evaluation, preview=True)[1]\n\n\n@require_POST\n@editor_or_delegate_required\ndef evaluation_direct_delegation(request, evaluation_id):\n    delegate_user_id = request.POST.get(\"delegate_to\")\n\n    evaluation = get_object_or_404(Evaluation, id=evaluation_id)\n    delegate_user = get_object_or_404(UserProfile, id=delegate_user_id)\n\n    contribution, created = Contribution.objects.update_or_create(\n        evaluation=evaluation,\n        contributor=delegate_user,\n        defaults={'role': Contribution.Role.EDITOR},\n    )\n    if created:\n        contribution.order = evaluation.contributions.all().aggregate(Max('order'))['order__max'] + 1\n        contribution.save()\n\n    template = EmailTemplate.objects.get(name=EmailTemplate.DIRECT_DELEGATION)\n    subject_params = {\"evaluation\": evaluation, \"user\": request.user, \"delegate_user\": delegate_user}\n    body_params = subject_params\n\n    # we don't provide the request here since send_to_user only uses it to display a warning message in case the user does not have\n    # an email address. In this special case, we don't want that warning. Instead, we want a mail to the admins.\n    template.send_to_user(delegate_user, subject_params, body_params, use_cc=True, additional_cc_users=[request.user])\n\n    messages.add_message(\n        request,\n        messages.SUCCESS,\n        _('{} was added as a contributor for evaluation \"{}\" and was sent an email with further information.').format(str(delegate_user), str(evaluation))\n    )\n\n    return redirect('contributor:index')\n\n\ndef export_contributor_results(contributor):\n    filename = \"Evaluation_{}.xls\".format(contributor.full_name)\n    response = FileResponse(filename, content_type=\"application/vnd.ms-excel\")\n    ResultsExporter().export(\n        response,\n        Semester.objects.all(),\n        [(Degree.objects.all(), CourseType.objects.all())],\n        include_not_enough_voters=True,\n        include_unpublished=False,\n        contributor=contributor\n    )\n    return response\n\n\n@responsible_or_contributor_or_delegate_required\ndef export(request):\n    return export_contributor_results(request.user)\n", "path": "evap/contributor/views.py"}]}