feat: store and update last_visit in person model
This commit is contained in:
@@ -41,6 +41,26 @@ class Booking(models.Model):
|
||||
to_current_timezone(self.end_time).strftime('%H:%M')
|
||||
if self.end_time else '')
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# update last_visit time of all involved persons
|
||||
prev = Booking.objects.get(pk=self.pk) if self.pk else None
|
||||
|
||||
rv = super().save(*args, **kwargs)
|
||||
|
||||
if prev and prev.user != self.user:
|
||||
prev.user.update_last_visit(None)
|
||||
if not prev or prev.user != self.user or \
|
||||
prev.begin_time.date() != self.begin_time.date():
|
||||
self.user.update_last_visit(self.begin_time.date())
|
||||
|
||||
return rv
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
rv = super().delete(*args, **kwargs)
|
||||
# update last_visit time for person
|
||||
self.user.update_last_visit(None)
|
||||
return rv
|
||||
|
||||
@property
|
||||
def duration(self) -> 'int|None':
|
||||
if self.end_time:
|
||||
@@ -54,11 +74,6 @@ class Booking(models.Model):
|
||||
traits = set(x[0] for x in traits)
|
||||
return self.type.price_with_traits(self.duration or 0, traits)
|
||||
|
||||
@staticmethod
|
||||
def latest_checkin_query(for_user: 'Person|OuterRef'):
|
||||
objects = Booking.objects.filter(user=for_user)
|
||||
return objects.order_by('-begin_time').values('begin_time')[:1]
|
||||
|
||||
@staticmethod
|
||||
def currently_open_checkin(for_user: 'Person|OuterRef') -> 'Booking|None':
|
||||
return Booking.objects.filter(
|
||||
|
||||
@@ -33,3 +33,39 @@ class CourseVisit(models.Model):
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('course-visit:detail', kwargs={'pk': self.pk})
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# update last_visit time of all involved persons
|
||||
old_date: 'date|None' = None
|
||||
old_list: 'list[Person]' = []
|
||||
|
||||
if self.pk:
|
||||
prev = CourseVisit.objects.get(pk=self.pk)
|
||||
old_date = prev.date
|
||||
old_list.append(prev.participant)
|
||||
if prev.teacher:
|
||||
old_list.append(prev.teacher)
|
||||
|
||||
rv = super().save(*args, **kwargs)
|
||||
|
||||
new_date = self.date
|
||||
new_list: 'list[Person]' = [self.participant]
|
||||
if self.teacher:
|
||||
new_list.append(self.teacher)
|
||||
|
||||
for person in old_list:
|
||||
if person not in new_list:
|
||||
person.update_last_visit(None)
|
||||
for person in new_list:
|
||||
if person not in old_list or old_date != new_date:
|
||||
person.update_last_visit(new_date)
|
||||
|
||||
return rv
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
rv = super().delete(*args, **kwargs)
|
||||
# update last_visit time of all involved persons
|
||||
self.participant.update_last_visit(None)
|
||||
if self.teacher:
|
||||
self.teacher.update_last_visit(None)
|
||||
return rv
|
||||
|
||||
@@ -3,17 +3,20 @@ from django.db.models import Q
|
||||
from django.urls import reverse
|
||||
|
||||
from app.base.forms.fields import DateField
|
||||
from app.base.models.course import Course
|
||||
from app.base.models.booking import Booking
|
||||
from app.base.models.course import Course
|
||||
from app.base.models.course_visit import CourseVisit
|
||||
|
||||
from datetime import datetime, date
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from app.base.models import Account, Note, CourseVisit, TraitMapping
|
||||
from app.base.models import Account, Note, TraitMapping
|
||||
|
||||
|
||||
class Person(models.Model):
|
||||
created: 'models.DateField[date]' = DateField('Angelegt', editable=False)
|
||||
last_visit: 'models.DateField[date]' = DateField(
|
||||
'Letzter Besuch', editable=False)
|
||||
|
||||
uuid = models.CharField('Karten-ID', max_length=200, blank=True)
|
||||
first_name = models.CharField('Vorname', max_length=200)
|
||||
@@ -55,6 +58,7 @@ class Person(models.Model):
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.pk:
|
||||
self.created = date.today()
|
||||
self.last_visit = date.today()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
@property
|
||||
@@ -76,15 +80,32 @@ class Person(models.Model):
|
||||
return self.traits_at_date(datetime.now()).values_list(
|
||||
'pk', 'trait__key', 'trait__label')
|
||||
|
||||
@property
|
||||
def current_checkin(self):
|
||||
return Booking.currently_open_checkin(self)
|
||||
|
||||
def traits_at_date(self, date: datetime):
|
||||
return self.traits.filter(
|
||||
Q(valid_from__lte=date),
|
||||
Q(valid_until__gte=date) | Q(valid_until=None))
|
||||
|
||||
def last_check_in(self) -> 'datetime|None':
|
||||
obj = Booking.latest_checkin_query(self).first()
|
||||
return obj['begin_time'] if obj else None
|
||||
def lookup_last_visit(self) -> date:
|
||||
''' Return newest date from either booking, course, or created. '''
|
||||
last_booking = Booking.objects.filter(
|
||||
user=self).order_by('-begin_time').first()
|
||||
last_course = CourseVisit.objects.filter(
|
||||
Q(participant=self) | Q(teacher=self)).order_by('-date').first()
|
||||
available_dates = [self.created]
|
||||
if last_booking:
|
||||
available_dates.append(last_booking.begin_time.date())
|
||||
if last_course:
|
||||
available_dates.append(last_course.date)
|
||||
return max(available_dates)
|
||||
|
||||
@property
|
||||
def current_checkin(self):
|
||||
return Booking.currently_open_checkin(self)
|
||||
def update_last_visit(self, new_visit: 'date|None') -> None:
|
||||
if self.last_visit == new_visit:
|
||||
return # no need to update
|
||||
if not new_visit or new_visit < self.last_visit:
|
||||
new_visit = self.lookup_last_visit()
|
||||
self.last_visit = new_visit
|
||||
self.save()
|
||||
|
||||
Reference in New Issue
Block a user