Private
Public Access
1
0

low level team functions

This commit is contained in:
Sander Roosendaal
2017-02-08 18:49:48 +01:00
parent 7e5d751aef
commit d279180d5d
12 changed files with 151 additions and 56 deletions

View File

@@ -32,7 +32,7 @@ class TeamAdmin(admin.ModelAdmin):
list_display = ('name','manager')
class TeamInviteAdmin(admin.ModelAdmin):
list_display = ('issuedate','team','user')
list_display = ('issuedate','team','user','code')
admin.site.unregister(User)
admin.site.register(User,UserAdmin)

View File

@@ -83,7 +83,7 @@ class PowerZonesField(models.TextField):
# For future Team functionality
class Team(models.Model):
name = models.CharField(max_length=150)
name = models.CharField(max_length=150,unique=True)
notes = models.CharField(blank=True,max_length=200)
manager = models.ForeignKey(User)
@@ -92,9 +92,9 @@ class Team(models.Model):
class TeamInvite(models.Model):
team = models.ForeignKey(Team)
user = models.ForeignKey(User)
user = models.ForeignKey(User,null=True)
issuedate = models.DateField(default=timezone.now)
code = models.CharField(max_length=150)
code = models.CharField(max_length=150,unique=True)
# Extension of User with rowing specific data

95
rowers/teams.py Normal file
View File

@@ -0,0 +1,95 @@
# All the Team related methods
# Python
from django.utils import timezone
from datetime import datetime
from datetime import timedelta
import time
from django.db import IntegrityError
import uuid
from rowers.models import (
Rower, Workout, Team, TeamInvite,User
)
# Low level functions - to be called by higher level methods
def create_team(name,manager,notes=''):
# needs some error testing
try:
t = Team(name=name,manager=manager,notes=notes)
t.save()
r = Rower.objects.get(user=manager)
r.team.add(t)
except IntegrityError:
return (0,'Team name duplication')
return (t.id,'Team created')
def remove_team(id):
t = Team.objects.get(id=id)
return t.delete()
def add_member(id,rower):
t= Team.objects.get(id=id)
rower.team.add(t)
return (1,'Member added')
def remove_member(id,rower):
t = Team.objects.get(id=id)
rower.team.remove(t)
return (1,'Member removed')
def mgr_remove_member(id,manager,rower):
t = Team.objects.get(id=id)
if t.manager == manager:
rower.team.remove(t)
return (1,'Member added')
else:
return (0,'You are not the team manager')
return 0
def count_members(id):
t = Team.objects.get(id=id)
return Rower.objects.filter(team=t).count()
def count_club_members(manager):
ts = Team.objects.filter(manager=manager)
return Rower.objects.filter(team__in=ts).distinct().count()
def get_club_members(manager):
ts = Team.objects.filter(manager=manager)
return Rower.objects.filter(team__in=ts).distinct()
def get_team_members(id):
t = Team.objects.get(id=id)
return Rower.objects.filter(team=t)
# Medium level functionality
def create_invite(team,manager,user=None):
if team.manager != manager:
return (0,'Not the team manager')
if user:
try:
r2 = Rower.objects.get(user=user)
except Rower.DoesNotExist:
return (0,'Rower does not exist')
if r2 in Rower.objects.filter(team=team):
return (0,'Already member of that team')
if count_club_members(team.manager) < r.clubsize:
codes = [i.code for i in TeamInvite.objects.all()]
code = uuid.uuid4().hex[:10].upper()
# prevent duplicates
while code in codes:
code = uuid.uuid4().hex[:10].upper()
invite = TeamInvite(team=team,code=code,user=user)
invite.save()
return code
else:
return (0,'You are at your club size limit')
return (0,'Nothing done')

View File

@@ -51,7 +51,7 @@
<div class="grid_6 alpha">
<div class="grid_2 alpha">
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/compare/{{ workout.id }}">Compare Workouts</a>
{% else %}
<a class="button blue small" href="/rowers/promembership/">Compare Workouts</a>
@@ -71,7 +71,7 @@
<div class="grid_2 omega tooltip">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/editintervals">Edit Intervals</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Edit Intervals</a>
@@ -88,7 +88,7 @@
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/adddistanceplot2">Dist Metrics Plot</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Dist Metrics Plot</a>
@@ -100,7 +100,7 @@
</div>
<div class="grid_2">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/addtimeplot2">Time Metrics Plot</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Time Metrics Plot</a>
@@ -123,7 +123,7 @@
<div class="grid_2 suffix_4 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/histo">Power Histogram</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Dist Metrics Plot</a>

