Private
Public Access
1
0

Merge branch 'release/v23.0.0'

This commit is contained in:
2024-12-31 16:41:12 +01:00
49 changed files with 294 additions and 897 deletions
+1 -1
View File
@@ -191,7 +191,7 @@ def get_garmin_workout_list(user): # pragma: no cover
def garmin_can_export_session(user): def garmin_can_export_session(user):
if user.rower.rowerplan not in ['coach', 'plan']: if user.rower.rowerplan != 'pro':
return False # pragma: no cover return False # pragma: no cover
result = get_garmin_permissions(user) result = get_garmin_permissions(user)
if 'WORKOUT_IMPORT' in result: if 'WORKOUT_IMPORT' in result:
+17 -18
View File
@@ -3,7 +3,7 @@ from rowers.models import Rower, User, Workout, TombStone, PlannedSession
from rowingdata import rowingdata from rowingdata import rowingdata
from rowingdata import FITParser as FP from rowingdata import FITParser as FP
from rowingdata.otherparsers import FitSummaryData from rowingdata.otherparsers import FitSummaryData
from rowers.rower_rules import user_is_not_basic, user_is_coachee #from rowers.rower_rules import user_is_not_basic, user_is_coachee
from rowers.dataroutines import totaltime_sec_to_string from rowers.dataroutines import totaltime_sec_to_string
from rowers import mytypes from rowers import mytypes
@@ -721,26 +721,25 @@ class IntervalsIntegration(SyncIntegration):
def import_activities(self, event, *args, **kwargs): def import_activities(self, event, *args, **kwargs):
if not self.rower.intervals_auto_import: if not self.rower.intervals_auto_import:
return 0 return 0
if user_is_not_basic(self.rower.user) or user_is_coachee(self.rower.user):
try:
record = event["activity"]
except KeyError:
records = []
try:
id = record['id']
external_id = record['external_id']
try: try:
record = event["activity"] w = Workout.objects.get(id=encoder.decode_hex(external_id))
except KeyError: result = self.update_workout(id)
records = [] except Workout.DoesNotExist:
result = self.get_workout(id, do_async=False)
except KeyError:
pass
try: return 1
id = record['id']
external_id = record['external_id']
try:
w = Workout.objects.get(id=encoder.decode_hex(external_id))
result = self.update_workout(id)
except Workout.DoesNotExist:
result = self.get_workout(id, do_async=False)
except KeyError:
pass
return 1
return 0
def delete_activities(self, event, *args, **kwargs): def delete_activities(self, event, *args, **kwargs):
try: try:
+7 -20
View File
@@ -86,9 +86,8 @@ class Command(BaseCommand):
rowers = Rower.objects.filter(c2_auto_import=True) rowers = Rower.objects.filter(c2_auto_import=True)
for r in rowers: # pragma: no cover for r in rowers: # pragma: no cover
try: try:
if user_is_not_basic(r.user) or user_is_coachee(r.user): c2integration = C2Integration(r.user)
c2integration = C2Integration(r.user) _ = c2integration.get_workouts()
_ = c2integration.get_workouts()
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
@@ -97,9 +96,8 @@ class Command(BaseCommand):
rowers = Rower.objects.filter(rp3_auto_import=True) rowers = Rower.objects.filter(rp3_auto_import=True)
for r in rowers: # pragma: no cover for r in rowers: # pragma: no cover
try: try:
if user_is_not_basic(r.user) or user_is_coachee(r.user): rp3_integration = RP3Integration(r.user)
rp3_integration = RP3Integration(r.user) _ = rp3_integration.get_workouts()
_ = rp3_integration.get_workouts()
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
@@ -108,25 +106,14 @@ class Command(BaseCommand):
rowers = Rower.objects.filter(nk_auto_import=True) rowers = Rower.objects.filter(nk_auto_import=True)
for r in rowers: # pragma: no cover for r in rowers: # pragma: no cover
try: try:
if user_is_not_basic(r.user) or user_is_coachee(r.user): dologging("nklog.log","NK Auto import set for rower {id}".format(id=r.user.id))
dologging("nklog.log","NK Auto import set for rower {id}".format(id=r.user.id)) nk_integration = NKIntegration(r.user)
nk_integration = NKIntegration(r.user) _ = nk_integration.get_workouts()
_ = nk_integration.get_workouts()
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
dologging('processemail.log', ''.join('!! ' + line for line in lines)) dologging('processemail.log', ''.join('!! ' + line for line in lines))
#rowers = Rower.objects.filter(intervals_auto_import=True)
#for r in rowers:
# try:
# if user_is_not_basic(r.user) or user_is_coachee(r.user):
# intervals_integration = IntervalsIntegration(r.user)
# _ = intervals_integration.get_workouts()
# except:
# exc_type, exc_value, exc_traceback = sys.exc_info()
# lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
# dologging('processemail.log', ''.join('!! ' + line for line in lines))
self.stdout.write(self.style.SUCCESS( self.stdout.write(self.style.SUCCESS(
'Successfully processed email attachments')) 'Successfully processed email attachments'))
+1 -1
View File
@@ -105,7 +105,7 @@ class RowerPlanMiddleWare(object):
self.get_response = get_response self.get_response = get_response
def __call__(self, request): def __call__(self, request):
if request.user.is_authenticated and request.user.rower.rowerplan not in ['basic', 'freecoach']: if request.user.is_authenticated and request.user.rower.rowerplan != 'basic':
if request.user.rower.paymenttype == 'single': if request.user.rower.paymenttype == 'single':
if request.user.rower.planexpires < timezone.now().date(): # pragma: no cover if request.user.rower.planexpires < timezone.now().date(): # pragma: no cover
messg = 'Your paid plan has expired. We have reset you to a free basic plan.' messg = 'Your paid plan has expired. We have reset you to a free basic plan.'
+4 -9
View File
@@ -862,9 +862,6 @@ weightcategories = mytypes.weightcategories
plans = ( plans = (
('basic', 'basic'), ('basic', 'basic'),
('pro', 'pro'), ('pro', 'pro'),
('plan', 'plan'),
('coach', 'coach'),
('freecoach', 'freecoach'),
) )
paymenttypes = ( paymenttypes = (
@@ -1219,7 +1216,7 @@ class Rower(models.Model):
polartokenexpirydate = models.DateTimeField(blank=True, null=True) polartokenexpirydate = models.DateTimeField(blank=True, null=True)
polarrefreshtoken = models.CharField(default='', max_length=1000, polarrefreshtoken = models.CharField(default='', max_length=1000,
blank=True, null=True) blank=True, null=True)
polaruserid = models.IntegerField(default=0) polaruserid = models.IntegerField(default=0, blank=True, null=True)
polar_auto_import = models.BooleanField(default=False) polar_auto_import = models.BooleanField(default=False)
garmintoken = models.CharField( garmintoken = models.CharField(
@@ -1329,8 +1326,6 @@ class Rower(models.Model):
for group in self.coachinggroups.all(): for group in self.coachinggroups.all():
try: try:
coach = Rower.objects.get(mycoachgroup=group) coach = Rower.objects.get(mycoachgroup=group)
if coach.rowerplan == 'freecoach': # pragma: no cover
self.coachinggroups.remove(group)
except Rower.DoesNotExist: # pragma: no cover except Rower.DoesNotExist: # pragma: no cover
pass pass
except ValueError: except ValueError:
@@ -1353,7 +1348,7 @@ class Rower(models.Model):
return coaches return coaches
def can_coach(self): def can_coach(self):
if self.rowerplan not in ['coach', 'freecoach']: if self.rowerplan != 'pro':
return False return False
rs = Rower.objects.filter(coachinggroups__in=[self.mycoachgroup]) rs = Rower.objects.filter(coachinggroups__in=[self.mycoachgroup])
@@ -1365,7 +1360,7 @@ class Rower(models.Model):
@property @property
def ispaid(self): # pragma: no cover def ispaid(self): # pragma: no cover
return self.rowerplan in ['pro', 'plan', 'coach'] return self.rowerplan == 'pro'
class DeactivateUserForm(forms.ModelForm): class DeactivateUserForm(forms.ModelForm):
@@ -2980,7 +2975,7 @@ class PlannedSession(models.Model):
if not is_virtualevent: if not is_virtualevent:
if not can_add_session(self.manager): if not can_add_session(self.manager):
raise ValidationError( raise ValidationError(
"You must be a Self-Coach user or higher to create a planned session" "You must be a Pro user or higher to create a planned session"
) )
# interval string # interval string
+1 -1
View File
@@ -35,7 +35,7 @@ class IsRowerOrNot(permissions.BasePermission):
class IsPlanOrHigher(permissions.BasePermission): class IsPlanOrHigher(permissions.BasePermission):
def has_object_permission(self, request, view, obj): # pragma: no cover def has_object_permission(self, request, view, obj): # pragma: no cover
r = Rower.objects.get(user=request.user) r = Rower.objects.get(user=request.user)
return r not in ['basic', 'pro', 'freecoach'] return r.rowerplan == 'pro'
class IsCompetitorOrNot(permissions.BasePermission): class IsCompetitorOrNot(permissions.BasePermission):
+2 -2
View File
@@ -831,12 +831,12 @@ def add_team_session(t, ps):
def add_rower_session(r, ps): def add_rower_session(r, ps):
teams = Team.objects.filter(manager=ps.manager) teams = Team.objects.filter(manager=ps.manager)
members = Rower.objects.filter(team__in=teams).distinct() members = Rower.objects.filter(team__in=teams).distinct()
if r in members and r.rowerplan != 'freecoach': if r in members:
ps.rower.add(r) ps.rower.add(r)
ps.save() ps.save()
return 1 return 1
elif ps.manager.rower == r and r.rowerplan != 'freecoach': elif ps.manager.rower == r:
ps.rower.add(r) ps.rower.add(r)
ps.save() ps.save()
+40 -53
View File
@@ -8,7 +8,7 @@ from django.utils import timezone
""" """
USER permissions USER permissions
- There are 5 types of user: basic, pro, plan, coach, freecoach - There are 2 types of user: basic, pro
- These methods exist on user - These methods exist on user
- user.rower - user.rower
- user.is_anonymous - user.is_anonymous
@@ -17,31 +17,31 @@ USER permissions
- These methods exist on rower - These methods exist on rower
- rower.rowerplan - rower.rowerplan
- rower.protrialexpires - rower.protrialexpires
- rower.plantrialexpires - rower.protrialexpires
- rower.mycoachgroup - rower.mycoachgroup
- rower.coachinggroups - rower.coachinggroups
- rower.team - rower.team
- These Rules apply to Rowers - These Rules apply to Rowers
- Coach can have any number of groups - Pro can have any number of groups
- test_permissions.PermissionFreeCoach.test_coach_groupmanager - test_permissions.PermissionFreeCoach.test_coach_groupmanager
- test_permissions.PermissionsBasicsTests.test_coach_groupmanager - test_permissions.PermissionsBasicsTests.test_coach_groupmanager
- test_permissions.PermissionsViewTests.test_coach_groups_create - test_permissions.PermissionsViewTests.test_coach_groups_create
- Pro and Plan users can have one group and not more - (REMOVE) Pro and Plan users can have one group and not more
- test_permissions.PermissionsFreeCoach.test_pro_groupmanager - test_permissions.PermissionsFreeCoach.test_pro_groupmanager
- test_permissions.PermissionsViewTests.test_pro_groups_create - test_permissions.PermissionsViewTests.test_pro_groups_create
- Free Coach user cannot have workouts - (REMOVE) Free Coach user cannot have workouts
- test_permissions.PermissionFreeCoach.test_add_workout_freecoach - test_permissions.PermissionFreeCoach.test_add_workout_freecoach
- Free coach can create more than one group - (REMOVE) Free coach can create more than one group
- test_permissions.PermissionsFreeCoach.test_plan_groupmanager - test_permissions.PermissionsFreeCoach.test_plan_groupmanager
- Free Coach & Plan (Self Coach) can create planned sessions and team planned sessions - (ADJUST) Free Coach & Plan (Self Coach) can create planned sessions and team planned sessions
- test_permissions.PermissionsFreeCoach.test_plan_create_session - test_permissions.PermissionsFreeCoach.test_plan_create_session
- test_permissions.PermissionsFreeCoach.test_coach_create_session - test_permissions.PermissionsFreeCoach.test_coach_create_session
- Pro cannot create planned sessions or team planned sessions - (REMOVE) Pro cannot create planned sessions or team planned sessions
- test_permissions.PermissionsViewTests.test_pro_create_session - test_permissions.PermissionsViewTests.test_pro_create_session
- Basic cannot join groups led by Free Coach - (REMOVE) Basic cannot join groups led by Free Coach
- test_permissions.PermissionFreeCoach.test_add_basic_pro_or_plan - test_permissions.PermissionFreeCoach.test_add_basic_pro_or_plan
- Coach can edit athlete settings (if in coachinggroup) - (ADJUST) Coach can edit athlete settings (if in coachinggroup)
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_prefs - test_permissions.PermissionsViewTests.test_coach_edit_athlete_prefs
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_prefs_not - test_permissions.PermissionsViewTests.test_coach_edit_athlete_prefs_not
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_settings - test_permissions.PermissionsViewTests.test_coach_edit_athlete_settings
@@ -50,25 +50,25 @@ USER permissions
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_account_not - test_permissions.PermissionsViewTests.test_coach_edit_athlete_account_not
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_exportsettings - test_permissions.PermissionsViewTests.test_coach_edit_athlete_exportsettings
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_exportsettings_not - test_permissions.PermissionsViewTests.test_coach_edit_athlete_exportsettings_not
- Coach can upload a workout on behalf of athlete - (ADJUST) Coach can upload a workout on behalf of athlete
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload - test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload_not - test_permissions.PermissionsViewTests.test_coach_edit_athlete_upload_not
- Pro and Plan cannot upload a workout on behalf of athlete - (REMOVE) Pro and Plan cannot upload a workout on behalf of athlete
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_upload - test_permissions.PermissionsViewTests.test_plan_edit_athlete_upload
- Coach can run analytics for athlete - (ADJUST) Coach can run analytics for athlete
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_analysis - test_permissions.PermissionsViewTests.test_coach_edit_athlete_analysis
- test_permissions.PermissionsViewTests.test_coach_edit_athlete_analysis_not - test_permissions.PermissionsViewTests.test_coach_edit_athlete_analysis_not
- test_permissions.PermissionsViewTests.test_pro_edit_athlete_analysis - test_permissions.PermissionsViewTests.test_pro_edit_athlete_analysis
- Pro and Plan user cannot run analysis for members of their groups - (ADJUST) Pro and Plan user cannot run analysis for members of their groups
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_analysis - test_permissions.PermissionsViewTests.test_plan_edit_athlete_analysis
- Pro and Plan user cannot edit athlete sessings - (ADJUST) Pro and Plan user cannot edit athlete sessings
- test_permissions.PermissionsViewTests.test_plan_edit_athlete_settings - test_permissions.PermissionsViewTests.test_plan_edit_athlete_settings
- test_permissions.PermissionsViewTests.test_pro_edit_athlete_settings - test_permissions.PermissionsViewTests.test_pro_edit_athlete_settings
- Self-Coach and Pro cannot create more than one group - (REMOVE) Self-Coach and Pro cannot create more than one group
- test_permissions.PermissionsFreeCoach.test_plan_groupmanager - test_permissions.PermissionsFreeCoach.test_plan_groupmanager
- Pro users and higher can join group led by other Pro or higher user - Pro users and higher can join group led by other Pro or higher user
- test_permissions.PermissionsFreeCoach.test_add_proplan_pro_or_plan - test_permissions.PermissionsFreeCoach.test_add_proplan_pro_or_plan
- Pro or basic cannot create planned sessions or team planned sessions - (ADJSUT) Pro or basic cannot create planned sessions or team planned sessions
- test_permissions.PermissionsFreeCoach.test_pro_create_plannedsession - test_permissions.PermissionsFreeCoach.test_pro_create_plannedsession
""" """
@@ -84,7 +84,7 @@ def user_is_not_basic(user):
if user.rower.protrialexpires >= timezone.now().date(): if user.rower.protrialexpires >= timezone.now().date():
return True # pragma: no cover return True # pragma: no cover
if user.rower.plantrialexpires >= timezone.now().date(): if user.rower.protrialexpires >= timezone.now().date():
return True # pragma: no cover return True # pragma: no cover
if user.rower.coachtrialexpires >= timezone.now().date(): if user.rower.coachtrialexpires >= timezone.now().date():
@@ -97,9 +97,9 @@ def user_is_not_basic(user):
def user_is_coachee(user): def user_is_coachee(user):
coaches = user.rower.get_coaches() coaches = user.rower.get_coaches()
for coach in coaches: for coach in coaches:
if coach.rowerplan == 'coach': if coach.rowerplan == 'pro':
return True return True
if coach.coachtrialexpires >= timezone.now().date(): if coach.protrialexpires >= timezone.now().date():
return True return True
return False return False
@@ -123,14 +123,14 @@ def can_start_plantrial(user):
if user.is_anonymous: # pragma: no cover if user.is_anonymous: # pragma: no cover
return False return False
return user.rower.plantrialexpires == datetime.date(1970, 1, 1) return user.rower.protrialexpires == datetime.date(1970, 1, 1)
@rules.predicate @rules.predicate
def can_start_coachtrial(user): def can_start_coachtrial(user):
if user.is_anonymous: # pragma: no cover if user.is_anonymous: # pragma: no cover
return False return False
return user.rower.coachtrialexpires == datetime.date(1970, 1, 1) return user.rower.protrialexpires == datetime.date(1970, 1, 1)
@rules.predicate @rules.predicate
@@ -144,20 +144,16 @@ def is_coach(user):
return False return False
if user.is_anonymous: if user.is_anonymous:
return False return False
if user.rower.coachtrialexpires >= timezone.now().date(): if user.rower.protrialexpires >= timezone.now().date():
return True return True
return user.rower.rowerplan in ['coach', 'freecoach'] return user.rower.rowerplan == 'pro'
@rules.predicate
def is_not_freecoach(user):
return user.rower.rowerplan != 'freecoach'
def is_paid_coach(user): def is_paid_coach(user):
if user.rower.coachtrialexpires >= timezone.now().date(): if user.rower.protrialexpires >= timezone.now().date():
return True return True
return user.rower.rowerplan == 'coach' return user.rower.rowerplan == 'pro'
@rules.predicate @rules.predicate
@@ -167,10 +163,10 @@ def is_planmember(user):
except AttributeError: # pragma: no cover except AttributeError: # pragma: no cover
return False return False
if user.rower.coachtrialexpires >= timezone.now().date(): if user.rower.protrialexpires >= timezone.now().date():
return True return True
return r.rowerplan in ['coach', 'plan'] # freecoach? return r.rowerplan == 'pro'
@rules.predicate @rules.predicate
@@ -180,7 +176,7 @@ def is_promember(user):
except AttributeError: except AttributeError:
return False return False
return r.rowerplan in ['pro', 'coach', 'plan'] # freecoach? return r.rowerplan == 'pro'
@rules.predicate @rules.predicate
@@ -192,9 +188,6 @@ def is_protrial(user):
if r.rowerplan == 'basic': if r.rowerplan == 'basic':
return r.protrialexpires >= timezone.now().date() return r.protrialexpires >= timezone.now().date()
if r.rowerplan == 'freecoach':
if r.mycoachgroup is not None:
return len(r.mycoachgroup) >= 4
return False # pragma: no cover return False # pragma: no cover
@@ -206,7 +199,7 @@ def is_coachtrial(user):
return False return False
if r.rowerplan == 'basic': if r.rowerplan == 'basic':
return r.coachtrialexpires >= timezone.now().date() return r.protrialexpires >= timezone.now().date()
return False # pragma: no cover return False # pragma: no cover
@@ -235,7 +228,7 @@ def can_add_team(user):
@rules.predicate @rules.predicate
def can_add_plan(user): def can_add_plan(user):
return isplanmember(user) or is_coach(user) return ispromember(user)
@rules.predicate @rules.predicate
@@ -243,7 +236,7 @@ def can_add_workout(user):
if user.is_anonymous: # pragma: no cover if user.is_anonymous: # pragma: no cover
return False return False
return user.rower.rowerplan != 'freecoach' return True
@rules.predicate @rules.predicate
@@ -253,11 +246,8 @@ def is_plantrial(user):
except AttributeError: # pragma: no cover except AttributeError: # pragma: no cover
return False return False
if r.rowerplan in ['basic', 'pro']: if r.rowerplan == 'basic':
return r.plantrialexpires >= timezone.now().date() return r.protrialexpires >= timezone.now().date()
if r.rowerplan == 'freecoach':
if r.mycoachgroup is not None:
return len(r.mycoachgroup) >= 4
return False # pragma: no cover return False # pragma: no cover
@@ -278,13 +268,10 @@ def can_add_session(user):
def can_plan(user): def can_plan(user):
if user.is_anonymous: # pragma: no cover if user.is_anonymous: # pragma: no cover
return False return False
if user.rower.rowerplan in ['plan', 'coach']: if user.rower.rowerplan == 'pro':
return True return True
if user.rower.rowerplan in ['basic', 'pro']: if user.rower.rowerplan == 'basic':
return user.rower.plantrialexpires >= timezone.now().date() or user.rower.coachtrialexpires >= timezone.now().date() return user.rower.protrialexpires >= timezone.now().date() or user.rower.protrialexpires >= timezone.now().date()
if user.rower.rowerplan == 'freecoach': # pragma: no cover
if user.rower.mycoachgroup is not None:
return len(user.rower.mycoachgroup) >= 4
# checks if rower is coach of user (or is user himself) # checks if rower is coach of user (or is user himself)
@@ -408,7 +395,7 @@ rules.add_perm('rower.add_plan', can_plan_user) # replaces checkaccessplanuser
rules.add_perm('rower.is_coach', is_coach_user) # replaces checkaccessuser rules.add_perm('rower.is_coach', is_coach_user) # replaces checkaccessuser
rules.add_perm('rower.is_pro', ispromember) rules.add_perm('rower.is_pro', ispromember)
rules.add_perm('rower.is_staff', is_staff) rules.add_perm('rower.is_staff', is_staff)
rules.add_perm('rower.is_not_freecoach', is_not_freecoach)
# WORKOUT permissions # WORKOUT permissions
@@ -781,9 +768,9 @@ def is_team_member(user, team): # pragma: no cover
@rules.predicate @rules.predicate
def can_view_team(user, team): def can_view_team(user, team):
# user based - below untested # user based - below untested
if team.manager.rower.coachtrialexpires >= timezone.now().date(): if team.manager.rower.protrialexpires >= timezone.now().date():
return True return True
if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'coach': # pragma: no cover if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'pro': # pragma: no cover
return is_plantrial(user) or is_protrial(user) or is_coachtrial(user) return is_plantrial(user) or is_protrial(user) or is_coachtrial(user)
# team is public # team is public
if team.private == 'open': if team.private == 'open':
+2 -2
View File
@@ -418,10 +418,10 @@ def create_sessions_from_json_async(plansteps, rower, startdate, manager, planby
teams = Team.objects.filter(manager=ps.manager) teams = Team.objects.filter(manager=ps.manager)
members = Rower.objects.filter(team__in=teams).distinct() members = Rower.objects.filter(team__in=teams).distinct()
if rower in members and rower.rowerplan != 'freecoach': if rower in members:
ps.rower.add(rower) ps.rower.add(rower)
ps.save() ps.save()
elif ps.manager.rower == rower and rower.rowerplan != 'freecoach': elif ps.manager.rower == rower:
ps.rower.add(rower) ps.rower.add(rower)
ps.save() ps.save()
+1 -1
View File
@@ -245,7 +245,7 @@ def create_coaching_request(coach, user): # pragma: no cover
while code in codes: # pragma: no cover while code in codes: # pragma: no cover
code = uuid.uuid4().hex[:10].upper() code = uuid.uuid4().hex[:10].upper()
if 'coach' in coach.rowerplan: if coach.rowerplan == 'pro':
rekwest = CoachRequest(coach=coach, user=user, code=code) rekwest = CoachRequest(coach=coach, user=user, code=code)
rekwest.save() rekwest.save()
+11 -177
View File
@@ -9,7 +9,7 @@
<li class="grid_4"> <li class="grid_4">
<p>Rowsandall.com offers free data and analysis for rowers, by rowers. <p>Rowsandall.com offers free data and analysis for rowers, by rowers.
Of course, offering this service is not free. To help cover the Of course, offering this service is not free. To help cover the
hosting costs, we have created paid plans offering extended hosting costs, we have created a paid plan offering extended
functionality. functionality.
</p> </p>
<p> <p>
@@ -25,9 +25,6 @@
<th>&nbsp;</th> <th>&nbsp;</th>
<th>BASIC</th> <th>BASIC</th>
<th>PRO</th> <th>PRO</th>
<th>SELF-COACH</th>
<th>COACH</th>
<th>Free COACH</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -35,146 +32,92 @@
<td>Basic rowing metrics (spm, time, distance, heart rate, power)</td> <td>Basic rowing metrics (spm, time, distance, heart rate, power)</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Manual Import, Export, Synchronization and download of all your data</td> <td>Manual Import, Export, Synchronization and download of all your data</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Heart rate and power zones</td> <td>Heart rate and power zones</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Ranking Pieces, Stroke Analysis</td> <td>Ranking Pieces, Stroke Analysis</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>All other rowing metrics (Work per Stroke, Average and Peak Force, Drive Length, Catch and Finish Angle, Slip and Wash, Peak Force Angle, and more)</td> <td>Compare Workouts</td>
<td>&nbsp;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Automatic Synchronization with other fitness sites</td> <td>Automatic Synchronization with other fitness sites</td>
<td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&nbsp;</td>
</tr> </tr>
<tr> <tr>
<td>Advanced Analysis (Critical Power, Stats, Box Chart, Trend Flex)</td> <td>Advanced Analysis (Critical Power, Stats, Box Chart, Trend Flex)</td>
<td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Compare Workouts</td> <td>All other rowing metrics (Work per Stroke, Average and Peak Force, Drive Length, Catch and Finish Angle, Slip and Wash, Peak Force Angle, and more)</td>
<td>&nbsp;</td> <td>partly</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Empower Stroke Profile</td> <td>Empower Stroke Profile</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Sensor Fusion, Split Workout, In-stroke metrics</td> <td>Sensor Fusion, Split Workout, In-stroke metrics</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Create and manage groups.</td> <td>Create and manage groups.</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004; (max 1)</td>
<td>&#10004; (max 1)</td>
<td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Create Training plans, tests and challenges for yourself and your training group. Track your performance <td>Create Training plans, tests and challenges for yourself and your training group. Track your performance
against plan.</td> against plan.</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
<td>&nbsp;</td>
</tr> </tr>
<tr> <tr>
<td>Create Training plans, tests and challenges for your athletes. Track their performance <td>Create Training plans, tests and challenges for your athletes. Track their performance
against plan. </td> against plan. </td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Manage your athlete's workouts</td> <td>Manage your athlete's workouts</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Run analytics for your athletes</td> <td>Run analytics for your athletes</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Change zone intensities and other workout related settings for your athletes</td> <td>Change zone intensities and other workout related settings for your athletes</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Pricing</td> <td>Pricing</td>
<td>FREE</td> <td>FREE</td>
<td nowrap="nowrap">From 25&euro;/year</td> <td nowrap="nowrap">From 25&euro;/year</td>
<td nowrap="nowrap">From 75&euro;/year</td>
<td nowrap="nowrap">From 90&euro;/year</td>
<td nowrap="nowrap">Free</td>
</tr> </tr>
<tr> <tr>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr> </tr>
{% if rower %} {% if rower %}
<tr> <tr>
@@ -193,27 +136,12 @@
&nbsp; &nbsp;
{% endif %} {% endif %}
</td> </td>
<td>
{% if rower.rowerplan == 'plan' %}
<h3>SELF-COACH ({{ rower.paymenttype }})</h3>
{% else %}
&nbsp;
{% endif %}
</td>
<td>
{% if rower.rowerplan == 'coach' %}
<h3>COACH ({{ rower.paymenttype }})</h3>
{% elif rower.rowerplan == 'freecoach' %}
<h3>Free COACH</h3>
{% else %}
&nbsp;
{% endif %}
</td>
</tr> </tr>
{% endif %} {% endif %}
{% if rower and rower.rowerplan == 'basic' %}
<tr> <tr>
<td> <td>
Available trials (no strings attached) Available trial (no strings attached)
</td> </td>
<td> <td>
&nbsp; &nbsp;
@@ -231,45 +159,14 @@
&nbsp; &nbsp;
{% endif %} {% endif %}
</td> </td>
<td>
{% if user.is_anonymous %}
<button style="width:100%">
<a href="/rowers/startplantrial/">Free SELF-COACH trial</a>
</button>
{% elif rower and rower.rowerplan == 'basic' and rower.plantrialexpires|date_dif == 1 %}
<button style="width:100%">
<a href="/rowers/startplantrial/">Free SELF-COACH trial</a>
</button>
{% elif rower and rower.rowerplan == 'pro' and rower.plantrialexpires|date_dif == 1 %}
<button style="width:100%">
<a href="/rowers/startplantrial/">Free SELF-COACH trial</a>
</button>
{% else %}
&nbsp;
{% endif %}
</td>
<td>
{% if user.is_anonymous %}
<button style="width:100%">
<a href="/rowers/startcoachtrial/">Free COACH trial</a>
</button>
{% elif rower and rower.rowerplan == 'basic' and rower.coachtrialexpires|date_dif == 1 %}
<button style="width:100%">
<a href="/rowers/startcoachtrial/">Free COACH trial</a>
</button>
{% elif rower and rower.rowerplan == 'pro' and rower.coachtrialexpires|date_dif == 1 %}
<button style="width:100%">
<a href="/rowers/startcoachtrial/">Free COACH trial</a>
</button>
{% else %}
&nbsp;
{% endif %}
</td>
</tr> </tr>
{% endif %}
<tr> <tr>
{% if rower and rower.rowerplan == 'basic' %}
<td> <td>
Available <a href="/rowers/upgrade/">upgrades</a> Available <a href="/rowers/upgrade/">upgrades</a>
</td> </td>
{% endif %}
<td> <td>
&nbsp; &nbsp;
</td> </td>
@@ -289,79 +186,16 @@
{% endif %} {% endif %}
</button> </button>
</td> </td>
{% elif rower and rower.rowerplan == 'freecoach' %}
<td colspan="3">
<button style="width:100%">
{% if user|existing_customer %}
<a href="/rowers/upgrade/">UPGRADE NOW</a>
{% else %}
<a href="/rowers/billing/">BUY NOW</a>
{% endif %}
</button>
</td>
{% elif rower and rower.rowerplan == 'pro' %}
<td>&nbsp;</td>
<td colspan="2">
<button style="width:100%">
{% if user|existing_customer %}
<a href="/rowers/upgrade/">UPGRADE NOW</a>
{% else %}
<a href="/rowers/billing/">BUY NOW</a>
{% endif %}
</button>
</td>
{% elif rower and rower.rowerplan == 'plan' %}
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>
<button style="width:100%">
{% if user|existing_customer %}
<a href="/rowers/upgrade/">UPGRADE NOW</a>
{% else %}
<a href="/rowers/billing/">BUY NOW</a>
{% endif %}
</button>
</td>
<td colspan=3>
&nbsp;
</td>
{% endif %} {% endif %}
</tr> </tr>
</tbody> </tbody>
</table> </table>
</p> </p>
<h2>Coach and Self-Coach Membership</h2> <p>
<strong>Payment methods</strong>: We accept credit card payments and PayPal through Braintree.
<p>Rowsandall.com's Training Planning functionality
is part of the paid "Self-Coach" and "Coach" plans.</p>
<p>On the "Self-Coach" plan, you can plan your own sessions.</p>
<p>On the "Coach" plan, you can establish teams, see workouts done by
athletes on your team, and plan individual and group sessions for your
athletes.
</p> </p>
<p>The Coach plan functionality listed is available to the coach only.
Individual athletes
can purchase upgrades to "Pro" and "Self-Coach" plans.
</p>
<p id="freecoach">
The Coach plans come in two versions: free and paid. On the free coach plan,
you can only have athletes who are on the PRO paid plans or higher, and you
cannot upload any workouts to your own account. Some of the advanced Analysis functionality
becomes available when the athlete group is larger than 4.
On the paid
plans, your athletes can be on the free plan, and you have full access to the
site functionality for your own workouts and those of your athletes.
</p>
<p>If you would like to find a coach who helps you plan your training
through rowsandall.com, contact me throught the contact form.</p>
<h2>Terms and Conditions, Contact Information</h2> <h2>Terms and Conditions, Contact Information</h2>
<p> <p>
+1 -1
View File
@@ -62,7 +62,7 @@
{% endif %} {% endif %}
</table> </table>
{% csrf_token %} {% csrf_token %}
{% if rower.rowerplan != 'coach' and rower.user == user %} {% if rower.rowerplan != 'pro' and rower.user == user %}
<p> <p>
<a href="/rowers/paidplans/">Upgrade</a> <a href="/rowers/paidplans/">Upgrade</a>
</p> </p>
+1 -1
View File
@@ -22,7 +22,7 @@ class VirtualEventViewTest(MyTestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True, surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
+12 -12
View File
@@ -21,7 +21,7 @@ class ListWorkoutTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -80,7 +80,7 @@ class PlannedSessionTests(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -135,7 +135,7 @@ class ForcecurveTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -275,7 +275,7 @@ class WorkoutCompareTestNew(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -377,7 +377,7 @@ class WorkoutBoxPlotTestNew(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -478,7 +478,7 @@ class WorkoutHistoTestNew(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -579,7 +579,7 @@ class History(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(20, user=self.r) self.user_workouts = WorkoutFactory.create_batch(20, user=self.r)
@@ -670,7 +670,7 @@ class GoldMedalScores(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(20, user=self.r) self.user_workouts = WorkoutFactory.create_batch(20, user=self.r)
@@ -774,7 +774,7 @@ class WorkoutFlexallTestNew(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -875,7 +875,7 @@ class WorkoutStatsTestNew(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -1188,7 +1188,7 @@ class MarkerPerformanceTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -1366,7 +1366,7 @@ class AlertTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
+2 -2
View File
@@ -56,7 +56,7 @@ class StravaPrivacy(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach',subscription_id=1) rowerplan='pro',subscription_id=1)
self.r.stravatoken = '12' self.r.stravatoken = '12'
self.r.stravarefreshtoken = '123' self.r.stravarefreshtoken = '123'
@@ -77,7 +77,7 @@ class StravaPrivacy(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach',clubsize=3) rowerplan='pro',clubsize=3)
self.r3 = Rower.objects.create(user=self.u3, self.r3 = Rower.objects.create(user=self.u3,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
+1 -1
View File
@@ -32,7 +32,7 @@ class AsyncTaskTests(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
+2 -2
View File
@@ -39,7 +39,7 @@ class ListWorkoutTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -144,7 +144,7 @@ class WorkoutViewTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.c2 = Client() # for anonymous self.c2 = Client() # for anonymous
+1 -1
View File
@@ -67,7 +67,7 @@ class BraintreeUnits(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach',subscription_id=1) rowerplan='pro',subscription_id=1)
self.pp = PaidPlan.objects.create(price=0,paymentprocessor='braintree') self.pp = PaidPlan.objects.create(price=0,paymentprocessor='braintree')
+2 -2
View File
@@ -18,7 +18,7 @@ class CourseUnitTest(TestCase):
'koeinsloot') 'koeinsloot')
self.r = Rower.objects.create(user=self.u,gdproptin=True, ftpset=True,surveydone=True, self.r = Rower.objects.create(user=self.u,gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
) )
self.nu = datetime.datetime.now() self.nu = datetime.datetime.now()
@@ -130,7 +130,7 @@ class CoursesTest(TestCase):
'koeinsloot') 'koeinsloot')
self.r = Rower.objects.create(user=self.u,gdproptin=True, ftpset=True,surveydone=True, self.r = Rower.objects.create(user=self.u,gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
) )
self.nu = datetime.datetime.now() self.nu = datetime.datetime.now()
+1 -1
View File
@@ -23,7 +23,7 @@ class CPChartTest(TestCase):
gdproptin=True, ftpset=True,surveydone=True,sex='male', gdproptin=True, ftpset=True,surveydone=True,sex='male',
weightcategory='hwt', weightcategory='hwt',
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
r = self.u.rower r = self.u.rower
age = calculate_age(r.birthdate) age = calculate_age(r.birthdate)
+2 -2
View File
@@ -26,7 +26,7 @@ class EmailUpload(TestCase):
birthdate = faker.profile()['birthdate'], birthdate = faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
nu = datetime.datetime.now() nu = datetime.datetime.now()
@@ -208,7 +208,7 @@ class EmailTests(TestCase):
birthdate = faker.profile()['birthdate'], birthdate = faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
nu = datetime.datetime.now() nu = datetime.datetime.now()
a2 = 'media/mailbox_attachments/colin3.csv' a2 = 'media/mailbox_attachments/colin3.csv'
+1 -1
View File
@@ -14,7 +14,7 @@ class EmpowerTest(TestCase):
'sander@ds.ds', 'sander@ds.ds',
'koeinsloot', 'koeinsloot',
) )
r = Rower.objects.create(user=u,rowerplan='coach',gdproptin=True, ftpset=True,surveydone=True, r = Rower.objects.create(user=u,rowerplan='pro',gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now()) gdproptindate=timezone.now())
self.c = Client() self.c = Client()
+1 -1
View File
@@ -14,7 +14,7 @@ class WorkoutViewTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
showfavoritechartnotes=True) showfavoritechartnotes=True)
self.c = Client() self.c = Client()
+3 -3
View File
@@ -47,7 +47,7 @@ class RojaboObjects(DjangoTestCase):
self.r.rojabo_refreshtoken = 'ab' self.r.rojabo_refreshtoken = 'ab'
self.r.rojabo_tokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime self.r.rojabo_tokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime
self.r.defaulttimezone = 'Europe/Prague' self.r.defaulttimezone = 'Europe/Prague'
self.r.rowerplan = 'plan' self.r.rowerplan = 'pro'
self.r.save() self.r.save()
self.u2 = User.objects.create_user('john2', self.u2 = User.objects.create_user('john2',
@@ -65,7 +65,7 @@ class RojaboObjects(DjangoTestCase):
self.r2.rojabo_refreshtoken = 'ab' self.r2.rojabo_refreshtoken = 'ab'
self.r2.rojabo_tokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime self.r2.rojabo_tokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime
self.r2.defaulttimezone = 'Europe/Prague' self.r2.defaulttimezone = 'Europe/Prague'
self.r2.rowerplan = 'pro' self.r2.rowerplan = 'basic'
self.r2.save() self.r2.save()
self.nu = datetime.datetime.now() self.nu = datetime.datetime.now()
@@ -134,7 +134,7 @@ class GarminObjects(DjangoTestCase):
) )
self.r.garmintoken = 'dfdzf' self.r.garmintoken = 'dfdzf'
self.r.garminrefreshtoken = 'fsls' self.r.garminrefreshtoken = 'fsls'
self.r.rowerplan = 'plan' self.r.rowerplan = 'pro'
self.r.save() self.r.save()
self.c.login(username='john',password='koeinsloot') self.c.login(username='john',password='koeinsloot')
+1 -1
View File
@@ -18,7 +18,7 @@ class MiscTests(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach',subscription_id=1) rowerplan='pro',subscription_id=1)
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
+13 -13
View File
@@ -183,7 +183,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -242,7 +242,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -306,7 +306,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -373,7 +373,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -413,7 +413,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='plan', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -465,7 +465,7 @@ description: ""
url = expected_url url = expected_url
response = self.c.get(url) response = self.c.get(url, follow=True)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
url = reverse('purchase_checkouts_view') url = reverse('purchase_checkouts_view')
@@ -507,7 +507,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -548,7 +548,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -570,7 +570,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -617,7 +617,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -663,7 +663,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -708,7 +708,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
@@ -759,7 +759,7 @@ description: ""
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
paymentprocessor='braintree', paymentprocessor='braintree',
street_address=faker.street_address(), street_address=faker.street_address(),
city=faker.city(), city=faker.city(),
+104 -400
View File
@@ -26,7 +26,7 @@ class PlanningPermissionsCoach(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
clubsize=10, clubsize=10,
) )
self.ucoachpassword = faker.word() self.ucoachpassword = faker.word()
@@ -97,184 +97,8 @@ class PlanningPermissionsCoach(TestCase):
def test_coachee_can_sync(self): def test_coachee_can_sync(self):
self.assertTrue(user_is_coachee(self.ucoachee)) self.assertTrue(user_is_coachee(self.ucoachee))
@override_settings(TESTING=True)
class PermissionsFreeCoach(TestCase):
def setUp(self):
self.c = Client()
## Users - Pro, Basic, Free Coach & Self Coach
self.ufreecoach = UserFactory(username='coachuser')
self.rfreecoach = Rower.objects.create(user=self.ufreecoach,
birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='freecoach',clubsize=100)
self.coachinggroup = CoachingGroup.objects.create()
self.rfreecoach.mycoachgroup = self.coachinggroup
self.rfreecoach.save()
self.factory = RequestFactory()
self.password = faker.word()
self.ufreecoach.set_password(self.password)
self.ufreecoach.save()
self.uplan = UserFactory(username='planuser')
self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
self.factory = RequestFactory()
self.password = faker.word()
self.uplan.set_password(self.password)
self.uplan.save()
self.upro = UserFactory(username='prouser')
self.rpro = Rower.objects.create(user=self.upro,
birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro_workouts = WorkoutFactory.create_batch(5, user=self.rpro)
self.factory = RequestFactory()
self.password = faker.word()
self.upro.set_password(self.password)
self.upro.save()
self.uplan2 = UserFactory(username='planuser2')
self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
self.factory = RequestFactory()
self.password = faker.word()
self.uplan2.set_password(self.password)
self.uplan2.save()
self.upro2 = UserFactory(username='prouser2')
self.rpro2 = Rower.objects.create(user=self.upro2,
birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2)
self.factory = RequestFactory()
self.password = faker.word()
self.upro2.set_password(self.password)
self.upro2.save()
self.ubasic = UserFactory(username='basicuser')
self.rbasic = Rower.objects.create(user=self.ubasic,
birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.ubasic_workouts = WorkoutFactory.create_batch(5, user=self.rbasic)
self.factory = RequestFactory()
self.ubasicpassword = faker.word()
self.ubasic.set_password(self.ubasicpassword)
self.ubasic.save()
## TeamFreeCoach
self.teamfreecoach = Team.objects.create(
name=faker.word()+'3',
notes=faker.text(),
manager=self.ufreecoach)
## Coach can have any number of groups
def test_coach_groupmanager(self):
team1 = Team.objects.create(
name = 'FirstTeam',
notes = faker.text(),
manager = self.ufreecoach,
)
self.assertEqual(team1.manager,self.ufreecoach)
team2 = Team.objects.create(
name = 'SecondTeam',
notes = faker.text(),
manager = self.ufreecoach,
)
self.assertEqual(team2.manager,self.ufreecoach)
team3 = Team.objects.create(
name = 'ThirdTeam',
notes = faker.text(),
manager = self.ufreecoach,
)
self.assertEqual(team3.manager,self.ufreecoach)
## Free coach can create more than one group
def test_plan_groupmanager(self):
team1 = Team.objects.create(
name = 'FirstTeam',
notes = faker.text(),
manager = self.ufreecoach,
)
self.assertEqual(team1.manager,self.ufreecoach)
team2 = Team.objects.create(
name = 'SecondTeam',
notes = faker.text(),
manager = self.ufreecoach,
)
self.assertEqual(team2.manager,self.ufreecoach)
## Free Coach can create planned sessions and team planned sessions
## Self Coach and higher can create planned sessions and team planned sessions
def test_plan_create_session(self):
ps = PlannedSession.objects.create(
manager=self.ufreecoach,
name=faker.word(),
comment=faker.text()
)
self.assertEqual(ps.manager,self.ufreecoach)
def test_coach_create_session(self):
ps = PlannedSession.objects.create(
manager=self.ufreecoach,
name=faker.word(),
comment=faker.text()
)
self.assertEqual(ps.manager,self.ufreecoach)
## Basic cannot join groups led by Free Coach
def test_add_basic_pro_or_plan(self):
with transaction.atomic():
with self.assertRaises(ValidationError):
self.rbasic.team.add(self.teamfreecoach)
## Free Coach user cannot have workouts
def test_add_workout_freecoach(self):
result = get_random_file(filename='rowers/tests/testdata/erg1.csv')
with transaction.atomic():
with self.assertRaises(ValidationError):
self.werg1 = WorkoutFactory(user=self.rfreecoach,
csvfilename=result['filename'],
starttime=result['starttime'],
startdatetime=result['startdatetime'],
duration=result['duration'],
distance=result['totaldist'],
workouttype = 'rower',
)
@override_settings(TESTING=True) @override_settings(TESTING=True)
class PermissionsBasicsTests(TestCase): class PermissionsBasicsTests(TestCase):
@@ -286,7 +110,7 @@ class PermissionsBasicsTests(TestCase):
self.rcoach = Rower.objects.create(user=self.ucoach, self.rcoach = Rower.objects.create(user=self.ucoach,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10) rowerplan='pro',clubsize=10)
self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach) self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach)
self.coachinggroup = CoachingGroup.objects.create() self.coachinggroup = CoachingGroup.objects.create()
@@ -301,7 +125,7 @@ class PermissionsBasicsTests(TestCase):
self.rplan = Rower.objects.create(user=self.uplan, self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan') rowerplan='pro')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan) self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
self.factory = RequestFactory() self.factory = RequestFactory()
@@ -325,7 +149,7 @@ class PermissionsBasicsTests(TestCase):
self.rplan2 = Rower.objects.create(user=self.uplan2, self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan') rowerplan='pro')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2) self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
self.factory = RequestFactory() self.factory = RequestFactory()
@@ -341,7 +165,7 @@ class PermissionsBasicsTests(TestCase):
self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2) self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2)
self.factory = RequestFactory() self.factory = RequestFactory()
self.password = faker.word() self.upro2password = faker.word()
self.upro2.set_password(self.password) self.upro2.set_password(self.password)
self.upro2.save() self.upro2.save()
@@ -366,15 +190,6 @@ class PermissionsBasicsTests(TestCase):
notes=faker.text(), notes=faker.text(),
manager=self.upro2) manager=self.upro2)
self.teamplan = Team.objects.create(
name=faker.word()+'2',
notes=faker.text(),
manager=self.uplan2)
self.teamcoach = Team.objects.create(
name=faker.word()+'3',
notes=faker.text(),
manager=self.ucoach)
# Requirements # Requirements
@@ -411,12 +226,11 @@ class PermissionsBasicsTests(TestCase):
## Basic athletes can be member of Coach led group ## Basic athletes can be member of Coach led group
def test_add_coach(self): def test_add_coach(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.assertIn(self.teamcoach,self.rbasic.team.all()) self.assertIn(self.teampro,self.rbasic.team.all())
## Self coach can create one group ## Pro member can create more than one group
## Self coach cannot create more than one group
def test_plan_groupmanager(self): def test_plan_groupmanager(self):
team1 = Team.objects.create( team1 = Team.objects.create(
name = 'FirstTeam', name = 'FirstTeam',
@@ -426,32 +240,24 @@ class PermissionsBasicsTests(TestCase):
self.assertEqual(team1.manager,self.uplan) self.assertEqual(team1.manager,self.uplan)
with self.assertRaises(ValidationError): team2 = Team.objects.create(
team2 = Team.objects.create( name = 'SecondTeam',
name = 'SecondTeam', notes = faker.text(),
notes = faker.text(), manager = self.uplan,
manager = self.uplan, )
)
self.assertEqual(team2.manager,self.uplan)
## Pro users (and higher) can join group led by other Pro (or higher) user ## Pro users (and higher) can join group led by other Pro (or higher) user
def test_add_proplan_pro_or_plan(self): def test_add_proplan_pro_or_plan(self):
self.rpro.team.add(self.teamplan)
self.assertIn(self.teamplan,self.rpro.team.all())
self.rpro.team.add(self.teampro) self.rpro.team.add(self.teampro)
self.assertIn(self.teampro,self.rpro.team.all()) self.assertIn(self.teampro,self.rpro.team.all())
self.rplan.team.add(self.teamplan)
self.assertIn(self.teamplan,self.rplan.team.all())
self.rplan.team.add(self.teampro) self.rplan.team.add(self.teampro)
self.assertIn(self.teampro,self.rplan.team.all()) self.assertIn(self.teampro,self.rplan.team.all())
self.rcoach.team.add(self.teamplan)
self.assertIn(self.teamplan,self.rcoach.team.all())
self.rcoach.team.add(self.teampro) self.rcoach.team.add(self.teampro)
self.assertIn(self.teampro,self.rcoach.team.all()) self.assertIn(self.teampro,self.rcoach.team.all())
@@ -476,8 +282,7 @@ class PermissionsBasicsTests(TestCase):
) )
self.assertEqual(ps.manager,self.ucoach) self.assertEqual(ps.manager,self.ucoach)
## Pro can have one group ## Pro can have more than one group
## Pro cannot create more than one group
def test_pro_groupmanager(self): def test_pro_groupmanager(self):
team1 = Team.objects.create( team1 = Team.objects.create(
name = 'FirstTeam', name = 'FirstTeam',
@@ -487,22 +292,23 @@ class PermissionsBasicsTests(TestCase):
self.assertEqual(team1.manager,self.upro) self.assertEqual(team1.manager,self.upro)
with self.assertRaises(ValidationError): team2 = Team.objects.create(
team2 = Team.objects.create( name = 'SecondTeam',
name = 'SecondTeam', notes = faker.text(),
notes = faker.text(), manager = self.upro,
manager = self.upro, )
)
self.assertEqual(team2.manager,self.upro)
## Pro or Basic cannot create planned sessions or team planned sessions ## Basic cannot create planned sessions or team planned sessions
def test_pro_create_plannedsession(self): def test_pro_create_plannedsession(self):
with self.assertRaises(ValidationError): ps = PlannedSession.objects.create(
ps = PlannedSession.objects.create( manager=self.upro,
manager=self.upro, name = faker.word(),
name = faker.word(), comment = faker.text()
comment = faker.text() )
)
self.assertEqual(ps.manager,self.upro)
def test_basic_create_plannedsession(self): def test_basic_create_plannedsession(self):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
@@ -512,15 +318,6 @@ class PermissionsBasicsTests(TestCase):
comment = faker.text() comment = faker.text()
) )
## Basic cannot join groups led by Pro or Self Coach
def test_add_basic_pro_or_plan(self):
with transaction.atomic():
with self.assertRaises(ValidationError):
self.rbasic.team.add(self.teamplan)
with transaction.atomic():
with self.assertRaises(ValidationError):
self.rbasic.team.add(self.teampro)
## Basic cannot manage a group ## Basic cannot manage a group
@@ -546,7 +343,7 @@ class PermissionsViewTests(TestCase):
self.rcoach = Rower.objects.create(user=self.ucoach, self.rcoach = Rower.objects.create(user=self.ucoach,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10) rowerplan='pro',clubsize=10)
self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach) self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach)
self.coachinggroup = CoachingGroup.objects.create() self.coachinggroup = CoachingGroup.objects.create()
@@ -561,7 +358,7 @@ class PermissionsViewTests(TestCase):
self.rplan = Rower.objects.create(user=self.uplan, self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan') rowerplan='pro')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan) self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
self.factory = RequestFactory() self.factory = RequestFactory()
@@ -585,7 +382,7 @@ class PermissionsViewTests(TestCase):
self.rplan2 = Rower.objects.create(user=self.uplan2, self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan') rowerplan='pro')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2) self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
self.factory = RequestFactory() self.factory = RequestFactory()
@@ -628,17 +425,12 @@ class PermissionsViewTests(TestCase):
notes=faker.text(), notes=faker.text(),
manager=self.upro2) manager=self.upro2)
self.teamplan = Team.objects.create(
name=faker.word()+'2',
notes=faker.text(),
manager=self.uplan2)
self.teamcoach = Team.objects.create( self.teamcoach = Team.objects.create(
name=faker.word()+'3', name=faker.word()+'3',
notes=faker.text(), notes=faker.text(),
manager=self.ucoach) manager=self.ucoach)
## only ubasic can view ubasic_workouts[0] which is private ## only ubasic can view ubasic_workouts[0] which is private
def test_view_workout(self): def test_view_workout(self):
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
@@ -756,7 +548,7 @@ class PermissionsViewTests(TestCase):
## Coach can edit on behalf of athlete if permitted ## Coach can edit on behalf of athlete if permitted
# 1, Preferences # 1, Preferences
def test_coach_edit_athlete_prefs(self): def test_coach_edit_athlete_prefs(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.rbasic.coachinggroups.add(self.coachinggroup) self.rbasic.coachinggroups.add(self.coachinggroup)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
@@ -768,7 +560,7 @@ class PermissionsViewTests(TestCase):
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
def test_coach_edit_athlete_prefs_not(self): def test_coach_edit_athlete_prefs_not(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -780,7 +572,7 @@ class PermissionsViewTests(TestCase):
# 2, Favorite Charts # 2, Favorite Charts
def test_coach_edit_athlete_settings(self): def test_coach_edit_athlete_settings(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.rbasic.coachinggroups.add(self.coachinggroup) self.rbasic.coachinggroups.add(self.coachinggroup)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
@@ -792,7 +584,7 @@ class PermissionsViewTests(TestCase):
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
def test_coach_edit_athlete_settings_not(self): def test_coach_edit_athlete_settings_not(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -804,7 +596,7 @@ class PermissionsViewTests(TestCase):
# 3, Export Settings # 3, Export Settings
def test_coach_edit_athlete_exportsettings(self): def test_coach_edit_athlete_exportsettings(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.rbasic.coachinggroups.add(self.coachinggroup) self.rbasic.coachinggroups.add(self.coachinggroup)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
@@ -816,7 +608,7 @@ class PermissionsViewTests(TestCase):
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
def test_coach_edit_athlete_exportsettings_not(self): def test_coach_edit_athlete_exportsettings_not(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -828,7 +620,7 @@ class PermissionsViewTests(TestCase):
# 4, Account settings # 4, Account settings
def test_coach_edit_athlete_account(self): def test_coach_edit_athlete_account(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.rbasic.coachinggroups.add(self.coachinggroup) self.rbasic.coachinggroups.add(self.coachinggroup)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
@@ -840,7 +632,7 @@ class PermissionsViewTests(TestCase):
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
def test_coach_edit_athlete_account_not(self): def test_coach_edit_athlete_account_not(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -853,7 +645,7 @@ class PermissionsViewTests(TestCase):
## Coach can run analytics for athlete ## Coach can run analytics for athlete
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats) @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats)
def test_coach_edit_athlete_analysis(self,mocked_df): def test_coach_edit_athlete_analysis(self,mocked_df):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.rbasic.coachinggroups.add(self.coachinggroup) self.rbasic.coachinggroups.add(self.coachinggroup)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
@@ -874,7 +666,7 @@ class PermissionsViewTests(TestCase):
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats) @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): def test_coach_edit_athlete_analysis_not(self,mocked_df):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -892,7 +684,7 @@ class PermissionsViewTests(TestCase):
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats) @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats)
def test_coach_edit_athlete_analysis_not2(self,mocked_df): def test_coach_edit_athlete_analysis_not2(self,mocked_df):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -961,7 +753,7 @@ class PermissionsViewTests(TestCase):
def test_coach_edit_athlete_uploadnot(self,mocked_sqlalchemy,mocked_read_data): def test_coach_edit_athlete_uploadnot(self,mocked_sqlalchemy,mocked_read_data):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teamcoach)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
url = reverse('team_workout_upload_view') url = reverse('team_workout_upload_view')
@@ -1001,9 +793,9 @@ class PermissionsViewTests(TestCase):
## Coach can edit athlete's workout ## Coach can edit athlete's workout
def test_coach_edit_athlete_workout(self): def test_coach_edit_athlete_workout(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
url = reverse('workout_edit_view', url = reverse('workout_edit_view',
@@ -1015,9 +807,11 @@ class PermissionsViewTests(TestCase):
## Coach can see list of workouts of athlete ## Coach can see list of workouts of athlete
def test_coach_athlete_workout_list(self): def test_coach_athlete_workout_list(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
# check if rbasic is in teampro
self.assertIn(self.teampro,self.rbasic.team.all())
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
url = reverse('workouts_view', url = reverse('workouts_view',
@@ -1072,7 +866,7 @@ class PermissionsViewTests(TestCase):
status_code=302,target_status_code=200) status_code=302,target_status_code=200)
# Create 2nd new team - should redirect to paid plans # Create 2nd new team - should not redirect to paid plans
form_data = { form_data = {
'name': faker.word(), 'name': faker.word(),
'notes': faker.text(), 'notes': faker.text(),
@@ -1089,12 +883,12 @@ class PermissionsViewTests(TestCase):
expected_url = reverse('paidplans_view') expected_url = reverse('paidplans_view')
response = self.c.post(url,form_data,follow=True) response = self.c.post(url,form_data,follow=True)
self.assertRedirects(response,
expected_url=expected_url, # check that it does not redirect and status code is 200
status_code=302,target_status_code=200) self.assertEqual(response.status_code,200)
## Self Coach can create planned sessions and team planned sessions ## Pro can create planned sessions and team planned sessions
def test_plan_create_session(self): def test_plan_create_session(self):
login = self.c.login(username=self.uplan2.username, password=self.uplan2password) login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
self.assertTrue(login) self.assertTrue(login)
@@ -1135,11 +929,11 @@ class PermissionsViewTests(TestCase):
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
## Self Coach cannot edit on behalf of athlete ## Team Manager cannot edit on behalf of athlete
def test_plan_edit_athlete_settings(self): def test_plan_edit_athlete_settings(self):
self.rpro.team.add(self.teamplan) self.rpro.team.add(self.teampro)
login = self.c.login(username=self.uplan2.username, password=self.uplan2password) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
url = reverse('rower_prefs_view',kwargs={'userid':self.ubasic.id}) url = reverse('rower_prefs_view',kwargs={'userid':self.ubasic.id})
@@ -1147,12 +941,12 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url) response = self.c.get(url)
self.assertEqual(response.status_code,403) self.assertEqual(response.status_code,403)
## Self Coach cannot run analytics on behalf of athlete ## Team Manager cannot run analytics on behalf of athlete
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats) @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats)
def test_plan_edit_athlete_analysis(self,mocked_df): def test_plan_edit_athlete_analysis(self,mocked_df):
self.rpro.team.add(self.teamplan) self.rpro.team.add(self.teampro)
login = self.c.login(username=self.uplan2.username, password=self.uplan2password) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
@@ -1166,23 +960,45 @@ class PermissionsViewTests(TestCase):
self.assertEqual(response.status_code,403) self.assertEqual(response.status_code,403)
## Self Coach cannot upload on behalf of athlete ## Team Manager cannot upload on behalf of athlete
@patch('rowers.dataprep.create_engine') @patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data) @patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_read_data): def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_read_data):
self.rpro.team.add(self.teamplan) self.rpro.team.add(self.teampro)
login = self.c.login(username=self.uplan2.username, password=self.uplan2password) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
url = reverse('team_workout_upload_view') url = reverse('team_workout_upload_view')
# can get to the page
response = self.c.get(url) response = self.c.get(url)
self.assertEqual(response.status_code,403) self.assertEqual(response.status_code,200)
# cannot post the form
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.upro.id
}
response = self.c.post(url, form_data, follow=True)
f.close()
# check that form errors are present in response content
self.assertContains(response,'Select a valid choice. That choice is not one of the available choices.')
## Pro can have one group ## Pro can have more than one group
## Pro cannot create more than one group
def test_pro_groups_create(self): def test_pro_groups_create(self):
login = self.c.login(username=self.upro.username, password=self.upropassword) login = self.c.login(username=self.upro.username, password=self.upropassword)
self.assertTrue(login) self.assertTrue(login)
@@ -1214,7 +1030,7 @@ class PermissionsViewTests(TestCase):
status_code=302,target_status_code=200) status_code=302,target_status_code=200)
# Create 2nd new team - should redirect to paid plans # Create 2nd new team - should not redirect to paid plans
form_data = { form_data = {
'name': faker.word(), 'name': faker.word(),
'notes': faker.text(), 'notes': faker.text(),
@@ -1228,7 +1044,7 @@ class PermissionsViewTests(TestCase):
self.assertTrue(form.is_valid()) self.assertTrue(form.is_valid())
expected_url = reverse('paidplans_view') expected_url = reverse('rower_teams_view')
response = self.c.post(url,form_data,follow=True) response = self.c.post(url,form_data,follow=True)
self.assertRedirects(response, self.assertRedirects(response,
@@ -1236,7 +1052,7 @@ class PermissionsViewTests(TestCase):
status_code=302,target_status_code=200) status_code=302,target_status_code=200)
## Pro cannot create planned sessions or team planned sessions ## Pro can create planned sessions or team planned sessions
def test_pro_create_session(self): def test_pro_create_session(self):
login = self.c.login(username=self.upro2.username, password=self.upro2password) login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login) self.assertTrue(login)
@@ -1247,117 +1063,14 @@ class PermissionsViewTests(TestCase):
enddate = (nu+datetime.timedelta(days=3)).date() enddate = (nu+datetime.timedelta(days=3)).date()
preferreddate = startdate preferreddate = startdate
response = self.c.get(url,follow=True) response = self.c.get(url,follow=False)
self.assertEqual(response.status_code,200)
expected_url = reverse('paidplans_view')
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
## Pro cannot edit on behalf of athlete
def test_pro_edit_athlete_settings(self):
self.rpro.team.add(self.teampro)
login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login)
url = reverse('rower_prefs_view',kwargs={'userid':self.ubasic.id})
response = self.c.get(url)
self.assertEqual(response.status_code,403)
## Pro cannot run analytics on behalf of athlete
@patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats)
def test_pro_edit_athlete_analysis(self,mocked_df):
with transaction.atomic():
self.rpro.team.add(self.teampro)
login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login)
url = reverse('analysis_new',
kwargs={
'userid':self.ubasic.id,
}
)
response = self.c.get(url)
self.assertEqual(response.status_code,403)
## Self Coach cannot upload on behalf of athlete
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_read_data):
self.rpro.team.add(self.teamplan)
login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
self.assertTrue(login)
url = reverse('team_workout_upload_view')
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
expected_url = reverse('paidplans_view')
self.assertRedirects(response,
expected_url = expected_url,
status_code=302,target_status_code=200)
## Pro users can see team members' workout, but not edit
def test_pro_edit_athlete_workout(self):
self.rpro.team.add(self.teampro)
self.rpro2.team.add(self.teampro)
login = self.c.login(username=self.upro2.username, password=self.upro2password)
self.assertTrue(login)
url = reverse('workout_edit_view',
kwargs={'id':encoder.encode_hex(self.upro_workouts[0].id)}
)
response = self.c.get(url)
self.assertEqual(response.status_code,403)
url = reverse('workout_view',
kwargs={'id':encoder.encode_hex(self.upro_workouts[0].id)}
)
response = self.c.get(url)
self.assertEqual(response.status_code,200)
## Self Coach users can see team members' workout, but not edit
def test_plan_edit_athlete_workout(self):
self.rpro.team.add(self.teamplan)
login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
self.assertTrue(login)
url = reverse('workout_edit_view',
kwargs={'id':encoder.encode_hex(self.ubasic_workouts[0].id)}
)
response = self.c.get(url)
self.assertEqual(response.status_code,403)
url = reverse('workout_view',
kwargs={'id':encoder.encode_hex(self.ubasic_workouts[0].id)}
)
response = self.c.get(url)
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
## Basic users can see team members' workout, but not edit ## Basic users can see team members' workout, but not edit
def test_basic_edit_athlete_workout(self): def test_basic_edit_athlete_workout(self):
self.rbasic.team.add(self.teamcoach) self.rbasic.team.add(self.teampro)
self.rplan2.team.add(self.teamcoach) self.rplan2.team.add(self.teampro)
login = self.c.login(username=self.ubasic.username, password=self.ubasicpassword) login = self.c.login(username=self.ubasic.username, password=self.ubasicpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -1421,7 +1134,7 @@ class PermissionsViewTests(TestCase):
expected_url = expected_url, expected_url = expected_url,
status_code=302,target_status_code=200) status_code=302,target_status_code=200)
## Basic cannot join groups from Pro or Self Coach users (redirects to paid plans) ## Basic can join groups from Pro
def test_team_member_request_basic_pro(self): def test_team_member_request_basic_pro(self):
login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword) login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword)
self.assertTrue(login) self.assertTrue(login)
@@ -1435,12 +1148,12 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url,follow=True) response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
expected_url = reverse('paidplans_view') expected_url = reverse('team_view',kwargs={'team_id':self.teampro.id})
self.assertRedirects(response, self.assertRedirects(response,
expected_url = expected_url, expected_url = expected_url,
status_code=302,target_status_code=200) status_code=302,target_status_code=200)
@override_settings(TESTING=True) @override_settings(TESTING=True)
class PermissionsCoachingTests(TestCase): class PermissionsCoachingTests(TestCase):
def setUp(self): def setUp(self):
@@ -1451,7 +1164,7 @@ class PermissionsCoachingTests(TestCase):
self.rcoach = Rower.objects.create(user=self.ucoach, self.rcoach = Rower.objects.create(user=self.ucoach,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10) rowerplan='pro',clubsize=10)
self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach) self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach)
self.coachinggroup = CoachingGroup.objects.create() self.coachinggroup = CoachingGroup.objects.create()
@@ -1466,7 +1179,7 @@ class PermissionsCoachingTests(TestCase):
self.rplan = Rower.objects.create(user=self.uplan, self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan') rowerplan='pro')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan) self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
self.factory = RequestFactory() self.factory = RequestFactory()
@@ -1490,7 +1203,7 @@ class PermissionsCoachingTests(TestCase):
self.rplan2 = Rower.objects.create(user=self.uplan2, self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan') rowerplan='pro')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2) self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
self.factory = RequestFactory() self.factory = RequestFactory()
@@ -1524,22 +1237,13 @@ class PermissionsCoachingTests(TestCase):
## TeamPro, TeamCoach, TeamSelfCoach ## TeamPro, Teampro, TeamSelfCoach
self.teampro = Team.objects.create( self.teampro = Team.objects.create(
name=faker.word()+'1', name=faker.word()+'1',
notes=faker.text(), notes=faker.text(),
manager=self.upro2) manager=self.upro2)
self.teamplan = Team.objects.create(
name=faker.word()+'2',
notes=faker.text(),
manager=self.uplan2)
self.teamcoach = Team.objects.create(
name=faker.word()+'3',
notes=faker.text(),
manager=self.ucoach)
def test_athlete_request_athlete_revoke(self): def test_athlete_request_athlete_revoke(self):
login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword) login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword)
+4 -18
View File
@@ -49,7 +49,7 @@ for id, row in df.iterrows():
viewstotest.append(tpl) viewstotest.append(tpl)
plans = ['basic','plan','coach','pro'] plans = ['basic','pro']
@override_settings(TESTING=True) @override_settings(TESTING=True)
class PermissionsViewTests(TestCase): class PermissionsViewTests(TestCase):
@@ -61,7 +61,7 @@ class PermissionsViewTests(TestCase):
rcoach = Rower.objects.create(user=ucoach, rcoach = Rower.objects.create(user=ucoach,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10) rowerplan='pro',clubsize=10)
ucoach_workouts = WorkoutFactory.create_batch(5, user=rcoach) ucoach_workouts = WorkoutFactory.create_batch(5, user=rcoach)
coachinggroup = CoachingGroup.objects.create() coachinggroup = CoachingGroup.objects.create()
@@ -83,7 +83,7 @@ class PermissionsViewTests(TestCase):
rplan = Rower.objects.create(user=uplan, rplan = Rower.objects.create(user=uplan,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan',clubsize=10) rowerplan='pro',clubsize=10)
uplan_workouts = WorkoutFactory.create_batch(5, user=rplan) uplan_workouts = WorkoutFactory.create_batch(5, user=rplan)
rcoach.save() rcoach.save()
@@ -103,7 +103,7 @@ class PermissionsViewTests(TestCase):
rplan2 = Rower.objects.create(user=uplan2, rplan2 = Rower.objects.create(user=uplan2,
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(), gdproptin=True, ftpset=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan',clubsize=10) rowerplan='pro',clubsize=10)
uplan2_workouts = WorkoutFactory.create_batch(5, user=rplan2) uplan2_workouts = WorkoutFactory.create_batch(5, user=rplan2)
rcoach.save() rcoach.save()
@@ -287,12 +287,6 @@ class PermissionsViewTests(TestCase):
elif permissions['own'] == 'pro': elif permissions['own'] == 'pro':
thisuser = self.upro thisuser = self.upro
notuser = self.ubasic notuser = self.ubasic
elif permissions['own'] == 'plan':
thisuser = self.uplan
notuser = self.upro
elif permissions['own'] == 'coach':
thisuser = self.ucoach
notuser = self.uplan
if permissions['workoutid']: if permissions['workoutid']:
@@ -370,14 +364,6 @@ class PermissionsViewTests(TestCase):
thisuser = self.upro thisuser = self.upro
memberuser = self.uplan memberuser = self.uplan
notuser = self.ubasic notuser = self.ubasic
elif permissions['member'] == 'plan':
thisuser = self.uplan
memberuser = self.ubasic
notuser = self.upro
elif permissions['member'] == 'coach':
thisuser = self.ucoach
memberuser = self.uplan
notuser = self.uplan
if permissions['workoutid']: if permissions['workoutid']:
+7 -7
View File
@@ -33,7 +33,7 @@ class TrainingPlanTest(TestCase):
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
defaulttimezone='US/Pacific', defaulttimezone='US/Pacific',
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -200,7 +200,7 @@ class SessionTemplateTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -306,7 +306,7 @@ class SessionLinkTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -551,7 +551,7 @@ class SessionCompleteTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
@@ -808,7 +808,7 @@ class ChallengeCompleteTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
@@ -1032,7 +1032,7 @@ class MandatoryTestCompleteTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
@@ -1246,7 +1246,7 @@ class PlannedSessionsView(TestCase):
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
defaulttimezone='US/Pacific', defaulttimezone='US/Pacific',
rowerplan='coach') rowerplan='pro')
self.r.save() self.r.save()
self.c = Client() self.c = Client()
+2 -2
View File
@@ -60,7 +60,7 @@ class ChallengesTest(TestCase):
birthdate=datetime.datetime.now()-datetime.timedelta(days=25*365), birthdate=datetime.datetime.now()-datetime.timedelta(days=25*365),
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.u2 = UserFactory() self.u2 = UserFactory()
self.r2 = Rower.objects.create(user=self.u2, self.r2 = Rower.objects.create(user=self.u2,
@@ -1089,7 +1089,7 @@ class IndoorChallengesTest(TestCase):
birthdate=datetime.datetime.now()-datetime.timedelta(days=25*365), birthdate=datetime.datetime.now()-datetime.timedelta(days=25*365),
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
+1 -22
View File
@@ -41,28 +41,7 @@ class TrialsTest(TestCase):
self.r.protrialexpires = (nu+datetime.timedelta(days=10)).date() self.r.protrialexpires = (nu+datetime.timedelta(days=10)).date()
self.r.save() self.r.save()
self.assertEqual(isplanmember(self.u),False)
self.assertEqual(iscoachmember(self.u),False)
self.assertEqual(ispromember(self.u),True)
self.r.plantrialexpires = (nu+datetime.timedelta(days=10)).date()
self.r.save()
self.assertEqual(isplanmember(self.u),True) self.assertEqual(isplanmember(self.u),True)
self.assertEqual(iscoachmember(self.u),False) self.assertEqual(iscoachmember(self.u),True)
self.assertEqual(ispromember(self.u),True) self.assertEqual(ispromember(self.u),True)
def test_protrial(self):
self.r.rowerplan = 'pro'
self.r.save()
self.assertEqual(isplanmember(self.u),False)
self.assertEqual(iscoachmember(self.u),False)
self.assertEqual(ispromember(self.u),True)
self.r.plantrialexpires = (nu+datetime.timedelta(days=10)).date()
self.r.save()
self.assertEqual(is_plantrial(self.u),True)
self.assertEqual(isplanmember(self.u),True)
self.assertEqual(iscoachmember(self.u),False)
self.assertEqual(ispromember(self.u),True)
+1 -1
View File
@@ -42,7 +42,7 @@ class SimpleViewTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True, surveydone=True, gdproptin=True, ftpset=True, surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
+2 -2
View File
@@ -43,7 +43,7 @@ class TeamTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
user=u, user=u,
clubsize=3 clubsize=3
) )
@@ -402,7 +402,7 @@ class TeamTestLowLevel(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
user=u, user=u,
clubsize=3 clubsize=3
) )
+4 -4
View File
@@ -35,7 +35,7 @@ class OtherUnitTests(TestCase):
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
defaulttimezone='US/Pacific', defaulttimezone='US/Pacific',
rowerplan='coach') rowerplan='pro')
# Test get_dates_timeperiod # Test get_dates_timeperiod
@@ -172,7 +172,7 @@ class PlannedSessionTests(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
@@ -430,7 +430,7 @@ class DataPrepTests(TestCase):
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
sex='male', sex='male',
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.r.birthdate = timezone.now()-datetime.timedelta(days=25*365) self.r.birthdate = timezone.now()-datetime.timedelta(days=25*365)
self.r.defaulttimezone = 'Europe/Amsterdam' self.r.defaulttimezone = 'Europe/Amsterdam'
@@ -649,7 +649,7 @@ class InteractivePlotTests(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
+2 -2
View File
@@ -27,7 +27,7 @@ class ForceUnits(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.user_workouts = WorkoutFactory.create_batch(12, user=self.r) self.user_workouts = WorkoutFactory.create_batch(12, user=self.r)
@@ -171,7 +171,7 @@ class TestForceUnit(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(14, user=self.r) self.user_workouts = WorkoutFactory.create_batch(14, user=self.r)
+1 -1
View File
@@ -21,7 +21,7 @@ class ViewTest(TestCase):
'koeinsloot') 'koeinsloot')
self.r = Rower.objects.create(user=self.u,gdproptin=True, ftpset=True,surveydone=True, self.r = Rower.objects.create(user=self.u,gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach', rowerplan='pro',
) )
add_defaultfavorites(self.r) add_defaultfavorites(self.r)
+1 -2
View File
@@ -25,7 +25,7 @@ class URLTests(TestCase):
'sander@ds.ds', 'sander@ds.ds',
'koeinsloot', 'koeinsloot',
) )
r = Rower.objects.create(user=u,rowerplan='coach',gdproptin=True, ftpset=True, r = Rower.objects.create(user=u,rowerplan='pro',gdproptin=True, ftpset=True,
gdproptindate=timezone.now()) gdproptindate=timezone.now())
self.c = Client() self.c = Client()
cs = courses.kmltocourse('rowers/tests/testdata/thyro.kml') cs = courses.kmltocourse('rowers/tests/testdata/thyro.kml')
@@ -119,7 +119,6 @@ class URLTests(TestCase):
'/rowers/me/workflowdefault/', '/rowers/me/workflowdefault/',
'/rowers/partners/', '/rowers/partners/',
'/rowers/physics/', '/rowers/physics/',
'/rowers/planrequired/',
'/rowers/register/', '/rowers/register/',
'/rowers/register/thankyou/', '/rowers/register/thankyou/',
'/rowers/sessions/', '/rowers/sessions/',
+1 -1
View File
@@ -82,7 +82,7 @@ class UserPreferencesTest(TestCase):
birthdate=faker.profile()['birthdate'], birthdate=faker.profile()['birthdate'],
gdproptin=True, ftpset=True,surveydone=True, gdproptin=True, ftpset=True,surveydone=True,
gdproptindate=timezone.now(), gdproptindate=timezone.now(),
rowerplan='coach') rowerplan='pro')
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
Binary file not shown.
+13 -15
View File
@@ -23,14 +23,14 @@
24,26,addmanual_view,upload a manual workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 24,26,addmanual_view,upload a manual workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, 26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
29,31,analysis_new,analysis front page,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, 29,31,analysis_new,analysis front page,TRUE,404,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
31,33,session_jobs_view,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 31,33,session_jobs_view,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
32,34,session_jobs_status,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 32,34,session_jobs_status,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, 35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 42,44,analysis_view_data,redirects to analysis direct,TRUE,404,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
47,53,graph_show_view,show a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 47,53,graph_show_view,show a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
48,54,GraphDelete,delete a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 48,54,GraphDelete,delete a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
@@ -38,7 +38,7 @@
50,56,otw_use_impeller,switch to impeller data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE, 50,56,otw_use_impeller,switch to impeller data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE,
51,57,otw_use_gps,switch to GPS data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE, 51,57,otw_use_gps,switch to GPS data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE,
52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE, 52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE,
53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 53,59,team_workout_upload_view,upload workout for team member,TRUE,302,pro,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE, 56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
57,63,workout_unsubscribe_view,unsubscribe from comments,TRUE,302,basic,200,302,basic,200,302,basic,200,302,FALSE,FALSE,TRUE,TRUE,TRUE, 57,63,workout_unsubscribe_view,unsubscribe from comments,TRUE,302,basic,200,302,basic,200,302,basic,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
@@ -110,7 +110,7 @@
148,188,coach_accept_coachrequest_view,Accept Coach request,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 148,188,coach_accept_coachrequest_view,Accept Coach request,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
149,189,rower_accept_coachoffer_view,Accept Coach offer,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 149,189,rower_accept_coachoffer_view,Accept Coach offer,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
150,190,team_delete_view,Delete Team,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 150,190,team_delete_view,Delete Team,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
151,191,team_create_view,Create Team,TRUE,302,pro,302,302,FALSE,200,200,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 151,191,team_create_view,Create Team,TRUE,302,pro,200,302,FALSE,200,200,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
152,192,manager_member_drop_view,Drop member,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 152,192,manager_member_drop_view,Drop member,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
153,193,invitation_reject_view,Reject invitation,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 153,193,invitation_reject_view,Reject invitation,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
154,194,invitation_revoke_view,redirects when no invitations,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 154,194,invitation_revoke_view,redirects when no invitations,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
@@ -151,20 +151,18 @@
193,249,checkouts_view,checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 193,249,checkouts_view,checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
194,250,upgrade_checkouts_view,upgrade checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 194,250,upgrade_checkouts_view,upgrade checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
195,251,downgrade_checkouts_view,downgrade checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 195,251,downgrade_checkouts_view,downgrade checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
196,252,planrequired_view,a plan is required,TRUE,302,basic,302,302,basic,302,302,coach,302,302,FALSE,FALSE,FALSE,TRUE,TRUE,
197,253,start_trial_view,payments,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 197,253,start_trial_view,payments,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
198,254,start_plantrial_view,paid plans,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 198,254,start_plantrial_view,paid plans,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
199,256,rower_register_view,register rower,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 199,256,rower_register_view,register rower,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
200,257,freecoach_register_view,register coach,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
201,259,workout_workflow_view,workout workflow vieq,TRUE,302,basic,200,200,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE, 201,259,workout_workflow_view,workout workflow vieq,TRUE,302,basic,200,200,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE,
202,260,workout_flexchart3_view,flex chart,TRUE,302,basic,200,403,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE, 202,260,workout_flexchart3_view,flex chart,TRUE,302,basic,200,403,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE,
203,264,rower_process_testcallback,test callback,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 203,264,rower_process_testcallback,test callback,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
204,265,rower_create_trainingplan,create training plan,TRUE,302,plan,200,302,FALSE,403,403,FALSE,200,403,FALSE,FALSE,FALSE,TRUE,TRUE, 204,265,rower_create_trainingplan,create training plan,TRUE,302,pro,200,302,FALSE,403,403,FALSE,200,403,FALSE,FALSE,FALSE,TRUE,TRUE,
205,267,TrainingPlanDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 205,267,TrainingPlanDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
206,268,MicroCycleDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 206,268,MicroCycleDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
207,269,MesoCycleDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 207,269,MesoCycleDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
208,270,MacroCycleDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 208,270,MacroCycleDelete,delete training plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
209,271,rower_trainingplan_view,see training plan,TRUE,200,plan,200,302,plan,403,403,coach,200,403,FALSE,TRUE,FALSE,FALSE,FALSE, 209,271,rower_trainingplan_view,see training plan,TRUE,200,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,FALSE,FALSE,
210,279,rower_trainingplan_execution_view,see training plan execution,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 210,279,rower_trainingplan_execution_view,see training plan execution,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
211,281,TrainingMacroCycleUpdate,update macro cycle,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 211,281,TrainingMacroCycleUpdate,update macro cycle,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
212,282,TrainingMesoCycleUpdate,update cycle,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 212,282,TrainingMesoCycleUpdate,update cycle,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
@@ -175,11 +173,11 @@
217,289,TrainingPlanUpdate,update trainingplan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 217,289,TrainingPlanUpdate,update trainingplan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
218,290,TrainingTargetUpdate,update training target,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 218,290,TrainingTargetUpdate,update training target,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
219,291,strokedataform,test strokedata,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 219,291,strokedataform,test strokedata,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
220,292,plannedsession_teamcreate_view,create planned session for team,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 220,292,plannedsession_teamcreate_view,create planned session for team,TRUE,302,pro,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
221,296,plannedsession_teamedit_view,edit planned sesssion,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 221,296,plannedsession_teamedit_view,edit planned sesssion,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
222,298,plannedsession_create_view,create planned session ,TRUE,302,plan,200,302,FALSE,200,302,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 222,298,plannedsession_create_view,create planned session ,TRUE,302,pro,200,302,FALSE,200,302,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
223,300,plannedsession_multiclone_view,clone multiple planned sessions,TRUE,302,plan,200,302,plan,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 223,300,plannedsession_multiclone_view,clone multiple planned sessions,TRUE,302,pro,200,302,pro,200,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
224,302,plannedsession_multicreate_view,create multiple planned sessions,TRUE,302,plan,200,302,plan,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 224,302,plannedsession_multicreate_view,create multiple planned sessions,TRUE,302,pro,200,302,pro,200,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
225,305,plannedsession_edit_view,edit planned sesssion,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 225,305,plannedsession_edit_view,edit planned sesssion,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
226,306,plannedsession_totemplate_view,planned session to template,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 226,306,plannedsession_totemplate_view,planned session to template,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
227,307,plannedsession_compare_view,compare workouts from planned session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 227,307,plannedsession_compare_view,compare workouts from planned session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
@@ -188,9 +186,9 @@
230,313,plannedsession_detach_view,remove workout from session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 230,313,plannedsession_detach_view,remove workout from session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
231,315,plannedsession_view,view session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 231,315,plannedsession_view,view session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
232,317,PlannedSessionDelete,delete session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 232,317,PlannedSessionDelete,delete session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
233,319,plannedsessions_manage_view,manage planned sesions,TRUE,302,plan,200,302,plan,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 233,319,plannedsessions_manage_view,manage planned sesions,TRUE,302,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
234,323,plannedsessions_coach_view,team view,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 234,323,plannedsessions_coach_view,team view,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
235,325,plannedsessions_coach_icsemail_view,team view,TRUE,302,coach,302,403,coach,302,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, 235,325,plannedsessions_coach_icsemail_view,team view,TRUE,302,pro,302,403,pro,302,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
236,326,plannedsessions_print_view,print view,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 236,326,plannedsessions_print_view,print view,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
237,327,plannedsession_comment_view,comment on planned session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 237,327,plannedsession_comment_view,comment on planned session,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
238,330,plannedsessions_icsemail_view,send ICS email,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE, 238,330,plannedsessions_icsemail_view,send ICS email,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE,
@@ -264,5 +262,5 @@
308,603,failed_queue_view,Other Apps views,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 308,603,failed_queue_view,Other Apps views,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
309,604,failed_queue_empty,Other Apps views,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 309,604,failed_queue_empty,Other Apps views,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
310,605,failed_job_view,Other Apps views,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE, 310,605,failed_job_view,Other Apps views,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE,
311,49,performancemanager_view,Performance Manager,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 311,49,performancemanager_view,Performance Manager,TRUE,404,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
312,606,workout_flexchart_stacked_view,flex chart,TRUE,302,basic,200,403,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE, 312,606,workout_flexchart_stacked_view,flex chart,TRUE,302,basic,200,403,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE,
1 id view function anonymous anonymous_response own own_response own_nonperm member member_response member_nonperm coachee coachee_response coachee_nonperm is_staff userid workoutid dotest realtest kwargs
23 24 26 addmanual_view upload a manual workout TRUE 302 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
24 26 28 workouts_join_view join workouts TRUE 302 pro 302 302 pro 403 403 coach 302 403 FALSE TRUE FALSE TRUE TRUE
25 27 29 workouts_join_select select workouts to join TRUE 404 pro 200 302 pro 403 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
26 29 31 analysis_new analysis front page TRUE 302 404 pro 200 302 FALSE 200 302 coach 200 302 FALSE TRUE FALSE TRUE TRUE
27 31 33 session_jobs_view view jobs TRUE 302 basic 200 302 FALSE 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
28 32 34 session_jobs_status view jobs TRUE 302 basic 200 302 FALSE 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
29 33 35 kill_async_job kill job TRUE 302 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
30 34 36 post_progress post progress TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
31 35 37 graphs_view view charts TRUE 302 basic 200 302 basic 200 302 coach 200 302 FALSE TRUE FALSE TRUE TRUE
32 41 43 cum_flex flex all chart TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
33 42 44 analysis_view_data redirects to analysis direct TRUE 302 404 pro 200 302 pro 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
34 43 47 cum_flex_data flex all chart data (json) TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
35 47 53 graph_show_view show a chart TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
36 48 54 GraphDelete delete a chart TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
38 50 56 otw_use_impeller switch to impeller data TRUE 403 basic 302 302 basic 403 302 coach 302 302 FALSE FALSE TRUE TRUE TRUE
39 51 57 otw_use_gps switch to GPS data TRUE 403 basic 302 302 basic 403 302 coach 302 302 FALSE FALSE TRUE TRUE TRUE
40 52 58 workout_toggle_ranking toggle ranking TRUE 302 basic 302 302 basic 403 302 coach 302 302 FALSE FALSE TRUE TRUE TRUE
41 53 59 team_workout_upload_view upload workout for team member TRUE 302 coach pro 200 302 FALSE 200 302 FALSE 200 302 FALSE FALSE FALSE TRUE TRUE
42 54 60 workout_upload_view upload a workout TRUE 302 basic 200 302 FALSE 200 302 FALSE 200 302 FALSE FALSE FALSE TRUE TRUE
43 56 62 workout_forcecurve_view force curve TRUE 302 pro 200 302 pro 403 302 coach 200 302 FALSE FALSE TRUE TRUE TRUE
44 57 63 workout_unsubscribe_view unsubscribe from comments TRUE 302 basic 200 302 basic 200 302 basic 200 302 FALSE FALSE TRUE TRUE TRUE
110 148 188 coach_accept_coachrequest_view Accept Coach request TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
111 149 189 rower_accept_coachoffer_view Accept Coach offer TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
112 150 190 team_delete_view Delete Team TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
113 151 191 team_create_view Create Team TRUE 302 pro 302 200 302 FALSE 200 200 FALSE 200 302 FALSE FALSE FALSE TRUE TRUE
114 152 192 manager_member_drop_view Drop member TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
115 153 193 invitation_reject_view Reject invitation TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
116 154 194 invitation_revoke_view redirects when no invitations TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
151 193 249 checkouts_view checkout TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
152 194 250 upgrade_checkouts_view upgrade checkout TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
153 195 251 downgrade_checkouts_view downgrade checkout TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
196 252 planrequired_view a plan is required TRUE 302 basic 302 302 basic 302 302 coach 302 302 FALSE FALSE FALSE TRUE TRUE
154 197 253 start_trial_view payments TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
155 198 254 start_plantrial_view paid plans TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
156 199 256 rower_register_view register rower TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
200 257 freecoach_register_view register coach TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
157 201 259 workout_workflow_view workout workflow vieq TRUE 302 basic 200 200 basic 200 200 coach 200 200 FALSE FALSE TRUE TRUE TRUE
158 202 260 workout_flexchart3_view flex chart TRUE 302 basic 200 403 basic 200 200 coach 200 200 FALSE FALSE TRUE TRUE TRUE
159 203 264 rower_process_testcallback test callback TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
160 204 265 rower_create_trainingplan create training plan TRUE 302 plan pro 200 302 FALSE 403 403 FALSE 200 403 FALSE FALSE FALSE TRUE TRUE
161 205 267 TrainingPlanDelete delete training plan TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
162 206 268 MicroCycleDelete delete training plan TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
163 207 269 MesoCycleDelete delete training plan TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
164 208 270 MacroCycleDelete delete training plan TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
165 209 271 rower_trainingplan_view see training plan TRUE 200 plan pro 200 302 plan pro 403 403 coach 200 403 FALSE TRUE FALSE FALSE FALSE
166 210 279 rower_trainingplan_execution_view see training plan execution TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
167 211 281 TrainingMacroCycleUpdate update macro cycle TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
168 212 282 TrainingMesoCycleUpdate update cycle TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
173 217 289 TrainingPlanUpdate update trainingplan TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
174 218 290 TrainingTargetUpdate update training target TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
175 219 291 strokedataform test strokedata TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
176 220 292 plannedsession_teamcreate_view create planned session for team TRUE 302 coach pro 200 302 FALSE 200 302 FALSE 200 302 FALSE FALSE FALSE TRUE TRUE
177 221 296 plannedsession_teamedit_view edit planned sesssion TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
178 222 298 plannedsession_create_view create planned session TRUE 302 plan pro 200 302 FALSE 200 302 coach 200 403 FALSE TRUE FALSE TRUE TRUE
179 223 300 plannedsession_multiclone_view clone multiple planned sessions TRUE 302 plan pro 200 302 plan pro 403 200 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
180 224 302 plannedsession_multicreate_view create multiple planned sessions TRUE 302 plan pro 200 302 plan pro 403 200 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
181 225 305 plannedsession_edit_view edit planned sesssion TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
182 226 306 plannedsession_totemplate_view planned session to template TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
183 227 307 plannedsession_compare_view compare workouts from planned session TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
186 230 313 plannedsession_detach_view remove workout from session TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
187 231 315 plannedsession_view view session TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
188 232 317 PlannedSessionDelete delete session TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
189 233 319 plannedsessions_manage_view manage planned sesions TRUE 302 plan pro 200 302 plan pro 403 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
190 234 323 plannedsessions_coach_view team view TRUE 302 basic 200 403 basic 403 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
191 235 325 plannedsessions_coach_icsemail_view team view TRUE 302 coach pro 302 403 coach pro 302 403 coach 302 403 FALSE TRUE FALSE TRUE TRUE
192 236 326 plannedsessions_print_view print view TRUE 302 basic 200 403 basic 403 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
193 237 327 plannedsession_comment_view comment on planned session TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
194 238 330 plannedsessions_icsemail_view send ICS email TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE TRUE FALSE FALSE FALSE
262 308 603 failed_queue_view Other Apps views TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
263 309 604 failed_queue_empty Other Apps views TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
264 310 605 failed_job_view Other Apps views TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE TRUE FALSE FALSE
265 311 49 performancemanager_view Performance Manager TRUE 302 404 pro 200 302 pro 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
266 312 606 workout_flexchart_stacked_view flex chart TRUE 302 basic 200 403 basic 200 200 coach 200 200 FALSE FALSE TRUE TRUE TRUE
+2 -4
View File
@@ -845,8 +845,6 @@ urlpatterns = [
name='downgrade_checkouts'), name='downgrade_checkouts'),
re_path(r'^purchasecheckouts/$', views.purchase_checkouts_view, re_path(r'^purchasecheckouts/$', views.purchase_checkouts_view,
name='purchase_checkouts_view'), name='purchase_checkouts_view'),
re_path(r'^planrequired/', views.planrequired_view,
name='planrequired_view'),
re_path(r'^starttrial/$', views.start_trial_view, name='start_trial_view'), re_path(r'^starttrial/$', views.start_trial_view, name='start_trial_view'),
re_path(r'^startplantrial/$', views.start_plantrial_view, re_path(r'^startplantrial/$', views.start_plantrial_view,
name='start_plantrial_view'), name='start_plantrial_view'),
@@ -856,8 +854,8 @@ urlpatterns = [
template_name='legal.html'), name='legal'), template_name='legal.html'), name='legal'),
re_path(r'^register/$', views.rower_register_view, re_path(r'^register/$', views.rower_register_view,
name='rower_register_view'), name='rower_register_view'),
re_path(r'^coachregister/$', views.freecoach_register_view, re_path(r'^coachregister/$', views.coach_register_view,
name='freecoach_register_view'), name='coach_register_view'),
path('activate/<uidb64>/<token>/', views.useractivate, name='useractivate'), path('activate/<uidb64>/<token>/', views.useractivate, name='useractivate'),
re_path(r'^register/thankyou/$', TemplateView.as_view( re_path(r'^register/thankyou/$', TemplateView.as_view(
template_name='registerthankyou.html'), name='registerthankyou'), template_name='registerthankyou.html'), name='registerthankyou'),
+5 -39
View File
@@ -27,11 +27,6 @@ defaultoptions = {
} }
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher."
" If you are already a Pro user,"
" please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach', @permission_required('rower.is_coach',
fn=get_user_by_userid, fn=get_user_by_userid,
raise_exception=True) raise_exception=True)
@@ -897,11 +892,6 @@ def statsdata(workouts, options):
def comparisondata(workouts, options): def comparisondata(workouts, options):
#try:
# workouts = workouts.exclude(workoutsource='strava')
#except AttributeError: # pragma: no cover
# workouts = [w for w in workouts if w.workoutsource != 'strava']
includereststrokes = options['includereststrokes'] includereststrokes = options['includereststrokes']
xparam = options['xaxis'] xparam = options['xaxis']
yparam1 = options['yaxis1'] yparam1 = options['yaxis1']
@@ -1013,10 +1003,6 @@ def boxplotdata(workouts, options):
return(script, div) return(script, div)
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher."
" If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True) @permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
def analysis_view_data(request, userid=0): def analysis_view_data(request, userid=0):
is_ajax = request_is_ajax(request) is_ajax = request_is_ajax(request)
@@ -1087,17 +1073,10 @@ def analysis_view_data(request, userid=0):
}) })
def planrequired_view(request):
messages.info(
request, "This functionality requires Coach or Self-Coach membership")
return HttpResponseRedirect(reverse('paidplans_view'))
@user_passes_test(ispromember, login_url="/rowers/paidplans", @login_required()
message="This functionality requires a Pro plan or higher." @permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
" If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
def create_marker_workouts_view(request, userid=0, def create_marker_workouts_view(request, userid=0,
startdate=timezone.now()-timezone.timedelta(days=42), startdate=timezone.now()-timezone.timedelta(days=42),
enddate=timezone.now()): enddate=timezone.now()):
@@ -1119,10 +1098,8 @@ def create_marker_workouts_view(request, userid=0,
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@user_passes_test(ispromember, login_url="/rowers/paidplans", @login_required()
message="This functionality requires a Pro plan or higher." @permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
" If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
def goldmedalscores_view(request, userid=0, def goldmedalscores_view(request, userid=0,
startdate=timezone.now()-timezone.timedelta(days=365), startdate=timezone.now()-timezone.timedelta(days=365),
enddate=timezone.now()): enddate=timezone.now()):
@@ -1184,10 +1161,6 @@ def goldmedalscores_view(request, userid=0,
}) })
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher."
" If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True) @permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
def trainingzones_view(request, userid=0): def trainingzones_view(request, userid=0):
r = getrequestrower(request, userid=userid) r = getrequestrower(request, userid=userid)
@@ -1255,6 +1228,7 @@ def trainingzones_view(request, userid=0):
@login_required() @login_required()
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
def trainingzones_view_data(request, userid=0): def trainingzones_view_data(request, userid=0):
r = getrequestrower(request, userid=userid) r = getrequestrower(request, userid=userid)
@@ -1296,10 +1270,6 @@ def trainingzones_view_data(request, userid=0):
}) })
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher."
" If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True) @permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
def performancemanager_view(request, userid=0, mode='rower', def performancemanager_view(request, userid=0, mode='rower',
startdate=timezone.now()-timezone.timedelta(days=365), startdate=timezone.now()-timezone.timedelta(days=365),
@@ -2060,10 +2030,6 @@ class AlertDelete(DeleteView):
return obj return obj
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher."
" If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True) @permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
def history_view(request, userid=0): def history_view(request, userid=0):
r = getrequestrower(request, userid=userid) r = getrequestrower(request, userid=userid)
-8
View File
@@ -101,7 +101,6 @@ def javascript_log(request):
return JSONResponse(status=200, data = {'status': 'true', 'message': message}) return JSONResponse(status=200, data = {'status': 'true', 'message': message})
@login_required() @login_required()
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
def strokedataform(request, id=0): def strokedataform(request, id=0):
id = encoder.decode_hex(id) id = encoder.decode_hex(id)
@@ -265,7 +264,6 @@ def api_get_dataframe(startdatetime, df):
@login_required() @login_required()
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
def strokedataform_v2(request, id=0): def strokedataform_v2(request, id=0):
id = encoder.decode_hex(id) id = encoder.decode_hex(id)
@@ -496,7 +494,6 @@ def strokedata_rowingdata(request):
@csrf_exempt @csrf_exempt
@api_view(["POST"]) @api_view(["POST"])
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
def strokedata_rowingdata_apikey(request): def strokedata_rowingdata_apikey(request):
""" """
@@ -547,7 +544,6 @@ def strokedata_rowingdata_apikey(request):
@csrf_exempt @csrf_exempt
@api_view(["POST"]) @api_view(["POST"])
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
@parser_classes([FITParser]) @parser_classes([FITParser])
def strokedata_fit(request): def strokedata_fit(request):
@@ -647,7 +643,6 @@ def strokedata_fit(request):
@csrf_exempt @csrf_exempt
#@login_required() #@login_required()
@api_view(["POST"]) @api_view(["POST"])
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
@parser_classes([XMLParser]) @parser_classes([XMLParser])
def strokedata_tcx(request): def strokedata_tcx(request):
@@ -768,7 +763,6 @@ def strokedata_tcx(request):
@csrf_exempt @csrf_exempt
@api_view(["POST"]) @api_view(["POST"])
#@login_required() #@login_required()
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
def strokedatajson_v3(request): def strokedatajson_v3(request):
""" """
@@ -913,7 +907,6 @@ def strokedatajson_v3(request):
# Return the GET stroke data according to the API definition # Return the GET stroke data according to the API definition
@csrf_exempt @csrf_exempt
#@login_required() #@login_required()
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@api_view(["GET", "POST"]) @api_view(["GET", "POST"])
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
def strokedatajson_v2(request, id): def strokedatajson_v2(request, id):
@@ -1073,7 +1066,6 @@ def strokedatajson_v2(request, id):
@csrf_exempt @csrf_exempt
#@login_required() #@login_required()
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@api_view(['GET', 'POST']) @api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
def strokedatajson(request, id=0): def strokedatajson(request, id=0):
+2 -4
View File
@@ -399,8 +399,6 @@ def rower_process_nkcallback(request): # pragma: no cover
@login_required() @login_required()
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
def workout_import_view(request, source='c2'): def workout_import_view(request, source='c2'):
startdate, enddate = get_dates_timeperiod( startdate, enddate = get_dates_timeperiod(
request, defaulttimeperiod='last30') request, defaulttimeperiod='last30')
@@ -756,8 +754,8 @@ def plannedsession_intervalsimport_view(request, message="", userid=0):
@login_required() @login_required()
@user_passes_test(isplanmember, login_url="/rowers/paidplans/", @user_passes_test(ispromember, login_url="/rowers/paidplans/",
message="This functionality requires a Self-coach plan or higher", message="This functionality requires a Pro plan or higher",
redirect_field_name=None) redirect_field_name=None)
@permission_required('plannedsession.add_session', fn=get_user_by_userid, raise_exception=True) @permission_required('plannedsession.add_session', fn=get_user_by_userid, raise_exception=True)
def workout_rojaboimport_view(request, message="", userid=0): # pragma: no cover def workout_rojaboimport_view(request, message="", userid=0): # pragma: no cover
+1 -1
View File
@@ -980,7 +980,7 @@ def rower_register_view(request):
# User registration # User registration
def freecoach_register_view(request): # pragma: no cover def coach_register_view(request): # pragma: no cover
nextpage = request.GET.get('next', '/rowers/me/teams/') nextpage = request.GET.get('next', '/rowers/me/teams/')
if nextpage == '': # pragma: no cover if nextpage == '': # pragma: no cover
+6 -9
View File
@@ -318,7 +318,7 @@ def plannedsession_multiclone_view(
add_rower_session(rower, ps) add_rower_session(rower, ps)
for team in teams: for team in teams:
add_team_session(team, ps) add_team_session(team, ps)
for rower in team.rower.all().exclude(rowerplan='freecoach'): for rower in team.rower.all():
add_rower_session(rower, ps) add_rower_session(rower, ps)
startdatestring = shiftstartdate.strftime('%Y-%m-%d') startdatestring = shiftstartdate.strftime('%Y-%m-%d')
@@ -974,7 +974,7 @@ def plannedsession_teamcreate_view(request,
for team in teams: for team in teams:
add_team_session(team, ps) add_team_session(team, ps)
rs = Rower.objects.filter( rs = Rower.objects.filter(
team__in=[team]).exclude(rowerplan='freecoach') team__in=[team])
for r in rs: for r in rs:
add_rower_session(r, ps) add_rower_session(r, ps)
@@ -1297,17 +1297,14 @@ def plannedsessions_coach_view(request,
rteams = therower.team.filter(viewing='allmembers') rteams = therower.team.filter(viewing='allmembers')
sps = get_sessions(therower, startdate=startdate, enddate=enddate) sps = get_sessions(therower, startdate=startdate, enddate=enddate)
if therower.rowerplan != 'freecoach': rowers = [therower]
rowers = [therower]
else: # pragma: no cover
rowers = []
for ps in sps: for ps in sps:
if is_coach(request.user) or is_coachtrial(request.user): if is_coach(request.user) or is_coachtrial(request.user):
rowers += ps.rower.all().exclude(rowerplan='freecoach') rowers += ps.rower.all()
else: # pragma: no cover else: # pragma: no cover
rowers += ps.rower.filter( rowers += ps.rower.filter(
team__in=rteams).exclude(rowerplan='freecoach') team__in=rteams)
rowers = list(set(rowers)) rowers = list(set(rowers))
@@ -1861,7 +1858,7 @@ def plannedsession_clone_view(request, id=0, userid=0):
add_rower_session(r, ps) add_rower_session(r, ps)
for team in teams: for team in teams:
add_team_session(team, ps) add_team_session(team, ps)
for rower in team.rower.all().exclude(rowerplan='freecoach'): for rower in team.rower.all():
add_rower_session(rower, ps) add_rower_session(rower, ps)
url = reverse(plannedsession_edit_view, url = reverse(plannedsession_edit_view,
+1 -11
View File
@@ -240,16 +240,6 @@ def rower_teams_view(request): # pragma: no cover
user__in=invitedathletes).exclude( user__in=invitedathletes).exclude(
user=request.user user=request.user
).exclude(coachinggroups__in=[request.user.rower.mycoachgroup]) ).exclude(coachinggroups__in=[request.user.rower.mycoachgroup])
elif request.user.rower.rowerplan == 'freecoach': # pragma: no cover
potentialathletes = Rower.objects.filter(
team__in=myteams).exclude(
user__in=invitedathletes).exclude(
user=request.user
).exclude(
coachinggroups__in=[request.user.rower.mycoachgroup]
).exclude(
rowerplan__in=['basic', 'freecoach']
)
else: else:
potentialathletes = [] potentialathletes = []
@@ -581,7 +571,7 @@ def invitation_reject_view(request, id=0):
def rower_invitations_view(request, code=None, message='', successmessage=''): def rower_invitations_view(request, code=None, message='', successmessage=''):
if code: if code:
teams.remove_expired_invites() teams.remove_expired_invites()
res, text = teams.process_invite_code(request.user, code) res, text = teams.process_invite_code(request.user, code)
if res: # pragma: no cover if res: # pragma: no cover
messages.info(request, text) messages.info(request, text)
+2 -14
View File
@@ -2101,7 +2101,7 @@ def workouts_bulk_actions(request):
teams = Team.objects.filter(manager=request.user) teams = Team.objects.filter(manager=request.user)
assignchoices.fields["rowers"].queryset = Rower.objects.filter( assignchoices.fields["rowers"].queryset = Rower.objects.filter(
team__in=teams team__in=teams
).distinct().order_by("user__last_name", "user__first_name").exclude(rowerplan='freecoach') ).distinct().order_by("user__last_name", "user__first_name")
assignchoices.fields["rowers"].initial = [] assignchoices.fields["rowers"].initial = []
form = WorkoutMultipleCompareForm() form = WorkoutMultipleCompareForm()
form.fields["workouts"].queryset = Workout.objects.filter(id__in=[w.id for w in workouts]) form.fields["workouts"].queryset = Workout.objects.filter(id__in=[w.id for w in workouts])
@@ -5191,9 +5191,6 @@ def workout_upload_view(request,
r = getrower(request.user) r = getrower(request.user)
if r.imports_are_private: if r.imports_are_private:
uploadoptions['makeprivate'] = True uploadoptions['makeprivate'] = True
if r.rowerplan == 'freecoach': # pragma: no cover
url = reverse('team_workout_upload_view')
return HttpResponseRedirect(url)
breadcrumbs = [ breadcrumbs = [
{ {
@@ -5622,7 +5619,7 @@ def workout_upload_view(request,
# This is the main view for processing uploaded files # This is the main view for processing uploaded files
@user_passes_test(iscoachmember, login_url="/rowers/paidplans", redirect_field_name=None, @user_passes_test(ispromember, login_url="/rowers/paidplans", redirect_field_name=None,
message="This functionality requires a Coach plan or higher") message="This functionality requires a Coach plan or higher")
def team_workout_upload_view(request, userid=0, message="", def team_workout_upload_view(request, userid=0, message="",
successmessage="", successmessage="",
@@ -5659,11 +5656,7 @@ def team_workout_upload_view(request, userid=0, message="",
rowerform.fields.pop('email') rowerform.fields.pop('email')
rowers = Rower.objects.filter( rowers = Rower.objects.filter(
coachinggroups__in=[r.mycoachgroup] coachinggroups__in=[r.mycoachgroup]
).exclude(
rowerplan='freecoach'
).distinct() ).distinct()
if r.rowerplan == 'freecoach': # pragma: no cover
rowers = rowers.exclude(rowerplan='basic')
rowerform.fields['user'].queryset = User.objects.filter( rowerform.fields['user'].queryset = User.objects.filter(
rower__in=rowers).distinct() rower__in=rowers).distinct()
@@ -5783,7 +5776,6 @@ def team_workout_upload_view(request, userid=0, message="",
id, jobid = uploads.make_plot(r, w, f1, f2, plottype, t) id, jobid = uploads.make_plot(r, w, f1, f2, plottype, t)
else: else:
response = render(request, response = render(request,
'team_document_form.html', 'team_document_form.html',
{'form': form, {'form': form,
@@ -5803,11 +5795,7 @@ def team_workout_upload_view(request, userid=0, message="",
rowers = Rower.objects.filter( rowers = Rower.objects.filter(
coachinggroups__in=[r.mycoachgroup] coachinggroups__in=[r.mycoachgroup]
).exclude(
rowerplan='freecoach'
).distinct() ).distinct()
if r.rowerplan == 'freecoach': # pragma: no cover
rowers = rowers.exclude(rowerplan='basic')
rowerform.fields['user'].queryset = User.objects.filter( rowerform.fields['user'].queryset = User.objects.filter(
rower__in=rowers).distinct() rower__in=rowers).distinct()
+1 -1
View File
@@ -156,7 +156,7 @@
<li> <li>
<a href="/rowers/me/prefs/" title="Profile"> <a href="/rowers/me/prefs/" title="Profile">
{% if user.rower.rowerplan == 'pro' %} {% if user.rower.rowerplan == 'pro' %}
<i class="fas fa-user-ninja "></i> <i class="fa-solid fa-user-astronaut "></i>
{% elif 'coach' in user.rower.rowerplan %} {% elif 'coach' in user.rower.rowerplan %}
<i class="fas fa-users "></i> <i class="fas fa-users "></i>
{% elif user.rower.rowerplan == 'plan' %} {% elif user.rower.rowerplan == 'plan' %}