athlete edit permissions in place
This commit is contained in:
@@ -167,6 +167,11 @@ def update_subscription(rower,data,method='up'):
|
||||
l = rower.user.last_name,
|
||||
)
|
||||
|
||||
if rower.paidplan != 'coach':
|
||||
coachees = Rower.objects.filter(coach__in=[rower]).distinct()
|
||||
for coachee in coachees:
|
||||
coachee.coaches.remove(rower)
|
||||
|
||||
if method == 'up':
|
||||
transactions = result.subscription.transactions
|
||||
|
||||
|
||||
@@ -340,6 +340,7 @@ class Team(models.Model):
|
||||
|
||||
viewing = models.CharField(max_length=30,choices=viewchoices,default='allmembers',verbose_name='Sharing Behavior')
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
@@ -831,6 +832,7 @@ class Rower(models.Model):
|
||||
|
||||
# Friends/Team
|
||||
friends = models.ManyToManyField("self",blank=True)
|
||||
coaches = models.ManyToManyField("self",blank=True)
|
||||
privacy = models.CharField(default='visible',max_length=30,
|
||||
choices=privacychoices)
|
||||
|
||||
@@ -986,12 +988,12 @@ def checkworkoutuser(user,workout):
|
||||
return False
|
||||
try:
|
||||
r = Rower.objects.get(user=user)
|
||||
teams = workout.team.all()
|
||||
coaches = user.rower.coaches.filter(rowerplan='coach')
|
||||
if workout.user == r:
|
||||
return True
|
||||
elif teams:
|
||||
for team in teams:
|
||||
if user == team.manager and workout.privacy == 'visible':
|
||||
elif coaches:
|
||||
for coach in coaches:
|
||||
if user.rower == coach and workout.privacy == 'visible':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -1003,17 +1005,17 @@ def checkworkoutuser(user,workout):
|
||||
def checkaccessuser(user,rower):
|
||||
try:
|
||||
r = Rower.objects.get(user=user)
|
||||
teams = Team.objects.filter(manager=user)
|
||||
if rower == r:
|
||||
return True
|
||||
elif teams:
|
||||
for team in teams:
|
||||
if team in rower.team.all():
|
||||
coaches = rower.coaches.filter(rowerplan='coach')
|
||||
if coaches:
|
||||
for coach in coaches:
|
||||
if user.rower == coach:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except Rower.DoesNotExist:
|
||||
return False
|
||||
return False
|
||||
|
||||
timezones = (
|
||||
(x,x) for x in pytz.common_timezones
|
||||
|
||||
@@ -102,6 +102,11 @@ def remove_team(id):
|
||||
|
||||
return (1,'Updated rower team expiry')
|
||||
|
||||
def add_coach(manager,rower):
|
||||
rower.coaches.add(m)
|
||||
|
||||
return (1,"Added Coach")
|
||||
|
||||
def add_member(id,rower):
|
||||
t= Team.objects.get(id=id)
|
||||
try:
|
||||
@@ -414,6 +419,7 @@ def process_request_code(manager,code):
|
||||
result = add_member(t.id,r)
|
||||
if not result:
|
||||
return (result,"The member couldn't be added")
|
||||
|
||||
|
||||
send_request_accept_email(rekwest)
|
||||
|
||||
@@ -439,6 +445,7 @@ def process_invite_code(user,code):
|
||||
if not result:
|
||||
return (result,"The member couldn't be added")
|
||||
|
||||
|
||||
send_invite_accept_email(invitation)
|
||||
invitation.delete()
|
||||
return result
|
||||
|
||||
@@ -376,6 +376,15 @@ def team_rowers(user):
|
||||
|
||||
return []
|
||||
|
||||
@register.filter
|
||||
def coach_rowers(user):
|
||||
try:
|
||||
members = Rower.objects.filter(coaches__in=user.rower).distinct().order_by(
|
||||
"user__last_name","user__last_name"
|
||||
)
|
||||
return members
|
||||
except TypeError:
|
||||
return []
|
||||
|
||||
@register.filter
|
||||
def verbosetimeperiod(timeperiod):
|
||||
|
||||
@@ -455,9 +455,10 @@ class PermissionsViewTests(TestCase):
|
||||
|
||||
|
||||
|
||||
## Coach can edit on behalf of athlete
|
||||
## Coach can edit on behalf of athlete if permitted
|
||||
def test_coach_edit_athlete_settings(self):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
self.rbasic.coaches.add(self.rcoach)
|
||||
|
||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||
self.assertTrue(login)
|
||||
@@ -467,10 +468,22 @@ class PermissionsViewTests(TestCase):
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
def test_coach_edit_athlete_settings_not(self):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
|
||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||
self.assertTrue(login)
|
||||
|
||||
url = reverse('rower_prefs_view',kwargs={'userid':self.ubasic.id})
|
||||
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,403)
|
||||
|
||||
## Coach can run analytics for athlete
|
||||
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats)
|
||||
def test_coach_edit_athlete_analysis(self,mocked_df):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
self.rbasic.coaches.add(self.rcoach)
|
||||
|
||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||
self.assertTrue(login)
|
||||
@@ -486,12 +499,31 @@ class PermissionsViewTests(TestCase):
|
||||
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats)
|
||||
def test_coach_edit_athlete_analysis_not(self,mocked_df):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
|
||||
## Coach can upload on behalf of athlete
|
||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||
self.assertTrue(login)
|
||||
|
||||
|
||||
url = reverse('cumstats',
|
||||
kwargs={
|
||||
'theuser':self.ubasic.id,
|
||||
}
|
||||
)
|
||||
|
||||
response = self.c.get(url)
|
||||
|
||||
self.assertEqual(response.status_code,403)
|
||||
|
||||
|
||||
## Coach can upload on behalf of athlete - if team allows
|
||||
@patch('rowers.dataprep.create_engine')
|
||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
||||
def test_coach_edit_athlete_upload(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
self.rbasic.coaches.add(self.rcoach)
|
||||
|
||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||
self.assertTrue(login)
|
||||
@@ -531,6 +563,50 @@ class PermissionsViewTests(TestCase):
|
||||
|
||||
self.assertEqual(aantal2,aantal+1)
|
||||
|
||||
## Coach can upload on behalf of athlete - if team allows
|
||||
@patch('rowers.dataprep.create_engine')
|
||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
||||
def test_coach_edit_athlete_uploadnot(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
|
||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||
self.assertTrue(login)
|
||||
|
||||
url = reverse('team_workout_upload_view')
|
||||
|
||||
aantal = len(Workout.objects.filter(user=self.rbasic))
|
||||
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
filename = 'rowers/tests/testdata/testdata.csv'
|
||||
f = open(filename,'rb')
|
||||
file_data = {'file': f}
|
||||
form_data = {
|
||||
'title':'test',
|
||||
'workouttype':'rower',
|
||||
'boattype':'1x',
|
||||
'notes':'aap noot mies',
|
||||
'make_plot':False,
|
||||
'upload_to_c2':False,
|
||||
'plottype':'timeplot',
|
||||
'file': f,
|
||||
'user': self.ubasic.id
|
||||
}
|
||||
|
||||
response = self.c.post(url, form_data, follow=True)
|
||||
f.close()
|
||||
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
self.assertRedirects(response,
|
||||
expected_url = url,
|
||||
status_code=302,target_status_code=200)
|
||||
|
||||
aantal2 = len(Workout.objects.filter(user=self.rbasic))
|
||||
|
||||
self.assertEqual(aantal2,aantal)
|
||||
|
||||
## Coach can edit athlete's workout
|
||||
def test_coach_edit_athlete_workout(self):
|
||||
self.rbasic.team.add(self.teamcoach)
|
||||
|
||||
@@ -404,6 +404,12 @@ def isprorower(r):
|
||||
result = r.rowerplan == 'basic' and r.protrialexpires >= datetime.date.today()
|
||||
|
||||
return result
|
||||
|
||||
def iscoach(m,r):
|
||||
result = False
|
||||
result = m in r.coaches
|
||||
|
||||
return result
|
||||
|
||||
# Exponentially weighted moving average
|
||||
# Used for data smoothing of the jagged data obtained by Strava
|
||||
|
||||
@@ -267,6 +267,7 @@ def team_requestmembership_view(request,teamid,userid):
|
||||
messages.info(request,text)
|
||||
else:
|
||||
messages.error(request,text)
|
||||
|
||||
|
||||
url = reverse('team_view',kwargs={
|
||||
'id':int(teamid),
|
||||
|
||||
@@ -4235,16 +4235,18 @@ def team_workout_upload_view(request,message="",
|
||||
|
||||
rowerform = TeamInviteForm(request.POST)
|
||||
rowerform.fields.pop('email')
|
||||
rowerform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct()
|
||||
rowers = Rower.objects.filter(coaches__in=[request.user.rower]).distinct()
|
||||
rowerform.fields['user'].queryset = User.objects.filter(rower__in=rowers).distinct()
|
||||
if form.is_valid():
|
||||
f = request.FILES['file']
|
||||
res = handle_uploaded_file(f)
|
||||
t = form.cleaned_data['title']
|
||||
offline = form.cleaned_data['offline']
|
||||
boattype = form.cleaned_data['boattype']
|
||||
workouttype = form.cleaned_data['workouttype']
|
||||
if rowerform.is_valid():
|
||||
u = rowerform.cleaned_data['user']
|
||||
if u:
|
||||
if u and request.user.rower in u.rower.coaches.all():
|
||||
r = getrower(u)
|
||||
else:
|
||||
message = 'Please select a rower'
|
||||
|
||||
Reference in New Issue
Block a user