From baea657d1aa30326f6e50490e22ae689e8524d7e Mon Sep 17 00:00:00 2001 From: Johannes Erwerle Date: Sun, 18 Oct 2026 15:04:00 +0200 Subject: [PATCH] Added option to bulk create vouchers via the WebUI. Closes #9 --- community_backup/webui/admin.py | 45 ++++++++++++++++++- .../webui/management/commands/add_vouchers.py | 9 +--- community_backup/webui/models.py | 22 ++++++++- .../webui/templates/admin/bulk_generate.html | 8 ++++ .../templates/admin/voucher_change_list.html | 6 +++ 5 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 community_backup/webui/templates/admin/bulk_generate.html create mode 100644 community_backup/webui/templates/admin/voucher_change_list.html diff --git a/community_backup/webui/admin.py b/community_backup/webui/admin.py index 7d0a18b..8f5f29c 100644 --- a/community_backup/webui/admin.py +++ b/community_backup/webui/admin.py @@ -1,7 +1,50 @@ from django.contrib import admin +from django.urls import path, reverse_lazy +from django.views.generic import FormView +from django import forms from .models import BorgRepository, Voucher + +class VoucherBulkCreateForm(forms.Form): + prefix = forms.CharField(label="Voucher prefix") + amount = forms.IntegerField(label="Amount") + + +class VoucherBulkCreateView(FormView): + form_class = VoucherBulkCreateForm + template_name = "admin/bulk_generate.html" + admin_site_context = None + success_url = reverse_lazy("admin:webui_voucher_changelist") + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + # inject the admin site context so that the navbar and other things work as intended + context.update(self.admin_site_context.each_context(self.request)) + return context + + def form_valid(self, form): + Voucher.bulk_generate(form.cleaned_data["prefix"], form.cleaned_data["amount"]) + return super().form_valid(form) + + +@admin.register(Voucher) +class VoucherAdmin(admin.ModelAdmin): + change_list_template = "admin/voucher_change_list.html" + + def get_urls(self): + urls = super().get_urls() + my_urls = [ + path( + "bulk_generate/", + self.admin_site.admin_view( + VoucherBulkCreateView.as_view(admin_site_context=self.admin_site) + ), + name="voucher_bulk_generate", + ) + ] + return my_urls + urls + + # Register your models here. admin.site.register(BorgRepository) -admin.site.register(Voucher) diff --git a/community_backup/webui/management/commands/add_vouchers.py b/community_backup/webui/management/commands/add_vouchers.py index f983d92..f8d0e6b 100644 --- a/community_backup/webui/management/commands/add_vouchers.py +++ b/community_backup/webui/management/commands/add_vouchers.py @@ -11,14 +11,7 @@ class Command(BaseCommand): parser.add_argument("amount", type=int) def handle(self, *args, **options): - unabmigous_characters = "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPQRTUVWXY1234679" - - vouchers = set() - while len(vouchers) < options["amount"]: - random_part = "".join(choices(unabmigous_characters, k=5)) - vouchers.add(f"{options['prefix']}-{random_part}") - - Voucher.objects.bulk_create(Voucher(code=v) for v in vouchers) + vouchers = Voucher.bulk_generate(options["prefix"], options["amount"]) header = r"""\begin{document} \begin{center} diff --git a/community_backup/webui/models.py b/community_backup/webui/models.py index 36e338f..f5686d8 100644 --- a/community_backup/webui/models.py +++ b/community_backup/webui/models.py @@ -1,11 +1,12 @@ +from random import choices +from pathlib import Path + from django.db import models from django.contrib.auth.models import User from django.core.validators import RegexValidator from django.conf import settings -from pathlib import Path import msgpack - from .tasks import update_user @@ -121,3 +122,20 @@ class Voucher(models.Model): def __str__(self): return f"Voucher '{self.code}'" + + @classmethod + def bulk_generate(cls, prefix: str, amount: int) -> set[str]: + """ + Create `amount` vouchers starting with `prefix`. + + Returns a set of the voucher codes as strings. + """ + unabmigous_characters = "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPQRTUVWXY1234679" + + vouchers = set() + while len(vouchers) < amount: + random_part = "".join(choices(unabmigous_characters, k=5)) + vouchers.add(f"{prefix}-{random_part}") + + Voucher.objects.bulk_create(Voucher(code=v) for v in vouchers) + return vouchers diff --git a/community_backup/webui/templates/admin/bulk_generate.html b/community_backup/webui/templates/admin/bulk_generate.html new file mode 100644 index 0000000..b44f745 --- /dev/null +++ b/community_backup/webui/templates/admin/bulk_generate.html @@ -0,0 +1,8 @@ +{% extends "admin/base_site.html" %} +{% block content %} +
+ {% csrf_token %} + {{ form }} + +
+{% endblock %} diff --git a/community_backup/webui/templates/admin/voucher_change_list.html b/community_backup/webui/templates/admin/voucher_change_list.html new file mode 100644 index 0000000..6283e9c --- /dev/null +++ b/community_backup/webui/templates/admin/voucher_change_list.html @@ -0,0 +1,6 @@ +{% extends "admin/change_list.html" %} + +{% block object-tools-items %} + {{ block.super }} +
  • Bulk Generate Vouchers
  • +{% endblock %}