Files
django-dav-events/dav_registration/models.py

228 lines
8.5 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.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_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)
@python_2_unicode_compatible
class Registration(models.Model):
event = models.ForeignKey(Event, related_name='registrations')
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'))
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_2migrate = models.BooleanField(default=False, verbose_name=_('Durch Tourleitung beantwortet'))
@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}
Erfahrung:
{experience}
Anmerkung:
{note}
"""
if not self.dav_member:
dav_info = _('Nein')
else:
dav_info = self.dav_number
return text.format(
fullname=self.get_full_name(),
address=self.address,
postal_code=self.postal_code,
city=self.city,
dav_info=dav_info,
experience=self.experience,
note=self.note,
)
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(Registration, self).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)
def answered(self, accepted):
if accepted is not True and accepted is not False:
raise ValueError('boolean parameter expected')
if hasattr(self, 'status'):
status = self.status
else:
status = RegistrationStatus(registration=self)
status.accepted = accepted
status.answered = True
status.save()
def accepted(self):
return self.answered(accepted=True)
def rejected(self):
return self.answered(accepted=False)
@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))
@python_2_unicode_compatible
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.NullBooleanField(_('Zusage erteilt'))
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.answered and self.accepted is None:
raise ValidationError({'accepted': 'if answered is true, accepted must not be none'})
elif not self.answered and self.accepted is not None:
raise ValidationError({'answered': 'if answered is false, accepted must be none'})
def save(self, **kwargs):
self.full_clean()
super(RegistrationStatus, self).save(**kwargs)