Skip to content

Commit 2e5b4d7

Browse files
authored
Grant/Proposal pending status (#4316)
1 parent fdfe60d commit 2e5b4d7

File tree

17 files changed

+426
-65
lines changed

17 files changed

+426
-65
lines changed

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ coverage:
1313
round: down
1414
status:
1515
changes: false
16-
patch: true
16+
patch: false
1717
project: false
1818
github_checks: false

backend/custom_admin/admin.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.db.models import F
12
from django.contrib import messages
23
from functools import wraps
34

@@ -52,3 +53,19 @@ def wrapper(modeladmin, request, queryset):
5253
return func(modeladmin, request, queryset)
5354

5455
return wrapper
56+
57+
58+
@admin.action(description="Confirm pending status change")
59+
@validate_single_conference_selection
60+
def confirm_pending_status(modeladmin, request, queryset):
61+
queryset.update(
62+
status=F("pending_status"),
63+
)
64+
65+
66+
@admin.action(description="Reset pending status to status")
67+
@validate_single_conference_selection
68+
def reset_pending_status_back_to_status(modeladmin, request, queryset):
69+
queryset.update(
70+
pending_status=F("status"),
71+
)

backend/grants/admin.py

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
)
66
from conferences.models.conference_voucher import ConferenceVoucher
77
from pycon.constants import UTC
8-
from custom_admin.admin import validate_single_conference_selection
8+
from custom_admin.admin import (
9+
confirm_pending_status,
10+
reset_pending_status_back_to_status,
11+
validate_single_conference_selection,
12+
)
913
from import_export.resources import ModelResource
1014
from datetime import timedelta
1115
from typing import Dict, List, Optional
@@ -25,11 +29,13 @@
2529
)
2630
from schedule.models import ScheduleItem
2731
from submissions.models import Submission
28-
from .models import Grant
29-
from django.db.models import Exists, OuterRef
32+
from .models import Grant, GrantConfirmPendingStatusProxy
33+
from django.db.models import Exists, OuterRef, F
3034

3135
from django.contrib.admin import SimpleListFilter
3236
from participants.models import Participant
37+
from django.urls import reverse
38+
from django.utils.safestring import mark_safe
3339

3440
EXPORT_GRANTS_FIELDS = (
3541
"name",
@@ -410,6 +416,7 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
410416
list_filter = (
411417
"conference",
412418
"status",
419+
"pending_status",
413420
"country_type",
414421
"occupation",
415422
"approved_type",
@@ -445,6 +452,7 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
445452
{
446453
"fields": (
447454
"status",
455+
"pending_status",
448456
"approved_type",
449457
"country_type",
450458
"ticket_amount",
@@ -575,3 +583,48 @@ def get_queryset(self, request):
575583

576584
class Media:
577585
js = ["admin/js/jquery.init.js"]
586+
587+
588+
@admin.register(GrantConfirmPendingStatusProxy)
589+
class GrantConfirmPendingStatusProxyAdmin(admin.ModelAdmin):
590+
list_display = (
591+
"id",
592+
"full_name",
593+
"status",
594+
"to",
595+
"pending_status",
596+
"open_grant",
597+
"conference",
598+
)
599+
list_filter = ("status", "pending_status", "conference")
600+
search_fields = ("full_name", "user__email")
601+
list_display_links = None
602+
actions = [
603+
confirm_pending_status,
604+
reset_pending_status_back_to_status,
605+
]
606+
607+
def to(self, obj):
608+
return "➡️"
609+
610+
def has_delete_permission(self, request, obj=None):
611+
return False
612+
613+
def has_add_permission(self, request):
614+
return False
615+
616+
def has_change_permission(self, request, obj=None):
617+
return False
618+
619+
def get_queryset(self, request):
620+
return (
621+
super()
622+
.get_queryset(request)
623+
.exclude(
624+
pending_status=F("status"),
625+
)
626+
)
627+
628+
def open_grant(self, obj):
629+
url = reverse("admin:grants_grant_change", args=[obj.id])
630+
return mark_safe(f'<a href="{url}">Open Grant</a>')
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 5.1.4 on 2025-01-20 00:57
2+
3+
from django.db import migrations, models
4+
5+
def copy_grant_status_to_pending_status(apps, schema_editor):
6+
Grant = apps.get_model('grants', 'Grant')
7+
for grant in Grant.objects.all():
8+
grant.pending_status = grant.status
9+
grant.save(update_fields=['pending_status'])
10+
11+
12+
class Migration(migrations.Migration):
13+
14+
dependencies = [
15+
('grants', '0025_alter_grant_approved_type'),
16+
]
17+
18+
operations = [
19+
migrations.AddField(
20+
model_name='grant',
21+
name='pending_status',
22+
field=models.CharField(blank=True, choices=[('pending', 'Pending'), ('rejected', 'Rejected'), ('approved', 'Approved'), ('waiting_list', 'Waiting List'), ('waiting_list_maybe', 'Waiting List, Maybe'), ('waiting_for_confirmation', 'Waiting for confirmation'), ('refused', 'Refused'), ('confirmed', 'Confirmed'), ('did_not_attend', 'Did Not Attend')], default='pending', max_length=30, verbose_name='pending status'),
23+
),
24+
migrations.RunPython(copy_grant_status_to_pending_status, reverse_code=migrations.RunPython.noop),
25+
]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Generated by Django 5.1.4 on 2025-01-23 14:21
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('grants', '0026_grant_pending_status'),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name='GrantConfirmPendingStatusProxy',
15+
fields=[
16+
],
17+
options={
18+
'verbose_name': 'Grant Confirm Pending Status',
19+
'verbose_name_plural': 'Grants Confirm Pending Status',
20+
'proxy': True,
21+
'indexes': [],
22+
'constraints': [],
23+
},
24+
bases=('grants.grant',),
25+
),
26+
]

backend/grants/models.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,13 @@ class ApprovedType(models.TextChoices):
145145
status = models.CharField(
146146
_("status"), choices=Status.choices, max_length=30, default=Status.pending
147147
)
148+
pending_status = models.CharField(
149+
_("pending status"),
150+
choices=Status.choices,
151+
max_length=30,
152+
default=Status.pending,
153+
blank=True,
154+
)
148155
approved_type = models.CharField(
149156
verbose_name=_("approved type"),
150157
choices=ApprovedType.choices,
@@ -331,3 +338,10 @@ def has_approved_accommodation(self):
331338
self.approved_type == Grant.ApprovedType.ticket_accommodation
332339
or self.approved_type == Grant.ApprovedType.ticket_travel_accommodation
333340
)
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")

0 commit comments

Comments
 (0)