🚧 hromadne akcie na registraciach + zapisovanie casov + automaticke vytvaranie kol
This commit is contained in:
@@ -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
|
||||
@@ -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)
|
||||
|
||||
19
src/events/migrations/0003_alter_registration_event.py
Normal file
19
src/events/migrations/0003_alter_registration_event.py
Normal 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'),
|
||||
),
|
||||
]
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ urlpatterns = [
|
||||
"my-registrations/<str:uid>/<str:email>/<str:security_code>/",
|
||||
MyRegistrationsListView.as_view(),
|
||||
name="my_registrations_list",
|
||||
)
|
||||
),
|
||||
|
||||
|
||||
]
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block content %}
|
||||
{% include 'menu/landing_page_menu.html' %}
|
||||
{% include 'partials/messages.html' %}
|
||||
{% block landing_content %}{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
{% block extra_head %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% include 'partials/messages.html' %}
|
||||
{% block content %}{% endblock %}
|
||||
{% block js %}{% endblock %}
|
||||
</body>
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'),
|
||||
),
|
||||
]
|
||||
@@ -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}'
|
||||
|
||||
@@ -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",
|
||||
),
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user