View File

@@ -51,7 +51,7 @@
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/compare/{{ workout.id }}">Compare Workouts</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Compare Workouts</a>
@@ -73,7 +73,7 @@
<div class="grid_2 omega tooltip">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/editintervals">Edit Intervals</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Edit Intervals</a>
@@ -90,7 +90,7 @@
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small"href="/rowers/workout/{{ workout.id }}/crewnerdsummary">CrewNerd Summary</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">CrewNerd Summary</a>
@@ -104,7 +104,7 @@
<div class="grid_2 tooltip">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/forcecurve">Stroke Profile (Empower)</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Stroke Profile (Empower)</a>
@@ -117,7 +117,7 @@
<div class="grid_2 omega tooltip">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/addotwpowerplot">OTW Power Plot</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">OTW Power Plot</a>
@@ -137,7 +137,7 @@
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/geeky">Geeky Stuff</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Geeky Stuff</a>
@@ -152,7 +152,7 @@
<div class="grid_2 tooltip">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small"href="/rowers/workout/{{ workout.id }}/smoothenpace">Smooth out Pace Data</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Smooth out Pace Data</a>
@@ -169,7 +169,7 @@
<div class="grid_2 omega">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small"href="/rowers/workout/{{ workout.id }}/undosmoothenpace">Raw Data</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Reset Smoothing</a>

View File

@@ -41,7 +41,7 @@
<h2>Pro</h2>
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/histo">Power Histogram</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Power Histogram</a>
@@ -53,7 +53,7 @@
</div>
<div class="grid_2">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/cumstats">Statistics</a>
{% else %}
<a class="button blue small" href="/rowers/promembership">Statistics</a>

View File

@@ -24,7 +24,7 @@
{% analytical_body_top %}
<div class="container_12">
<div id="logo" class="grid_2">
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<p><a href="/"><img src="/static/img/logocroppedpro.gif"
alt="Rowsandall logo" width="110" heigt="110"></a></p>
{% else %}
@@ -49,7 +49,7 @@
<p>Free Data and Analysis. For Rowers. By Rowers.</p>
</div>
<div class="grid_3">
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<h6>Pro Member</h6>
{% else %}
<p>&nbsp;</p>

View File

@@ -19,7 +19,7 @@
<body>
<div class="container_12">
<div id="logo" class="grid_2">
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<p><a href="/"><img src="/static/img/logocroppedpro.gif"
alt="Rowsandall logo" width="110" heigt="110"></a></p>
{% else %}
@@ -44,7 +44,7 @@
<p>Free Data and Analysis. For Rowers. By Rowers.</p>
</div>
<div class="grid_3">
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<h6>Pro Member</h6>
{% else %}
<p>&nbsp;</p>

View File

@@ -168,7 +168,7 @@
</div>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<div id="favorites" class="grid_12 alpha">
<div class="grid_2 suffix_4 alpha">
{% if maxfav >= 0 %}

View File

@@ -203,7 +203,7 @@
</div>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<div id="favorites" class="grid_12 alpha">
<div class="grid_2 suffix_4 alpha">
{% if maxfav >= 0 %}

View File

@@ -57,7 +57,7 @@
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/wind">Edit Wind Data</a>
{% else %}
<a class="button blue small" href="/rowers/about">Edit Wind Data</a>
@@ -70,7 +70,7 @@
</div>
<div class="grid_2">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/stream">Edit Stream Data</a>
{% else %}
<a class="button blue small" href="/rowers/about">Edit Stream Data</a>
@@ -83,7 +83,7 @@
</div>
<div class="grid_2 omega">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/otwsetpower">OTW Power</a>
{% else %}
<a class="button blue small" href="/rowers/about">OTW Power</a>
@@ -100,7 +100,7 @@
<div class="grid_2 alpha">
<p>
{% if user.rower.rowerplan == 'pro' %}
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/interactiveotwplot">Corrected Pace Plot</a>
{% else %}
<a class="button blue small" href="/rowers/about">Corrected Pace Plot</a>
@@ -159,4 +159,4 @@
</div>
</div>
{% endblock %}
{% endblock %}

View File

