Skip to content
Snippets Groups Projects
Commit 30ef4db5 authored by Roang's avatar Roang
Browse files

Add Invitation docstrings

parent 840c1e1d
No related branches found
No related tags found
No related merge requests found
...@@ -18,6 +18,10 @@ if TYPE_CHECKING: # pragma: no cover ...@@ -18,6 +18,10 @@ if TYPE_CHECKING: # pragma: no cover
class InvitationAlreadyExists(ValidationError): class InvitationAlreadyExists(ValidationError):
"""
This exception is raised when an invitation already exists between a requester and a requested entity.
"""
def __init__(self, invitation: 'Invitation') -> None: def __init__(self, invitation: 'Invitation') -> None:
self.invitation = invitation self.invitation = invitation
super().__init__( super().__init__(
...@@ -28,6 +32,10 @@ class InvitationAlreadyExists(ValidationError): ...@@ -28,6 +32,10 @@ class InvitationAlreadyExists(ValidationError):
class InvitationRejectedTimeout(ValidationError): class InvitationRejectedTimeout(ValidationError):
"""
This exception is raised when an invitation has been rejected and the timeout has not yet expired.
"""
def __init__(self) -> None: def __init__(self) -> None:
super().__init__( super().__init__(
_('Invitation__error__rejected_timeout'), _('Invitation__error__rejected_timeout'),
...@@ -36,6 +44,16 @@ class InvitationRejectedTimeout(ValidationError): ...@@ -36,6 +44,16 @@ class InvitationRejectedTimeout(ValidationError):
class RequestsState(models.TextChoices): class RequestsState(models.TextChoices):
"""
Enumeration for the state of requests.
Attributes:
REQUESTED: The request has been made.
WITHDRAWN: The request has been withdrawn.
ACCEPTED: The request has been accepted.
REJECTED: The request has been rejected.
"""
REQUESTED = 'requested', _('Invitation__requests_state-requested') REQUESTED = 'requested', _('Invitation__requests_state-requested')
WITHDRAWN = 'withdrawn', _('Invitation__requests_state-withdrawn') WITHDRAWN = 'withdrawn', _('Invitation__requests_state-withdrawn')
ACCEPTED = 'accepted', _('Invitation__requests_state-accepted') ACCEPTED = 'accepted', _('Invitation__requests_state-accepted')
...@@ -43,12 +61,34 @@ class RequestsState(models.TextChoices): ...@@ -43,12 +61,34 @@ class RequestsState(models.TextChoices):
class InvitationType(models.TextChoices): class InvitationType(models.TextChoices):
"""
Enumeration for the type of invitations.
Attributes:
ASSEMBLY_MEMBER: Invitation for an Conferencemember to join an assembly.
TEAM_MEMBER: Invitation for an Conferencemember to join a team.
HABITAT: Invitation of ah Assembly for a habitat.
"""
ASSEMBLY_MEMBER = 'ASSEMBLY_MEMBER', _('Assembly Member') ASSEMBLY_MEMBER = 'ASSEMBLY_MEMBER', _('Assembly Member')
TEAM_MEMBER = 'TEAM_MEMBER', _('Team Member') TEAM_MEMBER = 'TEAM_MEMBER', _('Team Member')
HABITAT = 'HABITAT', _('Habitat') HABITAT = 'HABITAT', _('Habitat')
class Invitation(models.Model): class Invitation(models.Model):
"""
Model representing an invitation.
Attributes:
requester_type: The type of the requester (ContentType).
requester_id: The ID of the requester.
requester: The requester (GenericForeignKey).
requested_type: The type of the requested entity (ContentType).
requested_id: The ID of the requested entity.
requested: The requested entity (GenericForeignKey).
comment: A comment associated with the invitation.
"""
class Meta: class Meta:
indexes = [ indexes = [
models.Index(fields=['requester_id', 'requested_id']), models.Index(fields=['requester_id', 'requested_id']),
...@@ -108,9 +148,20 @@ class Invitation(models.Model): ...@@ -108,9 +148,20 @@ class Invitation(models.Model):
@classmethod @classmethod
def type_is(cls, obj: object) -> TypeIs['Invitation']: def type_is(cls, obj: object) -> TypeIs['Invitation']:
"""Check if the object is an Invitation.
Returns:
TypeIs[Invitation]: True if the object is an Invitation, False otherwise.
"""
return isinstance(obj, cls) return isinstance(obj, cls)
def clean(self) -> None: def clean(self) -> None:
"""Validation for the invitation class.
Raises:
InvitationAlreadyExists: Is raised when an invitation already exists between a requester and a requested entity.
InvitationRejectedTimeout: Is raised when an invitation has been rejected and the timeout has not yet expired.
"""
qs = Invitation.objects.filter(requester_id=self.requester_id, requested_id=self.requested_id).exclude(id=self.id) qs = Invitation.objects.filter(requester_id=self.requester_id, requested_id=self.requested_id).exclude(id=self.id)
if qs.exists(): if qs.exists():
if qs.filter(state=RequestsState.REQUESTED).exists(): if qs.filter(state=RequestsState.REQUESTED).exists():
...@@ -123,9 +174,17 @@ class Invitation(models.Model): ...@@ -123,9 +174,17 @@ class Invitation(models.Model):
hours=settings.INVITATION_REJECTION_DEFAULT_TIMEOUT hours=settings.INVITATION_REJECTION_DEFAULT_TIMEOUT
): ):
raise InvitationRejectedTimeout raise InvitationRejectedTimeout
return super().clean() super().clean()
def accept(self, user: 'PlatformUser'): def accept(self, user: 'PlatformUser'):
"""Accept the invitation.
Args:
user (PlatformUser): The user who accepts the invitation.
Raises:
NotImplementedError: Raied when the invitation type is not yet implemented.
"""
self.decision_by = user self.decision_by = user
match self.type: match self.type:
case InvitationType.HABITAT: case InvitationType.HABITAT:
...@@ -134,6 +193,11 @@ class Invitation(models.Model): ...@@ -134,6 +193,11 @@ class Invitation(models.Model):
raise NotImplementedError raise NotImplementedError
def accept_habitat(self): def accept_habitat(self):
"""Accept the invitation for a joining a habitat.
Raises:
ValueError: I raised when the requested or requester type is not a habitat.
"""
from core.models import Assembly # pylint: disable=import-outside-toplevel from core.models import Assembly # pylint: disable=import-outside-toplevel
if not Assembly.type_is(self.requested): # pragma: no cover if not Assembly.type_is(self.requested): # pragma: no cover
...@@ -165,11 +229,21 @@ class Invitation(models.Model): ...@@ -165,11 +229,21 @@ class Invitation(models.Model):
) )
def reject(self, user: 'PlatformUser'): def reject(self, user: 'PlatformUser'):
"""Reject the invitation.
Args:
user (PlatformUser): The user rejecting the invitation.
"""
self.decision_by = user self.decision_by = user
self.state = RequestsState.REJECTED self.state = RequestsState.REJECTED
self.save() self.save()
def withdraw(self, user: 'PlatformUser'): def withdraw(self, user: 'PlatformUser'):
"""Withdraw the invitation.
Args:
user (PlatformUser): The user withdrawing the invitation.
"""
self.decision_by = user self.decision_by = user
self.state = RequestsState.WITHDRAWN self.state = RequestsState.WITHDRAWN
self.save() self.save()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment