Skip to content

Commit cc209c9

Browse files
committed
action
1 parent 288dd44 commit cc209c9

File tree

9 files changed

+183
-6
lines changed

9 files changed

+183
-6
lines changed

backend/grants/admin.py

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
)
2626
from schedule.models import ScheduleItem
2727
from submissions.models import Submission
28-
from .models import Grant
29-
from django.db.models import Exists, OuterRef
28+
from .models import Grant, GrantConfirmPendingStatusProxy
29+
from django.db.models import Exists, OuterRef, F
3030

3131
from django.contrib.admin import SimpleListFilter
3232
from participants.models import Participant
33+
from django.urls import reverse
34+
from django.utils.safestring import mark_safe
3335

3436
EXPORT_GRANTS_FIELDS = (
3537
"name",
@@ -575,3 +577,64 @@ def get_queryset(self, request):
575577

576578
class Media:
577579
js = ["admin/js/jquery.init.js"]
580+
581+
582+
@admin.action(description="Confirm pending status change")
583+
@validate_single_conference_selection
584+
def confirm_pending_status(modeladmin, request, queryset):
585+
Grant.objects.filter(id__in=queryset.values_list("id", flat=True)).update(
586+
status=F("pending_status"),
587+
)
588+
589+
590+
@admin.action(description="Reset pending status")
591+
@validate_single_conference_selection
592+
def reset_pending_status_back_to_status(modeladmin, request, queryset):
593+
Grant.objects.filter(id__in=queryset.values_list("id", flat=True)).update(
594+
pending_status=F("status"),
595+
)
596+
597+
598+
@admin.register(GrantConfirmPendingStatusProxy)
599+
class GrantConfirmPendingStatusProxyAdmin(admin.ModelAdmin):
600+
list_display = (
601+
"id",
602+
"full_name",
603+
"status",
604+
"to",
605+
"pending_status",
606+
"open_grant",
607+
"conference",
608+
)
609+
list_filter = ("status", "pending_status", "conference")
610+
search_fields = ("full_name", "user__email")
611+
list_display_links = None
612+
actions = [
613+
confirm_pending_status,
614+
reset_pending_status_back_to_status,
615+
]
616+
617+
def to(self, obj):
618+
return "➡️"
619+
620+
def has_delete_permission(self, request, obj=None):
621+
return False
622+
623+
def has_add_permission(self, request):
624+
return False
625+
626+
def has_change_permission(self, request, obj=None):
627+
return False
628+
629+
def get_queryset(self, request):
630+
return (
631+
super()
632+
.get_queryset(request)
633+
.exclude(
634+
pending_status=F("status"),
635+
)
636+
)
637+
638+
def open_grant(self, obj):
639+
url = reverse("admin:grants_grant_change", args=[obj.id])
640+
return mark_safe(f'<a href="{url}">Open Grant</a>')

backend/grants/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,10 @@ def has_approved_accommodation(self):
338338
self.approved_type == Grant.ApprovedType.ticket_accommodation
339339
or self.approved_type == Grant.ApprovedType.ticket_travel_accommodation
340340
)
341+
342+
343+
class GrantConfirmPendingStatusProxy(Grant):
344+
class Meta:
345+
proxy = True
346+
verbose_name = _("Grant Confirm Pending Status")
347+
verbose_name_plural = _("Grants Confirm Pending Status")

backend/grants/templates/admin/grants/grant_summary.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
.waiting_for_confirmation,
2222
.confirmed {
2323
font-weight: 600;
24-
color: var(--body-loud-color)
24+
color: var(--body-loud-color);
2525
}
2626

2727
#financialSummary td,

backend/grants/tests/test_admin.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from django.utils import timezone
99

1010
from grants.admin import (
11+
confirm_pending_status,
1112
create_grant_vouchers,
13+
reset_pending_status_back_to_status,
1214
send_reply_emails,
1315
mark_rejected_and_send_email,
1416
)
@@ -444,3 +446,63 @@ def test_mark_rejected_and_send_email(rf, mocker, admin_user):
444446
mock_send_rejected_email.assert_has_calls(
445447
[call(grant_id=grant1.id), call(grant_id=grant2.id)], any_order=True
446448
)
449+
450+
451+
def test_confirm_pending_status_action(rf):
452+
grant_1 = GrantFactory(
453+
status=Grant.Status.pending,
454+
pending_status=Grant.Status.confirmed,
455+
)
456+
457+
grant_2 = GrantFactory(
458+
status=Grant.Status.rejected,
459+
pending_status=Grant.Status.waiting_list,
460+
conference=grant_1.conference,
461+
)
462+
463+
grant_3 = GrantFactory(
464+
status=Grant.Status.waiting_list,
465+
pending_status=Grant.Status.waiting_list_maybe,
466+
conference=grant_1.conference,
467+
)
468+
469+
request = rf.get("/")
470+
confirm_pending_status(None, request, Grant.objects.all())
471+
472+
grant_1.refresh_from_db()
473+
grant_2.refresh_from_db()
474+
grant_3.refresh_from_db()
475+
476+
assert grant_1.status == Grant.Status.confirmed
477+
assert grant_2.status == Grant.Status.waiting_list
478+
assert grant_3.status == Grant.Status.waiting_list_maybe
479+
480+
481+
def test_reset_pending_status_back_to_status_action(rf):
482+
grant_1 = GrantFactory(
483+
status=Grant.Status.pending,
484+
pending_status=Grant.Status.confirmed,
485+
)
486+
487+
grant_2 = GrantFactory(
488+
status=Grant.Status.rejected,
489+
pending_status=Grant.Status.waiting_list,
490+
conference=grant_1.conference,
491+
)
492+
493+
grant_3 = GrantFactory(
494+
status=Grant.Status.waiting_list,
495+
pending_status=Grant.Status.waiting_list_maybe,
496+
conference=grant_1.conference,
497+
)
498+
499+
request = rf.get("/")
500+
reset_pending_status_back_to_status(None, request, Grant.objects.all())
501+
502+
grant_1.refresh_from_db()
503+
grant_2.refresh_from_db()
504+
grant_3.refresh_from_db()
505+
506+
assert grant_1.status == Grant.Status.pending
507+
assert grant_2.status == Grant.Status.rejected
508+
assert grant_3.status == Grant.Status.waiting_list

