ugettext and ugettext_lazy were deprecated in Django 3 and will be removed in Django 4.
256 lines
9.8 KiB
Python
256 lines
9.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import unicode_literals
|
|
import datetime
|
|
import logging
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import models
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from dav_base.validators import DAVNumberValidator
|
|
from dav_events.models.event import Event
|
|
|
|
from . import signals
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
midnight = datetime.time(00, 00, 00)
|
|
|
|
|
|
class Registration(models.Model):
|
|
event = models.ForeignKey(Event, related_name='registrations', on_delete=models.PROTECT)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
personal_names = models.CharField(max_length=1024,
|
|
verbose_name=_('Vorname(n)'))
|
|
family_names = models.CharField(max_length=1024,
|
|
verbose_name=_('Familienname'))
|
|
|
|
address = models.CharField(max_length=1024,
|
|
verbose_name=_('Anschrift'),
|
|
help_text=_('Straße, Hausnummer'))
|
|
postal_code = models.CharField(max_length=254,
|
|
verbose_name=_('Postleitzahl'))
|
|
city = models.CharField(max_length=1024,
|
|
verbose_name=_('Ort'))
|
|
email_address = models.EmailField(verbose_name=_('E-Mail-Adresse'))
|
|
phone_number = models.CharField(max_length=254,
|
|
verbose_name=_('Telefonnummer'),
|
|
help_text=_('Idealerweise eine Mobilfunk-Nummer'))
|
|
|
|
year_of_birth = models.IntegerField(verbose_name=_('Geburtsjahr'),
|
|
help_text=_('Manchmal müssen wir wissen, wie alt unsere Teilnehmer sind.'
|
|
' Darum brauchen wir die vierstellige Jahreszahl,'
|
|
' des Jahres in dem du geboren bist (zb. 1991).'))
|
|
|
|
apply_reduced_fee = models.BooleanField(default=False,
|
|
verbose_name=_('Antrag auf reduzierte Teilnahmegebühr'),
|
|
help_text=_('Für Jugendliche und Junioren'
|
|
' (bis zum vollendeten 25. Lebensjahr),'
|
|
' sowie Mitglieder mit geringen finanziellen Mitteln'
|
|
' (Nachweis durch "Karlsruher Pass"),'
|
|
' wird die Teilnahmegebühr auf 50% ermäßigt.'))
|
|
|
|
dav_member = models.BooleanField(default=True,
|
|
verbose_name=_('DAV Mitglied'))
|
|
dav_number = models.CharField(max_length=62,
|
|
blank=True, validators=[DAVNumberValidator],
|
|
verbose_name=_('DAV Mitgliedsnummer'),
|
|
help_text='%s<br /> %s %s' % (
|
|
_('Deine Mitgliedsnummer findest du unter dem Strichcode'
|
|
' auf deinem DAV Ausweis.'),
|
|
_('Beispiel: <tt>131/00/012345</tt>'),
|
|
_('(der Teil bis zum ersten * genügt)'),
|
|
))
|
|
emergency_contact = models.TextField(blank=True,
|
|
verbose_name=_('Notfall-Kontakt'),
|
|
help_text=_('Name und Telefonnummer bzw. Anschrift,'
|
|
' die in Notfällen informiert werden soll.'))
|
|
experience = models.TextField(blank=True,
|
|
verbose_name=_('Erfahrung'),
|
|
help_text=_('Welche Touren oder Kurse hast du bereits gemacht?'))
|
|
note = models.TextField(blank=True,
|
|
verbose_name=_('Anmerkung'),
|
|
help_text='%s<br /> %s' % (
|
|
_('Wissenswertes für den Tourenleiter, z.B. Allergien,'
|
|
' gesundheitliche Einschränkungen, ...'),
|
|
_('Kann frei gelassen werden.'))
|
|
)
|
|
|
|
privacy_policy = models.TextField(blank=True,
|
|
verbose_name=_('Erklärung zur Datenspeicherung'))
|
|
privacy_policy_accepted = models.BooleanField(default=False,
|
|
verbose_name=_('Einwilligung zur Datenspeicherung'))
|
|
purge_at = models.DateTimeField(_('Zeitpunkt der Datenlöschung'))
|
|
|
|
answered_obsolete = models.BooleanField(default=False, verbose_name=_('Durch Tourleitung beantwortet'))
|
|
|
|
def approx_age(self):
|
|
now = datetime.datetime.now()
|
|
year_now = now.year
|
|
return year_now - self.year_of_birth
|
|
|
|
@staticmethod
|
|
def pk2hexstr(pk):
|
|
return hex(pk * 113)[2:] # 113 has no meaning, but it produce nice looking hex codes.
|
|
|
|
@staticmethod
|
|
def hexstr2pk(hexstr):
|
|
return int('0x' + hexstr, 0) // 113
|
|
|
|
@property
|
|
def hexstr(self):
|
|
if not self.pk:
|
|
return None
|
|
return self.pk2hexstr(self.pk)
|
|
|
|
class Meta:
|
|
verbose_name = _('Anmeldung')
|
|
verbose_name_plural = _('Anmeldungen')
|
|
ordering = ['created_at']
|
|
|
|
def __str__(self):
|
|
return '{eventnumber} - {name} ({registration_id} - {created} - {purge})'.format(
|
|
eventnumber=self.event.get_number(),
|
|
name=self.get_full_name(),
|
|
registration_id=self.hexstr,
|
|
created=self.created_at.strftime('%d.%m.%Y %H:%M %Z'),
|
|
purge=self.purge_at.strftime('%d.%m.%Y %H:%M %Z')
|
|
)
|
|
|
|
def get_absolute_url(self):
|
|
return reverse('dav_registration:registered')
|
|
|
|
def get_full_name(self):
|
|
return '{} {}'.format(self.personal_names, self.family_names)
|
|
|
|
def get_info(self):
|
|
text = """{fullname}
|
|
{address}, {postal_code} {city}
|
|
|
|
DAV Mitglied: {dav_info}
|
|
Jahrgang: {year_of_birth} (ungefähres Alter: {approx_age})
|
|
Antrag auf reduzierte Teilnehmergebühr: {apply_reduced_fee_yesno}
|
|
|
|
Erfahrung:
|
|
{experience}
|
|
|
|
Anmerkung:
|
|
{note}
|
|
"""
|
|
if not self.dav_member:
|
|
dav_info = _('Nein')
|
|
else:
|
|
dav_info = self.dav_number
|
|
|
|
if self.apply_reduced_fee:
|
|
apply_reduced_fee_yesno = _('Ja')
|
|
else:
|
|
apply_reduced_fee_yesno = _('Nein')
|
|
|
|
return text.format(
|
|
fullname=self.get_full_name(),
|
|
address=self.address,
|
|
postal_code=self.postal_code,
|
|
city=self.city,
|
|
dav_info=dav_info,
|
|
year_of_birth=self.year_of_birth,
|
|
approx_age=self.approx_age(),
|
|
apply_reduced_fee_yesno=apply_reduced_fee_yesno,
|
|
experience=self.experience,
|
|
note=self.note,
|
|
)
|
|
|
|
def get_data_dict(self):
|
|
data = {}
|
|
for field in self._meta.fields:
|
|
if not field.primary_key:
|
|
data[field.name] = getattr(self, field.name)
|
|
return data
|
|
|
|
def clean(self):
|
|
if self.dav_member and not self.dav_number:
|
|
raise ValidationError({'dav_number': _('Wenn du DAV Mitglied bist, brauchen wir deine Mitgliedsnummer.')})
|
|
|
|
def save(self, **kwargs):
|
|
creating = False
|
|
if not self.id:
|
|
creating = True
|
|
|
|
if not self.purge_at and self.event:
|
|
self.purge_at = self.__class__.calc_purge_at(self.event)
|
|
|
|
self.full_clean()
|
|
super().save(**kwargs)
|
|
|
|
if creating:
|
|
status = RegistrationStatus(registration=self)
|
|
status.save()
|
|
logger.info('Registration stored: %s', self)
|
|
signals.registration_created.send(sender=self.__class__, registration=self)
|
|
|
|
@classmethod
|
|
def calc_purge_at(cls, event):
|
|
if event.alt_last_day:
|
|
last_day = event.alt_last_day
|
|
elif event.last_day:
|
|
last_day = event.last_day
|
|
elif event.alt_first_day:
|
|
last_day = event.alt_first_day
|
|
else:
|
|
last_day = event.first_day
|
|
|
|
april = datetime.date(last_day.year, 4, 1)
|
|
july = datetime.date(last_day.year, 7, 1)
|
|
july_nextyear = datetime.date(last_day.year + 1, 7, 1)
|
|
october = datetime.date(last_day.year, 10, 1)
|
|
january_nextyear = datetime.date(last_day.year + 1, 1, 1)
|
|
|
|
if last_day < april:
|
|
purge_date = july
|
|
elif last_day < october:
|
|
purge_date = january_nextyear
|
|
else:
|
|
purge_date = july_nextyear
|
|
|
|
return timezone.make_aware(datetime.datetime.combine(purge_date, midnight))
|
|
|
|
|
|
class RegistrationStatus(models.Model):
|
|
registration = models.OneToOneField(Registration, on_delete=models.CASCADE, related_name='status')
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
answered = models.BooleanField(_('Durch Tourleitung beantwortet'), default=False)
|
|
accepted = models.BooleanField(_('Zusage erteilt'), null=True, blank=True)
|
|
|
|
class Meta:
|
|
verbose_name = _('Anmeldungsstatus')
|
|
verbose_name_plural = _('Anmeldungsstati')
|
|
ordering = ['updated_at']
|
|
|
|
def __str__(self):
|
|
return '{} (Updated: {})'.format(self.registration, self.updated_at.strftime('%d.%m.%Y %H:%M:%S'))
|
|
|
|
def clean(self):
|
|
if self.accepted is not None and self.answered is not True:
|
|
raise ValidationError({'answered': 'if accepted is not None, answered must be True'})
|
|
|
|
def save(self, **kwargs):
|
|
self.full_clean()
|
|
super().save(**kwargs)
|
|
|
|
def set_accepted(self):
|
|
self.accepted = True
|
|
self.answered = True
|
|
self.save()
|
|
|
|
def set_rejected(self):
|
|
self.accepted = False
|
|
self.answered = True
|
|
self.save()
|
|
|
|
def reset(self):
|
|
self.accepted = None
|
|
self.answered = False
|
|
self.save()
|