This repository has been archived by the owner on Aug 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from epantry/follow-up-question
Follow up question
- Loading branch information
Showing
18 changed files
with
369 additions
and
492 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
include LICENSE | ||
include README.md | ||
recursive-include netpromoterscore/templates * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from django.http import HttpResponse | ||
from .app_settings import PROMOTERSCORE_PERMISSION_VIEW | ||
from .utils import safe_admin_login_prompt | ||
|
||
|
||
def login_required(f): | ||
def wrap(request, *args, **kwargs): | ||
if request.user.is_anonymous(): | ||
return HttpResponse(status=401) | ||
return f(request, *args, **kwargs) | ||
return wrap | ||
|
||
|
||
def admin_required(f): | ||
def wrap(request, *args, **kwargs): | ||
if not PROMOTERSCORE_PERMISSION_VIEW(request.user): | ||
return safe_admin_login_prompt(request) | ||
return f(request, *args, **kwargs) | ||
return wrap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from django import forms | ||
from .models import PromoterScore | ||
|
||
class PromoterScoreForm(forms.ModelForm): | ||
score = forms.IntegerField(min_value=-1, max_value=10, required=False) | ||
reason = forms.CharField(max_length=512, required=False) | ||
|
||
class Meta: | ||
model = PromoterScore | ||
fields = ('score', 'reason', 'user') |
261 changes: 26 additions & 235 deletions
261
netpromoterscore/migrations/0001_initial.py
100755 → 100644
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import unicode_literals | ||
|
||
from django.db import models, migrations | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('netpromoterscore', '0001_initial'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='promoterscore', | ||
name='reason', | ||
field=models.TextField(null=True, blank=True), | ||
preserve_default=True, | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from datetime import datetime, timedelta | ||
from django.contrib.auth import get_user_model | ||
from netpromoterscore.models import PromoterScore | ||
|
||
|
||
class TestMixin(object): | ||
|
||
def create_users(self): | ||
self.user_model = get_user_model() | ||
|
||
self.user = self.user_model.objects.create_user( | ||
username='jared', email='[email protected]', password='foobar123' | ||
) | ||
self.user2 = self.user_model.objects.create_user( | ||
username='cole', email='[email protected]', password='foobar321' | ||
) | ||
|
||
self.user.save() | ||
self.user2.save() | ||
|
||
def create_promoter_scores(self): | ||
self.now = datetime.now() | ||
|
||
self.ps1 = PromoterScore(user=self.user, score=8) | ||
self.ps1.save() | ||
|
||
self.ps2 = PromoterScore(user=self.user, score=9) | ||
self.ps2.save() | ||
self.ps2.created_at = self.now - timedelta(4*365/12) | ||
self.ps2.save() | ||
|
||
self.ps3 = PromoterScore(user=self.user2, score=9) | ||
self.ps3.save() | ||
self.ps3.created_at = self.now - timedelta(7*365/12) | ||
self.ps3.save() | ||
|
||
def delete_users(self): | ||
self.user_model.objects.all().delete() | ||
|
||
def delete_promoter_scores(self): | ||
PromoterScore.objects.all().delete() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,23 @@ | ||
import datetime | ||
from django.contrib.auth.models import User | ||
from django.test import TestCase | ||
from netpromoterscore.models import PromoterScore, NetPromoterScore | ||
from netpromoterscore.models import PromoterScore | ||
from . import TestMixin | ||
|
||
class TestPromoterScoreModels(TestCase, TestMixin): | ||
|
||
class TestPromoterScoreModels(TestCase): | ||
def setUp(self): | ||
self.user1 = User.objects.create_user(username='jared', email='[email protected]', password='foobar123') | ||
self.user1.save() | ||
self.user2 = User.objects.create_user(username='cole', email='[email protected]', password='foobar321') | ||
self.now = datetime.datetime.now() | ||
self.ps1 = PromoterScore(user=self.user1, score=8) | ||
self.ps1.save() | ||
self.ps2 = PromoterScore(user=self.user1, score=9) | ||
self.ps2.save() | ||
self.ps2.created_at = self.now+datetime.timedelta(-4*365/12) | ||
self.ps2.save() | ||
self.ps3 = PromoterScore(user=self.user2, score=9) | ||
self.ps3.save() | ||
self.ps3.created_at = self.now+datetime.timedelta(-7*365/12) | ||
self.ps3.save() | ||
self.create_users() | ||
self.create_promoter_scores() | ||
|
||
def tearDown(self): | ||
self.delete_promoter_scores() | ||
self.delete_users() | ||
|
||
def test_rolling_months(self): | ||
got = PromoterScore.objects._rolling(month=self.now) | ||
expected = {self.user1.pk: self.ps1.score, self.user2.pk: self.ps3.score} | ||
got = PromoterScore.objects.rolling(month=self.now) | ||
expected = {self.user.pk: self.ps1.score, self.user2.pk: self.ps3.score} | ||
self.assertEqual(expected, got) | ||
|
||
def test_one_month_only(self): | ||
got = PromoterScore.objects._one_month_only(month=self.now) | ||
expected = {self.user1.pk: self.ps1.score} | ||
got = PromoterScore.objects.one_month_only(month=self.now) | ||
expected = {self.user.pk: self.ps1.score} | ||
self.assertEqual(expected, got) | ||
|
||
def test_get_netpromoter_with_rolling(self): | ||
got = PromoterScore.objects._get_netpromoter(month=self.now, rolling=True) | ||
self.assertEqual([1, 1], [got.promoters, got.passive]) | ||
|
||
def test_get_netpromoter_without_rolling(self): | ||
got = PromoterScore.objects._get_netpromoter(month=self.now, rolling=False) | ||
self.assertEqual([0, 1], [got.promoters, got.passive]) | ||
|
||
class TestNetPromoterScoreModels(TestCase): | ||
|
||
def test_net_promoter_score_calculation(self): | ||
self.label = 'January 2014' | ||
self.promoters = 50 | ||
self.detractors = 25 | ||
self.passive = 25 | ||
self.skipped = 0 | ||
nps = NetPromoterScore(self.label, self.promoters, self.detractors, self.passive, self.skipped) | ||
self.assertEqual(float(25.0), nps.score) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.