starting plan view tests
This commit is contained in:
@@ -246,7 +246,7 @@ class PowerTimeFitnessMetric(models.Model):
|
|||||||
('water','On the water')
|
('water','On the water')
|
||||||
)
|
)
|
||||||
|
|
||||||
date = models.DateField(default=timezone.now)
|
date = models.DateField(default=datetime.date.today)
|
||||||
last_workout = models.IntegerField(default=0)
|
last_workout = models.IntegerField(default=0)
|
||||||
user = models.ForeignKey(User)
|
user = models.ForeignKey(User)
|
||||||
PowerFourMin = models.FloatField(default=0)
|
PowerFourMin = models.FloatField(default=0)
|
||||||
@@ -334,7 +334,7 @@ class TeamForm(ModelForm):
|
|||||||
class TeamInvite(models.Model):
|
class TeamInvite(models.Model):
|
||||||
team = models.ForeignKey(Team)
|
team = models.ForeignKey(Team)
|
||||||
user = models.ForeignKey(User,null=True)
|
user = models.ForeignKey(User,null=True)
|
||||||
issuedate = models.DateField(default=timezone.now)
|
issuedate = models.DateField(default=datetime.date.today)
|
||||||
code = models.CharField(max_length=150,unique=True)
|
code = models.CharField(max_length=150,unique=True)
|
||||||
email = models.CharField(max_length=150,null=True,blank=True)
|
email = models.CharField(max_length=150,null=True,blank=True)
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ class TeamInviteForm(ModelForm):
|
|||||||
class TeamRequest(models.Model):
|
class TeamRequest(models.Model):
|
||||||
team = models.ForeignKey(Team)
|
team = models.ForeignKey(Team)
|
||||||
user = models.ForeignKey(User,null=True)
|
user = models.ForeignKey(User,null=True)
|
||||||
issuedate = models.DateField(default=timezone.now)
|
issuedate = models.DateField(default=datetime.date.today)
|
||||||
code = models.CharField(max_length=150,unique=True)
|
code = models.CharField(max_length=150,unique=True)
|
||||||
|
|
||||||
from utils import (
|
from utils import (
|
||||||
@@ -655,8 +655,8 @@ class Rower(models.Model):
|
|||||||
|
|
||||||
paidplan = models.ForeignKey(PaidPlan,null=True,default=None)
|
paidplan = models.ForeignKey(PaidPlan,null=True,default=None)
|
||||||
|
|
||||||
planexpires = models.DateField(default=timezone.now)
|
planexpires = models.DateField(default=datetime.date.today)
|
||||||
teamplanexpires = models.DateField(default=timezone.now)
|
teamplanexpires = models.DateField(default=datetime.date.today)
|
||||||
clubsize = models.IntegerField(default=0)
|
clubsize = models.IntegerField(default=0)
|
||||||
protrialexpires = models.DateField(blank=True,null=True)
|
protrialexpires = models.DateField(blank=True,null=True)
|
||||||
plantrialexpires = models.DateField(blank=True,null=True)
|
plantrialexpires = models.DateField(blank=True,null=True)
|
||||||
@@ -1022,10 +1022,10 @@ class GeoPoint(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
def half_year_from_now():
|
def half_year_from_now():
|
||||||
return timezone.now()+timezone.timedelta(days=182)
|
return (timezone.now()+timezone.timedelta(days=182)).date()
|
||||||
|
|
||||||
def a_week_from_now():
|
def a_week_from_now():
|
||||||
return timezone.now()+timezone.timedelta(days=7)
|
return (timezone.now()+timezone.timedelta(days=7)).date()
|
||||||
|
|
||||||
# models related to training planning - draft
|
# models related to training planning - draft
|
||||||
# Do we need a separate class TestTarget?
|
# Do we need a separate class TestTarget?
|
||||||
@@ -1089,20 +1089,6 @@ class TrainingTargetForm(ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# SportTracks has a TrainingGoal like this
|
|
||||||
#class TrainingGoal(models.Model):
|
|
||||||
# rower = models.ForeignKey(Rower)
|
|
||||||
# name = models.CharField(max_length=150,blank=True)
|
|
||||||
# startdate = models.DateField(default=timezone.now)
|
|
||||||
# enddate = models.DateField(
|
|
||||||
# default=timezone.now()+datetime.timedelta(days=28))
|
|
||||||
# goalmetric = models.CharField(max_length=150,default='rower',
|
|
||||||
# choices = modechoices)
|
|
||||||
# value = models.IntegerValue(default=1)
|
|
||||||
|
|
||||||
# I think we can use PlannedSession for that (in challenge mode)
|
|
||||||
# although such a TrainingGoal could have automatically calculated
|
|
||||||
# values without needing the user to assign
|
|
||||||
|
|
||||||
|
|
||||||
class TrainingPlan(models.Model):
|
class TrainingPlan(models.Model):
|
||||||
@@ -1118,7 +1104,7 @@ class TrainingPlan(models.Model):
|
|||||||
name = models.CharField(max_length=150,blank=True)
|
name = models.CharField(max_length=150,blank=True)
|
||||||
status = models.BooleanField(default=True,verbose_name='Active')
|
status = models.BooleanField(default=True,verbose_name='Active')
|
||||||
target = models.ForeignKey(TrainingTarget,blank=True,null=True)
|
target = models.ForeignKey(TrainingTarget,blank=True,null=True)
|
||||||
startdate = models.DateField(default=timezone.now)
|
startdate = models.DateField(default=datetime.date.today)
|
||||||
enddate = models.DateField(
|
enddate = models.DateField(
|
||||||
default=half_year_from_now)
|
default=half_year_from_now)
|
||||||
|
|
||||||
@@ -1482,7 +1468,7 @@ def macrocyclecheckdates(plan):
|
|||||||
class TrainingMacroCycle(models.Model):
|
class TrainingMacroCycle(models.Model):
|
||||||
plan = models.ForeignKey(TrainingPlan)
|
plan = models.ForeignKey(TrainingPlan)
|
||||||
name = models.CharField(max_length=150,blank=True)
|
name = models.CharField(max_length=150,blank=True)
|
||||||
startdate = models.DateField(default=timezone.now)
|
startdate = models.DateField(default=datetime.date.today)
|
||||||
enddate = models.DateField(
|
enddate = models.DateField(
|
||||||
default=half_year_from_now)
|
default=half_year_from_now)
|
||||||
notes = models.TextField(max_length=300,blank=True)
|
notes = models.TextField(max_length=300,blank=True)
|
||||||
@@ -1568,7 +1554,7 @@ class TrainingMacroCycleForm(ModelForm):
|
|||||||
class TrainingMesoCycle(models.Model):
|
class TrainingMesoCycle(models.Model):
|
||||||
plan = models.ForeignKey(TrainingMacroCycle)
|
plan = models.ForeignKey(TrainingMacroCycle)
|
||||||
name = models.CharField(max_length=150,blank=True)
|
name = models.CharField(max_length=150,blank=True)
|
||||||
startdate = models.DateField(default=timezone.now)
|
startdate = models.DateField(default=datetime.date.today)
|
||||||
enddate = models.DateField(
|
enddate = models.DateField(
|
||||||
default=half_year_from_now)
|
default=half_year_from_now)
|
||||||
notes = models.TextField(max_length=300,blank=True)
|
notes = models.TextField(max_length=300,blank=True)
|
||||||
@@ -1643,7 +1629,7 @@ class TrainingMesoCycle(models.Model):
|
|||||||
class TrainingMicroCycle(models.Model):
|
class TrainingMicroCycle(models.Model):
|
||||||
plan = models.ForeignKey(TrainingMesoCycle)
|
plan = models.ForeignKey(TrainingMesoCycle)
|
||||||
name = models.CharField(max_length=150,blank=True)
|
name = models.CharField(max_length=150,blank=True)
|
||||||
startdate = models.DateField(default=timezone.now)
|
startdate = models.DateField(default=datetime.date.today)
|
||||||
enddate = models.DateField(
|
enddate = models.DateField(
|
||||||
default=half_year_from_now)
|
default=half_year_from_now)
|
||||||
notes = models.TextField(max_length=300,blank=True)
|
notes = models.TextField(max_length=300,blank=True)
|
||||||
@@ -1790,7 +1776,7 @@ class PlannedSession(models.Model):
|
|||||||
comment = models.TextField(max_length=500,blank=True,
|
comment = models.TextField(max_length=500,blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
startdate = models.DateField(default=timezone.now,
|
startdate = models.DateField(default=datetime.date.today,
|
||||||
verbose_name='On or After')
|
verbose_name='On or After')
|
||||||
|
|
||||||
enddate = models.DateField(default=a_week_from_now,
|
enddate = models.DateField(default=a_week_from_now,
|
||||||
@@ -3302,10 +3288,10 @@ class RowerForm(ModelForm):
|
|||||||
# An announcement that goes to the right of the workouts list
|
# An announcement that goes to the right of the workouts list
|
||||||
# optionally sends a tweet to our twitter account
|
# optionally sends a tweet to our twitter account
|
||||||
class SiteAnnouncement(models.Model):
|
class SiteAnnouncement(models.Model):
|
||||||
created = models.DateField(default=timezone.now)
|
created = models.DateField(default=datetime.date.today)
|
||||||
announcement = models.TextField(max_length=280)
|
announcement = models.TextField(max_length=280)
|
||||||
expires = models.DateField(default=timezone.now)
|
expires = models.DateField(default=datetime.date.today)
|
||||||
modified = models.DateField(default=timezone.now)
|
modified = models.DateField(default=datetime.date.today)
|
||||||
dotweet = models.BooleanField(default=False)
|
dotweet = models.BooleanField(default=False)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#from __future__ import print_function
|
#from __future__ import print_function
|
||||||
from statements import *
|
from statements import *
|
||||||
nu = datetime.datetime.now()
|
nu = datetime.datetime.now()
|
||||||
|
from rowers.utils import allmonths,allsundays
|
||||||
|
|
||||||
import rowers.plannedsessions as plannedsessions
|
import rowers.plannedsessions as plannedsessions
|
||||||
|
|
||||||
@@ -988,3 +989,213 @@ class MandatoryTestCompleteTest(TestCase):
|
|||||||
response = self.c.get(url)
|
response = self.c.get(url)
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
|
class PlannedSessionsView(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
# user
|
||||||
|
self.u = UserFactory()
|
||||||
|
|
||||||
|
self.r = Rower.objects.create(user=self.u,
|
||||||
|
birthdate=faker.profile()['birthdate'],
|
||||||
|
gdproptin=True,
|
||||||
|
gdproptindate=timezone.now(),
|
||||||
|
rowerplan='coach')
|
||||||
|
self.r.save()
|
||||||
|
self.c = Client()
|
||||||
|
|
||||||
|
# workouts
|
||||||
|
# workout 1 - 2019-01-13, rScore 69
|
||||||
|
result = get_random_file(filename='rowers/tests/testdata/2019-01-13_session.csv',name='sprintervals')
|
||||||
|
|
||||||
|
|
||||||
|
self.factory = RequestFactory()
|
||||||
|
self.password = faker.word()
|
||||||
|
self.u.set_password(self.password)
|
||||||
|
self.u.save()
|
||||||
|
|
||||||
|
self.w1 = Workout.objects.create(
|
||||||
|
name='sprintervals',
|
||||||
|
notes=faker.text(),
|
||||||
|
startdatetime = result['startdatetime'],
|
||||||
|
starttime = result['starttime'],
|
||||||
|
workouttype='rower',
|
||||||
|
date=result['date'],
|
||||||
|
duration=result['duration'],
|
||||||
|
distance=result['totaldist'],
|
||||||
|
csvfilename=result['filename'],
|
||||||
|
trimp = 77,
|
||||||
|
rscore = 69,
|
||||||
|
hrtss = 43,
|
||||||
|
normp = 236,
|
||||||
|
user=self.u.rower,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# plan
|
||||||
|
self.target = TrainingTarget.objects.create(
|
||||||
|
name = faker.word(),
|
||||||
|
manager = self.u.rower,
|
||||||
|
notes = faker.text()
|
||||||
|
)
|
||||||
|
self.target.rowers.add(self.u.rower)
|
||||||
|
self.target.save()
|
||||||
|
|
||||||
|
self.plan = TrainingPlan.objects.create(
|
||||||
|
manager = self.u.rower,
|
||||||
|
name = faker.word(),
|
||||||
|
status=True,
|
||||||
|
target = self.target,
|
||||||
|
startdate=timezone.now().date(),
|
||||||
|
enddate = self.target.date,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.plan.rowers.add(self.u.rower)
|
||||||
|
self.plan.save()
|
||||||
|
|
||||||
|
# cycles
|
||||||
|
self.macro = TrainingMacroCycle.objects.create(
|
||||||
|
plan=self.plan,
|
||||||
|
name=faker.word(),
|
||||||
|
type='userdefined',
|
||||||
|
notes = faker.text(),
|
||||||
|
startdate = self.plan.startdate,
|
||||||
|
enddate = self.plan.enddate,
|
||||||
|
)
|
||||||
|
|
||||||
|
mesos = TrainingMesoCycle.objects.filter(plan=self.macro)
|
||||||
|
for m in mesos:
|
||||||
|
m.delete()
|
||||||
|
|
||||||
|
monthstarts = [d for d in allmonths(self.macro.startdate,self.macro.enddate)]
|
||||||
|
monthstarts.append(self.macro.enddate)
|
||||||
|
|
||||||
|
for i in range(len(monthstarts)-1):
|
||||||
|
firstday = monthstarts[i]
|
||||||
|
lastday = monthstarts[i+1]-datetime.timedelta(days=1)
|
||||||
|
if lastday < self.macro.enddate and i == len(monthstarts)-2:
|
||||||
|
lastday = self.macro.enddate
|
||||||
|
|
||||||
|
meso = TrainingMesoCycle(startdate=firstday,
|
||||||
|
enddate=lastday,
|
||||||
|
plan=self.macro,
|
||||||
|
name = '%s' % firstday.strftime("%B"),
|
||||||
|
type = 'userdefined')
|
||||||
|
meso.save()
|
||||||
|
|
||||||
|
mesos = TrainingMesoCycle.objects.filter(plan=self.macro)
|
||||||
|
|
||||||
|
for cycle in mesos:
|
||||||
|
micros = TrainingMicroCycle.objects.filter(plan=cycle)
|
||||||
|
for m in micros:
|
||||||
|
m.delete()
|
||||||
|
|
||||||
|
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]-datetime.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()
|
||||||
|
|
||||||
|
|
||||||
|
# sessions
|
||||||
|
startdatetime = self.w1.startdatetime
|
||||||
|
|
||||||
|
startdate = (startdatetime-datetime.timedelta(days=1)).date()
|
||||||
|
enddate = (startdatetime+datetime.timedelta(days=1)).date()
|
||||||
|
preferreddate = startdatetime.date()
|
||||||
|
|
||||||
|
self.ps_rscore = SessionFactory(
|
||||||
|
startdate=startdate,enddate=enddate,
|
||||||
|
sessiontype='test',
|
||||||
|
sessionmode = 'rScore',
|
||||||
|
criterium = 'none',
|
||||||
|
sessionvalue = 69,
|
||||||
|
sessionunit='None',
|
||||||
|
preferreddate=preferreddate,
|
||||||
|
manager=self.u,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.ps_rscore.save()
|
||||||
|
added = plannedsessions.add_rower_session(self.u.rower,self.ps_rscore)
|
||||||
|
|
||||||
|
self.ps_dist = SessionFactory(
|
||||||
|
startdate=startdate,enddate=enddate,
|
||||||
|
sessiontype='test',
|
||||||
|
sessionmode = 'distance',
|
||||||
|
criterium = 'none',
|
||||||
|
sessionvalue = result['totaldist'],
|
||||||
|
sessionunit='m',
|
||||||
|
preferreddate=preferreddate,
|
||||||
|
manager=self.u,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.ps_dist.save()
|
||||||
|
added = plannedsessions.add_rower_session(self.u.rower,self.ps_dist)
|
||||||
|
|
||||||
|
self.ps_time = SessionFactory(
|
||||||
|
startdate=startdate,enddate=enddate,
|
||||||
|
sessiontype='test',
|
||||||
|
sessionmode = 'time',
|
||||||
|
criterium = 'none',
|
||||||
|
sessionvalue = 38,
|
||||||
|
sessionunit='min',
|
||||||
|
preferreddate=preferreddate,
|
||||||
|
manager=self.u,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.ps_time.save()
|
||||||
|
added = plannedsessions.add_rower_session(self.u.rower,self.ps_time)
|
||||||
|
|
||||||
|
self.ps_trimp = SessionFactory(
|
||||||
|
startdate=startdate,enddate=enddate,
|
||||||
|
sessiontype='test',
|
||||||
|
sessionmode = 'TRIMP',
|
||||||
|
criterium = 'none',
|
||||||
|
sessionvalue = 77,
|
||||||
|
sessionunit='none',
|
||||||
|
preferreddate=preferreddate,
|
||||||
|
manager=self.u,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.ps_trimp.save()
|
||||||
|
added = plannedsessions.add_rower_session(self.u.rower,self.ps_trimp)
|
||||||
|
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
os.remove(self.w1.csvfilename)
|
||||||
|
except (IOError, WindowsError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_clone_view(self):
|
||||||
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
|
self.assertTrue(login)
|
||||||
|
|
||||||
|
url = '/rowers/sessions/{id}/clone/'.format(id=self.ps_trimp.id)
|
||||||
|
|
||||||
|
response = self.c.get(url,follow=True)
|
||||||
|
self.assertEqual(response.status_code,200)
|
||||||
|
self.assertRedirects(response,
|
||||||
|
expected_url='/rowers/session/5/edit/user/1/?when=2019-02-04/2019-02-10',
|
||||||
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
|||||||
BIN
rowers/tests/testdata/testdata.csv.gz
vendored
BIN
rowers/tests/testdata/testdata.csv.gz
vendored
Binary file not shown.
@@ -468,3 +468,17 @@ def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high
|
|||||||
s = requests.get(url,headers=headers)
|
s = requests.get(url,headers=headers)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def allmonths(startdate,enddate):
|
||||||
|
d = startdate
|
||||||
|
while d<enddate:
|
||||||
|
yield d
|
||||||
|
d = datetime.date(d.year+(d.month / 12),((d.month % 12) + 1),1)
|
||||||
|
|
||||||
|
def allsundays(startdate,enddate):
|
||||||
|
d = startdate
|
||||||
|
d += datetime.timedelta(days = 6 - d.weekday()) # first Sunday
|
||||||
|
while d<=enddate:
|
||||||
|
yield d
|
||||||
|
d += datetime.timedelta(days=7)
|
||||||
|
|
||||||
|
|||||||
@@ -18412,12 +18412,7 @@ class TrainingTargetUpdate(UpdateView):
|
|||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def allsundays(startdate,enddate):
|
from rowers.utils import allsundays
|
||||||
d = startdate
|
|
||||||
d += timedelta(days = 6 - d.weekday()) # first Sunday
|
|
||||||
while d<=enddate:
|
|
||||||
yield d
|
|
||||||
d += timedelta(days=7)
|
|
||||||
|
|
||||||
@user_passes_test(hasplannedsessions,login_url="/rowers/paidplans",
|
@user_passes_test(hasplannedsessions,login_url="/rowers/paidplans",
|
||||||
message="This functionality requires a Coach or Self-Coach plan",
|
message="This functionality requires a Coach or Self-Coach plan",
|
||||||
@@ -18472,12 +18467,7 @@ def planmesocyclebyweek(request,id=0,userid=0):
|
|||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
from rowers.utils import allmonths
|
||||||
def allmonths(startdate,enddate):
|
|
||||||
d = startdate
|
|
||||||
while d<enddate:
|
|
||||||
yield d
|
|
||||||
d = datetime.date(d.year+(d.month / 12),((d.month % 12) + 1),1)
|
|
||||||
|
|
||||||
@user_passes_test(hasplannedsessions,login_url="/rowers/paidplans",
|
@user_passes_test(hasplannedsessions,login_url="/rowers/paidplans",
|
||||||
message="This functionality requires a Coach or Self-Coach plan",
|
message="This functionality requires a Coach or Self-Coach plan",
|
||||||
|
|||||||
Reference in New Issue
Block a user