"""File containing Members app models.""" from django.db import models from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django.db.models import Q, OuterRef, Subquery class BaseMember(models.Model): """Abstract base model for member.""" id = models.AutoField(primary_key=True) first_name = models.CharField(_("First name"), max_length=127) last_name = models.CharField(_("Last name"), max_length=127) email = models.EmailField(_("Email"), unique=True) POR = models.CharField( _("Place of residence"), max_length=255 ) # place of residence AYY = models.BooleanField(_("AYY"), default=False) jas = models.BooleanField(_("JAS"), default=False) class Meta: """Meta for base member model.""" abstract = True def __str__(self): """Return member last name, first name and email.""" return "{} {}, {}".format(self.last_name, self.first_name, self.email) def as_array(self): """Return member model as an array.""" return [ self.first_name, self.last_name, self.email, self.POR, int(self.AYY), int(self.jas), ] class Request(BaseMember): """Member request model represents one member request.""" class Meta: permissions = (("read_application", "Can see member application in list"),) submitted = models.DateTimeField(_("Submitted"), default=timezone.now) def to_member(self): """Convert array to member model.""" member = Member.from_array(self.as_array()) return member class Payment(models.Model): """Payment model representing one payment event.""" class Meta: permissions = (("read_payment", "Can see payment in list"),) id = models.AutoField(primary_key=True) date = models.DateTimeField(_("Date"), default=timezone.now) source = models.CharField( _("Source"), choices=[ ("AYY", _("AYY")), ("cash", _("Cash")), ("bank_transfer", _("Bank transfer")), ], max_length=255, ) member = models.ForeignKey( "Member", on_delete=models.PROTECT, blank=True, null=True, related_name="payments", ) def __str__(self): """Return payment id and date.""" return "Payment no. {}, {}".format(self.id, str(self.date)) @staticmethod def find_payments_by_name(query_name): qs = Payment.objects.all() for term in query_name.split(): qs = qs.filter( Q(member__first_name__icontains=term) | Q(member__last_name__icontains=term) ) return qs class Member(BaseMember): """Member model represets one member on the registry.""" created = models.DateTimeField(_("Created"), default=timezone.now) class Meta: permissions = ( ("check_by_email", "Can check if user exists by email"), ("read_member", "Can see member in list"), ) verbose_name = _("Member") verbose_name_plural = _("Members") @staticmethod def from_array(array): """Create member from array.""" if len(array) != 6: raise Exception("Invalid array length for member instantiation") return Member.objects.create( first_name=array[0], last_name=array[1], email=array[2], POR=array[3], AYY=bool(array[4]), jas=bool(array[5]), ) @staticmethod def find_members_by_name(query_name): qs = Member.objects.all() for term in query_name.split(): qs = qs.filter(Q(first_name__icontains=term) | Q(last_name__icontains=term)) return qs @staticmethod def get_members_with_latest_payment(members_query): """Return QuerySet of given members QS with last_paid attribute.""" latest = Payment.objects.filter(member=OuterRef("pk")).order_by("-date") return members_query.annotate(last_paid=Subquery(latest.values("date")[:1]))