1 from datetime import timedelta
2 from django.apps import apps
3 from django.utils.timezone import now
4 from django.utils.translation import gettext_lazy as _
17 allow_negative_offset = False
21 def __init__(self, time=None, min_days_since=None, max_days_since=None, test=False):
22 self.time = time or now()
23 self.min_days_since = min_days_since
24 self.max_days_since = max_days_since
27 def get_contacts(self):
28 Contact = apps.get_model('messaging', 'Contact')
29 contacts = Contact.objects.filter(level=self.level)
31 if self.min_days_since is not None or self.expired:
32 cutoff = self.time - timedelta(self.min_days_since or 0)
34 contacts = contacts.filter(expires_at__lt=cutoff)
36 contacts = contacts.filter(since__lt=cutoff)
38 if self.max_days_since is not None:
39 cutoff = self.time - timedelta(self.max_days_since)
41 contacts = contacts.filter(expires_at__gt=cutoff)
43 contacts = contacts.filter(since__gt=cutoff)
45 if self.expired is False:
46 contacts = contacts.exclude(expires_at__lt=self.time)
50 def get_context(self, contact):
52 return self.get_example_context(contact)
54 Schedule = apps.get_model('club', 'Schedule')
55 schedules = Schedule.objects.filter(email=contact.email)
57 "schedule": self.get_schedule(schedules)
60 def get_example_context(self, contact):
61 Schedule = apps.get_model('club', 'Schedule')
67 payed_at=self.time - timedelta(2),
68 started_at=self.time - timedelta(1),
69 expires_at=self.time + timedelta(1),
74 class ClubSingle(State):
76 name = _('club one-time donors')
80 def get_schedule(self, schedules):
81 # Find first single non-expired schedule.
82 return schedules.filter(
83 monthly=False, yearly=False,
84 expires_at__gt=self.time
85 ).order_by('started_at').first()
88 class ClubSingleExpired(State):
89 slug = 'club-membership-expiring'
90 allow_negative_offset = True
91 name = _('club one-time donors with donation expiring')
95 def get_schedule(self, schedules):
96 # Find last single expired schedule.
97 return schedules.filter(
98 monthly=False, yearly=False,
99 expires_at__lt=self.time
100 ).order_by('-expires_at').first()
103 class ClubTried(State):
104 slug = 'club-payment-unfinished'
105 name = _('club would-be donors')
108 def get_schedule(self, schedules):
109 # Find last unpaid schedule.
110 return schedules.filter(
112 ).order_by('-started_at').first()
115 class ClubRecurring(State):
116 slug = 'club-recurring'
117 name = _('club recurring donors')
118 level = Level.RECURRING
121 def get_schedule(self, schedules):
122 # Find first recurring non-expired schedule.
123 return schedules.exclude(
124 monthly=False, yearly=False
126 expires_at__gt=self.time
127 ).order_by('started_at').first()
130 class ClubRecurringExpired(State):
131 slug = 'club-recurring-payment-problem'
132 name = _('club recurring donors with donation expired')
133 level = Level.RECURRING
136 def get_schedule(self, schedules):
137 # Find last recurring expired schedule.
138 return schedules.exclude(
139 monthly=False, yearly=False
141 expires_at__lt=self.time
142 ).order_by('-expires_at').first()
147 name = _('cold group')
150 def get_context(self, contact):
160 ClubRecurringExpired,