🚧 hromadne akcie na registraciach + zapisovanie casov + automaticke vytvaranie kol

This commit is contained in:
2025-03-06 20:07:46 +01:00
parent 2346e644a7
commit 2656626a37
14 changed files with 133 additions and 46 deletions

View File

@@ -53,7 +53,7 @@ http://0.0.0.0:8234/admin/
# TODO
- [x] casy (id_timeru, cas, id_karty)
- [ ] laps (star, end, id_karty)
- [x] laps (star, end, id_karty)
- [ ] bar zaznamy (id_karty, polozka, cas)
- [x] doplnit mysql kontajner a zmenit connetor v settings.py
- [ ] doplnit phpmyadmin kontajner
@@ -62,3 +62,4 @@ http://0.0.0.0:8234/admin/
- [x] bezpecnostne kody pre email pre pristup k registraciam
- [x] zoznam registracii pre email zabezpeceny bezpecnostnym kodom
- [x] moznost priamej registracie bez mailoveho potvrdenia
- [x] hromadne akcie v adminovi na registraciach

View File

@@ -1,4 +1,4 @@
from django.contrib import admin
from django.contrib import admin, messages
from events import models
@@ -13,11 +13,43 @@ class EventAdmin(admin.ModelAdmin):
list_display = ('start', 'name', 'is_actual', 'is_public', 'registrations_enabled')
def presentation(modeladmin, request, queryset):
for registration in queryset:
registration.is_presented = True
try:
registration.save()
except Exception as e:
messages.error(request, f"Registraciu {registration} sa nepodarilo zaprezentovat: {e}")
presentation.short_description = "Zaprezentovat registraciu"
def pay(modeladmin, request, queryset):
for registration in queryset:
registration.is_paid = True
try:
registration.save()
except Exception as e:
messages.error(request, f"Registraciu {registration} sa nepodarilo uhradit: {e}")
pay.short_description = "Oznacit registraciu ako uhradenu"
def finish(modeladmin, request, queryset):
for registration in queryset:
registration.is_finished = True
try:
registration.save()
except Exception as e:
messages.error(request, f"Registraciu {registration} sa nepodarilo dokoncit: {e}")
finish.short_description = "Dokoncit registraciu"
@admin.register(models.Registration)
class RegistrationAdmin(admin.ModelAdmin):
list_display = ('created', 'variable_symbol', 'event', 'email', 'first_name', 'last_name', 'is_confirmed' ,'is_paid', 'is_finished')
list_filter = ('event', 'is_confirmed', 'is_paid', 'is_finished', 'email')
list_filter = ('event', 'category', 'is_confirmed', 'is_paid', 'is_finished', 'email')
search_fields = ('email', 'first_name', 'last_name', 'variable_symbol')
actions = [presentation, pay, finish]
@admin.register(models.HTMLSection)

View File

@@ -0,0 +1,19 @@
# Generated by Django 5.1.6 on 2025-03-06 18:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('events', '0002_category_mapy_cz_url'),
]
operations = [
migrations.AlterField(
model_name='registration',
name='event',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='registrations', to='events.event', verbose_name='Event'),
),
]

View File

