-
Notifications
You must be signed in to change notification settings - Fork 32
/
models.py
110 lines (86 loc) · 3.42 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.contrib.auth.models import User
from account.models import SignupCode
from kaleo.signals import invite_sent
DEFAULT_INVITE_EXPIRATION = getattr(settings, "KALEO_DEFAULT_EXPIRATION", 168) # 168 Hours = 7 Days
DEFAULT_INVITE_ALLOCATION = getattr(settings, "KALEO_DEFAULT_INVITE_ALLOCATION", 0)
class NotEnoughInvitationsError(Exception):
pass
class JoinInvitation(models.Model):
STATUS_SENT = 1
STATUS_ACCEPTED = 2
STATUS_JOINED_INDEPENDENTLY = 3
INVITE_STATUS_CHOICES = [
(STATUS_SENT, "Sent"),
(STATUS_ACCEPTED, "Accepted"),
(STATUS_JOINED_INDEPENDENTLY, "Joined Independently")
]
from_user = models.ForeignKey(User, related_name="invites_sent")
to_user = models.ForeignKey(User, null=True, related_name="invites_received")
message = models.TextField(null=True)
sent = models.DateTimeField(default=timezone.now)
status = models.IntegerField(choices=INVITE_STATUS_CHOICES)
signup_code = models.OneToOneField(SignupCode)
def to_user_email(self):
return self.signup_code.email
@classmethod
def invite(cls, from_user, to_email, message=None):
if not from_user.invitationstat.can_send():
raise NotEnoughInvitationsError()
signup_code = SignupCode.create(
email=to_email,
inviter=from_user,
expiry=DEFAULT_INVITE_EXPIRATION,
check_exists=False # before we are called caller must check for existence
)
signup_code.save()
join = cls.objects.create(
from_user=from_user,
message=message,
status=JoinInvitation.STATUS_SENT,
signup_code=signup_code
)
signup_code.send()
stat = from_user.invitationstat
stat.invites_sent += 1
stat.save()
invite_sent.send(sender=cls, invitation=join)
return join
class InvitationStat(models.Model):
user = models.OneToOneField(User)
invites_sent = models.IntegerField(default=0)
invites_allocated = models.IntegerField(default=DEFAULT_INVITE_ALLOCATION)
invites_accepted = models.IntegerField(default=0)
@classmethod
def add_invites_to_user(cls, user, amount):
stat, _ = InvitationStat.objects.get_or_create(user=user)
stat.invites_allocated = -1
stat.save()
@classmethod
def add_invites(cls, amount):
for user in User.objects.all():
cls.add_invites_to_user(user, amount)
@classmethod
def topoff_user(cls, user, amount):
"Makes sure user has a certain number of invites"
stat, _ = cls.objects.get_or_create(user=user)
remaining = stat.invites_remaining()
if remaining < amount:
stat.invites_allocated += (amount - remaining)
stat.save()
@classmethod
def topoff(cls, amount):
"Makes sure all users have a certain number of invites"
for user in User.objects.all():
cls.topoff_user(user, amount)
def invites_remaining(self):
if self.invites_allocated == -1:
return -1
return self.invites_allocated - self.invites_sent
def can_send(self):
if self.invites_allocated == -1:
return True
return self.invites_allocated > self.invites_sent
can_send.boolean = True