Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pythonitalia/pycon
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b613840eefa0bd3a8e22a10b41f3ee6d362b9101
Choose a base ref
..
head repository: pythonitalia/pycon
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3d051f9acb6208dee2237d976e69c47114ec1bf7
Choose a head ref
15 changes: 15 additions & 0 deletions backend/conferences/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from .conference import (
ConferenceAdmin,
DeadlineAdmin,
AudienceLevelAdmin,
SpeakerVoucherAdmin,
TopicAdmin,
)

__all__ = [
"AudienceLevelAdmin",
"ConferenceAdmin",
"DeadlineAdmin",
"SpeakerVoucherAdmin",
"TopicAdmin",
]
69 changes: 69 additions & 0 deletions backend/conferences/admin/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from django.contrib import admin, messages
from conferences.models import SpeakerVoucher
from pretix import create_voucher
from schedule.tasks import send_speaker_voucher_email


@admin.action(description="Send voucher via email")
def send_voucher_via_email(modeladmin, request, queryset):
is_filtered_by_conference = (
queryset.values_list("conference_id").distinct().count() == 1
)

if not is_filtered_by_conference:
messages.error(request, "Please select only one conference")
return

count = 0
for speaker_voucher in queryset.filter(pretix_voucher_id__isnull=False):
send_speaker_voucher_email.delay(speaker_voucher_id=speaker_voucher.id)
count = count + 1

messages.success(request, f"{count} Voucher emails scheduled!")


@admin.action(description="Create speaker vouchers on Pretix")
def create_speaker_vouchers_on_pretix(modeladmin, request, queryset):
is_filtered_by_conference = (
queryset.values_list("conference_id").distinct().count() == 1
)

if not is_filtered_by_conference:
messages.error(request, "Please select only one conference")
return

conference = queryset.only("conference_id").first().conference

if not conference.pretix_speaker_voucher_quota_id:
messages.error(
request,
"Please configure the speaker voucher quota ID in the conference settings",
)
return

count = 0

for speaker_voucher in queryset.filter(pretix_voucher_id__isnull=True):
if speaker_voucher.voucher_type == SpeakerVoucher.VoucherType.SPEAKER:
price_mode = "set"
value = "0.00"
elif speaker_voucher.voucher_type == SpeakerVoucher.VoucherType.CO_SPEAKER:
price_mode = "percent"
value = "25.00"

pretix_voucher = create_voucher(
conference=speaker_voucher.conference,
code=speaker_voucher.voucher_code,
comment=f"Voucher for user_id={speaker_voucher.user_id}",
tag="speakers",
quota_id=speaker_voucher.conference.pretix_speaker_voucher_quota_id,
price_mode=price_mode,
value=value,
)

pretix_voucher_id = pretix_voucher["id"]
speaker_voucher.pretix_voucher_id = pretix_voucher_id
speaker_voucher.save()
count = count + 1

messages.success(request, f"{count} Vouchers created on Pretix!")
Original file line number Diff line number Diff line change
@@ -19,13 +19,11 @@
from itertools import permutations
from unicodedata import normalize
from conferences.models import SpeakerVoucher
from pretix import create_voucher
from schedule.models import ScheduleItem
from schedule.tasks import send_speaker_voucher_email
from sponsors.models import SponsorLevel
from voting.models import IncludedEvent
import re
from .models import (
from conferences.models import (
AudienceLevel,
Conference,
Deadline,
@@ -34,6 +32,8 @@
KeynoteSpeaker,
Topic,
)
from conferences.admin.views import grants_summary
from .actions import send_voucher_via_email, create_speaker_vouchers_on_pretix


def validate_deadlines_form(forms):
@@ -100,7 +100,10 @@ class IncludedEventInline(admin.TabularInline):


@admin.register(Conference)
class ConferenceAdmin(OrderedInlineModelAdminMixin, admin.ModelAdmin):
class ConferenceAdmin(
OrderedInlineModelAdminMixin,
admin.ModelAdmin,
):
list_display = (
"name",
"code",
@@ -201,6 +204,11 @@ def get_urls(self):
self.admin_site.admin_view(self.schedule_builder),
name="schedule_builder",
),
path(
"<int:object_id>/grants-summary/",
self.admin_site.admin_view(grants_summary),
name="grants_summary",
),
] + super().get_urls()