@@ -118,7 +118,8 @@ class Category(models.Model):
class Registration(TimeStampedModel):
uid = models.UUIDField(blank=True, null=True, verbose_name=_('UUID'))
event = models.ForeignKey(Event, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('Event'))
event = models.ForeignKey(Event, null=True, blank=True, on_delete=models.SET_NULL,
related_name='registrations', verbose_name=_('Event'))
variable_symbol = models.CharField(max_length=10, blank=True, null=True, verbose_name=_('Variable symbol'))
# data from form
@@ -196,7 +197,8 @@ class Lap(TimeStampedModel):
:return:
"""
if self.start and self.end:
return self.end - self.start
return (self.end - self.start)
return timedelta(0)

View File

@@ -26,6 +26,7 @@ urlpatterns = [
"my-registrations/<str:uid>/<str:email>/<str:security_code>/",
MyRegistrationsListView.as_view(),
name="my_registrations_list",
)
),
]

View File

@@ -6,6 +6,7 @@ from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import RedirectView, TemplateView
from django.shortcuts import get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin
from core.mailer import Emailer
from core.utils import generate_random_string

View File

@@ -1,5 +1,6 @@
<footer class="w3-center {{ actual_event.get_bg_color }} w3-padding-64">
<a href="#home" class="w3-button w3-light-grey">CHOD ZASA HORE</a>
<p>Powered by <a href="https://www.w3schools.com/w3css/default.asp" title="W3.CSS" target="_blank"
class="w3-hover-text-green">w3.css</a></p>
</footer>

View File

@@ -4,6 +4,7 @@
{% block content %}
{% include 'menu/landing_page_menu.html' %}
{% include 'partials/messages.html' %}
{% block landing_content %}{% endblock %}
{% endblock %}

View File

@@ -17,7 +17,6 @@
{% block extra_head %}{% endblock %}
</head>
<body>
{% include 'partials/messages.html' %}
{% block content %}{% endblock %}
{% block js %}{% endblock %}
</body>

View File

@@ -5,7 +5,7 @@ from timer import models
@admin.register(models.TimeRecord)
class TimeRecordAdmin(admin.ModelAdmin):
list_display = ('timer_id', 'card_id', 'time')
search_fields = ('timer_id', 'card_id')
list_filter = ('timer_id', 'card_id')
list_display_links = ('timer_id', 'card_id')
list_display = ('timer_id', 'chip_id', 'time')
search_fields = ('timer_id', 'chip_id')
list_filter = ('timer_id', 'chip_id')
list_display_links = ('timer_id', 'chip_id')

View File

@@ -0,0 +1,22 @@
# Generated by Django 5.1.6 on 2025-03-06 18:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timer', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='timerecord',
name='card_id',
),
migrations.AddField(
model_name='timerecord',
name='chip_id',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Chip identifier'),
),
]

View File

@@ -15,7 +15,7 @@ class TimeRecord(TimeStampedModel):
TimeRecord database model holding the time records from the timer.
"""
timer_id = models.CharField(max_length=20, null=True, blank=True, verbose_name=_('Timer identifier'))
card_id = models.CharField(max_length=100, null=True, blank=True, verbose_name=_('Card identifier'))
chip_id = models.CharField(max_length=100, null=True, blank=True, verbose_name=_('Chip identifier'))
time = models.DateTimeField(verbose_name=_('Time'))
class Meta:
@@ -23,4 +23,4 @@ class TimeRecord(TimeStampedModel):
verbose_name_plural = _('Time Records')
def __str__(self):
return f'{self.timer_id} - {self.card_id}'
return f'{self.timer_id} - {self.chip_id}'

View File

@@ -4,7 +4,7 @@ from timer.views import WriteTimeApiView
urlpatterns = [
path(
"write/<str:timer_id>/<str:card_id>/<str:time>/",
"write/<str:timer_id>/<str:chip_id>/<str:time>/",
WriteTimeApiView.as_view(),
name="write_time",
),

View File

@@ -5,7 +5,7 @@ from datetime import datetime
from django.views.generic import View
from django.http import JsonResponse
from events.models import Event
from events.models import Event, Lap
logger = logging.getLogger(__name__)
@@ -27,39 +27,47 @@ class WriteTimeApiView(View):
# create new TimeRecord object and save it to the database
TimeRecord(
card_id=kwargs['card_id'],
chip_id=kwargs['chip_id'],
timer_id=kwargs['timer_id'],
time=record_time,
).save()
# find the active event
event = Event.objects.filter(
is_active=True,
is_actual=True,
)
# if there is no active event, log error
if not event:
logger.error("No active event found")
return JsonResponse({"error": "No active event found"}, status=http.HTTPStatus.NOT_FOUND, safe=False)
return JsonResponse({"status": "ok"}, status=http.HTTPStatus.OK, safe=False)
# find registration with the given card_id
registration = event[0].registrations.filter(
card_id=kwargs['card_id'],
chip_id=kwargs['chip_id'],
)
if not registration:
logger.error(f"No registration found for card_id: {kwargs['card_id']}")
logger.error(f"No registration found for chip_id: {kwargs['chip_id']}")
return JsonResponse({"status": "ok"}, status=http.HTTPStatus.OK, safe=False)
# if there is more than one registration with the same card_id, log error
if len(registration) > 1:
logger.error(f"Multiple registrations found for card_id: {kwargs['card_id']}")
logger.error(f"Multiple registrations found for chip_id: {kwargs['chip_id']}")
# create new lap or update existing lap
registration[0].laps.filter(end = None).update(end = record_time)
laps = Lap.objects.filter(registration=registration[0])
open_lap = laps.filter(end=None)
if not open_lap:
registration[0].laps.create(
start=record_time,
number=len(laps) + 1,
)
else:
open_lap[0].end = record_time
open_lap[0].save()
return JsonResponse({"status": "ok"}, status=http.HTTPStatus.OK ,safe=False)
except Exception as e:
logger.error(f"Error while getting prometheus data: {e}")
return JsonResponse({"error": f"Error while getting prometheus data: {e}"}, status=http.HTTPStatus.INTERNAL_SERVER_ERROR , safe=False)
logger.error(f"Error while writing lap: {e}")
return JsonResponse({"status": "ok"}, status=http.HTTPStatus.OK, safe=False)