2021-02-28 22:00:11 +00:00
|
|
|
from typing import Optional
|
|
|
|
|
2021-02-27 20:07:48 +00:00
|
|
|
from django.contrib.postgres.fields import DateTimeRangeField
|
2018-06-23 19:08:56 +00:00
|
|
|
from django.db import models
|
2021-02-28 22:00:11 +00:00
|
|
|
from django.utils import timezone
|
2018-06-23 19:08:56 +00:00
|
|
|
from django.utils.translation import gettext as _
|
|
|
|
|
|
|
|
|
|
|
|
class CreatedModifiedAbstract(models.Model):
|
|
|
|
|
2019-08-31 22:27:36 +00:00
|
|
|
modified = models.DateTimeField(auto_now=True, verbose_name=_("modified"))
|
|
|
|
created = models.DateTimeField(auto_now_add=True, verbose_name=_("created"))
|
2018-06-23 19:08:56 +00:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
|
|
|
|
class Membership(CreatedModifiedAbstract):
|
|
|
|
"""
|
2021-02-28 22:00:11 +00:00
|
|
|
Tracks that a user has membership of a given type for a given period.
|
2018-06-23 19:08:56 +00:00
|
|
|
"""
|
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
class QuerySet(models.QuerySet):
|
|
|
|
def for_user(self, user):
|
|
|
|
return self.filter(user=user)
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
def _current(self):
|
|
|
|
return self.filter(period__contains=timezone.now())
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
def current(self) -> Optional["Membership"]:
|
|
|
|
try:
|
|
|
|
return self._current().get()
|
|
|
|
except self.model.DoesNotExist:
|
|
|
|
return None
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
def previous(self):
|
|
|
|
# A naïve way to get previous by just excluding the current. This
|
|
|
|
# means that there must be some protection against "future"
|
|
|
|
# memberships.
|
|
|
|
return self.all().difference(self._current())
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
objects = QuerySet.as_manager()
|
2018-06-23 19:08:56 +00:00
|
|
|
|
|
|
|
class Meta:
|
2021-02-28 22:00:11 +00:00
|
|
|
verbose_name = _("membership")
|
|
|
|
verbose_name_plural = _("memberships")
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
user = models.ForeignKey("auth.User", on_delete=models.PROTECT)
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
membership_type = models.ForeignKey(
|
|
|
|
"membership.MembershipType",
|
2019-08-31 22:27:36 +00:00
|
|
|
related_name="memberships",
|
2018-06-23 19:08:56 +00:00
|
|
|
verbose_name=_("subscription type"),
|
|
|
|
on_delete=models.PROTECT,
|
|
|
|
)
|
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
period = DateTimeRangeField(help_text=_("The duration this subscription is for. "))
|
2018-06-23 19:08:56 +00:00
|
|
|
|
2021-02-28 22:00:11 +00:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.user} - {self.period}"
|
|
|
|
|
|
|
|
|
|
|
|
class MembershipType(CreatedModifiedAbstract):
|
|
|
|
"""
|
|
|
|
Models membership types. Currently only a name, but will in the future
|
|
|
|
possibly contain more information like fees.
|
|
|
|
"""
|
2018-06-23 19:08:56 +00:00
|
|
|
|
|
|
|
class Meta:
|
2021-02-28 22:00:11 +00:00
|
|
|
verbose_name = _("membership type")
|
|
|
|
verbose_name_plural = _("membership types")
|
|
|
|
|
|
|
|
name = models.CharField(verbose_name=_("name"), max_length=64)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return self.name
|