Permalink
Browse files

added cohort support

  • Loading branch information...
1 parent 39f944b commit 8f544e61f32a91a94a1281a851b0db0e658c0f87 @brosner brosner committed Apr 14, 2012
Showing with 218 additions and 5 deletions.
  1. +18 −0 waitinglist/admin.py
  2. +8 −0 waitinglist/forms.py
  3. +72 −0 waitinglist/models.py
  4. +8 −3 waitinglist/stats.py
  5. +5 −0 waitinglist/urls.py
  6. +107 −2 waitinglist/views.py
View
@@ -1,11 +1,29 @@
from django.contrib import admin
from waitinglist.models import WaitingListEntry
+from waitinglist.models import SignupCodeCohort, UserCohort, Cohort
class WaitingListEntryAdmin(admin.ModelAdmin):
+
list_display = ["email", "created"]
search_fields = ["email"]
+class SignupCodeCohortInline(admin.TabularInline):
+
+ model = SignupCodeCohort
+
+
+class UserCohortInline(admin.TabularInline):
+
+ model = UserCohort
+
+
admin.site.register(WaitingListEntry, WaitingListEntryAdmin)
+admin.site.register(Cohort,
+ inlines = [
+ SignupCodeCohortInline,
+ UserCohortInline,
+ ]
+)
View
@@ -1,6 +1,7 @@
from django import forms
from waitinglist.models import WaitingListEntry
+from waitinglist.models import Cohort, SignupCodeCohort, UserCohort
class WaitingListEntryForm(forms.ModelForm):
@@ -21,3 +22,10 @@ def clean_email(self):
"date": entry.created.strftime("%m/%d/%y"),
}
)
+
+
+class CohortCreate(forms.ModelForm):
+
+ class Meta:
+ model = Cohort
+ exclude = ["created"]
View
@@ -2,6 +2,11 @@
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
+from django.contrib.auth.models import User
+
+from account.models import SignupCode, SignupCodeResult
+from account.signals import user_signed_up
+
class WaitingListEntry(models.Model):
@@ -11,3 +16,70 @@ class WaitingListEntry(models.Model):
class Meta:
verbose_name = _("waiting list entry")
verbose_name_plural = _("waiting list entries")
+
+
+class Cohort(models.Model):
+
+ name = models.CharField(_("name"), max_length=35)
+ created = models.DateTimeField(_("created"), default=timezone.now, editable=False)
+
+ def members(self):
+ members = []
+ for scc in self.signupcodecohort_set.select_related("signup_code"):
+ member = collections.namedtuple("Member", ["email", "signup_code", "user", "invited"])
+ member.email = scc.signup_code.email
+ member.signup_code = scc.signup_code
+ member.invited = bool(scc.signup_code.sent)
+ try:
+ scr = SignupCodeResult.objects.get(signup_code=scc.signup_code_id)
+ except SignupCodeResult.DoesNotExist:
+ member.user = None
+ else:
+ member.user = scr.user
+ members.append(member)
+ return members
+
+ def member_counts(self):
+ members = self.members()
+ return {
+ "total": len(members),
+ "users": len([m for m in members if m.user is not None]),
+ "pending": len([m.signup_code for m in members if not m.invited]),
+ }
+
+ def send_invitations(self):
+ for sc in [m.signup_code for m in self.members() if not m.invited]:
+ sc.send()
+
+ def __unicode__(self):
+ return self.name
+
+
+class SignupCodeCohort(models.Model):
+ """
+ fetch cohort of a given signup code
+ SignupCodeCohort.objects.select_related("cohort").get(signup_code__code="abc").cohort
+
+ list of people waiting NOT on the site already or invited
+ WaitingListEntry.objects.exclude(email__in=SignupCode.objects.values("email")).exclude(email__in=User.objects.values("email"))
+ """
+ signup_code = models.OneToOneField(SignupCode)
+ cohort = models.ForeignKey(Cohort)
+
+
+class UserCohort(models.Model):
+ """
+ Upon signup we create an instance of this model associating the new user and their cohort
+ """
+ user = models.OneToOneField(User)
+ cohort = models.ForeignKey(Cohort)
+
+
+@reciever(user_signed_up)
+def handle_user_signup(sender, **kwargs):
+ signup_code = kwargs["form"].cleaned_data["signup_code"]
+ # fetch the cohort for the signup code
+ qs = SignupCodeCohort.objects.select_related("cohort")
+ cohort = qs.get(signup_code=signup_code).cohort
+ # create a UserCohort for user association to a cohort
+ UserCohort.objects.create(user=user, cohort=cohort)
View
@@ -1,11 +1,16 @@
-import datetime
+from django.utils import timezone
+
+from django.contrib.auth.models import User
+
+from account.models import SignupCode
from waitinglist.models import WaitingListEntry
def stats():
return {
"waiting_list_entries": WaitingListEntry.objects.count(),
- "waitinglist_added_last_seven_days": WaitingListEntry.objects.filter(created__gt=datetime.datetime.now() - datetime.timedelta(days=7)).count(),
- "waitinglist_added_last_thirty_days": WaitingListEntry.objects.filter(created__gt=datetime.datetime.now() - datetime.timedelta(days=30)).count(),
+ "waitinglist_added_last_seven_days": WaitingListEntry.objects.filter(created__gt=timezone.now() - datetime.timedelta(days=7)).count(),
+ "waitinglist_added_last_thirty_days": WaitingListEntry.objects.filter(created__gt=timezone.now() - datetime.timedelta(days=30)).count(),
+ "waiting_list_entries_to_invite": WaitingListEntry.objects.exclude(email__in=SignupCode.objects.values("email")).exclude(email__in=User.objects.values("email")).count()
}
View
@@ -5,4 +5,9 @@
urlpatterns = patterns("",
url(r"^list_signup/$", "waitinglist.views.list_signup", name="waitinglist_list_signup"),
url(r"^success/$", direct_to_template, {"template": "waitinglist/success.html"}, name="waitinglist_success"),
+ url(r"^cohorts/$", "waitinglist.views.cohort_list", name="waitinglist_cohort_list"),
+ url(r"^cohorts/create/$", "waitinglist.views.cohort_create", name="waitinglist_cohort_create"),
+ url(r"^cohorts/cohort/(\d+)/$", "waitinglist.views.cohort_detail", name="waitinglist_cohort_detail"),
+ url(r"^cohorts/cohort/(\d+)/add_member/$", "waitinglist.views.cohort_member_add", name="waitinglist_cohort_member_add"),
+ url(r"^cohorts/cohort/(\d+)/send_invitations/$", "waitinglist.views.cohort_send_invitations", name="waitinglist_cohort_send_invitations"),
)
View
@@ -1,8 +1,14 @@
from django.core.urlresolvers import reverse
+from django.http import Http404
from django.template import RequestContext
-from django.shortcuts import render, redirect
+from django.shortcuts import render, redirect, get_object_or_404
+
+from django.contrib.auth.models import User
+
+from account.models import SignupCode
+from waitinglist.forms import WaitingListEntryForm, CohortCreate
+from waitinglist.models import WaitingListEntry, Cohort, SignupCodeCohort
-from waitinglist.forms import WaitingListEntryForm
def list_signup(request, post_save_redirect=None):
@@ -21,3 +27,102 @@ def list_signup(request, post_save_redirect=None):
"form": form,
}
return render(request, "waitinglist/list_signup.html", ctx)
+
+
+def cohort_list(request):
+
+ if not request.user.is_staff:
+ raise Http404()
+
+ ctx = {
+ "cohorts": Cohort.objects.order_by("-created")
+ }
+ ctx = RequestContext(request, ctx)
+ return render_to_response("cohorts/cohort_list.html", ctx)
+
+
+def cohort_create(request):
+
+ if not request.user.is_staff:
+ raise Http404()
+
+ if request.method == "POST":
+ form = CohortCreate(request.POST)
+
+ if form.is_valid():
+ cohort = form.save()
+ return redirect("cohort_detail", cohort.id)
+ else:
+ form = CohortCreate()
+
+ ctx = {
+ "form": form,
+ }
+ return render(request, "cohorts/cohort_create.html", ctx)
+
+
+def cohort_detail(request, pk):
+
+ if not request.user.is_staff:
+ raise Http404()
+
+ cohort = get_object_or_404(Cohort, pk=pk)
+
+ # people who are NOT invited or on the site already
+ waiting_list = WaitingListEntry.objects.exclude(
+ email__in=SignupCode.objects.values("email")
+ ).exclude(
+ email__in=User.objects.values("email")
+ )
+
+ ctx = {
+ "cohort": cohort,
+ "waiting_list": waiting_list,
+ }
+ return render(request, "cohorts/cohort_detail.html", ctx)
+
+
+def cohort_member_add(request, pk):
+
+ if not request.user.is_staff:
+ raise Http404()
+
+ cohort = Cohort.objects.get(pk=pk)
+
+ if "invite_next" in request.POST:
+ try:
+ N = int(request.POST["invite_next"])
+ except ValueError:
+ return redirect("cohort_detail", cohort.id)
+ # people who are NOT invited or on the site already
+ waiting_list = WaitingListEntry.objects.exclude(
+ email__in=SignupCode.objects.values("email")
+ ).exclude(
+ email__in=User.objects.values("email")
+ )
+ emails = waiting_list.values_list("email", flat=True)[:N]
+ else:
+ email = request.POST["email"].strip()
+ if email:
+ emails = [email]
+ else:
+ emails = []
+
+ for email in emails:
+ if not SignupCode.objects.filter(email=email).exists():
+ signup_code = SignupCode.create(email, 730)
+ signup_code.save()
+ SignupCodeCohort.objects.create(signup_code=signup_code, cohort=cohort)
+
+ return redirect("cohort_detail", cohort.id)
+
+
+def cohort_send_invitations(request, pk):
+
+ if not request.user.is_staff:
+ raise Http404()
+
+ cohort = Cohort.objects.get(pk=pk)
+ cohort.send_invitations()
+
+ return redirect("cohort_detail", cohort.id)

0 comments on commit 8f544e6

Please sign in to comment.