backend/grants/tests/test_summary.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def grants_set():
1212
5,
1313
conference=conference,
1414
status="approved",
15+
pending_status="approved",
1516
country_type="italy",
1617
gender="female",
1718
departure_country="IT",
@@ -20,6 +21,7 @@ def grants_set():
2021
3,
2122
conference=conference,
2223
status="rejected",
24+
pending_status="rejected",
2325
country_type="europe",
2426
gender="male",
2527
departure_country="FR",
@@ -28,6 +30,7 @@ def grants_set():
2830
7,
2931
conference=conference,
3032
status="waiting_list",
33+
pending_status="waiting_list",
3134
country_type="extra_eu",
3235
gender="other",
3336
departure_country="US",

backend/reviews/templates/proposals-recap.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ <h3>Show proposals with N reviews:</h3>
342342
</select>
343343
</div>
344344
<div class="opt-filter">
345-
<h3>Show proposals with status:</h3>
345+
<h3>Show proposals with pending status:</h3>
346346
<div>
347347
{% for status in all_statuses %}
348348
<label>
@@ -379,6 +379,10 @@ <h3>Show proposals with status:</h3>
379379
<div class="text"><span>Status</span></div>
380380
<div class="clear"></div>
381381
</th>
382+
<th scope="col">
383+
<div class="text"><span>Pending Status</span></div>
384+
<div class="clear"></div>
385+
</th>
382386
<th scope="col">
383387
<div class="text"><span>Decision</span></div>
384388
<div class="clear"></div>
@@ -390,8 +394,8 @@ <h3>Show proposals with status:</h3>
390394
<script>
391395
submissionsById[{{ item.id }}] = {
392396
id: {{ item.id }},
393-
status: "{{ item.status }}",
394-
originalStatus: "{{ item.status }}",
397+
status: "{{ item.pending_status }}",
398+
originalStatus: "{{ item.pending_status }}",
395399
audienceLevel: {{ item.audience_level.id }},
396400
languages: [{% for language in item.languages.all %}"{{language.code}}",{% endfor %}],
397401
numOfVotes: {{item.userreview_set.count}},
@@ -485,6 +489,10 @@ <h3>Show proposals with status:</h3>
485489
{{item.status}}
486490
</td>
487491

492+
<td>
493+
{{item.pending_status}}
494+
</td>
495+
488496
<td class="decision-input-wrapper">
489497
<label>
490498
<input

backend/submissions/admin.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
ProposalMaterial,
2121
Submission,
2222
SubmissionComment,
23+
SubmissionConfirmPendingStatusProxy,
2324
SubmissionTag,
2425
SubmissionType,
2526
)
@@ -311,3 +312,8 @@ class SubmissionTagAdmin(admin.ModelAdmin):
311312
@admin.register(SubmissionComment)
312313
class SubmissionCommentAdmin(admin.ModelAdmin):
313314
list_display = ("submission", "author", "text")
315+
316+
317+
@admin.register(SubmissionConfirmPendingStatusProxy)
318+
class SubmissionConfirmPendingStatusProxyAdmin(admin.ModelAdmin):
319+
...
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Generated by Django 5.1.4 on 2025-01-20 22:54
2+
3+
from django.db import migrations
4+
5+
def sync_pending_status(apps, schema_editor):
6+
from django.db import models
7+
8+
Submission = apps.get_model('submissions', 'Submission')
9+
Submission.objects.update(
10+
pending_status=models.F('status')
11+
)
12+
13+
class Migration(migrations.Migration):
14+
15+
dependencies = [
16+
('submissions', '0025_remove_proposalmaterial_title_proposalmaterial_name'),
17+
]
18+
19+
operations = [
20+
migrations.RunPython(sync_pending_status, reverse_code=migrations.RunPython.noop),
21+
]

backend/submissions/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,10 @@ def __str__(self):
257257
class Meta:
258258
verbose_name = _("comment")
259259
verbose_name_plural = _("comments")
260+
261+
262+
class SubmissionConfirmPendingStatusProxy(Submission):
263+
class Meta:
264+
proxy = True
265+
verbose_name = _("Submission Confirm Pending Status")
266+
verbose_name_plural = _("Submissions Confirm Pending Status")

0 commit comments

Comments
 (0)