def schedule_builder(self, request, object_id):
@@ -471,71 +479,6 @@ def get_queryset(self, request):
return Keynote.all_objects.all()


@admin.action(description="Send voucher via email")
def send_voucher_via_email(modeladmin, request, queryset):
is_filtered_by_conference = (
queryset.values_list("conference_id").distinct().count() == 1
)

if not is_filtered_by_conference:
messages.error(request, "Please select only one conference")
return

count = 0
for speaker_voucher in queryset.filter(pretix_voucher_id__isnull=False):
send_speaker_voucher_email.delay(speaker_voucher_id=speaker_voucher.id)
count = count + 1

messages.success(request, f"{count} Voucher emails scheduled!")


@admin.action(description="Create speaker vouchers on Pretix")
def create_speaker_vouchers_on_pretix(modeladmin, request, queryset):
is_filtered_by_conference = (
queryset.values_list("conference_id").distinct().count() == 1
)

if not is_filtered_by_conference:
messages.error(request, "Please select only one conference")
return

conference = queryset.only("conference_id").first().conference

if not conference.pretix_speaker_voucher_quota_id:
messages.error(
request,
"Please configure the speaker voucher quota ID in the conference settings",
)
return

count = 0

for speaker_voucher in queryset.filter(pretix_voucher_id__isnull=True):
if speaker_voucher.voucher_type == SpeakerVoucher.VoucherType.SPEAKER:
price_mode = "set"
value = "0.00"
elif speaker_voucher.voucher_type == SpeakerVoucher.VoucherType.CO_SPEAKER:
price_mode = "percent"
value = "25.00"

pretix_voucher = create_voucher(
conference=speaker_voucher.conference,
code=speaker_voucher.voucher_code,
comment=f"Voucher for user_id={speaker_voucher.user_id}",
tag="speakers",
quota_id=speaker_voucher.conference.pretix_speaker_voucher_quota_id,
price_mode=price_mode,
value=value,
)

pretix_voucher_id = pretix_voucher["id"]
speaker_voucher.pretix_voucher_id = pretix_voucher_id
speaker_voucher.save()
count = count + 1

messages.success(request, f"{count} Vouchers created on Pretix!")


class SpeakerVoucherForm(forms.ModelForm):
class Meta:
model = SpeakerVoucher
13 changes: 13 additions & 0 deletions backend/conferences/admin/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.shortcuts import render
from grants.summary import GrantSummary
from django.contrib.admin import site as admin_site


def grants_summary(request, object_id):
context = GrantSummary().calculate(conference_id=object_id)

return render(
request,
"admin/grants/grant_summary.html",
{**context, **admin_site.each_context(request)},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends "admin/change_form.html" %}
{% block object-tools-items %}
<li>
<a href="{% url 'admin:grants_summary' object_id=original.id %}" class="button">
Grants Summary
</a>
</li>
{{ block.super }}
{% endblock %}
36 changes: 22 additions & 14 deletions backend/conferences/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -19,11 +19,15 @@

from conferences.admin import (
ConferenceAdmin,
DeadlineForm,
)
from conferences.admin.actions import (
create_speaker_vouchers_on_pretix,
send_voucher_via_email,
)
from conferences.admin.conference import (
validate_deadlines_form,
walk_conference_videos_folder,
DeadlineForm,
)
from conferences.models import SpeakerVoucher
from schedule.models import ScheduleItem
@@ -185,8 +189,10 @@ def test_send_voucher_via_email(
rf,
mocker,
):
mocker.patch("conferences.admin.messages")
mock_send_email = mocker.patch("conferences.admin.send_speaker_voucher_email")
mocker.patch("conferences.admin.actions.messages")
mock_send_email = mocker.patch(
"conferences.admin.actions.send_speaker_voucher_email"
)

