from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals from rowers.views.statements import * @login_required() def plannedsession_comment_view(request,id=0,userid=0): r = getrequestplanrower(request,userid=userid) try: ps = PlannedSession.objects.get(id=id) except PlannedSession.DoesNotExist: raise Http404("Planned Session does not exist") m = ps.manager mm = Rower.objects.get(user=m) if ps.manager != request.user and ps.sessiontype not in ['race','indoorrace']: if r.rowerplan == 'coach' and r not in ps.rower.all(): teams = Team.objects.filter(manager=request.user) members = Rower.objects.filter(team__in=teams).distinct() teamusers = [m.user for m in members] if ps.manager not in teamusers: raise PermissionDenied("You do not have access to this session") elif r not in ps.rower.all(): raise PermissionDenied("You do not have access to this session") comments = PlannedSessionComment.objects.filter(plannedsession=ps).order_by("created") if request.method == 'POST': manager = ps.manager form = PlannedSessionCommentForm(request.POST) if form.is_valid(): cd = form.cleaned_data comment = cd['comment'] comment = bleach.clean(comment) try: if isinstance(comment,unicode): comment = comment.encode('utf8') elif isinstance(comment, str): comment = comment.decode('utf8') except: pass notification = cd['notification'] c = PlannedSessionComment(plannedsession=ps,user=request.user,comment=comment, notification=notification) c.save() url = reverse('plannedsession_comment_view', kwargs={ 'id':id }) message = '{name} says: {comment}'.format( name = request.user.first_name, comment = comment, url = url, ) if request.user != manager: a_messages.info(r.user,message.encode('ascii','ignore')) sessiontype = 'training session' if ps.sessiontype == 'race': sessiontype = 'online virtual race' elif ps.sessiontype == 'indoorrace': sessiontype = 'indoor online virtual race' res = myqueue(queuehigh, handle_sendemailnewcomment,r.user.first_name, r.user.last_name, r.user.email, request.user.first_name, request.user.last_name, comment,ps.name,ps.id, emailbounced = r.emailbounced, sessiontype = sessiontype, commentlink = url ) commenters = {oc.user for oc in comments if oc.notification} if ps.sessiontype=='race': registrations = VirtualRaceResult.objects.filter( race__id=ps.id, emailnotifications=True) ids = [rg.userid for rg in registrations] rwrs = Rower.objects.filter(id__in= ids) rowers = {u.user for u in rwrs} elif ps.sessiontype=='indoorrace': registrations = IndoorVirtualRaceResult.objects.filter( race__id=ps.id, emailnotifications=True) ids = [rg.userid for rg in registrations] rwrs = Rower.objects.filter(id__in= ids) rowers = {u.user for u in rwrs} else: rowers = {r.user for r in ps.rower.all()} commenters = set(list(commenters)+list(rowers)) for u in commenters: a_messages.info(u,message) if u != request.user and u != r.user: ocr = Rower.objects.get(user=u) res = myqueue(queuelow, handle_sendemailnewresponse, u.first_name, u.last_name, u.email, request.user.first_name, request.user.last_name, comment, ps.name, ps.id, c.id, emailbounced = ocr.emailbounced, sessiontype = sessiontype, commentlink = url ) url = reverse('plannedsession_comment_view',kwargs={'id':ps.id}) return HttpResponseRedirect(url) form = WorkoutCommentForm() rower = getrower(request.user) if ps.sessiontype in ['race','indoorrace']: breadcrumbs = [ { 'url':reverse('virtualevents_view'), 'name': 'Races' }, { 'url': reverse('virtualevent_view',kwargs={'id':ps.id}), 'name': ps.name }, { 'url':reverse('plannedsession_comment_view',kwargs={'id':ps.id}), 'name': 'Comments' } ] active = 'nav-racing' else: breadcrumbs = [ { 'url':reverse('plannedsessions_view'), 'name': 'Sessions' }, { 'url': reverse('plannedsession_view',kwargs={'id':ps.id}), 'name': ps.name }, { 'url':reverse('plannedsession_comment_view',kwargs={'id':ps.id}), 'name': 'Comments' } ] active = 'nav-plan' return render(request, 'plannedsession_comments.html', {'plannedsession':ps, 'rower':rower, 'breadcrumbs':breadcrumbs, 'active':active, 'comments':comments, 'form':form, }) # Cloning sessions @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_multiclone_view( request, userid=0,): r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) if request.method == 'POST' and 'daterange' in request.POST: dateform = DateRangeForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') request.session['startdate'] = startdatestring request.session['enddate'] = enddatestring else: dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) if request.method == 'POST' and 'plannedsessions' in request.POST: form = PlannedSessionMultipleCloneForm(request.POST) dateshiftform = SessionDateShiftForm(request.POST) if form.is_valid() and dateshiftform.is_valid(): cd = form.cleaned_data sps = cd['plannedsessions'] std = min([ps.startdate for ps in sps]) shiftstartdate = dateshiftform.cleaned_data['shiftstartdate'] delta = shiftstartdate-std lastdate = shiftstartdate for ps in sps: rowers = ps.rower.all() teams = ps.team.all() ps.pk = None ps.startdate += delta ps.preferreddate += delta ps.enddate += delta if ps.enddate > lastdate: lastdate = ps.enddate ps.save() for rower in rowers: add_rower_session(rower,ps) for team in teams: add_team_session(team,ps) startdatestring = shiftstartdate.strftime('%Y-%m-%d') enddatestring = lastdate.strftime('%Y-%m-%d') url = reverse(plannedsessions_view, kwargs = { 'userid':r.user.id, }) url+='?when='+startdatestring+'/'+enddatestring return HttpResponseRedirect(url) sps = PlannedSession.objects.filter( manager=request.user, rower__in=[r], startdate__lte=enddate, enddate__gte=startdate).order_by( "startdate","preferreddate","enddate").exclude( sessiontype='race') query = request.GET.get('q') if query: query_list = query.split() sps = sps.filter( reduce(operator.and_, (Q(name__icontains=q) for q in query_list)) | reduce(operator.and_, (Q(comment__icontains=q) for q in query_list)) ) form = PlannedSessionMultipleCloneForm() form.fields["plannedsessions"].queryset = sps dateshiftform = SessionDateShiftForm() try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, { 'url': reverse(plannedsession_multiclone_view), 'name': 'Clone Multiple Sessions' } ] dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) return render(request, 'plannedsessions_multiclone_select.html', {'plannedsessions':sps, 'breadcrumbs':breadcrumbs, 'plan':trainingplan, 'dateform':dateform, 'startdate':startdate, 'enddate':enddate, 'form':form, 'dateshiftform':dateshiftform, 'rower':r, 'active':'nav-plan', 'timeperiod':timeperiod, } ) # Individual user creates training for himself @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_create_view(request, userid=0, startdatestring='', enddatestring=''): r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request,startdatestring=startdatestring, enddatestring=enddatestring) if request.method == 'POST': sessioncreateform = PlannedSessionForm(request.POST) if sessioncreateform.is_valid(): cd = sessioncreateform.cleaned_data startdate = cd['startdate'] enddate = cd['enddate'] preferreddate = cd['preferreddate'] sessiontype = cd['sessiontype'] sessionmode = cd['sessionmode'] criterium = cd['criterium'] sessionvalue = cd['sessionvalue'] sessionunit = cd['sessionunit'] comment = cd['comment'] course = cd['course'] name = cd['name'] if sessionunit == 'min': sessionmode = 'time' elif sessionunit in ['km','m']: sessionmode = 'distance' ps = PlannedSession( name=name, startdate=startdate, enddate=enddate, preferreddate=preferreddate, course=course, sessiontype=sessiontype, sessionmode=sessionmode, sessionvalue=sessionvalue, sessionunit=sessionunit, comment=comment, criterium=criterium, manager=request.user) ps.save() add_rower_session(r,ps) request.session['fstartdate'] = str(arrow.get(startdate)) request.session['fenddate'] = str(arrow.get(enddate)) request.session['fprefdate'] = str(arrow.get(preferreddate)) else: if 'fstartdate' in request.session: try: fstartdate = arrow.get(request.session['fstartdate']).date() except KeyError: fstartdate = timezone.now().date() if fstartdate < startdate: fstartdate = startdate try: fenddate = arrow.get(request.session['fenddate']).date() except KeyError: fenddate = timezone.now().date() if fenddate > enddate: fenddate = enddate try: fprefdate = arrow.get(request.session['fprefdate']).date() except KeyError: fprefdate = timezone.now().date() if fprefdate < startdate: fprefdate = startdate if fprefdate > enddate: fprefdate = enddate forminitial = { 'startdate':fstartdate, 'enddate':fenddate, 'preferreddate':fprefdate } else: preferreddate = startdate if preferreddate < timezone.now().date(): preferreddate = timezone.now().date() if preferreddate > enddate: preferreddate = enddate forminitial = { 'startdate':startdate, 'enddate':enddate, 'preferreddate':preferreddate, } sessioncreateform = PlannedSessionForm(initial=forminitial) if request.GET.get('startdate') or request.GET.get('when'): startdate, enddate = get_dates_timeperiod(request) sps = get_sessions(r,startdate=startdate,enddate=enddate).exclude( sessiontype='race') try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) return render(request,'plannedsessioncreate.html', { 'teams':get_my_teams(request.user), 'plan':trainingplan, 'dateform':dateform, 'form':sessioncreateform, 'active':'nav-plan', 'plannedsessions':sps, 'rower':r, 'timeperiod':timeperiod, }) @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_multicreate_view(request, teamid=0,userid=0,extrasessions=0): extrasessions=int(extrasessions) r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None m = Rower.objects.get(user=request.user) qset = PlannedSession.objects.filter( rower__in=[r], manager = request.user, startdate__lte=enddate, enddate__gte=startdate, ).order_by("startdate","preferreddate","enddate").exclude( sessiontype='race') initial = { 'startdate':startdate, 'enddate':enddate, 'sessionvalue':60, 'manager':request.user, 'name': 'NEW SESSION' } initials = [initial for i in range(extrasessions)] PlannedSessionFormSet = modelformset_factory( PlannedSession, form=PlannedSessionFormSmall, can_delete=True, extra=extrasessions, ) if request.method == "POST": ps_formset = PlannedSessionFormSet(queryset = qset, data = request.POST) if ps_formset.is_valid(): instances = ps_formset.save(commit=False) for ps in instances: ps.save() add_rower_session(r,ps) messages.info(request,"Saved changes for Planned Session "+str(ps)) for obj in ps_formset.deleted_objects: messages.info(request,"Deleted Planned Session "+str(obj)) obj.delete() url = reverse(plannedsession_multicreate_view, kwargs = { 'userid':r.user.id, } ) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') url += '?when='+startdatestring+'/'+enddatestring return HttpResponseRedirect(url) ps_formset = PlannedSessionFormSet(queryset = qset, initial=initials) timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, { 'url': reverse(plannedsession_multicreate_view), 'name': 'Plan MicroCycle' } ] dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate }) context = { 'ps_formset':ps_formset, 'breadcrumbs':breadcrumbs, 'rower':r, 'active':'nav-plan', 'dateform':dateform, 'plan':trainingplan, 'timeperiod':timeperiod, 'teams':get_my_teams(request.user), 'extrasessions': extrasessions+1 } return render(request,'plannedsession_multicreate.html',context) # Manager creates sessions for entire team @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_teamcreate_view(request, teamid=0,userid=0): therower = getrequestplanrower(request,userid=userid) teams = Team.objects.filter(manager=request.user) if len(teams)>0: teamchoices = [(team.id, team.name) for team in teams] teaminitial = [str(teams[0].id)] else: messages.info(request,"You have no teams established yet. We are redirecting you to the Team Management page.") url = reverse('rower_teams_view') return HttpResponseRedirect(url) startdate,enddate = get_dates_timeperiod(request) trainingplan = None sps = [] for team in teams: res = get_sessions_manager(request.user,startdate=startdate,enddate=enddate) sps += res sps = list(set(sps)) ids = [ps.id for ps in sps] sps = PlannedSession.objects.filter(id__in=ids).order_by( "preferreddate","startdate","enddate") if request.method == 'POST': sessioncreateform = PlannedSessionForm(request.POST) sessionteamselectform = PlannedSessionTeamForm( request.user,request.POST ) if sessioncreateform.is_valid() and sessionteamselectform.is_valid(): cd = sessioncreateform.cleaned_data startdate = cd['startdate'] enddate = cd['enddate'] preferreddate = cd['preferreddate'] sessiontype = cd['sessiontype'] sessionmode = cd['sessionmode'] criterium = cd['criterium'] sessionvalue = cd['sessionvalue'] sessionunit = cd['sessionunit'] comment = cd['comment'] course = cd['course'] name = cd['name'] if sessionunit == 'min': sessionmode = 'time' elif sessionunit in ['km','m']: sessionmode = 'distance' ps = PlannedSession( name=name, startdate=startdate, enddate=enddate, preferreddate=preferreddate, sessiontype=sessiontype, sessionmode=sessionmode, sessionvalue=sessionvalue, sessionunit=sessionunit, comment=comment, criterium=criterium, course=course, manager=request.user) ps.save() cd = sessionteamselectform.cleaned_data teams = cd['team'] request.session['teams'] = [team.id for team in teams] for team in teams: add_team_session(team,ps) rs = Rower.objects.filter(team__in=[team]) for r in rs: add_rower_session(r,ps) url = reverse(plannedsession_teamcreate_view) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') url += '?when='+startdatestring+'/'+enddatestring return HttpResponseRedirect(url) else: timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, { 'url': reverse(plannedsession_teamcreate_view), 'name': 'Add Team Session' } ] return render(request,'plannedsessionteamcreate.html', { 'teams':get_my_teams(request.user), 'plan':trainingplan, 'breadcrumbs':breadcrumbs, 'form':sessioncreateform, 'teamform':sessionteamselectform, 'timeperiod':timeperiod, 'plannedsessions':sps, 'rower':therower, 'active':'nav-plan' }) else: initial = { 'startdate':startdate, 'enddate':enddate, 'preferreddate':startdate, } if 'teams' in request.session: teams = request.session['teams'] theteams = Team.objects.filter(id__in=teams) initialteam = { 'team':theteams } else: initialteam = {} sessioncreateform = PlannedSessionForm(initial=initial) sessionteamselectform = PlannedSessionTeamForm( request.user,initial=initialteam ) timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, { 'url': reverse(plannedsession_teamcreate_view), 'name': 'Add Team Session' } ] dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) return render(request,'plannedsessionteamcreate.html', { 'teams':get_my_teams(request.user), 'plan':trainingplan, 'dateform':dateform, 'breadcrumbs':breadcrumbs, 'form':sessioncreateform, 'teamform':sessionteamselectform, 'timeperiod':timeperiod, 'plannedsessions':sps, 'rower':therower, 'active':'nav-plan' }) # Manager edits sessions for entire team @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_teamedit_view(request, sessionid=0,userid=0): r = getrequestplanrower(request,userid=userid) try: ps = PlannedSession.objects.get(id=sessionid) except PlannedSession.DoesNotExist: raise Http404("This session doesn't exist") if not ps.manager == request.user: raise PermissionDenied("You are not the manager of this session") teams = Team.objects.filter(manager=request.user) teamchoices = [(team.id, team.name) for team in teams] teaminitial = ps.team.all() startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None sps = [] rowers = [] for team in teams: res = get_sessions_manager(request.user,startdate=startdate,enddate=enddate) sps += res rowers += Rower.objects.filter(team__in=[team]) rowers = list(set(rowers)) sps = list(set(sps)) ids = [pps.id for pps in sps] sps = PlannedSession.objects.filter(id__in=ids).order_by( "preferreddate","startdate","enddate") if request.method == 'POST': sessioncreateform = PlannedSessionForm(request.POST,instance=ps) sessionteamselectform = PlannedSessionTeamForm( request.user,request.POST ) sessionrowerform = PlannedSessionTeamMemberForm(ps,request.POST) if sessioncreateform.is_valid(): cd = sessioncreateform.cleaned_data if cd['sessionunit'] == 'min': cd['sessionmode'] = 'time' elif cd['sessionunit'] in ['km','m']: cd['sessionmode'] = 'distance' res,message = update_plannedsession(ps,cd) if res: messages.info(request,message) else: messages.error(request,message) # some logic when to add all selected rowers if sessionteamselectform.is_valid(): cd = sessionteamselectform.cleaned_data selectedteams = cd['team'] for team in teams: if team in selectedteams: add_team_session(team,ps) rs = Rower.objects.filter(team__in=[team]) for r in rs: add_rower_session(r,ps) else: remove_team_session(team,ps) else: selectedteams = [] for team in teams: remove_team_session(team,ps) if sessionrowerform.is_valid(): cd = sessionrowerform.cleaned_data selectedrowers = cd['members'] for r in rowers: if r in selectedrowers: add_rower_session(r,ps) else: remove_rower_session(r,ps) for t in selectedteams: if t in r.team.all(): add_rower_session(r,ps) url = reverse(plannedsession_teamedit_view, kwargs = { 'sessionid':sessionid, }) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') url += '?when='+startdatestring+'/'+enddatestring return HttpResponseRedirect(url) else: sessioncreateform = PlannedSessionForm(instance=ps) sessionteamselectform = PlannedSessionTeamForm( request.user ) sessionteamselectform.fields['team'].initial = teaminitial sessionrowerform = PlannedSessionTeamMemberForm( ps ) sessionrowerform.fields['members'].initial = ps.rower.all() timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, { 'url': reverse(plannedsession_teamcreate_view), 'name': 'Add Team Session' } ] dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) return render(request,'plannedsessionteamedit.html', { 'plannedsession':ps, 'plan':trainingplan, 'dateform':dateform, 'breadcrumbs':breadcrumbs, 'rower':r, 'active':'nav-plan', 'teams':get_my_teams(request.user), 'form':sessioncreateform, 'teamform':sessionteamselectform, 'rowersform':sessionrowerform, 'timeperiod':timeperiod, 'plannedsessions':sps, }) #@user_passes_test(iscoachmember,login_url="/rowers/paidplans/", # redirect_field_name=None) @login_required() def plannedsessions_coach_view(request, teamid=0,userid=0): therower = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) trainingplan = None if teamid != 0: try: theteam = Team.objects.get(id=teamid) except Team.DoesNotExist: theteam = False else: theteam = False if request.user.rower.rowerplan == 'coach': sps = get_sessions_manager(request.user,teamid=teamid, enddate=enddate, startdate=startdate) else: rteams = therower.team.filter(viewing='allmembers') sps = get_sessions(therower,startdate=startdate,enddate=enddate) rowers = [therower] for ps in sps: if request.user.rower.rowerplan == 'coach': rowers += ps.rower.all() else: rowers += ps.rower.filter(team__in=rteams) rowers = list(set(rowers)) statusdict = [] for ps in sps: rowerstatus = {} rowercolor = {} for r in rowers: ratio, status,completiondate = is_session_complete(r,ps) rowerstatus[r.id] = status rowercolor[r.id] = cratiocolors[status] sessiondict = { 'id': ps.id, 'results':rowerstatus, 'name': ps.name, 'startdate': ps.startdate, 'color': rowercolor, 'preferreddate': ps.preferreddate, 'enddate': ps.enddate, } statusdict.append(sessiondict) unmatchedworkouts = [] for r in rowers: unmatchedworkouts += Workout.objects.filter( user=r, plannedsession=None, date__gte=startdate,date__lte=enddate) myteams = Team.objects.filter(manager=request.user) timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, { 'url': reverse(plannedsessions_coach_view), 'name': 'Coach View' } ] dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) return render(request,'plannedsessionscoach.html', { 'myteams':myteams, 'plannedsessions':sps, 'breadcrumbs':breadcrumbs, 'plan':trainingplan, 'statusdict':statusdict, 'dateform':dateform, 'timeperiod':timeperiod, 'rowers':rowers, 'rower':therower, 'active':'nav-plan', 'theteam':theteam, 'unmatchedworkouts':unmatchedworkouts, 'rower':getrower(request.user) } ) from rowers.plannedsessions import cratiocolors @login_required() def plannedsessions_view(request, userid=0,startdatestring='',enddatestring=''): r = getrequestplanrower(request,userid=userid) if startdatestring: try: startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring: try: enddate = iso8601.parse_date(enddatestring) except ParseError: pass startdate,enddate = get_dates_timeperiod( request, startdatestring=startdatestring, enddatestring=enddatestring) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None sps = get_sessions(r,startdate=startdate,enddate=enddate) completeness = {} actualvalue = {} completiondate = {} sessioncolor = {} totals = { 'trimp':0, 'rscore':0, 'distance':0, 'time':0, 'plannedtime':0, 'planneddistance':0, 'plannedtrimp':0, 'plannedrscore':0, 'actualtime':0, 'actualdistance':0, 'actualtrimp':0, 'actualrscore':0, } ws = Workout.objects.filter( user=r, date__gte=startdate,date__lte=enddate) for w in ws: thetrimp,hrtss = dataprep.workout_trimp(w) totals['trimp'] += thetrimp tss = dataprep.workout_rscore(w)[0] if not np.isnan(tss) and tss != 0: totals['rscore'] += tss elif tss == 0: totals['rscore'] += hrtss tss = hrtss totals['distance'] += w.distance totals['time'] += timefield_to_seconds_duration(w.duration) if w.plannedsession: if w.plannedsession.sessionmode == 'distance': totals['actualdistance'] += w.distance elif w.plannedsession.sessionmode == 'time': totals['actualtime'] += timefield_to_seconds_duration(w.duration) elif w.plannedsession.sessionmode == 'rScore': totals['actualrscore'] += tss elif w.plannedsession.sessionmode == 'TRIMP': totals['actualtrimp'] += thetrimp if not sps and request.user.rower.rowerplan == 'basic': messages.error(request, "You must purchase Coach or Self-coach plans or be part of a team to get planned sessions") for ps in sps: ratio,status,cdate = is_session_complete(r,ps) actualvalue[ps.id] = int(ps.sessionvalue*ratio) completeness[ps.id] = status sessioncolor[ps.id] = cratiocolors[status] ws = Workout.objects.filter(user=r,plannedsession=ps) completiondate[ps.id] = cdate if ps.sessionmode == 'distance': totals['planneddistance'] += ps.sessionvalue elif ps.sessionmode == 'time': totals['plannedtime'] += ps.sessionvalue elif ps.sessionmode == 'rScore': totals['plannedrscore'] += ps.sessionvalue elif ps.sessionmode == 'TRIMP': totals['plannedtrimp'] += ps.sessionvalue totals['time'] = int(totals['time']/60.) totals['actualtime'] = int(totals['actualtime']/60.) totals['plannedtime'] = int(totals['plannedtime']) unmatchedworkouts = Workout.objects.filter( user=r, plannedsession=None, date__gte=startdate,date__lte=enddate) timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url': reverse(plannedsessions_view), 'name': 'Planned Sessions' }, ] initial = { 'startdate':startdate, 'enddate':enddate, } dateform = DateRangeForm(initial=initial) return render(request,'plannedsessions.html', { 'teams':get_my_teams(request.user), 'breadcrumbs':breadcrumbs, 'plannedsessions':sps, 'plan':trainingplan, 'active': 'nav-plan', 'dateform':dateform, 'totals':totals, 'rower':r, 'timeperiod':timeperiod, 'completeness':completeness, 'sessioncolor':sessioncolor, 'actualvalue':actualvalue, 'completiondate':completiondate, 'unmatchedworkouts':unmatchedworkouts, }) @login_required() def plannedsessions_print_view(request,userid=0): r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None sps = get_sessions(r,startdate=startdate,enddate=enddate) completeness = {} actualvalue = {} completiondate = {} timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') return render(request,'plannedsessions_print.html', { 'teams':get_my_teams(request.user), 'plan':trainingplan, 'plannedsessions':sps, 'rower':r, 'active':'nav-plan', 'startdate':startdate, 'enddate':enddate, 'timeperiod':timeperiod, }) @login_required() def plannedsessions_manage_view(request,userid=0, initialsession=0): is_ajax = False if request.is_ajax(): is_ajax = True r = getrequestrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None sps = get_sessions(r,startdate=startdate,enddate=enddate) if initialsession==0: try: initialsession=sps[0].id except IndexError: initialsession=0 if initialsession: try: ps0 = PlannedSession.objects.get(id=initialsession) except PlannedSession.DoesNotExist: ps0 = None else: ps0 = None ws = Workout.objects.filter( user=r,date__gte=startdate, date__lte=enddate ).order_by( "date","startdatetime","id" ) initialworkouts = [w.id for w in Workout.objects.filter(user=r,plannedsession=ps0)] linkedworkouts = [] for w in ws: if w.plannedsession is not None: linkedworkouts.append(w.id) plannedsessionstuple = [] for ps in sps: sessiontpl = (ps.id,ps.__str__()) plannedsessionstuple.append(sessiontpl) plannedsessionstuple = tuple(plannedsessionstuple) workoutdata = {} workoutdata['initial'] = [] choices = [] for w in ws: wtpl = (w.id, w.__str__()) choices.append(wtpl) if w.id in initialworkouts: workoutdata['initial'].append(w.id) workoutdata['choices'] = tuple(choices) if request.method == 'POST': ps_form = PlannedSessionSelectForm(plannedsessionstuple,request.POST) w_form = WorkoutSessionSelectForm(workoutdata,request.POST) if ps_form.is_valid(): ps = PlannedSession.objects.get(id=ps_form.cleaned_data['plannedsession']) if w_form.is_valid(): selectedworkouts = w_form.cleaned_data['workouts'] else: selectedworkouts = [] if len(selectedworkouts)==0: for w in ws: remove_workout_plannedsession(w,ps) if selectedworkouts: workouts = Workout.objects.filter(user=r,id__in=selectedworkouts) for w in ws: if w.id not in selectedworkouts: remove_workout_plannedsession(w,ps) result,comments,errors = add_workouts_plannedsession(workouts,ps,r) for c in comments: messages.info(request,c) for er in errors: messages.error(request,er) ps_form = PlannedSessionSelectForm(plannedsessionstuple, initialsession=initialsession) w_form = WorkoutSessionSelectForm(workoutdata=workoutdata) if is_ajax: ajax_workouts = [] for id,name in workoutdata['choices']: ininitial = id in initialworkouts inlinked = id in linkedworkouts ajax_workouts.append((id,name,ininitial,inlinked)) ajax_response = { 'workouts':ajax_workouts, 'plannedsessionstuple':plannedsessionstuple, } return JSONResponse(ajax_response) breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(plannedsessions_manage_view, kwargs={ 'userid':userid, 'initialsession':initialsession, } ), 'name': 'Link Sessions to Workouts' }, ] timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) return render(request,'plannedsessionsmanage.html', { 'teams':get_my_teams(request.user), 'plan':trainingplan, 'dateform':dateform, 'plannedsessions':sps, 'workouts':ws, 'active':'nav-plan', 'breadcrumbs':breadcrumbs, 'timeperiod':timeperiod, 'rower':r, 'ps_form':ps_form, 'w_form':w_form, }) # Clone an existing planned session # need clarity on cloning behavior time shift @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_clone_view(request,id=0,userid=0): r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None try: ps = PlannedSession.objects.get(id=id) except PlannedSession.DoesNotExist: raise Http404("Planned Session does not exist") if ps.manager != request.user: raise PermissionDenied("You are not allowed to clone this planned session") rowers = ps.rower.all() teams = ps.team.all() ps.pk = None deltadays = ps.enddate-ps.startdate ps.startdate = timezone.now().date() ps.enddate = (timezone.now()+deltadays).date() ps.preferreddate = ps.preferreddate+deltadays ps.name += ' (copy)' ps.save() for rower in rowers: add_rower_session(rower,ps) for team in teams: add_team_session(team,ps) url = reverse(plannedsession_edit_view, kwargs = { 'id':ps.id, 'userid':r.user.id, } ) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') url += '?when='+startdatestring+'/'+enddatestring return HttpResponseRedirect(url) # Edit an existing planned session @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def plannedsession_edit_view(request,id=0,userid=0): r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None try: ps = PlannedSession.objects.get(id=id) except PlannedSession.DoesNotExist: raise Http404("Planned Session does not exist") if ps.manager != request.user: raise PermissionDenied("You are not allowed to edit this planned session") if ps.sessiontype in ['race','indoorrace']: raise PermissionDenied("You are not allowed to edit this planned session because it is a race") if ps.team.all() or len(ps.rower.all())>1: url = reverse(plannedsession_teamedit_view, kwargs={ 'sessionid':id, }) return HttpResponseRedirect(url) if request.method == 'POST': sessioncreateform = PlannedSessionForm(request.POST,instance=ps) if sessioncreateform.is_valid(): cd = sessioncreateform.cleaned_data if cd['sessionunit'] == 'min': cd['sessionmode'] = 'time' elif cd['sessionunit'] in ['km','m']: cd['sessionmode'] = 'distance' res,message = update_plannedsession(ps,cd) if res: messages.info(request,message) else: messages.error(request,message) url = reverse(plannedsession_edit_view, kwargs={ 'id':int(ps.id), 'userid':r.user.id, }) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') url += '?when='+startdatestring+'/'+enddatestring return HttpResponseRedirect(url) else: sessioncreateform = PlannedSessionForm(instance=ps) sps = get_sessions(r,startdate=startdate,enddate=enddate) breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url': reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Sessions' }, { 'url':reverse(plannedsession_view, kwargs={ 'userid':userid, 'id':id, } ), 'name': ps.id }, { 'url':reverse(plannedsession_edit_view, kwargs={ 'userid':userid, 'id':id, } ), 'name': 'Edit' } ] dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') return render(request,'plannedsessionedit.html', { 'teams':get_my_teams(request.user), 'plan':trainingplan, 'breadcrumbs':breadcrumbs, 'form':sessioncreateform, 'active':'nav-plan', 'plannedsessions':sps, 'thesession':ps, 'dateform':dateform, 'rower':r, 'timeperiod':timeperiod, }) @login_required() def plannedsession_detach_view(request,id=0,psid=0): r = getrequestrower(request) try: ps = PlannedSession.objects.get(id=psid) except PlannedSession.DoesNotExist: raise Http404("Planned Session does not exist") w = get_workout(id) if (checkworkoutuser(request.user,w)==False): return HttpResponseForbidden("Permission Error") remove_workout_plannedsession(w,ps) url = reverse(plannedsession_view,kwargs={'id':psid}) return HttpResponseRedirect(url) @login_required() def plannedsession_view(request,id=0,userid=0): r = getrequestplanrower(request,userid=userid) try: ps = PlannedSession.objects.get(id=id) except PlannedSession.DoesNotExist: raise Http404("Planned Session does not exist") if ps.sessiontype in ['race','indoorrace']: url = reverse('virtualevent_view', kwargs={'id':ps.id} ) return HttpResponseRedirect(url) if ps.course: coursescript,coursediv = course_map(ps.course) else: coursescript = '' coursediv = '' m = ps.manager mm = Rower.objects.get(user=m) if ps.manager != request.user: if r.rowerplan == 'coach' and r not in ps.rower.all(): teams = Team.objects.filter(manager=request.user) members = Rower.objects.filter(team__in=teams).distinct() teamusers = [m.user for m in members] if ps.manager not in teamusers: raise PermissionDenied("You do not have access to this session") elif r not in ps.rower.all(): raise PermissionDenied("You do not have access to this session") resultsdict = get_session_metrics(ps) resultsdict = pd.DataFrame(resultsdict).transpose().to_dict() psdict = my_dict_from_instance(ps,PlannedSession) ws = get_workouts_session(r,ps) ratio,status,completiondate = is_session_complete(r,ps) ratio = int(100.*ratio) # ranking for test ranking = [] if ps.sessiontype in ['test','coursetest']: if ps.sessionmode == 'distance': rankws = Workout.objects.filter( plannedsession=ps).order_by("duration") else: rankws = Workout.objects.filter( plannedsession=ps).order_by("-distance") for w in rankws: dd = w.duration dddelta = datetime.timedelta(hours=dd.hour, minutes=dd.minute, seconds=dd.second, microseconds=dd.microsecond) wdict = { 'name': w.user.user.first_name+' '+w.user.user.last_name, 'date': w.date, 'distance': w.distance, 'time': dddelta, 'type': w.workouttype, 'coursecompleted':True, } if ps.sessiontype == 'coursetest': vs = CourseTestResult.objects.filter(plannedsession=ps, workoutid=w.id) if vs: for record in vs: if record.workoutid == w.id: coursemeters = record.distance coursecompleted = record.coursecompleted t = record.duration wdict['time'] = datetime.timedelta( hours=t.hour, seconds=t.second, minutes=t.minute, microseconds=t.microsecond ) wdict['distance'] = int(round(coursemeters)) wdict['coursecompleted'] = coursecompleted else: record = CourseTestResult( userid=w.user.id, workoutid=w.id, plannedsession=ps, duration=w.duration, coursecompleted=False, ) record.save() job = myqueue(queue,handle_check_race_course, w.csvfilename,w.id,ps.course.id, record.id,mode='coursetest') intsecs = 0 microsecs = 0 # taking workout duration plus 1 minute penalty wdict['time'] = w.duration wdict['distance'] = ps.course.distance wdict['coursecompleted'] = False ranking.append(wdict) if ps.sessiontype == 'coursetest': ranking = sorted(ranking, key=lambda k: k['time']) # if coursetest, need to reorder the ranking startdate,enddate = get_dates_timeperiod(request) try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url': reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Sessions' }, { 'url':reverse(plannedsession_view, kwargs={ 'userid':userid, 'id':id, } ), 'name': ps.id } ] comments = PlannedSessionComment.objects.filter(plannedsession=ps).order_by("created") return render(request,'plannedsessionview.html', { 'psdict': psdict, 'attrs':[ 'name','startdate','enddate','preferreddate', 'sessiontype', 'sessionmode','criterium', 'sessionvalue','sessionunit','comment', ], 'workouts': ws, 'active':'nav-plan', 'breadcrumbs':breadcrumbs, 'manager':mm, 'rower':r, 'ratio':ratio, 'plan':trainingplan, 'status':status, 'results':resultsdict, 'plannedsession':ps, 'timeperiod':timeperiod, 'ranking':ranking, 'coursescript': coursescript, 'coursediv': coursediv, 'comments': comments, } ) class PlannedSessionDelete(DeleteView): model = PlannedSession template_name = 'plannedsessiondeleteconfirm.html' # extra parameters def get_context_data(self, **kwargs): context = super(PlannedSessionDelete,self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid = 0 context['active']= 'nav-plan' context['rower'] = getrequestrower(self.request,userid=userid) context['ps'] = self.object psdict = my_dict_from_instance(self.object,PlannedSession) context['psdict'] = psdict context['attrs'] = ['name','startdate','enddate','sessiontype'] breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url': reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Sessions' }, { 'url':reverse(plannedsession_view, kwargs={ 'userid':userid, 'id':self.object.pk, } ), 'name': self.object.pk }, { 'url':reverse('plannedsession_delete_view', kwargs={'pk':self.object.pk}), 'name': 'Delete' } ] context['breadcrumbs'] = breadcrumbs return context def get_success_url(self): ws = Workout.objects.filter(plannedsession=self.object) for w in ws: w.plannedsession = None w.save() url = reverse(plannedsessions_view) return url def get_object(self, *args, **kwargs): obj = super(PlannedSessionDelete, self).get_object(*args, **kwargs) m = Rower.objects.get(user=obj.manager) if not checkaccessuser(self.request.user,m): raise PermissionDenied('You are not allowed to delete this planned session') return obj @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def rower_create_trainingplan(request,userid=0): therower = getrequestrower(request,userid=userid) theuser = therower.user themanager = getrower(request.user) if request.method == 'POST' and 'date' in request.POST: targetform = TrainingTargetForm(request.POST,user=request.user) if targetform.is_valid(): name = targetform.cleaned_data['name'] date = targetform.cleaned_data['date'] notes = targetform.cleaned_data['notes'] t = TrainingTarget( name=name, date=date, manager=themanager, notes=notes) t.save() t.rowers.add(therower) t.save() elif request.method == 'POST' and 'startdate' in request.POST: form = TrainingPlanForm(request.POST,user=request.user) if form.is_valid(): name = form.cleaned_data['name'] try: target = form.cleaned_data['target'] except KeyError: try: targetid = request.POST['target'] if targetid != '': target = TrainingTarget.objects.get(id=int(targetid)) else: target = None except KeyError: target = None startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] try: athletes = form.cleaned_data['rowers'] except KeyError: athletes = [therower] p = TrainingPlan( name=name, target=target, manager=themanager, startdate=startdate, enddate=enddate, ) p.save() for athlete in athletes: p.rowers.add(athlete) targets = TrainingTarget.objects.filter( rowers=therower, date__gte=datetime.date.today(), ).order_by("date") targetform = TrainingTargetForm(user=request.user) plans = TrainingPlan.objects.filter(rowers=therower).order_by("-startdate") form = TrainingPlanForm(targets=targets, initial={'status':False,'rowers':[therower]}, user=request.user) breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_create_trainingplan, kwargs={'userid':userid}), 'name': 'Manage Plans and Targets' } ] return render(request,'trainingplan_create.html', { 'form':form, 'rower':therower, 'breadcrumbs':breadcrumbs, 'plans':plans, 'active':'nav-plan', 'targets':targets, 'targetform':targetform, }) @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def rower_delete_trainingtarget(request,id=0): try: target = TrainingTarget.objects.get(id=id) except TrainingPlan.DoesNotExist: raise Http404("Training Plan Does Not Exist") if checkaccessuser(request.user,target.manager): target.delete() messages.info(request,"We have deleted the training target") else: raise PermissionDenied("Access denied") url = reverse(rower_create_trainingplan) return HttpResponseRedirect(url) @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def rower_delete_trainingplan(request,id=0): try: plan = TrainingPlan.objects.get(id=id) except TrainingPlan.DoesNotExist: raise Http404("Training Plan Does Not Exist") if checkaccessuser(request.user,plan.manager): plan.delete() messages.info(request,"We have deleted the training plan") else: raise PermissionDenied("Access denied") url = reverse(rower_create_trainingplan) return HttpResponseRedirect(url) class TrainingPlanDelete(DeleteView): model = TrainingPlan template_name = 'trainingplan_delete.html' success_url = reverse_lazy(rower_create_trainingplan) def get_object(self, *args, **kwargs): obj = super(TrainingPlanDelete, self).get_object(*args, **kwargs) if not checkaccessuser(self.request.user,obj.manager): raise PermissionDenied('You are not allowed to delete this training plan') return obj class MicroCycleDelete(DeleteView): model = TrainingMicroCycle template_name = 'trainingplan_delete.html' # extra parameters def get_context_data(self, **kwargs): context = super(MicroCycleDelete, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.plan.plan.plan.id}), 'name': self.object.plan.plan.plan.name }, { 'url':reverse('macrocycle_update_view', kwargs={'pk':self.object.plan.plan.pk}), 'name': self.object.plan.plan.name }, { 'url':reverse('mesocycle_update_view', kwargs={'pk':self.object.plan.pk}), 'name': self.object.plan.name }, { 'url':reverse('microcycle_update_view', kwargs={'pk':self.object.pk}), 'name': self.object.name } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): plan = self.object.plan.plan.plan createmacrofillers(plan) thismesoid = self.object.plan.pk return reverse(rower_trainingplan_view, kwargs = { 'id':plan.id, 'thismesoid':thismesoid }) def get_object(self, *args, **kwargs): obj = super(MicroCycleDelete, self).get_object(*args, **kwargs) if not checkaccessuser(self.request.user,obj.plan.plan.plan.manager): raise PermissionDenied('You are not allowed to delete this training plan cycle') return obj class MesoCycleDelete(DeleteView): model = TrainingMesoCycle template_name = 'trainingplan_delete.html' # extra parameters def get_context_data(self, **kwargs): context = super(MesoCycleDelete, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.plan.plan.id}), 'name': self.object.plan.plan.name }, { 'url':reverse('macrocycle_update_view', kwargs={'pk':self.object.plan.pk}), 'name': self.object.plan.name }, { 'url':reverse('mesocycle_update_view', kwargs={'pk':self.object.pk}), 'name': self.object.name } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): plan = self.object.plan.plan thismacroid = self.object.plan.pk createmacrofillers(plan) return reverse(rower_trainingplan_view, kwargs = { 'id':plan.id, 'thismacroid':thismacroid, }) def get_object(self, *args, **kwargs): obj = super(MesoCycleDelete, self).get_object(*args, **kwargs) if not checkaccessuser(self.request.user,obj.plan.plan.manager): raise PermissionDenied('You are not allowed to delete this training plan cycle') return obj class MacroCycleDelete(DeleteView): model = TrainingMacroCycle template_name = 'trainingplan_delete.html' # extra parameters def get_context_data(self, **kwargs): context = super(MacroCycleDelete, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.plan.id}), 'name': self.object.plan.name }, { 'url':reverse('macrocycle_update_view', kwargs={'pk':self.object.pk}), 'name': self.object.name } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): plan = self.object.plan createmacrofillers(plan) return reverse(rower_trainingplan_view, kwargs = { 'id':plan.id }) def get_object(self, *args, **kwargs): obj = super(MacroCycleDelete, self).get_object(*args, **kwargs) if not checkaccessuser(self.request.user,obj.plan.manager): raise PermissionDenied('You are not allowed to delete this training plan cycle') return obj @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def rower_trainingplan_view(request, id=0, userid=0, thismicroid=0, thismacroid=0, thismesoid=0): startdate,enddate = get_dates_timeperiod(request) try: plan = TrainingPlan.objects.get(id=id) except TrainingPlan.DoesNotExist: raise Http404("Training Plan Does Not Exist") r = getrequestrower(request,userid=userid) if not checkaccessuser(request.user,plan.manager): if request.user.rower not in plan.rowers.all(): raise PermissionDenied("Access denied") createmacrofillers(plan) macrocycles = TrainingMacroCycle.objects.filter( plan=plan, type='userdefined').order_by("startdate") for m in macrocycles: createmesofillers(m) m.plantime = 0 m.actualtime = 0 m.plandistance = 0 m.actualdistance = 0 m.planrscore = 0 m.actualrscore = 0 m.plantrimp = 0 m.actualtrimp = 0 mesocycles = TrainingMesoCycle.objects.filter( plan=m, type='userdefined').order_by("startdate") for me in mesocycles: me.plantime = 0 me.actualtime = 0 me.plandistance = 0 me.actualdistance = 0 me.planrscore = 0 me.actualrscore = 0 me.plantrimp = 0 me.actualtrimp = 0 microcycles = TrainingMicroCycle.objects.filter( plan=me, type='userdefined').order_by("startdate") for mm in microcycles: sps = get_sessions(r,startdate=mm.startdate,enddate=mm.enddate) # sps = PlannedSession.objects.filter( # rower = r, # startdate__lte=mm.enddate, # enddate__gte=mm.startdate) mm.plantime = 0 mm.actualtime = 0 mm.plandistance = 0 mm.actualdistance = 0 mm.planrscore = 0 mm.actualrscore = 0 mm.plantrimp = 0 mm.actualtrimp = 0 if mm.type == 'userdefined': for ps in sps: ratio, status, cdate = is_session_complete(r,ps) if ps.sessionmode == 'time': mm.plantime += ps.sessionvalue mm.actualtime += int(ps.sessionvalue*ratio) elif ps.sessionmode == 'distance' and ps.sessiontype != 'race': mm.plandistance += ps.sessionvalue mm.actualdistance += int(ps.sessionvalue*ratio) elif ps.sessionmode == 'rScore': mm.planrscore += ps.sessionvalue mm.actualrscore += int(ps.sessionvalue*ratio) elif ps.sessionmode == 'TRIMP': mm.plantrimp += ps.sessionvalue mm.actualtrimp += int(ps.sessionvalue*ratio) mm.save() me.plantime += mm.plantime me.actualtime += mm.actualtime me.plandistance += mm.plandistance me.actualdistance += mm.actualdistance me.planrscore += mm.planrscore me.actualrscore += mm.actualrscore me.plantrimp += mm.plantrimp me.actualtrimp += mm.actualtrimp if me.type == 'userdefined': me.save() m.plantime += me.plantime m.actualtime += me.actualtime m.plandistance += me.plandistance m.actualdistance += me.actualdistance m.planrscore += me.planrscore m.actualrscore += me.actualrscore m.plantrimp += me.plantrimp m.actualtrimp += me.actualtrimp if m.type == 'userdefined': m.save() createmacrofillers(plan) macrocycles = TrainingMacroCycle.objects.filter(plan=plan).order_by("startdate") count = 0 cycles = {} for m in macrocycles: createmesofillers(m) mesocycles = TrainingMesoCycle.objects.filter(plan=m).order_by("startdate") mesos = {} count2 = 0 for me in mesocycles: createmicrofillers(me) microcycles = TrainingMicroCycle.objects.filter(plan=me).order_by("startdate") mesos[count2] = (me, microcycles) count2 += 1 cycles[count] = (m,mesos) count += 1 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':id}), 'name': plan.name } ] if not thismicroid and not thismacroid and not thismesoid: try: thismicro = get_todays_micro(plan,thedate=startdate) thismicroid = thismicro.pk except AttributeError: thismicroid = None return render(request,'trainingplan.html', { 'plan':plan, 'active':'nav-plan', 'breadcrumbs':breadcrumbs, 'rower':r, 'cycles':cycles, 'thismicroid':thismicroid, 'thismacroid':thismacroid, 'thismesoid':thismesoid, } ) class TrainingMacroCycleUpdate(UpdateView): model = TrainingMacroCycle template_name = 'trainingplan_edit.html' form_class = TrainingMacroCycleForm # extra parameters def get_context_data(self, **kwargs): context = super(TrainingMacroCycleUpdate, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.plan.id}), 'name': self.object.plan.name }, { 'url':reverse('macrocycle_update_view', kwargs={'pk':self.object.pk}), 'name': self.object.name } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): plan = self.object.plan createmacrofillers(plan) return reverse(rower_trainingplan_view, kwargs = { 'id':plan.id, 'thismacroid':self.object.id, } ) def form_valid(self, form): form.instance.user = self.request.user form.instance.post_date = datetime.datetime.now() macrocycle = form.save() mesocyclecheckdates(macrocycle) return super(TrainingMacroCycleUpdate, self).form_valid(form) def get_object(self, *args, **kwargs): obj = super(TrainingMacroCycleUpdate, self).get_object(*args, **kwargs) if obj.plan.manager is not None and self.request.user.rower != obj.plan.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') if not checkaccessuser(self.request.user,obj.plan.manager): raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' obj.save() return obj class TrainingMesoCycleUpdate(UpdateView): model = TrainingMesoCycle template_name = 'trainingplan_edit.html' form_class = TrainingMesoCycleForm # extra parameters def get_context_data(self, **kwargs): context = super(TrainingMesoCycleUpdate, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.plan.plan.id}), 'name': self.object.plan.plan.name }, { 'url':reverse('macrocycle_update_view', kwargs={'pk':self.object.plan.pk}), 'name': self.object.plan.name }, { 'url':reverse('mesocycle_update_view', kwargs={'pk':self.object.pk}), 'name': self.object.name } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): plan = self.object.plan createmesofillers(plan) return reverse(rower_trainingplan_view, kwargs = { 'id':plan.plan.id, 'thismesoid':self.object.id, } ) def form_valid(self, form): form.instance.user = self.request.user form.instance.post_date = datetime.datetime.now() mesocycle = form.save() microcyclecheckdates(mesocycle) return super(TrainingMesoCycleUpdate, self).form_valid(form) def get_object(self, *args, **kwargs): obj = super(TrainingMesoCycleUpdate, self).get_object(*args, **kwargs) if obj.plan.plan.manager is not None and self.request.user.rower != obj.plan.plan.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' obj.save() obj.plan.type = 'userdefined' obj.plan.save() return obj class TrainingMicroCycleUpdate(UpdateView): model = TrainingMicroCycle template_name = 'trainingplan_edit.html' form_class = TrainingMicroCycleForm # extra parameters def get_context_data(self, **kwargs): context = super(TrainingMicroCycleUpdate, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.plan.plan.plan.id}), 'name': self.object.plan.plan.plan.name }, { 'url':reverse('macrocycle_update_view', kwargs={'pk':self.object.plan.plan.pk}), 'name': self.object.plan.plan.name }, { 'url':reverse('mesocycle_update_view', kwargs={'pk':self.object.plan.pk}), 'name': self.object.plan.name }, { 'url':reverse('microcycle_update_view', kwargs={'pk':self.object.pk}), 'name': self.object.name } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): plan = self.object.plan createmicrofillers(plan) return reverse(rower_trainingplan_view, kwargs = { 'id':plan.plan.plan.id, 'thismicroid':self.object.pk } ) def form_valid(self, form): form.instance.user = self.request.user form.instance.post_date = datetime.datetime.now() microcycle = form.save() return super(TrainingMicroCycleUpdate, self).form_valid(form) def get_object(self, *args, **kwargs): obj = super(TrainingMicroCycleUpdate, self).get_object(*args, **kwargs) if obj.plan.plan.plan.manager is not None and self.request.user.rower != obj.plan.plan.plan.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' obj.save() obj.plan.type = 'userdefined' obj.plan.save() return obj class TrainingPlanUpdate(UpdateView): model = TrainingPlan template_name = 'trainingplan_edit.html' form_class = TrainingPlanForm # extra parameters def get_context_data(self, **kwargs): context = super(TrainingPlanUpdate, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse(rower_trainingplan_view, kwargs={'userid':userid, 'id':self.object.id}), 'name': self.object.name }, { 'url':reverse('trainingplan_update_view', kwargs={'pk':self.object.pk}), 'name': 'Edit' } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): return reverse(rower_create_trainingplan) def form_valid(self, form): form.instance.user = self.request.user form.instance.post_date = datetime.datetime.now() plan = form.save() plan.manager = self.request.user.rower plan.save() macrocyclecheckdates(plan) return super(TrainingPlanUpdate, self).form_valid(form) def get_object(self, *args, **kwargs): obj = super(TrainingPlanUpdate, self).get_object(*args, **kwargs) if obj.manager is not None and self.request.user.rower != obj.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') if obj.manager.rowerplan not in ['coach','plan']: raise PermissionDenied('You are not allowed to edit this training plan') return obj class TrainingTargetUpdate(UpdateView): model = TrainingTarget template_name = 'trainingplan_edit.html' form_class = TrainingTargetForm # extra parameters def get_context_data(self, **kwargs): context = super(TrainingTargetUpdate, self).get_context_data(**kwargs) if 'userid' in kwargs: userid = kwargs['userid'] else: userid=0 breadcrumbs = [ { 'url':reverse(plannedsessions_view, kwargs={'userid':userid}), 'name': 'Plan' }, { 'url':reverse('trainingtarget_update_view', kwargs={'pk':self.object.pk}), 'name': 'Edit' } ] context['active'] = 'nav-plan' context['breadcrumbs'] = breadcrumbs context['rower'] = getrequestrower(self.request,userid=userid) return context def get_success_url(self): return reverse(rower_create_trainingplan) def form_valid(self, form): form.instance.user = self.request.user form.instance.post_date = datetime.datetime.now() target = form.save() return super(TrainingTargetUpdate, self).form_valid(form) def get_object(self, *args, **kwargs): obj = super(TrainingTargetUpdate, self).get_object(*args, **kwargs) if obj.manager is not None and self.request.user.rower != obj.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') return obj from rowers.utils import allsundays @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def planmesocyclebyweek(request,id=0,userid=0): try: cycle = TrainingMesoCycle.objects.get(id=id) except TrainingMesoCycle.DoesNotExist: raise Http404("Training Cycle does not exist") if not checkaccessuser(request.user,cycle.plan.plan.manager): raise PermissionDenied("You are not allowed to do this") micros = TrainingMicroCycle.objects.filter(plan=cycle) for m in micros: m.delete() cycle.type = 'userdefined' cycle.save() #we're still here. We have permission sundays = [s for s in allsundays(cycle.startdate,cycle.enddate)] if sundays and sundays[-1] < cycle.enddate: sundays = sundays+[cycle.enddate] elif not sundays: sundays = [cycle.enddate] for i in range(len(sundays)): if i==0: monday = cycle.startdate else: monday = sundays[i]-timedelta(days=6) if monday < cycle.startdate: monday = cycle.startdate nextsunday = sundays[i] micro = TrainingMicroCycle(startdate = monday, enddate = nextsunday, plan = cycle, name = 'Week %s' % monday.isocalendar()[1], type = 'userdefined') micro.save() micros = TrainingMicroCycle.objects.filter(plan=cycle) url = reverse(rower_trainingplan_view, kwargs = {'userid':str(userid), 'id':str(cycle.plan.plan.id), 'thismicroid':str(micros[0].id)}) return HttpResponseRedirect(url) from rowers.utils import allmonths @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def planmacrocyclebymonth(request,id=0,userid=0): try: cycle = TrainingMacroCycle.objects.get(id=id) except TrainingMacroCycle.DoesNotExist: raise Http404("Training Cycle does not exist") if not checkaccessuser(request.user,cycle.plan.manager): raise PermissionDenied("You are not allowed to do this") mesos = TrainingMesoCycle.objects.filter(plan=cycle) for m in mesos: m.delete() cycle.type = 'userdefined' cycle.save() #we're still here. We have permission monthstarts = [d for d in allmonths(cycle.startdate,cycle.enddate)] monthstarts.append(cycle.enddate) for i in range(len(monthstarts)-1): firstday = monthstarts[i] lastday = monthstarts[i+1]-timedelta(days=1) if lastday < cycle.enddate and i == len(monthstarts)-2: lastday = cycle.enddate meso = TrainingMesoCycle(startdate = firstday, enddate = lastday, plan = cycle, name = '%s' % firstday.strftime("%B"), type = 'userdefined') meso.save() mesos = TrainingMesoCycle.objects.filter(plan=cycle) url = reverse(rower_trainingplan_view, kwargs = {'userid':str(userid), 'id':str(cycle.plan.id), 'thismesoid':str(mesos[0].id)}) return HttpResponseRedirect(url)