@@ -199,7 +199,7 @@ def splitstdata(lijst):
from utils import geo_distance,serialize_list,deserialize_list
# Check if a user is a Pro member
def promember(user):
def ispromember(user):
r = Rower.objects.get(user=user)
result = user.is_authenticated() and (r.rowerplan=='pro' or r.rowerplan=='coach')
return result
@@ -1301,7 +1301,7 @@ def histo_all(request,theuser=0):
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -1371,7 +1371,7 @@ def cum_flex(request,theuser=0,
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -1463,14 +1463,14 @@ def cum_flex(request,theuser=0,
})
# Show the EMpower Oarlock generated Stroke Profile
@user_passes_test(promember,login_url="/",redirect_field_name=None)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_forcecurve_view(request,id=0,workstrokesonly=False):
row = Workout.objects.get(id=id)
promember=0
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
if request.user == row.user.user:
@@ -1509,7 +1509,7 @@ def workout_histo_view(request,id=0):
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
if request.user == row.user.user:
@@ -1561,7 +1561,7 @@ def histo(request,theuser=0,
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -1671,7 +1671,7 @@ def rankings_view(request,theuser=0,
promember=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -2040,7 +2040,7 @@ def workouts_view(request,message='',successmessage='',
return HttpResponse("User has no rower instance")
# List of workouts to compare a selected workout to
@user_passes_test(promember,login_url="/",redirect_field_name=None)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_comparison_list(request,id=0,message='',successmessage='',
startdatestring="",enddatestring="",
startdate=timezone.now()-datetime.timedelta(days=365),
@@ -2155,7 +2155,7 @@ def workout_view(request,id=0):
except Workout.DoesNotExist:
return HttpResponseNotFound("Workout doesn't exist")
# Resets stroke data to raw data (pace)
# Resets stroke data to raw data (pace)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2182,7 +2182,7 @@ def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""):
return HttpResponseRedirect(url)
# Data smoothing of pace data
# Data smoothing of pace data
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_smoothenpace_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2218,7 +2218,7 @@ def workout_smoothenpace_view(request,id=0,message="",successmessage=""):
return HttpResponseRedirect(url)
# Process CrewNerd Summary CSV and update summary
# Process CrewNerd Summary CSV and update summary
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2263,7 +2263,7 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""):
{'form':form,
'id':row.id})
# Get weather for given location and date/time
# Get weather for given location and date/time
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_downloadwind_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2320,7 +2320,7 @@ def workout_downloadwind_view(request,id=0,message="",successmessage=""):
return response
# Show form to update wind data
# Show form to update wind data
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_wind_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2420,7 +2420,7 @@ def workout_wind_view(request,id=0,message="",successmessage=""):
'gmapdiv':gmdiv})
# Show form to update River stream data (for river dwellers)
# Show form to update River stream data (for river dwellers)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_stream_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2482,7 +2482,7 @@ def workout_stream_view(request,id=0,message="",successmessage=""):
'form':form,
'the_div':div})
# Form to set average crew weight and boat type, then run power calcs
# Form to set average crew weight and boat type, then run power calcs
@user_passes_test(ispromember, login_url="/",redirect_field_name=None)
def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
row = Workout.objects.get(id=id)
@@ -2654,7 +2654,7 @@ def cumstats(request,theuser=0,
theuser = request.user.id
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -3086,7 +3086,7 @@ def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'):
def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'):
promember=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -3113,7 +3113,7 @@ def workout_comparison_view2(request,id1=0,id2=0,xparam='distance',
yparam='spm',plottype='line'):
promember=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -3161,7 +3161,7 @@ def workout_flexchart3_view(request,*args,**kwargs):
promember=0
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -3316,7 +3316,7 @@ def workout_biginteractive_view(request,id=0,message="",successmessage=""):
promember=0
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -3353,7 +3353,7 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
promember=0
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and ispromember(request.user)
if result:
promember=1
@@ -3555,7 +3555,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
})
return HttpResponseRedirect(url)
# Create the chart image with wind corrected pace (OTW)
# Create the chart image with wind corrected pace (OTW)
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_add_otw_powerplot_view(request,id):
w = Workout.objects.get(id=id)
@@ -3818,7 +3818,7 @@ def workout_add_distanceplot_view(request,id):
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the advanced parameters distance overview chart
# Create the advanced parameters distance overview chart
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_add_distanceplot2_view(request,id):
w = Workout.objects.get(id=id)
@@ -3871,7 +3871,7 @@ def workout_add_distanceplot2_view(request,id):
return HttpResponseRedirect(url)
# Create the advanced parameters time based overview chart
# Create the advanced parameters time based overview chart
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
def workout_add_timeplot2_view(request,id):
w = Workout.objects.get(id=id)
@@ -4934,7 +4934,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
'savebutton':savebutton,
})
# Page where user can manage his favorite charts
# Page where user can manage his favorite charts
@user_passes_test(ispromember,login_url="/rowers/me/edit",redirect_field_name=None)
def rower_favoritecharts_view(request):
message = ''