conference = ConferenceFactory(pretix_speaker_voucher_quota_id=123)
schedule_item_1 = ScheduleItemFactory(
@@ -229,8 +235,10 @@ def test_send_voucher_via_email_requires_filtering_by_conference(
rf,
mocker,
):
mock_messages = mocker.patch("conferences.admin.messages")
mock_send_email = mocker.patch("conferences.admin.send_speaker_voucher_email")
mock_messages = mocker.patch("conferences.admin.actions.messages")
mock_send_email = mocker.patch(
"conferences.admin.actions.send_speaker_voucher_email"
)

conference = ConferenceFactory(pretix_speaker_voucher_quota_id=123)
conference_2 = ConferenceFactory(pretix_speaker_voucher_quota_id=123)
@@ -274,14 +282,14 @@ def test_send_voucher_via_email_requires_filtering_by_conference(

def test_create_speaker_vouchers_on_pretix(rf, mocker):
mock_create_voucher = mocker.patch(
"conferences.admin.create_voucher",
"conferences.admin.actions.create_voucher",
side_effect=[
{"id": 1},
{"id": 2},
{"id": 3},
],
)
mocker.patch("conferences.admin.messages")
mocker.patch("conferences.admin.actions.messages")

conference = ConferenceFactory(pretix_speaker_voucher_quota_id=123)

@@ -354,12 +362,12 @@ def test_create_speaker_vouchers_on_pretix(rf, mocker):

def test_create_speaker_vouchers_on_pretix_only_for_missing_ones(rf, mocker):
mock_create_voucher = mocker.patch(
"conferences.admin.create_voucher",
"conferences.admin.actions.create_voucher",
side_effect=[
{"id": 1},
],
)
mocker.patch("conferences.admin.messages")
mocker.patch("conferences.admin.actions.messages")

conference = ConferenceFactory(pretix_speaker_voucher_quota_id=123)

@@ -402,13 +410,13 @@ def test_create_speaker_vouchers_on_pretix_doesnt_work_with_multiple_conferences
rf, mocker
):
mock_create_voucher = mocker.patch(
"conferences.admin.create_voucher",
"conferences.admin.actions.create_voucher",
side_effect=[
{"id": 1},
{"id": 2},
],
)
mock_messages = mocker.patch("conferences.admin.messages")
mock_messages = mocker.patch("conferences.admin.actions.messages")

conference = ConferenceFactory(pretix_speaker_voucher_quota_id=123)
conference_2 = ConferenceFactory(pretix_speaker_voucher_quota_id=123)
@@ -451,13 +459,13 @@ def test_create_speaker_vouchers_on_pretix_doesnt_work_without_pretix_config(
rf, mocker
):
mock_create_voucher = mocker.patch(
"conferences.admin.create_voucher",
"conferences.admin.actions.create_voucher",
side_effect=[
{"id": 1},
{"id": 2},
],
)
mock_messages = mocker.patch("conferences.admin.messages")
mock_messages = mocker.patch("conferences.admin.actions.messages")

conference = ConferenceFactory(pretix_speaker_voucher_quota_id=None)

@@ -507,7 +515,7 @@ def test_video_uploaded_path_matcher(
marcsed = UserFactory(id=99, name="Marcsed", full_name="Marcsed Cazzęfa")

mocker.patch(
"conferences.admin.walk_conference_videos_folder",
"conferences.admin.conference.walk_conference_videos_folder",
return_value=[
"conf/video-1/1-Kim Kitsuragi.mp4",
"conf/video-2/2-Opening.mp4",
Loading