diff --git a/rowers/forms.py b/rowers/forms.py index 1b3793fb..fdb19df6 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1120,6 +1120,9 @@ class AnalysisOptionsForm(forms.Form): label='Water Boat Type', initial=mytypes.waterboattype) + ranking = forms.BooleanField(label='Ranking Workouts Only', + initial=False,required=False) + # form to select modality and boat type for trend flex class TrendFlexModalForm(forms.Form): diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 591ab34c..55b4fc32 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -34,7 +34,7 @@ import rowers.stravastuff as stravastuff import rowers.nkstuff as nkstuff from rowers.opaque import encoder -from rowers.rower_rules import user_is_not_basic +from rowers.rower_rules import user_is_not_basic, user_is_coachee from rowers.utils import dologging # If you find a solution that does not need the two paths, please comment! @@ -90,7 +90,7 @@ class Command(BaseCommand): try: rowers = Rower.objects.filter(c2_auto_import=True) for r in rowers: # pragma: no cover - if user_is_not_basic(r.user): + if user_is_not_basic(r.user) or user_is_coachee(r.user): c2stuff.get_c2_workouts(r) except: # pragma: no cover exc_type, exc_value, exc_traceback = sys.exc_info() @@ -100,7 +100,7 @@ class Command(BaseCommand): try: rowers = Rower.objects.filter(rp3_auto_import=True) for r in rowers: # pragma: no cover - if user_is_not_basic(r.user): + if user_is_not_basic(r.user) or user_is_coachee(r.user): _ = rp3stuff.get_rp3_workouts(r) except: # pragma: no cover exc_type, exc_value, exc_traceback = sys.exc_info() @@ -111,7 +111,7 @@ class Command(BaseCommand): rowers = Rower.objects.filter(nk_auto_import=True) for r in rowers: # pragma: no cover dologging("nklog.log","NK Auto import set for rower {id}".format(id=r.user.id)) - if user_is_not_basic(r.user): + if user_is_not_basic(r.user) or user_is_coachee(r.user): dologging("nklog.log","User is not basic") _ = nkstuff.get_nk_workouts(r) except: # pragma: no cover diff --git a/rowers/rower_rules.py b/rowers/rower_rules.py index be51fcc8..33724ef2 100644 --- a/rowers/rower_rules.py +++ b/rowers/rower_rules.py @@ -86,6 +86,15 @@ def user_is_not_basic(user): return False +@rules.predicate +def user_is_coachee(user): + coaches = user.rower.get_coaches() + for coach in coaches: + if coach.rowerplan == 'coach': + return True + + return False + @rules.predicate def user_is_basic(user): diff --git a/rowers/tasks.py b/rowers/tasks.py index d3d9f497..45f806ea 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -338,6 +338,12 @@ def handle_strava_sync(stravatoken, workoutid, filename, name, activity_type, de tb = traceback.format_exc() dologging('strava_fail.log', tb) failed = True + except stravalib.exc.TimeoutExceeded: + dologging('strava_fail.log', 'Strava upload failed for Workout {id} TimeOutExceeded'.format( + id=workoutid)) + tb = traceback.format_exc() + dologging('strava_fail.log', tb) + failed = True except JSONDecodeError: # pragma: no cover dologging('strava_fail.log', 'Strava upload failed for Workout {id} JSONDecodeError'.format( id=workoutid)) diff --git a/rowers/tests/test_permissions.py b/rowers/tests/test_permissions.py index 5f4bcdd2..0f5a8c3e 100644 --- a/rowers/tests/test_permissions.py +++ b/rowers/tests/test_permissions.py @@ -13,7 +13,7 @@ from django.db import transaction import rowers.teams as teams import rowers.plannedsessions as plannedsessions -from rowers.rower_rules import is_coach_user +from rowers.rower_rules import is_coach_user, user_is_coachee @override_settings(TESTING=True) class PlanningPermissionsCoach(TestCase): @@ -94,6 +94,9 @@ class PlanningPermissionsCoach(TestCase): athletes = plan.rowers.all() self.assertTrue(self.rgroupmember in athletes) + def test_coachee_can_sync(self): + self.assertTrue(user_is_coachee(self.ucoachee)) + @override_settings(TESTING=True) class PermissionsFreeCoach(TestCase): diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 3f5e4729..7b46b5c9 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -19,7 +19,8 @@ defaultoptions = { 'includereststrokes': False, 'workouttypes': ['rower', 'dynamic', 'slides'], 'waterboattype': mytypes.waterboattype, - 'function': 'boxplot' + 'function': 'boxplot', + 'ranking': False, } @@ -72,6 +73,11 @@ def analysis_new(request, modalities = [m[0] for m in mytypes.workouttypes_ordered.items()] modality = 'all' + try: + ranking = options['ranking'] + except KeyError: + ranking = False + try: worldclass = options['cpoverlay'] except KeyError: @@ -109,6 +115,7 @@ def analysis_new(request, modality = optionsform.cleaned_data['modality'] waterboattype = optionsform.cleaned_data['waterboattype'] + ranking = optionsform.cleaned_data['ranking'] if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: # pragma: no cover @@ -118,6 +125,7 @@ def analysis_new(request, options['modalities'] = modalities options['waterboattype'] = waterboattype + options['ranking'] = ranking try: worldclass = options['cpoverlay'] except KeyError: @@ -173,17 +181,24 @@ def analysis_new(request, if b[0] not in waterboattype: # pragma: no cover negtypes.append(b[0]) + rankingtypes = [False,True] + if ranking: + rankingtypes = [True] + + if theteam is not None and (theteam.viewing == 'allmembers' or theteam.manager == request.user): # pragma: no cover workouts = Workout.objects.filter(team=theteam, startdatetime__gte=startdate, startdatetime__lte=enddate, workouttype__in=modalities, + rankingpiece__in=rankingtypes, ) elif theteam is not None and theteam.viewing == 'coachonly': # pragma: no cover workouts = Workout.objects.filter(team=theteam, user=r, startdatetime__gte=startdate, startdatetime__lte=enddate, workouttype__in=modalities, + rankingpiece__in=rankingtypes, ) elif thesession is not None: workouts = get_workouts_session(r, thesession) @@ -192,6 +207,7 @@ def analysis_new(request, startdatetime__gte=startdate, startdatetime__lte=enddate, workouttype__in=modalities, + rankingpiece__in=rankingtypes, ) if firstworkout: workouts = firstworkoutquery | workouts @@ -229,6 +245,7 @@ def analysis_new(request, optionsform = AnalysisOptionsForm(initial={ 'modality': modality, 'waterboattype': waterboattype, + 'ranking': ranking, }) if r.birthdate: