4189 lines
139 KiB
Python
4189 lines
139 KiB
Python
from rowers.plannedsessions import cratiocolors, checkscores
|
|
from rowers.utils import allmonths
|
|
from rowers.utils import allsundays
|
|
|
|
from rowers.views.statements import *
|
|
|
|
import rowers.garmin_stuff as gs
|
|
from rowers import credits
|
|
from json.decoder import JSONDecodeError
|
|
from rowers.utils import step_to_string
|
|
|
|
|
|
@login_required
|
|
@permission_required('plannedsession.view_session', fn=get_session_by_pk, raise_exception=True)
|
|
def plannedsession_comment_view(request, id=0, userid=0):
|
|
r = getrequestplanrower(request, userid=userid)
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
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): # pragma: no cover
|
|
comment = comment.encode('utf8')
|
|
elif isinstance(comment, str): # pragma: no cover
|
|
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: <a href="{url}">{comment}</a>'.format(
|
|
name=request.user.first_name,
|
|
comment=comment,
|
|
url=url,
|
|
)
|
|
if request.user != manager: # pragma: no cover
|
|
a_messages.info(r.user, message.encode('ascii', 'ignore'))
|
|
|
|
sessiontype = 'training session'
|
|
if ps.sessiontype == 'race': # pragma: no cover
|
|
sessiontype = 'online virtual race'
|
|
elif ps.sessiontype == 'indoorrace': # pragma: no cover
|
|
sessiontype = 'indoor online virtual race'
|
|
|
|
_ = 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': # pragma: no cover
|
|
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': # pragma: no cover
|
|
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:
|
|
try:
|
|
a_messages.info(u, message)
|
|
except ValueError: # pragma: no cover
|
|
pass
|
|
if u != request.user and u != r.user: # pragma: no cover
|
|
ocr = Rower.objects.get(user=u)
|
|
_ = myqueue(queue,
|
|
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
|
|
)
|
|
if ps.sessiontype in ['race', 'indoorrace']: # pragma: no cover
|
|
followers = VirtualRaceFollower.objects.filter(race__id=ps.id)
|
|
for follower in followers:
|
|
othername = ''
|
|
if follower.user:
|
|
othername = follower.user.first_name+' '+follower.user.last_name
|
|
email = follower.emailaddress
|
|
_ = myqueue(queue,
|
|
handle_sendemailnewresponse,
|
|
othername, '', email,
|
|
request.user.first_name,
|
|
request.user.last_name,
|
|
comment,
|
|
ps.name, ps.id, c.id,
|
|
emailbounced=False,
|
|
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']: # pragma: no cover
|
|
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,
|
|
})
|
|
|
|
|
|
@login_required
|
|
@permission_required('virtualevent.change_race', fn=get_session_by_pk, raise_exception=True)
|
|
def plannedsession_message_view(request, id=0, userid=0):
|
|
r = getrequestplanrower(request, userid=userid)
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
userform = VirtualRaceAthleteForm(instance=ps)
|
|
|
|
if request.method == 'POST':
|
|
userform = VirtualRaceAthleteForm(request.POST, instance=ps)
|
|
if userform.is_valid():
|
|
subject = userform.cleaned_data['subject']
|
|
message = userform.cleaned_data['message']
|
|
rowers = userform.cleaned_data['rower']
|
|
|
|
for participant in rowers:
|
|
rowername = participant.user.first_name
|
|
fromemail = ps.manager.email
|
|
|
|
_ = myqueue(
|
|
queue,
|
|
handle_send_template_email,
|
|
'virtualracemessage.html',
|
|
participant.user.email,
|
|
fromemail,
|
|
rowername,
|
|
subject,
|
|
message,
|
|
)
|
|
|
|
url = reverse('plannedsession_view', kwargs={'id': ps.id})
|
|
if ps.sessiontype in ['race', 'indoorrace']: # pragma: no cover
|
|
url = reverse('virtualevent_view', kwargs={'id': ps.id})
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
if ps.sessiontype in ['race', 'indoorrace']: # pragma: no cover
|
|
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_message.html',
|
|
{'plannedsession': ps,
|
|
'rower': r,
|
|
'breadcrumbs': breadcrumbs,
|
|
'active': active,
|
|
'userform': userform,
|
|
})
|
|
|
|
|
|
# Cloning sessions
|
|
@user_passes_test(can_plan, 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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
teamid = get_team(request)
|
|
|
|
if request.method == 'POST' and 'daterange' in request.POST: # pragma: no cover
|
|
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.fitfile = None
|
|
ps.save()
|
|
for rower in rowers:
|
|
add_rower_session(rower, ps)
|
|
for team in teams:
|
|
add_team_session(team, ps)
|
|
for rower in team.rower.all().exclude(rowerplan='freecoach'):
|
|
add_rower_session(rower, 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],
|
|
is_template=False,
|
|
startdate__lte=enddate,
|
|
enddate__gte=startdate).order_by(
|
|
"startdate", "preferreddate", "enddate").exclude(
|
|
sessiontype='race')
|
|
|
|
if teamid: # pragma: no cover
|
|
sps = sps.filter(team__in=[teamid])
|
|
try:
|
|
team = Team.objects.get(id=teamid)
|
|
if team.manager != request.user:
|
|
team = None
|
|
except Team.DoesNotExist:
|
|
team = None
|
|
else:
|
|
team = None
|
|
|
|
query = request.GET.get('q')
|
|
if query: # pragma: no cover
|
|
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,
|
|
})
|
|
|
|
if Team.objects.filter(manager=request.user).count() >= 1:
|
|
teamform = RowerTeamForm(request.user)
|
|
if teamid: # pragma: no cover
|
|
teamform = RowerTeamForm(request.user, initial={'team': teamid})
|
|
else:
|
|
teamform = None
|
|
|
|
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,
|
|
'team': team,
|
|
'teamform': teamform,
|
|
}
|
|
)
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def template_share_view(request, id=0, userid=0):
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
if ps.can_be_shared:
|
|
ps.is_public = True
|
|
ps.save()
|
|
else: # pragma: no cover
|
|
messages.error(
|
|
request, 'This planned session comes from a third party and cannot be shared')
|
|
|
|
return HttpResponseRedirect(reverse(template_library_view))
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def template_makeprivate_view(request, id=0, userid=0):
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
ps.is_public = False
|
|
ps.save()
|
|
|
|
return HttpResponseRedirect(reverse(template_library_view))
|
|
|
|
|
|
# Manage Template sessions (library)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def template_library_view(request, userid=0):
|
|
r = getrequestplanrower(request, userid=userid)
|
|
templates = PlannedSession.objects.filter(
|
|
manager=request.user, is_template=True)
|
|
templates2 = PlannedSession.objects.filter(
|
|
is_template=True, is_public=True)
|
|
|
|
templates = templates | templates2
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
try:
|
|
trainingplan = TrainingPlan.objects.filter(
|
|
startdate__lte=startdate,
|
|
rowers=r,
|
|
enddate__gte=enddate)[0]
|
|
except IndexError:
|
|
trainingplan = None
|
|
|
|
alltags = []
|
|
for t in templates:
|
|
tags = t.tags.all()
|
|
for tag in tags:
|
|
alltags.append(tag)
|
|
|
|
alltags = uniqify(alltags)
|
|
|
|
tag = request.GET.get('tag')
|
|
if tag: # pragma: no cover
|
|
tags = [tag]
|
|
templates = templates.filter(tags__name__in=tags).distinct()
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view),
|
|
'name': 'Planned Sessions'
|
|
},
|
|
{
|
|
'url': reverse(template_library_view),
|
|
'name': 'Session Library',
|
|
}
|
|
]
|
|
|
|
return render(request, 'templatelibrary.html',
|
|
{
|
|
'teams': get_my_teams(request.user),
|
|
'breadcrumbs': breadcrumbs,
|
|
'templates': templates,
|
|
'plan': trainingplan,
|
|
'rower': r,
|
|
'active': 'nav-plan',
|
|
'alltags': alltags,
|
|
}
|
|
)
|
|
|
|
|
|
# Individual user creates training for himself
|
|
@user_passes_test(can_plan, 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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
|
|
if request.method == 'POST':
|
|
sessioncreateform = PlannedSessionForm(request.POST, request.FILES)
|
|
if sessioncreateform.is_valid():
|
|
ps = sessioncreateform.save(commit=False)
|
|
ps.manager = request.user
|
|
ps.save()
|
|
|
|
add_rower_session(r, ps)
|
|
|
|
request.session['fstartdate'] = str(arrow.get(ps.startdate))
|
|
request.session['fenddate'] = str(arrow.get(ps.enddate))
|
|
request.session['fprefdate'] = str(arrow.get(ps.preferreddate))
|
|
|
|
url = reverse(plannedsessions_view, kwargs={
|
|
'userid': userid,
|
|
})
|
|
|
|
if '_continue' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_edit_view', kwargs={
|
|
'id': ps.id,
|
|
})
|
|
elif '_addanother' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_create_view',
|
|
kwargs={'userid': userid})
|
|
|
|
url = url+'?when='+timeperiod
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
else:
|
|
if 'fstartdate' in request.session: # pragma: no cover
|
|
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:
|
|
try:
|
|
preferreddate = startdate.date()
|
|
except AttributeError:
|
|
preferreddate = startdate
|
|
if preferreddate < timezone.now().date(): # pragma: no cover
|
|
preferreddate = timezone.now().date()
|
|
|
|
try:
|
|
enddate = enddate.date()
|
|
except AttributeError:
|
|
pass
|
|
|
|
if preferreddate > enddate: # pragma: no cover
|
|
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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
sps = get_sessions(r, startdate=startdate, enddate=enddate).exclude(
|
|
sessiontype='race')
|
|
|
|
sessiontemplates = PlannedSession.objects.filter(
|
|
manager=request.user,
|
|
is_template=True).order_by("name")
|
|
|
|
sessiontemplates2 = PlannedSession.objects.filter(
|
|
is_template=True, is_public=True
|
|
).order_by("name")
|
|
|
|
sessiontemplates = sessiontemplates | sessiontemplates2
|
|
|
|
sessiontemplates = sessiontemplates.order_by("name")
|
|
|
|
alltags = []
|
|
for t in sessiontemplates: # pragma: no cover
|
|
tags = t.tags.all()
|
|
for tag in tags:
|
|
alltags.append(tag)
|
|
|
|
alltags = uniqify(alltags)
|
|
|
|
tag = request.GET.get('tag')
|
|
if tag: # pragma: no cover
|
|
tags = [tag]
|
|
sessiontemplates = sessiontemplates.filter(
|
|
tags__name__in=tags).distinct()
|
|
|
|
try:
|
|
trainingplan = TrainingPlan.objects.filter(
|
|
startdate__lte=startdate,
|
|
rowers=r,
|
|
enddate__gte=enddate)[0]
|
|
except IndexError:
|
|
trainingplan = None
|
|
|
|
dateform = DateRangeForm(initial={
|
|
'startdate': startdate,
|
|
'enddate': enddate,
|
|
})
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view),
|
|
'name': 'Planned Sessions'
|
|
},
|
|
{
|
|
'url': reverse(plannedsessions_view)+'?when='+timeperiod,
|
|
'name': timeperiod,
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_create_view),
|
|
'name': 'Add Session'
|
|
}
|
|
]
|
|
|
|
return render(request, 'plannedsessioncreate.html',
|
|
{
|
|
'teams': get_my_teams(request.user),
|
|
'plan': trainingplan,
|
|
'dateform': dateform,
|
|
'breadcrumbs': breadcrumbs,
|
|
'form': sessioncreateform,
|
|
'active': 'nav-plan',
|
|
'plannedsessions': sps,
|
|
'sessiontemplates': sessiontemplates,
|
|
'rower': r,
|
|
'timeperiod': timeperiod,
|
|
'alltags': alltags,
|
|
})
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def plannedsession_createtemplate_view(request,
|
|
userid=0,
|
|
):
|
|
|
|
r = getrequestplanrower(request, userid=userid)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
if request.method == 'POST':
|
|
sessioncreateform = PlannedSessionTemplateForm(
|
|
request.POST, request.FILES)
|
|
if sessioncreateform.is_valid():
|
|
ps = sessioncreateform.save(commit=False)
|
|
ps.manager = request.user
|
|
ps.is_template = True
|
|
ps.save()
|
|
sessioncreateform.save_m2m()
|
|
|
|
add_rower_session(r, ps)
|
|
|
|
url = reverse('template_library_view')
|
|
|
|
if '_continue' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_templateedit_view', kwargs={
|
|
'id': ps.id,
|
|
})
|
|
elif '_addanother' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_createtemplate_view')
|
|
|
|
return HttpResponseRedirect(url)
|
|
else:
|
|
sessioncreateform = PlannedSessionTemplateForm()
|
|
|
|
sessiontemplates = PlannedSession.objects.filter(
|
|
manager=request.user,
|
|
is_template=True).order_by("name")
|
|
|
|
sessiontemplates2 = PlannedSession.objects.filter(
|
|
is_template=True, is_public=True
|
|
).order_by("name")
|
|
|
|
sessiontemplates = sessiontemplates | sessiontemplates2
|
|
|
|
sessiontemplates = sessiontemplates.order_by("name")
|
|
|
|
alltags = []
|
|
for t in sessiontemplates: # pragma: no cover
|
|
tags = t.tags.all()
|
|
for tag in tags:
|
|
alltags.append(tag)
|
|
|
|
alltags = uniqify(alltags)
|
|
|
|
try:
|
|
trainingplan = TrainingPlan.objects.filter(
|
|
startdate__lte=startdate,
|
|
rowers=r,
|
|
enddate__gte=enddate)[0]
|
|
except IndexError:
|
|
trainingplan = None
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view),
|
|
'name': 'Sessions'
|
|
},
|
|
{
|
|
'url': reverse('template_library_view'),
|
|
'name': 'Session Library'
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_createtemplate_view),
|
|
'name': 'Create Library Session'
|
|
}
|
|
]
|
|
|
|
return render(request, 'plannedsessiontemplatecreate.html',
|
|
{
|
|
'teams': get_my_teams(request.user),
|
|
'plan': trainingplan,
|
|
'form': sessioncreateform,
|
|
'breadcrumbs': breadcrumbs,
|
|
'active': 'nav-plan',
|
|
'rower': r,
|
|
'alltags': alltags,
|
|
})
|
|
|
|
|
|
@user_passes_test(can_plan, 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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
teamid = get_team(request)
|
|
try:
|
|
trainingplan = TrainingPlan.objects.filter(
|
|
startdate__lte=startdate,
|
|
rowers=r,
|
|
enddate__gte=enddate)[0]
|
|
except IndexError:
|
|
trainingplan = None
|
|
|
|
qset = PlannedSession.objects.filter(
|
|
rower__in=[r],
|
|
manager=request.user,
|
|
startdate__lte=enddate,
|
|
enddate__gte=startdate,
|
|
).order_by("startdate", "preferreddate", "enddate").exclude(
|
|
sessiontype='race')
|
|
|
|
if teamid: # pragma: no cover
|
|
qset = qset.filter(team__in=[teamid])
|
|
try:
|
|
team = Team.objects.get(id=teamid)
|
|
if team.manager != request.user:
|
|
team = None
|
|
except Team.DoesNotExist:
|
|
team = None
|
|
else:
|
|
team = None
|
|
|
|
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(): # pragma: no cover
|
|
instances = ps_formset.save(commit=False)
|
|
for ps in instances:
|
|
ps.save()
|
|
add_rower_session(r, ps)
|
|
if team: # pragma: no cover
|
|
add_team_session(team, ps)
|
|
messages.info(
|
|
request, "Saved changes for Planned Session "+str(ps))
|
|
for obj in ps_formset.deleted_objects: # pragma: no cover
|
|
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
|
|
|
|
if team: # pragma: no cover
|
|
url += '&team={teamid}'.format(teamid=team.id)
|
|
|
|
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
|
|
})
|
|
|
|
if Team.objects.filter(manager=request.user).count() >= 1:
|
|
teamform = RowerTeamForm(request.user)
|
|
if teamid: # pragma: no cover
|
|
teamform = RowerTeamForm(request.user, initial={'team': teamid})
|
|
else:
|
|
teamform = None
|
|
|
|
context = {
|
|
'ps_formset': ps_formset,
|
|
'breadcrumbs': breadcrumbs,
|
|
'rower': r,
|
|
'active': 'nav-plan',
|
|
'dateform': dateform,
|
|
'teamform': teamform,
|
|
'plan': trainingplan,
|
|
'timeperiod': timeperiod,
|
|
'teams': get_my_teams(request.user),
|
|
'extrasessions': extrasessions+1,
|
|
'team': team,
|
|
}
|
|
|
|
return render(request, 'plannedsession_multicreate.html', context)
|
|
|
|
# Manager creates sessions for entire team
|
|
|
|
|
|
@user_passes_test(can_plan, 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)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
|
|
teams = Team.objects.filter(manager=request.user)
|
|
if teams.count() == 0:
|
|
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)
|
|
|
|
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")
|
|
|
|
sessiontemplates = PlannedSession.objects.filter(
|
|
manager=request.user, is_template=True)
|
|
sessiontemplates2 = PlannedSession.objects.filter(
|
|
is_template=True, is_public=True)
|
|
sessiontemplates = sessiontemplates | sessiontemplates2
|
|
|
|
if request.method == 'POST':
|
|
sessioncreateform = PlannedSessionForm(request.POST, request.FILES)
|
|
sessionteamselectform = PlannedSessionTeamForm(
|
|
request.user, request.POST
|
|
)
|
|
|
|
if sessioncreateform.is_valid() and sessionteamselectform.is_valid():
|
|
cd = sessioncreateform.cleaned_data
|
|
ps = sessioncreateform.save(commit=False)
|
|
ps.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]).exclude(rowerplan='freecoach')
|
|
for r in rs:
|
|
add_rower_session(r, ps)
|
|
|
|
url = reverse(plannedsessions_view, kwargs={
|
|
'userid': userid,
|
|
})
|
|
|
|
if '_continue' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_edit_view', kwargs={
|
|
'id': ps.id,
|
|
})
|
|
elif '_addanother' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_teamcreate_view',
|
|
kwargs={'userid': userid})
|
|
|
|
url = url+'?when='+timeperiod
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
else: # pragma: no cover
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view),
|
|
'name': 'Planned Sessions'
|
|
},
|
|
{
|
|
'url': reverse(plannedsessions_view)+'?when='+timeperiod,
|
|
'name': timeperiod,
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_teamcreate_view),
|
|
'name': 'Add Team Session'
|
|
}
|
|
]
|
|
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
|
|
return render(request, 'plannedsessionteamcreate.html',
|
|
{
|
|
'teams': get_my_teams(request.user),
|
|
'plan': trainingplan,
|
|
'breadcrumbs': breadcrumbs,
|
|
'form': sessioncreateform,
|
|
'sessiontemplates': sessiontemplates,
|
|
'teamform': sessionteamselectform,
|
|
'timeperiod': timeperiod,
|
|
'plannedsessions': sps,
|
|
'rower': therower,
|
|
'active': 'nav-plan'
|
|
})
|
|
|
|
else:
|
|
initial = {
|
|
'startdate': startdate,
|
|
'enddate': enddate,
|
|
'preferreddate': startdate,
|
|
}
|
|
|
|
if 'teams' in request.session: # pragma: no cover
|
|
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(plannedsessions_view)+'?when='+timeperiod,
|
|
'name': timeperiod,
|
|
},
|
|
{
|
|
'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,
|
|
'sessiontemplates': sessiontemplates,
|
|
'teamform': sessionteamselectform,
|
|
'timeperiod': timeperiod,
|
|
'plannedsessions': sps,
|
|
'rower': therower,
|
|
'active': 'nav-plan'
|
|
})
|
|
|
|
# Manager edits sessions for entire team
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
def plannedsession_teamedit_view(request,
|
|
id=0, userid=0):
|
|
|
|
r = getrequestplanrower(request, userid=userid)
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
|
|
teams = Team.objects.filter(manager=request.user)
|
|
|
|
teaminitial = ps.team.all()
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
try:
|
|
trainingplan = TrainingPlan.objects.filter(
|
|
startdate__lte=startdate,
|
|
rowers=r,
|
|
enddate__gte=enddate)[0]
|
|
except IndexError: # pragma: no cover
|
|
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, request.FILES, 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': # pragma: no cover
|
|
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: # pragma: no cover
|
|
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: # pragma: no cover
|
|
remove_team_session(team, ps)
|
|
else: # pragma: no cover
|
|
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('plannedsessions_view')
|
|
|
|
if "_continue" in request.POST: # pragma: no cover
|
|
url = reverse(plannedsession_edit_view,
|
|
kwargs={
|
|
'id': int(ps.id),
|
|
'userid': r.user.id,
|
|
})
|
|
|
|
url = url+'?when='+timeperiod
|
|
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(plannedsessions_view)+'?when='+timeperiod,
|
|
'name': timeperiod,
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_view,
|
|
kwargs={
|
|
'userid': userid,
|
|
'id': id,
|
|
}
|
|
),
|
|
'name': ps.id
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_teamedit_view,
|
|
kwargs={
|
|
'userid': userid,
|
|
'id': id,
|
|
}),
|
|
'name': 'Edit'
|
|
}
|
|
]
|
|
|
|
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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
trainingplan = None
|
|
|
|
if teamid != 0: # pragma: no cover
|
|
try:
|
|
theteam = Team.objects.get(id=teamid)
|
|
except Team.DoesNotExist:
|
|
theteam = False
|
|
else:
|
|
theteam = False
|
|
|
|
if is_coach(request.user) or is_coachtrial(request.user):
|
|
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)
|
|
|
|
if therower.rowerplan != 'freecoach':
|
|
rowers = [therower]
|
|
else: # pragma: no cover
|
|
rowers = []
|
|
|
|
for ps in sps:
|
|
if is_coach(request.user) or is_coachtrial(request.user):
|
|
rowers += ps.rower.all().exclude(rowerplan='freecoach')
|
|
else: # pragma: no cover
|
|
rowers += ps.rower.filter(
|
|
team__in=rteams).exclude(rowerplan='freecoach')
|
|
|
|
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,
|
|
})
|
|
|
|
ttemplate = 'plannedsessionscoach.html'
|
|
if len(rowers) > 5 and len(rowers) > len(sps): # pragma: no cover
|
|
ttemplate = 'plannedsessionscoach2.html'
|
|
|
|
return render(request, ttemplate,
|
|
{
|
|
'myteams': myteams,
|
|
'plannedsessions': sps,
|
|
'breadcrumbs': breadcrumbs,
|
|
'plan': trainingplan,
|
|
'statusdict': statusdict,
|
|
'dateform': dateform,
|
|
'timeperiod': timeperiod,
|
|
'rowers': rowers,
|
|
'active': 'nav-plan',
|
|
'theteam': theteam,
|
|
'unmatchedworkouts': unmatchedworkouts,
|
|
'rower': getrower(request.user)
|
|
}
|
|
)
|
|
|
|
@login_required()
|
|
def save_plan_yaml(request, userid=0):
|
|
r = getrequestrower(request, userid=userid)
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
duration = (enddate-startdate).days+1
|
|
filename = 'myplan.yml'
|
|
|
|
plan = {
|
|
'filename': filename,
|
|
'name': 'Training Plan',
|
|
'duration': duration,
|
|
'description': 'My Training Plan',
|
|
}
|
|
|
|
sps = get_sessions(r, startdate=startdate, enddate=enddate)
|
|
|
|
trainingdays = []
|
|
|
|
# add sessions to days
|
|
for i in range(duration):
|
|
dd = startdate+timedelta(days=i)
|
|
workouts = []
|
|
for ps in sps:
|
|
if ps.preferreddate == dd:
|
|
sessionsport = mytypes.fitmapping[ps.sessionsport].capitalize()
|
|
if ps.steps:
|
|
steps = ps.steps
|
|
steps['filename'] = ""
|
|
workouts.append(steps)
|
|
else: # pragma: no cover
|
|
if ps.sessionmode == 'distance':
|
|
ps.interval_string = '{d}m'.format(d=ps.sessionvalue)
|
|
elif ps.sessionmode == 'time':
|
|
ps.interval_string = '{d}min'.format(d=ps.sessionvalue)
|
|
elif ps.sessionmode == 'rScore':
|
|
ps.approximate_duration = ps.sessionvalue
|
|
ps.interval_string = '{d}min'.format(d=ps.sessionvalue)
|
|
elif ps.sessionmode == 'TRIMP':
|
|
ps.approximate_duration = int(ps.sessionvalue/2.)
|
|
ps.interval_string = '{d}min'.format(d=int(ps.sessionvalue/2.))
|
|
ps.fitfile = ''
|
|
ps.steps = None
|
|
ps.save()
|
|
ps_reload = PlannedSession.objects.get(id=ps.id)
|
|
steps = ps_reload.steps
|
|
steps['filename'] = ""
|
|
steps['workoutName'] = ps.name
|
|
workouts.append(steps)
|
|
|
|
trainingdays.append({'order': i+1, 'workouts': workouts})
|
|
|
|
plan['trainingDays'] = trainingdays
|
|
|
|
response = HttpResponse(yaml.dump(plan))
|
|
|
|
response['Content-Disposition'] = 'attachment; filename="training_plan_{u}_{d1}_{d2}.yml"'.format(
|
|
u=request.user.username,
|
|
d1=startdate.strftime("%Y%m%d"),
|
|
d2=enddate.strftime("%Y%m%d"),
|
|
)
|
|
|
|
response['Content-Type'] = 'application/octet-stream'
|
|
|
|
return response
|
|
|
|
|
|
|
|
@login_required()
|
|
def plannedsessions_view(request,
|
|
userid=0, startdatestring='', enddatestring=''):
|
|
|
|
try:
|
|
r = getrequestplanrower(request, userid=userid)
|
|
except PermissionDenied: # pragma: no cover
|
|
r = request.user.rower
|
|
|
|
if startdatestring: # pragma: no cover
|
|
try:
|
|
startdate = iso8601.parse_date(startdatestring)
|
|
except ParseError:
|
|
pass
|
|
|
|
if enddatestring: # pragma: no cover
|
|
try:
|
|
enddate = iso8601.parse_date(enddatestring)
|
|
except ParseError:
|
|
pass
|
|
|
|
startdate, enddate = get_dates_timeperiod(
|
|
request,
|
|
startdatestring=startdatestring,
|
|
enddatestring=enddatestring,
|
|
rower=r)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
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
|
|
row = {
|
|
'rscore': w.rscore,
|
|
'hrtss': w.hrtss,
|
|
'rpe': w.rpe,
|
|
'duration': w.duration,
|
|
'id': w.id
|
|
}
|
|
tss = dataprep.rscore_approx(row)
|
|
totals['rscore'] += tss
|
|
totals['distance'] += w.distance
|
|
totals['time'] += timefield_to_seconds_duration(w.duration)
|
|
if w.plannedsession: # pragma: no cover
|
|
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': # pragma: no cover
|
|
if user_is_basic(request.user):
|
|
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.steps:
|
|
sdict, totalmeters, totalseconds, totalrscore = ps_dict_order(
|
|
ps.steps, rower=r)
|
|
totals['planneddistance'] += int(totalmeters)
|
|
totals['plannedtime'] += int(totalseconds)/60.
|
|
totals['plannedrscore'] += int(totalrscore)
|
|
totals['plannedtrimp'] += int(totalrscore)*2
|
|
else:
|
|
if ps.sessionmode == 'distance':
|
|
totals['planneddistance'] += ps.sessionvalue
|
|
else:
|
|
totals['planneddistance'] += ps.approximate_distance
|
|
if ps.sessionmode == 'time':
|
|
totals['plannedtime'] += ps.sessionvalue
|
|
else:
|
|
totals['plannedtime'] += ps.approximate_duration
|
|
if ps.sessionmode == 'rScore': # pragma: no cover
|
|
totals['plannedrscore'] += ps.sessionvalue
|
|
else:
|
|
totals['plannedrscore'] += ps.approximate_rscore
|
|
if ps.sessionmode == 'TRIMP': # pragma: no cover
|
|
totals['plannedtrimp'] += ps.sessionvalue
|
|
else:
|
|
totals['plannedtrimp'] += ps.approximate_rscore*2
|
|
|
|
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,
|
|
})
|
|
|
|
|
|
@allow_shares
|
|
# @login_required()
|
|
def plannedsessions_print_view(request, userid=0, startdatestring='', enddatestring=''):
|
|
|
|
r = getrequestplanrower(request, userid=userid)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request, startdatestring=startdatestring,
|
|
enddatestring=enddatestring)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
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)
|
|
|
|
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()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def plannedsessions_manage_view(request, userid=0,
|
|
initialsession=0):
|
|
|
|
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
|
|
|
|
r = getrequestrower(request, userid=userid)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
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: # pragma: no cover
|
|
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: # pragma: no cover
|
|
selectedworkouts = []
|
|
|
|
if len(selectedworkouts) == 0: # pragma: no cover
|
|
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: # pragma: no cover
|
|
messages.error(request, er)
|
|
|
|
ps_form = PlannedSessionSelectForm(plannedsessionstuple,
|
|
initialsession=initialsession)
|
|
w_form = WorkoutSessionSelectForm(workoutdata=workoutdata)
|
|
|
|
if is_ajax: # pragma: no cover
|
|
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
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, 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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
rowers = ps.rower.all()
|
|
teams = ps.team.all()
|
|
|
|
ps.pk = None
|
|
ps.id = None
|
|
if not ps.is_template:
|
|
ps.name += ' (copy)'
|
|
ps.is_template = False
|
|
|
|
deltadays = ps.preferreddate-ps.startdate
|
|
|
|
ps.startdate = startdate
|
|
ps.enddate = enddate
|
|
ps.preferreddate = ps.startdate+deltadays
|
|
ps.fitfile = None
|
|
|
|
ps.save()
|
|
|
|
if rowers:
|
|
for rower in rowers:
|
|
add_rower_session(rower, ps)
|
|
else: # pragma: no cover
|
|
add_rower_session(r, ps)
|
|
for team in teams:
|
|
add_team_session(team, ps)
|
|
for rower in team.rower.all().exclude(rowerplan='freecoach'):
|
|
add_rower_session(rower, 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
|
|
|
|
next = request.GET.get('next', url)
|
|
return HttpResponseRedirect(next)
|
|
|
|
# Clone an existing planned session
|
|
# need clarity on cloning behavior time shift
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def plannedsession_teamclone_view(request, id=0):
|
|
|
|
r = getrequestplanrower(request)
|
|
|
|
teams = Team.objects.filter(manager=request.user)
|
|
if teams.count() == 0: # pragma: no cover
|
|
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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
ps.pk = None
|
|
ps.id = None
|
|
if not ps.is_template:
|
|
ps.name += ' (copy)'
|
|
ps.is_template = False
|
|
ps.fitfile = None
|
|
|
|
deltadays = ps.preferreddate-ps.startdate
|
|
|
|
ps.startdate = startdate
|
|
ps.enddate = enddate
|
|
ps.preferreddate = startdate+deltadays
|
|
|
|
ps.save()
|
|
|
|
url = reverse(plannedsession_teamedit_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
|
|
|
|
next = request.GET.get('next', url)
|
|
return HttpResponseRedirect(next)
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def plannedsession_templateedit_view(request, id=0):
|
|
r = getrequestrower(request)
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
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: # pragma: no cover
|
|
raise Http404("Planned Session does not exist")
|
|
|
|
if ps.manager != request.user: # pragma: no cover
|
|
raise PermissionDenied(
|
|
"You are not allowed to edit this planned session")
|
|
|
|
if ps.sessiontype in ['race', 'indoorrace']: # pragma: no cover
|
|
raise PermissionDenied(
|
|
"You are not allowed to edit this planned session because it is a race")
|
|
|
|
if not ps.is_template: # pragma: no cover
|
|
ps.pk = None
|
|
ps.id = None
|
|
ps.is_template = True
|
|
ps.startdate = datetime.date(1970, 1, 1)
|
|
ps.enddate = datetime.date(1970, 1, 1)
|
|
ps.team.clear()
|
|
ps.fitfile = None
|
|
ps.save()
|
|
|
|
sessioncreateform = PlannedSessionTemplateForm(instance=ps)
|
|
|
|
if request.method == 'POST':
|
|
sessioncreateform = PlannedSessionTemplateForm(
|
|
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']: # pragma: no cover
|
|
cd['sessionmode'] = 'distance'
|
|
|
|
obj = sessioncreateform.save(commit=False)
|
|
obj.save()
|
|
sessioncreateform.save_m2m()
|
|
|
|
res, message = update_plannedsession(ps, cd)
|
|
# sessioncreateform.save_m2m()
|
|
|
|
if res:
|
|
messages.info(request, message)
|
|
else: # pragma: no cover
|
|
messages.error(request, message)
|
|
|
|
url = reverse('template_library_view')
|
|
|
|
if '_continue' in request.POST: # pragma: no cover
|
|
url = reverse('plannedsession_templateedit_view', kwargs={
|
|
'id': ps.id,
|
|
})
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view),
|
|
'name': 'Sessions'
|
|
},
|
|
{
|
|
'url': reverse('template_library_view'),
|
|
'name': 'Library',
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_templateedit_view,
|
|
kwargs={
|
|
'id': id,
|
|
}
|
|
),
|
|
'name': 'Edit Session'
|
|
}
|
|
]
|
|
|
|
sessiontemplates = PlannedSession.objects.filter(
|
|
manager=request.user, is_template=True)
|
|
sessiontemplates2 = PlannedSession.objects.filter(
|
|
is_template=True, is_public=True
|
|
).order_by("name")
|
|
|
|
sessiontemplates = sessiontemplates | sessiontemplates2
|
|
|
|
steps = ''
|
|
if ps.steps: # pragma: no cover
|
|
d = ps.steps
|
|
|
|
steps = ps_dict_get_description_html(d, short=False)
|
|
|
|
return render(request, 'plannedsessiontemplateedit.html',
|
|
{
|
|
'teams': get_my_teams(request.user),
|
|
'plan': trainingplan,
|
|
'breadcrumbs': breadcrumbs,
|
|
'form': sessioncreateform,
|
|
'active': 'nav-plan',
|
|
'thesession': ps,
|
|
'sessiontemplates': sessiontemplates,
|
|
'rower': r,
|
|
'steps': steps,
|
|
})
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def plannedsession_tointervals_view(request, id=0):
|
|
|
|
r = getrequestplanrower(request)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
intervals = IntervalsIntegration(request.user)
|
|
result = intervals.plannedsession_create(ps)
|
|
|
|
if not result: # pragma: no cover
|
|
messages.error(
|
|
request, 'You failed to export your session to Intervals')
|
|
else:
|
|
messages.info(
|
|
request, 'Session is now on Intervals.')
|
|
|
|
url = reverse(plannedsession_view, kwargs={'userid': r.user.id,
|
|
'id': ps.id, })
|
|
|
|
startdatestring = startdate.strftime('%Y-%m-%d')
|
|
enddatestring = enddate.strftime('%Y-%m-%d')
|
|
url += '?when='+startdatestring+'/'+enddatestring
|
|
|
|
next = request.GET.get('next', url)
|
|
|
|
return HttpResponseRedirect(next)
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def plannedsession_togarmin_view(request, id=0):
|
|
|
|
r = getrequestplanrower(request)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
result = gs.garmin_session_create(ps, r.user)
|
|
|
|
if not result: # pragma: no cover
|
|
messages.error(
|
|
request, 'You failed to export your session to Garmin Connect') # pragma: no cover
|
|
else: # pragma: no cover
|
|
messages.info(
|
|
request, 'Session is now on Garmin Connect. Sync your Garmin watch')
|
|
|
|
url = reverse(plannedsession_view, kwargs={'userid': r.user.id,
|
|
'id': ps.id, })
|
|
|
|
startdatestring = startdate.strftime('%Y-%m-%d')
|
|
enddatestring = enddate.strftime('%Y-%m-%d')
|
|
url += '?when='+startdatestring+'/'+enddatestring
|
|
|
|
next = request.GET.get('next', url)
|
|
|
|
return HttpResponseRedirect(next)
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans/",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def plannedsession_totemplate_view(request, id=0):
|
|
|
|
r = getrequestplanrower(request)
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
ps.pk = None
|
|
ps.id = None
|
|
ps.is_template = True
|
|
ps.fitfile = None
|
|
ps.startdate = datetime.date(1970, 1, 1)
|
|
ps.enddate = datetime.date(1970, 1, 1)
|
|
ps.save()
|
|
|
|
url = reverse(plannedsession_create_view, kwargs={'userid': r.user.id})
|
|
|
|
startdatestring = startdate.strftime('%Y-%m-%d')
|
|
enddatestring = enddate.strftime('%Y-%m-%d')
|
|
url += '?when='+startdatestring+'/'+enddatestring
|
|
|
|
next = request.GET.get('next', url)
|
|
|
|
return HttpResponseRedirect(next)
|
|
|
|
# Edit an existing planned session
|
|
|
|
|
|
@permission_required('plannedsession.change_session', fn=get_session_by_pk, raise_exception=True)
|
|
@user_passes_test(can_plan, 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)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
|
|
try:
|
|
trainingplan = TrainingPlan.objects.filter(
|
|
startdate__lte=startdate,
|
|
rowers=r,
|
|
enddate__gte=enddate)[0]
|
|
except IndexError: # pragma: no cover
|
|
trainingplan = None
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
if ps.team.all() or ps.rower.all().count() > 1:
|
|
url = reverse(plannedsession_teamedit_view,
|
|
kwargs={
|
|
'id': id,
|
|
})
|
|
url = url+"?when="+timeperiod
|
|
return HttpResponseRedirect(url)
|
|
|
|
if request.method == 'POST':
|
|
sessioncreateform = PlannedSessionForm(
|
|
request.POST, request.FILES, instance=ps)
|
|
if sessioncreateform.is_valid():
|
|
cd = sessioncreateform.cleaned_data
|
|
|
|
if cd['sessionunit'] == 'min': # pragma: no cover
|
|
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: # pragma: no cover
|
|
messages.error(request, message)
|
|
|
|
url = reverse('plannedsessions_view')
|
|
|
|
if "_continue" in request.POST: # pragma: no cover
|
|
url = reverse(plannedsession_edit_view,
|
|
kwargs={
|
|
'id': int(ps.id),
|
|
'userid': r.user.id,
|
|
})
|
|
|
|
url += '?when='+timeperiod
|
|
|
|
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': 'Sessions'
|
|
},
|
|
{
|
|
'url': reverse(plannedsessions_view)+'?when='+timeperiod,
|
|
'name': timeperiod,
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_view,
|
|
kwargs={
|
|
'userid': userid,
|
|
'id': id,
|
|
}
|
|
),
|
|
'name': ps.id
|
|
},
|
|
{
|
|
'url': reverse(plannedsession_edit_view,
|
|
kwargs={
|
|
'userid': userid,
|
|
'id': id,
|
|
}
|
|
),
|
|
'name': 'Edit'
|
|
}
|
|
]
|
|
|
|
sessiontemplates = PlannedSession.objects.filter(
|
|
manager=request.user, is_template=True)
|
|
sessiontemplates2 = PlannedSession.objects.filter(
|
|
is_template=True, is_public=True
|
|
).order_by("name")
|
|
|
|
sessiontemplates = sessiontemplates | sessiontemplates2
|
|
|
|
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,
|
|
'sessiontemplates': sessiontemplates,
|
|
'rower': r,
|
|
'timeperiod': timeperiod,
|
|
})
|
|
|
|
|
|
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
|
def plannedsession_detach_view(request, id=0, psid=0):
|
|
ps = get_object_or_404(PlannedSession, pk=psid)
|
|
|
|
w = get_workout(id)
|
|
|
|
remove_workout_plannedsession(w, ps)
|
|
|
|
url = reverse(plannedsession_view, kwargs={'id': psid})
|
|
next = request.GET.get('next', url)
|
|
return HttpResponseRedirect(next)
|
|
|
|
|
|
@login_required()
|
|
@permission_required('plannedsession.view_session', fn=get_session_by_pk, raise_exception=True)
|
|
def plannedsession_view(request, id=0, userid=0):
|
|
|
|
r = getrequestplanrower(request, userid=userid)
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
try: # pragma: no cover
|
|
r = VirtualRace.objects.get(id=ps.id)
|
|
url = reverse('virtualevent_view',
|
|
kwargs={'id': ps.id}
|
|
)
|
|
return HttpResponseRedirect(url)
|
|
except VirtualRace.DoesNotExist:
|
|
pass
|
|
|
|
if ps.course: # pragma: no cover
|
|
coursescript, coursediv = course_map(ps.course)
|
|
else:
|
|
coursescript = ''
|
|
coursediv = ''
|
|
|
|
m = ps.manager
|
|
mm = Rower.objects.get(user=m)
|
|
|
|
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,
|
|
'sessionresult': 0,
|
|
'workoutid': w.id,
|
|
}
|
|
if ps.sessiontype == 'coursetest': # pragma: no cover
|
|
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
|
|
wdict['sessionresult'] = record.id
|
|
else:
|
|
record = CourseTestResult(
|
|
userid=w.user.id,
|
|
workoutid=w.id,
|
|
plannedsession=ps,
|
|
duration=w.duration,
|
|
coursecompleted=False,
|
|
)
|
|
record.save()
|
|
_ = myqueue(queue, handle_check_race_course,
|
|
w.csvfilename, w.id, ps.course.id,
|
|
record.id,
|
|
w.user.user.email, w.user.user.first_name,
|
|
mode='coursetest')
|
|
|
|
# taking workout duration plus 1 minute penalty
|
|
wdict['time'] = datetime.timedelta(
|
|
hours=w.duration.hour,
|
|
minutes=w.duration.minute,
|
|
seconds=w.duration.second,
|
|
)
|
|
wdict['distance'] = ps.course.distance
|
|
wdict['coursecompleted'] = False
|
|
ranking.append(wdict)
|
|
if ps.sessiontype == 'coursetest': # pragma: no cover
|
|
ranking = sorted(ranking, key=lambda k: k['time'])
|
|
|
|
if ps.sessiontype == 'fastest_distance': # pragma: no cover
|
|
vs = CourseTestResult.objects.filter(plannedsession=ps)
|
|
|
|
if vs:
|
|
for record in vs:
|
|
userid = record.userid
|
|
uu = User.objects.get(id=userid)
|
|
try:
|
|
w = Workout.objects.get(id=record.workoutid)
|
|
wdict = {
|
|
'name': uu.first_name+' '+uu.last_name,
|
|
'date': w.date,
|
|
'distance': record.distance,
|
|
'type': w.workouttype,
|
|
'workoutid': w.id,
|
|
'coursecompleted': True,
|
|
'sessionresult': record.id
|
|
}
|
|
|
|
coursecompleted = record.coursecompleted
|
|
t = record.duration
|
|
wdict['time'] = datetime.timedelta(
|
|
hours=t.hour,
|
|
seconds=t.second,
|
|
minutes=t.minute,
|
|
microseconds=t.microsecond
|
|
)
|
|
|
|
wdict['coursecompleted'] = coursecompleted
|
|
|
|
ranking.append(wdict)
|
|
except Workout.DoesNotExist:
|
|
pass
|
|
|
|
ranking = sorted(ranking, key=lambda k: k['time'])
|
|
if ps.sessiontype == 'fastest_time': # pragma: no cover
|
|
vs = CourseTestResult.objects.filter(plannedsession=ps)
|
|
|
|
if vs:
|
|
for record in vs:
|
|
userid = record.userid
|
|
uu = User.objects.get(id=userid)
|
|
w = Workout.objects.get(id=record.workoutid)
|
|
wdict = {
|
|
'name': uu.first_name+' '+uu.last_name,
|
|
'date': w.date,
|
|
'distance': record.distance,
|
|
'type': w.workouttype,
|
|
'workoutid': w.id,
|
|
'coursecompleted': True,
|
|
'sessionresult': record.id,
|
|
}
|
|
|
|
coursecompleted = record.coursecompleted
|
|
t = record.duration
|
|
wdict['time'] = datetime.timedelta(
|
|
hours=t.hour,
|
|
seconds=t.second,
|
|
minutes=t.minute,
|
|
microseconds=t.microsecond
|
|
)
|
|
|
|
wdict['coursecompleted'] = coursecompleted
|
|
|
|
ranking.append(wdict)
|
|
ranking = sorted(ranking, key=lambda k: -k['distance'])
|
|
|
|
# if coursetest, need to reorder the ranking
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
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")
|
|
|
|
steps = ''
|
|
steps_intervals = ''
|
|
if ps.steps: # pragma: no cover
|
|
d = ps.steps
|
|
steps = ps_dict_get_description_html(d, short=False)
|
|
steps_intervals = ps.steps_intervals()
|
|
|
|
return render(request, 'plannedsessionview.html',
|
|
{
|
|
'psdict': psdict,
|
|
'attrs': [
|
|
'name', 'startdate', 'enddate', 'preferreddate',
|
|
'sessionsport',
|
|
'sessiontype',
|
|
'sessionmode', 'criterium',
|
|
'sessionvalue', 'sessionunit',
|
|
'approximate_distance', 'approximate_duration',
|
|
'approximate_rscore',
|
|
'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,
|
|
'steps': steps,
|
|
'steps_intervals': steps_intervals,
|
|
}
|
|
)
|
|
|
|
|
|
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: # pragma: no cover
|
|
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: # pragma: no cover
|
|
w.plannedsession = None
|
|
w.save()
|
|
|
|
url = reverse(plannedsessions_view)
|
|
next = self.request.GET.get('next', url)
|
|
|
|
return next
|
|
|
|
def get_object(self, *args, **kwargs):
|
|
obj = super(PlannedSessionDelete, self).get_object(*args, **kwargs)
|
|
if not can_delete_session(self.request.user, obj): # pragma: no cover
|
|
raise PermissionDenied(
|
|
'You are not allowed to delete this planned session')
|
|
|
|
return obj
|
|
|
|
|
|
def rower_view_instantplan(request, id='', userid=0):
|
|
r = getrequestrower(request, userid=userid)
|
|
if not id: # pragma: no cover
|
|
raise Http404("Plan does not exist")
|
|
|
|
plan = InstantPlan.objects.get(uuid=id)
|
|
|
|
authorizationstring = 'Bearer '+settings.WORKOUTS_FIT_TOKEN
|
|
url = settings.WORKOUTS_FIT_URL+"/trainingplan/"+id
|
|
headers = {'Authorization': authorizationstring}
|
|
|
|
response = requests.get(url=url, headers=headers)
|
|
if response.status_code != 200: # pragma: no cover
|
|
messages.error(
|
|
request, "Could not connect to the training plan server")
|
|
return HttpResponseRedirect(reverse('rower_select_instantplan'))
|
|
|
|
plansteps = response.json()
|
|
|
|
trainingdays = plansteps['trainingDays']
|
|
|
|
|
|
|
|
trainingdays2 = []
|
|
nextday = trainingdays.pop(0)
|
|
|
|
for i in range(plansteps['duration']):
|
|
if nextday['order'] == i+1:
|
|
nextday['week'] = (divmod(i, 7)[0])+1
|
|
|
|
trainingdays2.append(nextday)
|
|
|
|
workouts = nextday['workouts']
|
|
try:
|
|
nextday = trainingdays.pop(0)
|
|
except IndexError:
|
|
continue
|
|
else:
|
|
trainingdays2.append(
|
|
{
|
|
'order': i+1,
|
|
'week': (divmod(i, 7)[0])+1,
|
|
'workouts': []
|
|
}
|
|
)
|
|
|
|
|
|
targets = TrainingTarget.objects.filter(
|
|
rowers=r,
|
|
date__gte=timezone.now(),
|
|
).order_by("-date")
|
|
|
|
if request.method == 'POST' and not request.user.is_anonymous:
|
|
if not can_plan(request.user) and plan.price == 0: # pragma: no cover
|
|
messages.error(
|
|
request, 'You must be on a <a href="/rowers/paidplans">paid plan</a> to use free training plans')
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': id,
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
|
|
# check if plan is free or credits are sufficient
|
|
if plan.price > 0: # pragma: no cover
|
|
if plan.price > r.eurocredits:
|
|
messages.error(
|
|
request, 'You did not have enough credit to purchase this plan')
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': id,
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
if not can_plan(request.user):
|
|
messages.error(
|
|
request, 'You must be on a <a href="/rowers/paidplans">paid plan</a> to use free training plans')
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': id,
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
|
|
form = InstantPlanSelectForm(request.POST, targets=targets)
|
|
byrscoreform = PlanByRscoreForm(request.POST)
|
|
if byrscoreform.is_valid():
|
|
try:
|
|
byrscore = byrscoreform.cleaned_data['byrscore']
|
|
except KeyError:
|
|
byrscore = False
|
|
else:
|
|
byrscore = False
|
|
|
|
if form.is_valid():
|
|
if plan.price > 0: # pragma: no cover
|
|
_ = credits.withdraw(plan.price, r)
|
|
|
|
plansteps = response.json()
|
|
name = form.cleaned_data['name']
|
|
try:
|
|
targetid = form.cleaned_data['target']
|
|
if targetid != '': # pragma: no cover
|
|
target = TrainingTarget.objects.get(id=int(targetid))
|
|
else:
|
|
target = None
|
|
except KeyError: # pragma: no cover
|
|
try:
|
|
targetid = request.POST['target']
|
|
if targetid != '':
|
|
target = TrainingTarget.objects.get(id=int(targetid))
|
|
else:
|
|
target = None
|
|
except KeyError:
|
|
target = None
|
|
enddate = form.cleaned_data['enddate']
|
|
startdate = form.cleaned_data['startdate']
|
|
notes = form.cleaned_data['notes']
|
|
datechoice = form.cleaned_data['datechoice']
|
|
plan_past_days = form.cleaned_data['plan_past_days']
|
|
status = True
|
|
|
|
if target and datechoice == 'target': # pragma: no cover
|
|
enddate = target.date
|
|
startdate = enddate-datetime.timedelta(days=plan.duration)
|
|
elif datechoice == 'startdate':
|
|
enddate = startdate+datetime.timedelta(days=plan.duration)
|
|
else: # pragma: no cover
|
|
startdate = enddate-datetime.timedelta(days=plan.duration)
|
|
|
|
p = TrainingPlan(
|
|
name=name,
|
|
target=target,
|
|
manager=r,
|
|
startdate=startdate,
|
|
enddate=enddate, status=status,
|
|
notes=notes,
|
|
)
|
|
|
|
if not plan_past_days:
|
|
p.startdate = timezone.now().date()
|
|
|
|
p.save()
|
|
p.rowers.add(r)
|
|
|
|
create_sessions_from_json(plansteps, r, startdate, r.user, planbyrscore=byrscore,
|
|
plan=p, plan_past_days = plan_past_days, asynchronous=True)
|
|
|
|
messages.info(request, 'Your Sessions have been added')
|
|
|
|
url = reverse('plannedsessions_view')
|
|
timeperiod = timezone.now().date().strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
url = url+'?when='+timeperiod
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
elif not request.user.is_anonymous:
|
|
tz = pytz.timezone(r.defaulttimezone)
|
|
nowdate = timezone.now().astimezone(tz)
|
|
initial = {
|
|
'datechoice': 'startdate',
|
|
'startdate': nowdate,
|
|
'enddate': nowdate+datetime.timedelta(days=21)
|
|
}
|
|
form = InstantPlanSelectForm(
|
|
targets=targets, instantplan=plan, initial=initial)
|
|
if request.user.is_superuser:
|
|
byrscoreform = PlanByRscoreForm()
|
|
else:
|
|
byrscoreform = None
|
|
|
|
|
|
|
|
else: # pragma: no cover
|
|
form = None
|
|
byrscoreform = None
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse('plannedsessions_view'),
|
|
'name': 'Sessions'
|
|
},
|
|
{
|
|
'url': reverse(rower_create_trainingplan,
|
|
kwargs={'id': userid}),
|
|
'name': 'Manage Plans and Targets'
|
|
},
|
|
{
|
|
'url': reverse('rower_select_instantplan'),
|
|
'name': 'Select Existing Plans'
|
|
},
|
|
{
|
|
'url': reverse('rower_view_instantplan', kwargs={
|
|
'id': id,
|
|
# 'userid':userid,
|
|
}),
|
|
'name': plan.name
|
|
}
|
|
]
|
|
|
|
return render(request,
|
|
'instantplan.html',
|
|
{
|
|
'rower': r,
|
|
'active': 'nav-plan',
|
|
'plan': plan,
|
|
'byrscoreform': byrscoreform,
|
|
'trainingdays': trainingdays2,
|
|
'breadcrumbs': breadcrumbs,
|
|
'form': form,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def remove_groupsession_view(request, id=0):
|
|
r = getrequestrower(request)
|
|
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
res = remove_rower_session(r, ps)
|
|
|
|
if res:
|
|
messages.info(request, "We have removed you from this group session")
|
|
else: # pragma: no cover
|
|
messages.error(
|
|
request, "For some reason we could not remove you from this group session")
|
|
|
|
url = reverse('plannedsessions_view')
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
|
@login_required()
|
|
def add_instantplan_view(request):
|
|
if not request.user.is_staff: # pragma: no cover
|
|
raise PermissionDenied("Not Allowed")
|
|
|
|
r = request.user.rower
|
|
|
|
if request.method == 'POST': # pragma: no cover
|
|
form = InstantPlanForm(request.POST, request.FILES)
|
|
if form.is_valid():
|
|
ip = form.save(commit=False)
|
|
ip.owner = r.user
|
|
ip.save()
|
|
|
|
url = reverse(rower_select_instantplan)
|
|
|
|
return HttpResponseRedirect(url)
|
|
else:
|
|
form = InstantPlanForm()
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse('plannedsessions_view'),
|
|
'name': 'Sessions'
|
|
},
|
|
{
|
|
'url': reverse(rower_create_trainingplan),
|
|
'name': 'Manage Plans and Targets'
|
|
},
|
|
{
|
|
'url': reverse('rower_select_instantplan'),
|
|
'name': 'Select Existing Plans'
|
|
},
|
|
{
|
|
'url': reverse(add_instantplan_view),
|
|
'name': 'Add New Instant Plan'
|
|
}
|
|
]
|
|
|
|
return render(request, 'add_instantplan.html',
|
|
{
|
|
'form': form,
|
|
'rower': r,
|
|
'active': 'nav-plan',
|
|
'breadcrumbs': breadcrumbs,
|
|
}
|
|
)
|
|
|
|
|
|
def rower_select_instantplan(request, id=0):
|
|
r = getrequestrower(request, userid=id)
|
|
|
|
# get and present available plans
|
|
ips = InstantPlan.objects.filter(private=False)
|
|
|
|
if not request.user.is_anonymous:
|
|
|
|
ips2 = InstantPlan.objects.filter(owner=request.user)
|
|
|
|
ips = ips | ips2
|
|
|
|
ips = ips.order_by("private", "name", "sessionsperweek", "hoursperweek", "duration", "id")
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse('plannedsessions_view'),
|
|
'name': 'Sessions'
|
|
},
|
|
{
|
|
'url': reverse(rower_create_trainingplan,
|
|
kwargs={'id': id}),
|
|
'name': 'Manage Plans and Targets'
|
|
},
|
|
{
|
|
'url': reverse('rower_select_instantplan'),
|
|
'name': 'Select Existing Plans'
|
|
}
|
|
]
|
|
|
|
return render(request,
|
|
'instantplans.html',
|
|
{
|
|
'rower': r,
|
|
'active': 'nav-plan',
|
|
'plans': ips,
|
|
'breadcrumbs': breadcrumbs,
|
|
})
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def rower_create_trainingplan(request, id=0):
|
|
therower = getrequestrower(request, userid=id)
|
|
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']
|
|
try:
|
|
rowers = targetform.cleaned_data['rowers']
|
|
except KeyError:
|
|
rowers = [therower]
|
|
|
|
t = TrainingTarget(
|
|
name=name,
|
|
date=date,
|
|
manager=themanager,
|
|
notes=notes)
|
|
|
|
t.save()
|
|
for athlete in rowers:
|
|
t.rowers.add(athlete)
|
|
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: # pragma: no cover
|
|
target = None
|
|
except KeyError: # pragma: no cover
|
|
target = None
|
|
startdate = form.cleaned_data['startdate']
|
|
status = form.cleaned_data['status']
|
|
enddate = form.cleaned_data['enddate']
|
|
notes = form.cleaned_data['notes']
|
|
|
|
try:
|
|
athletes = form.cleaned_data['rowers']
|
|
except KeyError:
|
|
athletes = [therower]
|
|
|
|
p = TrainingPlan(
|
|
name=name,
|
|
target=target,
|
|
manager=themanager,
|
|
startdate=startdate,
|
|
enddate=enddate, status=status,
|
|
notes=notes,
|
|
)
|
|
|
|
p.save()
|
|
|
|
for athlete in athletes:
|
|
if can_plan_user(request.user, athlete):
|
|
p.rowers.add(athlete)
|
|
|
|
targets = TrainingTarget.objects.filter(
|
|
rowers=therower,
|
|
date__gte=timezone.now(),
|
|
).order_by("date")
|
|
|
|
old_targets = TrainingTarget.objects.filter(
|
|
rowers=therower,
|
|
date__lt=timezone.now(),
|
|
).order_by("-date")
|
|
|
|
targetform = TrainingTargetForm(user=request.user)
|
|
|
|
plans = TrainingPlan.objects.filter(rowers=therower).order_by("-startdate")
|
|
|
|
plans_to_deactivate = TrainingPlan.objects.filter(
|
|
rowers=therower,
|
|
enddate__lt=timezone.now(),
|
|
status=True,
|
|
).order_by("-startdate")
|
|
|
|
for p in plans_to_deactivate: # pragma: no cover
|
|
p.status = False
|
|
p.save()
|
|
|
|
form = TrainingPlanForm(targets=targets,
|
|
initial={'status': False, 'rowers': [therower]},
|
|
user=request.user)
|
|
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view,
|
|
kwargs={'userid': id}),
|
|
'name': 'Plan'
|
|
},
|
|
{
|
|
'url': reverse(rower_create_trainingplan,
|
|
kwargs={'id': id}),
|
|
'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,
|
|
'old_targets': old_targets,
|
|
})
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def stepadder(request, id=0):
|
|
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
|
|
|
|
if not is_ajax: # pragma: no cover
|
|
return JSONResponse(
|
|
status=403, data={
|
|
'status': 'false',
|
|
'message': 'this view cannot be accessed directly'
|
|
}
|
|
)
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
is_save = request.GET.get('save',0)
|
|
|
|
if request.method != 'POST': # pragma: no cover
|
|
message = {'status': 'false',
|
|
'message': 'this view cannot be accessed through GET'}
|
|
return JSONResponse(status=403, data=message)
|
|
|
|
try:
|
|
json_data = json.loads(request.body)
|
|
post_data = json_data
|
|
except (KeyError, JSONDecodeError): # pragma: no cover
|
|
q = request.POST
|
|
post_data = {k: q.getlist(k) if len(
|
|
q.getlist(k)) > 1 else v for k, v in q.items()}
|
|
|
|
# only allow local host
|
|
hostt = request.get_host().split(':')
|
|
|
|
if hostt[0] not in ['localhost', '127.0.0.1', 'dev.rowsandall.com', 'rowsandall.com',
|
|
'testserver']: # pragma: no cover
|
|
message = {'status': 'false',
|
|
'message': 'permission denied for host '+hostt[0]}
|
|
return JSONResponse(status=403, data=message)
|
|
|
|
if ps.steps:
|
|
filename = ps.steps.get('filename','')
|
|
sport = ps.steps.get('sport','rowing')
|
|
else: # pragma: no cover
|
|
filename = ''
|
|
sport = 'rowing'
|
|
|
|
steps = {
|
|
"filename": filename,
|
|
"sport": sport,
|
|
"steps": []
|
|
}
|
|
|
|
for nr,id in enumerate(post_data):
|
|
try:
|
|
step = PlannedSessionStep.objects.get(id=int(id))
|
|
# add JSON
|
|
d = step.asdict()
|
|
d['stepId'] = nr
|
|
steps['steps'].append(d)
|
|
except PlannedSessionStep.DoesNotExist: # pragma: no cover
|
|
pass
|
|
|
|
if is_save: # pragma: no cover
|
|
# save the darn thing
|
|
ps.steps = steps
|
|
|
|
ps.interval_string = ''
|
|
ps.fitfile = None
|
|
ps.save()
|
|
|
|
return JSONResponse(status=200,data=post_data)
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def stepdelete(request, id=0):
|
|
step = get_object_or_404(PlannedSessionStep, pk=id)
|
|
|
|
step.delete()
|
|
|
|
backid = request.GET.get('id',0)
|
|
|
|
if backid: # pragma: no cover
|
|
url = reverse(stepeditor,kwargs={'id':backid})
|
|
else:
|
|
url = reverse('plannedsessions_view')
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def stepedit(request, id=0, psid=0):
|
|
step = get_object_or_404(PlannedSessionStep, pk=id)
|
|
try:
|
|
ps = PlannedSession.objects.get(id=psid)
|
|
except PlannedSession.DoesNotExist: # pragma: no cover
|
|
ps = None
|
|
|
|
form = StepEditorForm(instance=step)
|
|
|
|
if request.method == 'POST':
|
|
form = StepEditorForm(request.POST)
|
|
if form.is_valid():
|
|
if ps:
|
|
dd = step.asdict()
|
|
dd.pop('stepId')
|
|
for id,ss in enumerate(ps.steps['steps']):
|
|
ee = ss.copy()
|
|
ee.pop('stepId')
|
|
|
|
if (dd == ee): # pragma: no cover
|
|
ss['durationType'] = form.cleaned_data['durationtype']
|
|
ss['durationValue'] = form.cleaned_data['durationvalue']
|
|
ss['targetType'] = form.cleaned_data['targettype']
|
|
ss['targetValue'] = form.cleaned_data['targetvalue']
|
|
ss['targetValueLow']= form.cleaned_data['targetvaluelow']
|
|
ss['targetValueHigh'] = form.cleaned_data['targetvaluehigh']
|
|
ss['intensity'] = form.cleaned_data['intensity']
|
|
ss['wkt_step_name'] = form.cleaned_data['name']
|
|
ss['description'] = form.cleaned_data['description']
|
|
|
|
if form.cleaned_data['durationtype'] == 'Time':
|
|
ss['durationValue'] = form.cleaned_data['durationvalue']*60000
|
|
elif form.cleaned_data['durationtype'] == 'Distance':
|
|
ss[durationValue] = form.cleaned_data['durationvalue']*100
|
|
|
|
ss['durationValue'] = int(ss['durationValue'])
|
|
ps.fitfile = None
|
|
ps.interval_string = ""
|
|
|
|
ps.save()
|
|
|
|
step.durationtype = form.cleaned_data['durationtype']
|
|
step.durationvalue = form.cleaned_data['durationvalue']
|
|
step.targettype = form.cleaned_data['targettype']
|
|
step.targetvalue = form.cleaned_data['targetvalue']
|
|
step.targetvaluelow = form.cleaned_data['targetvaluelow']
|
|
step.targetvaluehigh = form.cleaned_data['targetvaluehigh']
|
|
step.intensity = form.cleaned_data['intensity']
|
|
step.name = form.cleaned_data['name']
|
|
step.description = form.cleaned_data['description']
|
|
|
|
if step.durationtype == 'Time': # pragma: no cover
|
|
step.durationvalue *= 60000
|
|
elif step.durationtype == 'Distance': # pragma: no cover
|
|
step.durationvalue *= 100
|
|
|
|
step.save()
|
|
|
|
|
|
if step.durationtype == 'Time': # pragma: no cover
|
|
form.fields['durationvalue'].initial = step.durationvalue / 60000
|
|
elif step.durationtype == 'Distance':
|
|
form.fields['durationvalue'].initial = step.durationvalue / 100
|
|
|
|
|
|
stepdescription = step_to_string(step.asdict(), short=False)[0]
|
|
|
|
if request.method == 'POST':
|
|
if 'stepsave_and_return' in request.POST: # pragma: no cover
|
|
url = reverse('stepeditor',kwargs = {'id': ps.id})
|
|
return HttpResponseRedirect(url)
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse('template_library_view'),
|
|
'name': 'Session Templates'
|
|
},
|
|
{
|
|
'url': reverse('plannedsession_templateedit_view', kwargs={'id': ps.id}),
|
|
'name': ps.name
|
|
},
|
|
{
|
|
'url': reverse('stepeditor', kwargs={'id':ps.id}),
|
|
'name': 'Edit Steps'
|
|
},
|
|
{
|
|
'url': reverse('stepedit', kwargs={'psid': ps.id, 'id': step.id}),
|
|
'name': 'Edit Step'
|
|
}
|
|
]
|
|
|
|
return render(request,'stepedit.html',
|
|
{
|
|
'step': step,
|
|
'stepdescription': stepdescription,
|
|
'form': form,
|
|
'ps': ps,
|
|
'breadcrumbs': breadcrumbs,
|
|
})
|
|
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def stepeditor(request, id=0):
|
|
ps = get_object_or_404(PlannedSession, pk=id)
|
|
|
|
currentsteps = []
|
|
if ps.steps:
|
|
for step in ps.steps['steps']:
|
|
durationtype = step.get('durationType','')
|
|
durationvalue = step.get('durationValue',0)
|
|
targetvalue = step.get('targetValue',0)
|
|
targettype = step.get('targetType','')
|
|
targetvaluelow = step.get('targetValueLow',0)
|
|
targetvaluehigh = step.get('targetValueHigh',0)
|
|
intensity = step.get('intensity','Active')
|
|
|
|
archived_steps = PlannedSessionStep.objects.filter(
|
|
manager = request.user,
|
|
durationtype = durationtype,
|
|
durationvalue = durationvalue,
|
|
targetvalue = targetvalue,
|
|
targettype = targettype,
|
|
targetvaluelow = targetvaluelow,
|
|
targetvaluehigh = targetvaluehigh,
|
|
intensity = intensity,
|
|
)
|
|
if not archived_steps.count():
|
|
s = PlannedSessionStep(
|
|
manager = request.user,
|
|
durationtype = durationtype,
|
|
durationvalue = durationvalue,
|
|
targetvalue = targetvalue,
|
|
targettype = targettype,
|
|
targetvaluelow = targetvaluelow,
|
|
targetvaluehigh = targetvaluehigh,
|
|
intensity = intensity,
|
|
name = step.get('wkt_step_name','Step')
|
|
)
|
|
s.save()
|
|
else: # pragma: no cover
|
|
s = archived_steps[0]
|
|
currentsteps.append(s)
|
|
|
|
|
|
form = StepEditorForm()
|
|
|
|
if request.method == 'POST': # pragma: no cover
|
|
form = StepEditorForm(request.POST)
|
|
if form.is_valid():
|
|
step = form.save(commit=False)
|
|
step.manager = request.user
|
|
step.save()
|
|
|
|
|
|
steps = PlannedSessionStep.objects.filter(
|
|
manager=request.user,
|
|
durationtype__in=['Time','Distance','RepeatUntilStepsCmplt']
|
|
).order_by(
|
|
'intensity','-durationvalue','durationtype',
|
|
)
|
|
|
|
stepdescriptions = {}
|
|
|
|
for step in steps:
|
|
stepdescriptions[step.id] = step_to_string(step.asdict(), short=False)[0]
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse('template_library_view'),
|
|
'name': 'Session Templates'
|
|
},
|
|
{
|
|
'url': reverse('plannedsession_templateedit_view', kwargs={'id': ps.id}),
|
|
'name': ps.name
|
|
},
|
|
{
|
|
'url': reverse('stepeditor', kwargs={'id': ps.id}),
|
|
'name': 'Edit Steps'
|
|
}
|
|
]
|
|
|
|
|
|
return render(request, 'stepeditor.html',
|
|
{
|
|
'steps':steps,
|
|
'currentsteps': currentsteps,
|
|
'stepdescriptions': stepdescriptions,
|
|
'form':form,
|
|
'ps':ps,
|
|
'breadcrumbs': breadcrumbs,
|
|
})
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
@permission_required('target.delete_target', fn=get_target_by_pk, raise_exception=True)
|
|
def rower_delete_trainingtarget(request, id=0):
|
|
|
|
target = get_object_or_404(TrainingTarget, pk=id)
|
|
target.delete()
|
|
|
|
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 post(self, request, *args, **kwargs):
|
|
delete_sessions = request.POST.get('delete_sessions',0)
|
|
delete_all_sessions = request.POST.get('delete_all_sessions',0)
|
|
self.object = self.get_object()
|
|
self.object.delete(delete_sessions=delete_sessions, delete_all_sessions=delete_all_sessions)
|
|
return HttpResponseRedirect(self.get_success_url())
|
|
|
|
def get_object(self, *args, **kwargs):
|
|
obj = super(TrainingPlanDelete, self).get_object(*args, **kwargs)
|
|
if not can_delete_plan(self.request.user, obj): # pragma: no cover
|
|
raise PermissionDenied(
|
|
'You are not allowed to delete this training plan')
|
|
|
|
return obj
|
|
|
|
|
|
class MicroCycleDelete(DeleteView): # pragma: no cover
|
|
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 can_delete_cycle(self.request.user, obj):
|
|
raise PermissionDenied(
|
|
'You are not allowed to delete this training plan cycle')
|
|
return obj
|
|
|
|
|
|
class MesoCycleDelete(DeleteView): # pragma: no cover
|
|
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 can_delete_cycle(self.request.user, obj):
|
|
raise PermissionDenied(
|
|
'You are not allowed to delete this training plan cycle')
|
|
|
|
return obj
|
|
|
|
|
|
class MacroCycleDelete(DeleteView): # pragma: no cover
|
|
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 can_delete_cycle(self.request.user, obj):
|
|
raise PermissionDenied(
|
|
'You are not allowed to delete this training plan cycle')
|
|
|
|
return obj
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
def rower_trainingplan_execution_view(request,
|
|
id=0,
|
|
userid=0):
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
r = getrequestrower(request, userid=userid)
|
|
|
|
if int(id) > 0:
|
|
try:
|
|
plan = TrainingPlan.objects.get(id=id)
|
|
except TrainingPlan.DoesNotExist: # pragma: no cover
|
|
raise Http404("Training Plan Does Not Exist")
|
|
if not is_coach_user(request.user, plan.manager.user): # pragma: no cover
|
|
if request.user.rower not in plan.rowers.all():
|
|
raise PermissionDenied("Access denied")
|
|
|
|
if not startdate or not enddate: # pragma: no cover
|
|
if int(id) > 0:
|
|
startdate = plan.startdate
|
|
enddate = plan.enddate
|
|
else:
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
else:
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
if int(id) > 0:
|
|
data, message = get_execution_report(r, startdate, enddate, plan=plan)
|
|
else: # pragma: no cover
|
|
data, message = get_execution_report(r, startdate, enddate)
|
|
|
|
if not data.is_empty():
|
|
script, div = interactive_planchart(data, startdate, enddate)
|
|
else: # pragma: no cover
|
|
script = ''
|
|
div = ''
|
|
messages.error(request, 'The plan does not cover this time range')
|
|
|
|
if int(id):
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view,
|
|
kwargs={'userid': userid}),
|
|
'name': 'Plan'
|
|
},
|
|
{
|
|
'url': reverse(rower_trainingplan_view,
|
|
kwargs={'userid': userid,
|
|
'id': id}),
|
|
'name': plan.name
|
|
},
|
|
{
|
|
'url': reverse(rower_trainingplan_execution_view,
|
|
kwargs={'userid': userid,
|
|
'id': id}),
|
|
'name': 'Execution'
|
|
}
|
|
]
|
|
else: # pragma: no cover
|
|
breadcrumbs = [
|
|
{
|
|
'url': reverse(plannedsessions_view,
|
|
kwargs={'userid': userid}),
|
|
'name': 'Plan'
|
|
},
|
|
{
|
|
'url': reverse(rower_trainingplan_execution_view,
|
|
kwargs={'userid': userid,
|
|
'id': id}),
|
|
'name': 'Execution'
|
|
}
|
|
]
|
|
|
|
return render(request, 'trainingplan_chart.html',
|
|
{
|
|
'todays_date': timezone.now().date(),
|
|
'active': 'nav-plan',
|
|
'breadcrumbs': breadcrumbs,
|
|
'rower': r,
|
|
'the_script': script,
|
|
'the_div': div
|
|
}
|
|
)
|
|
|
|
|
|
# @user_passes_test(can_plan,login_url="/rowers/paidplans",
|
|
# message="This functionality requires a Coach or Self-Coach plan",
|
|
# redirect_field_name=None)
|
|
@login_required()
|
|
@permission_required('plan.view_plan', fn=get_plan_by_pk, raise_exception=True)
|
|
def rower_trainingplan_view(request,
|
|
id=0,
|
|
userid=0,
|
|
thismicroid=0,
|
|
thismacroid=0,
|
|
thismesoid=0):
|
|
|
|
startdate, enddate = get_dates_timeperiod(request)
|
|
startdate = startdate.date()
|
|
enddate = enddate.date()
|
|
|
|
plan = get_object_or_404(TrainingPlan, pk=id)
|
|
r = getrequestrower(request, userid=userid)
|
|
|
|
createmacrofillers(plan)
|
|
macrocycles = TrainingMacroCycle.objects.filter(
|
|
plan=plan,
|
|
type='userdefined').order_by("startdate")
|
|
|
|
checkscores(r, macrocycles)
|
|
|
|
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: # pragma: no cover
|
|
thismicroid = None
|
|
|
|
return render(request, 'trainingplan.html',
|
|
{
|
|
'plan': plan,
|
|
'todays_date': timezone.now().date(),
|
|
'active': 'nav-plan',
|
|
'breadcrumbs': breadcrumbs,
|
|
'rower': r,
|
|
'cycles': cycles,
|
|
'thismicroid': thismicroid,
|
|
'thismacroid': thismacroid,
|
|
'thismesoid': thismesoid,
|
|
}
|
|
)
|
|
|
|
|
|
class TrainingMacroCycleUpdate(UpdateView): # pragma: no cover
|
|
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 not can_change_cycle(self.request.user, obj):
|
|
raise PermissionDenied(
|
|
'You are not allowed to edit this training plan cycle')
|
|
else:
|
|
obj.type = 'userdefined'
|
|
obj.save()
|
|
return obj
|
|
|
|
|
|
class TrainingMesoCycleUpdate(UpdateView): # pragma: no cover
|
|
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 not can_change_cycle(self.request.user, obj):
|
|
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): # pragma: no cover
|
|
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()
|
|
_ = form.save()
|
|
|
|
return super(TrainingMicroCycleUpdate, self).form_valid(form)
|
|
|
|
def get_object(self, *args, **kwargs):
|
|
obj = super(TrainingMicroCycleUpdate, self).get_object(*args, **kwargs)
|
|
if not can_change_cycle(self.request.user, obj):
|
|
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): # pragma: no cover
|
|
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 not can_change_plan(self.request.user, obj):
|
|
raise PermissionDenied(
|
|
'You are not allowed to edit this training plan cycle')
|
|
|
|
return obj
|
|
|
|
|
|
class TrainingTargetUpdate(UpdateView): # pragma: no cover
|
|
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()
|
|
_ = form.save()
|
|
return super(TrainingTargetUpdate, self).form_valid(form)
|
|
|
|
def get_object(self, *args, **kwargs):
|
|
obj = super(TrainingTargetUpdate, self).get_object(*args, **kwargs)
|
|
if not can_change_target(self.request.user, obj):
|
|
raise PermissionDenied(
|
|
'You are not allowed to edit this training plan cycle')
|
|
|
|
return obj
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
@permission_required('cycle.change_cycle', fn=get_meso_by_pk, raise_exception=True)
|
|
def planmesocyclebyweek(request, id=0, userid=0): # pragma: no cover
|
|
cycle = get_object_or_404(TrainingMesoCycle, pk=id)
|
|
|
|
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)
|
|
|
|
|
|
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
|
message="This functionality requires a Coach or Self-Coach plan",
|
|
redirect_field_name=None)
|
|
@permission_required('cycle.change_cycle', fn=get_macro_by_pk, raise_exception=True)
|
|
def planmacrocyclebymonth(request, id=0, userid=0): # pragma: no cover
|
|
cycle = get_object_or_404(TrainingMacroCycle, pk=id)
|
|
|
|
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)
|