From ada4cdb225baa9b42ff1b2a0cb7910330102fb93 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 29 Oct 2018 16:33:55 +0100 Subject: [PATCH 1/3] first cut --- rowers/models.py | 44 +++++++++++++++------- rowers/templates/trainingplan_create.html | 2 + rowers/views.py | 46 ++++++++++++----------- 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/rowers/models.py b/rowers/models.py index 67cb73c1..de1946fa 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -983,9 +983,18 @@ class TrainingTargetForm(ModelForm): class TrainingPlan(models.Model): - rower = models.ForeignKey(Rower,related_name='planathlete') + + statuschoices = ( + ('active','active'), + ('deactivated','inactive'), + ) + + # rower field is obsolete. Use rowers + rower = models.ForeignKey(Rower,related_name='planathlete',null=True) + rowers = models.ManyToManyField(Rower,related_name='planathletes') manager = models.ForeignKey(Rower,related_name='planmanager',null=True) - name = models.CharField(max_length=150,blank=True) + name = models.CharField(max_length=150,blank=True) + status = models.CharField(max_length=150,default='active',choices=statuschoices) target = models.ForeignKey(TrainingTarget,blank=True,null=True) startdate = models.DateField(default=timezone.now) enddate = models.DateField( @@ -995,10 +1004,10 @@ class TrainingPlan(models.Model): name = self.name startdate = self.startdate enddate = self.enddate - firstname = self.rower.user.first_name - lastname = self.rower.user.last_name + firstname = self.manager.user.first_name + lastname = self.manager.user.last_name - stri = u'Training Plan for {firstname} {lastname} {s} - {e}: {name}'.format( + stri = u'Training Plan by {firstname} {lastname} {s} - {e}: {name}'.format( s = startdate.strftime('%Y-%m-%d'), e = enddate.strftime('%Y-%m-%d'), firstname = firstname, @@ -1014,18 +1023,27 @@ class TrainingPlan(models.Model): enddate = self.enddate self.startdate = enddate self.enddate = startdate - - otherplans = TrainingPlan.objects.filter(rower=self.rower).exclude(pk=self.pk).order_by("-startdate") - for otherplan in otherplans: - if otherplan.startdate <= self.enddate and otherplan.startdate >= self.startdate: - self.enddate = otherplan.startdate-datetime.timedelta(days=1) - if otherplan.enddate >= self.startdate and otherplan.enddate <= self.enddate: - self.startdate = otherplan.enddate+datetime.timedelta(days=1) + if self.status == 'active': + otherplans = TrainingPlan.objects.filter( + rower=self.rower, + status='active').exclude(pk=self.pk).order_by("-startdate") + + for otherplan in otherplans: + if otherplan.startdate <= self.enddate and otherplan.startdate >= self.startdate: + self.status = 'deactivated' + if otherplan.enddate >= self.startdate and otherplan.enddate <= self.enddate: + self.status = 'deactivated' if not self.enddate <= self.startdate: super(TrainingPlan,self).save(*args, **kwargs) + if self.rower is not None: + self.rowers.add(self.rower) + self.rower = None + self.save() + + macrocycles = TrainingMacroCycle.objects.filter(plan = self) if not macrocycles: m = TrainingMacroCycle( @@ -1043,7 +1061,7 @@ class TrainingPlan(models.Model): class TrainingPlanForm(ModelForm): class Meta: model = TrainingPlan - fields = ['name','target','startdate','enddate'] + fields = ['name','target','startdate','enddate','status'] widgets = { 'startdate': AdminDateWidget(), diff --git a/rowers/templates/trainingplan_create.html b/rowers/templates/trainingplan_create.html index cbf7ffb6..013ada82 100644 --- a/rowers/templates/trainingplan_create.html +++ b/rowers/templates/trainingplan_create.html @@ -62,6 +62,7 @@ Start Date End Date Name + Status @@ -70,6 +71,7 @@ {{ plan.startdate }} {{ plan.enddate }} {{ plan.name }} + {{ plan.status }} Edit Plan Delete diff --git a/rowers/views.py b/rowers/views.py index 3396d11b..7c56c41f 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -14032,7 +14032,7 @@ def plannedsession_multiclone_view( try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14178,7 +14178,7 @@ def plannedsession_create_view(request, try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14211,7 +14211,7 @@ def plannedsession_multicreate_view(request, try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14468,7 +14468,7 @@ def plannedsession_teamedit_view(request, try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14702,7 +14702,7 @@ def plannedsessions_view(request, try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14765,7 +14765,7 @@ def plannedsessions_print_view(request,userid=0): try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14807,7 +14807,7 @@ def plannedsessions_manage_view(request,userid=0, try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -14961,7 +14961,7 @@ def plannedsession_clone_view(request,id=0,userid=0): try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -15026,7 +15026,7 @@ def plannedsession_edit_view(request,id=0,userid=0): try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -15243,7 +15243,7 @@ def plannedsession_view(request,id=0,userid=0): try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, - rower = r, + rowers = r, enddate__gte = enddate)[0] except IndexError: trainingplan = None @@ -16156,7 +16156,7 @@ def rower_create_trainingplan(request,userid=0): date = targetform.cleaned_data['date'] notes = targetform.cleaned_data['notes'] - t = TrainingTarget(rower=therower, + t = TrainingTarget(rowers=[therower], name=name, date=date, manager=themanager, @@ -16189,6 +16189,10 @@ def rower_create_trainingplan(request,userid=0): targetform = TrainingTargetForm() plans = TrainingPlan.objects.filter(rower=therower).order_by("-startdate") + plans2 = TrainingPlan.objects.filter(rowers=therower).order_by("-startdate") + + plans = plans | plans2 + form = TrainingPlanForm(targets=targets) breadcrumbs = [ @@ -16564,12 +16568,16 @@ def rower_trainingplan_view(request, try: plan = TrainingPlan.objects.get(id=id) + if plan.rower is not None: + plan.rowers.add(plan.rower) + plan.rower = None + plan.save() except TrainingPlan.DoesNotExist: raise Http404("Training Plan Does Not Exist") r = getrequestrower(request,userid=userid) - if not checkaccessuser(request.user,plan.rower): + if not checkaccessuser(request.user,plan.manager): raise PermissionDenied("Access denied") createmacrofillers(plan) @@ -16677,8 +16685,6 @@ def rower_trainingplan_view(request, count = 0 cycles = {} - r = plan.rower - for m in macrocycles: createmesofillers(m) mesocycles = TrainingMesoCycle.objects.filter(plan=m).order_by("startdate") @@ -16787,7 +16793,7 @@ class TrainingMacroCycleUpdate(UpdateView): if obj.plan.manager is not None and self.request.user.rower != obj.plan.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') - if not checkaccessuser(self.request.user,obj.plan.rower): + if not checkaccessuser(self.request.user,obj.plan.manager): raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' @@ -16862,7 +16868,7 @@ class TrainingMesoCycleUpdate(UpdateView): if obj.plan.plan.manager is not None and self.request.user.rower != obj.plan.plan.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') - if not checkaccessuser(self.request.user,r): + if r is not None and not checkaccessuser(self.request.user,r): raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' @@ -16943,7 +16949,7 @@ class TrainingMicroCycleUpdate(UpdateView): if obj.plan.plan.plan.manager is not None and self.request.user.rower != obj.plan.plan.plan.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') - if not checkaccessuser(self.request.user,r): + if r is not None and not checkaccessuser(self.request.user,r): raise PermissionDenied('You are not allowed to edit this training plan cycle') else: obj.type = 'userdefined' @@ -17006,11 +17012,9 @@ class TrainingPlanUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingPlanUpdate, self).get_object(*args, **kwargs) - if obj.manager is not None and self.request.user.rower != obj.manager.user: + if obj.manager is not None and self.request.user.rower != obj.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') - if not checkaccessuser(self.request.user,obj.rower): - raise PermissionDenied('You are not allowed to edit this training plan cycle') return obj class TrainingTargetUpdate(UpdateView): @@ -17029,7 +17033,7 @@ class TrainingTargetUpdate(UpdateView): def get_object(self, *args, **kwargs): obj = super(TrainingTargetUpdate, self).get_object(*args, **kwargs) - if obj.manager is not None and self.request.user.rower != obj.manager.user: + if obj.manager is not None and self.request.user.rower != obj.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') if not checkaccessuser(self.request.user,obj.rower): From 8369eb1042fb7d70affec56a172ee7c229ee34de Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 29 Oct 2018 20:29:20 +0100 Subject: [PATCH 2/3] multiple athletes for plans and targets --- rowers/models.py | 60 +++++++++++++++++----- rowers/templates/trainingplan_create.html | 2 +- rowers/templatetags/rowerfilters.py | 6 ++- rowers/views.py | 61 +++++++++++++++++++---- 4 files changed, 103 insertions(+), 26 deletions(-) diff --git a/rowers/models.py b/rowers/models.py index de1946fa..c2cd5004 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -934,7 +934,9 @@ def a_week_from_now(): # models related to training planning - draft # Do we need a separate class TestTarget? class TrainingTarget(models.Model): - rower = models.ForeignKey(Rower,related_name='targetathlete') + rower = models.ForeignKey(Rower,related_name='targetathlete',null=True) + rowers = models.ManyToManyField(Rower, related_name='targetathletes', + verbose_name='Athletes') manager = models.ForeignKey(Rower,related_name='targetmanager',null=True) name = models.CharField(max_length=150,blank=True) date = models.DateField( @@ -944,8 +946,12 @@ class TrainingTarget(models.Model): def __unicode__(self): date = self.date name = self.name - ownerfirst = self.rower.user.first_name - ownerlast = self.rower.user.last_name + try: + ownerfirst = self.manager.user.first_name + ownerlast = self.manager.user.last_name + except AttributeError: + ownerfirst = '' + ownerlast = '' stri = u'{ownerfirst} {ownerlast} {d} {n}'.format( ownerfirst = ownerfirst, @@ -959,12 +965,24 @@ class TrainingTarget(models.Model): class TrainingTargetForm(ModelForm): class Meta: model = TrainingTarget - fields = ['name','date','notes'] + fields = ['name','date','notes','rowers'] widgets = { 'date': AdminDateWidget() } + def __init__(self,*args, **kwargs): + super(TrainingTargetForm, self).__init__(*args, **kwargs) + + try: + teams = Team.objects.filter(manager=self.instance.manager.user) + + self.fields['rowers'].queryset = Rower.objects.filter( + team__in=teams + ).distinct().order_by("user__last_name","user__first_name") + except AttributeError: + self.fields.pop('rowers') + # SportTracks has a TrainingGoal like this #class TrainingGoal(models.Model): @@ -991,10 +1009,11 @@ class TrainingPlan(models.Model): # rower field is obsolete. Use rowers rower = models.ForeignKey(Rower,related_name='planathlete',null=True) - rowers = models.ManyToManyField(Rower,related_name='planathletes') + rowers = models.ManyToManyField(Rower,related_name='planathletes', + verbose_name='Athletes') manager = models.ForeignKey(Rower,related_name='planmanager',null=True) name = models.CharField(max_length=150,blank=True) - status = models.CharField(max_length=150,default='active',choices=statuschoices) + status = models.BooleanField(default=True,verbose_name='Active') target = models.ForeignKey(TrainingTarget,blank=True,null=True) startdate = models.DateField(default=timezone.now) enddate = models.DateField( @@ -1024,16 +1043,23 @@ class TrainingPlan(models.Model): self.startdate = enddate self.enddate = startdate - if self.status == 'active': + if self.status: otherplans = TrainingPlan.objects.filter( - rower=self.rower, - status='active').exclude(pk=self.pk).order_by("-startdate") + status=True).exclude( + pk=self.pk).order_by( + "-startdate") for otherplan in otherplans: if otherplan.startdate <= self.enddate and otherplan.startdate >= self.startdate: - self.status = 'deactivated' + for rower in self.rowers.all(): + if rower in otherplan.rowers.all(): + print otherplan + self.status = False if otherplan.enddate >= self.startdate and otherplan.enddate <= self.enddate: - self.status = 'deactivated' + for rower in self.rowers.all(): + if rower in otherplan.rowers.all(): + print otherplan + self.status = False if not self.enddate <= self.startdate: super(TrainingPlan,self).save(*args, **kwargs) @@ -1061,7 +1087,7 @@ class TrainingPlan(models.Model): class TrainingPlanForm(ModelForm): class Meta: model = TrainingPlan - fields = ['name','target','startdate','enddate','status'] + fields = ['name','target','startdate','enddate','status','rowers'] widgets = { 'startdate': AdminDateWidget(), @@ -1076,8 +1102,16 @@ class TrainingPlanForm(ModelForm): targetchoices = [(x.id,x) for x in targets] targetchoices.append((None,'---')) self.fields['target'].choices = targetchoices + + try: + teams = Team.objects.filter(manager=self.instance.manager.user) + + self.fields['rowers'].queryset = Rower.objects.filter( + team__in=teams + ).distinct().order_by("user__last_name","user__first_name") + except AttributeError: + self.fields.pop('rowers') - cycletypechoices = ( ('filler','System Defined'), ('userdefined','User Defined') diff --git a/rowers/templates/trainingplan_create.html b/rowers/templates/trainingplan_create.html index 013ada82..2ec6d3d1 100644 --- a/rowers/templates/trainingplan_create.html +++ b/rowers/templates/trainingplan_create.html @@ -71,7 +71,7 @@ {{ plan.startdate }} {{ plan.enddate }} {{ plan.name }} - {{ plan.status }} + {% if plan.status %} active {% else %} inactive {% endif %} Edit Plan Delete diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index c8f67040..1707661d 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -273,7 +273,7 @@ def team_members(user): members = Rower.objects.filter( team__in=teams ).distinct().order_by( - "user__last_name","user__last_name" + "user__last_name","user__first_name" ) return [rower.user for rower in members] except TypeError: @@ -397,7 +397,9 @@ def timeurl(path,timestring): @register.filter def trainingplans(rower): - plans = TrainingPlan.objects.filter(rower=rower).order_by("-startdate") + plans = TrainingPlan.objects.filter( + rowers=rower, + status=True).order_by("-startdate") return plans diff --git a/rowers/views.py b/rowers/views.py index 7c56c41f..2b8220a7 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -16156,12 +16156,15 @@ def rower_create_trainingplan(request,userid=0): date = targetform.cleaned_data['date'] notes = targetform.cleaned_data['notes'] - t = TrainingTarget(rowers=[therower], - name=name, - date=date, - manager=themanager, - notes=notes) + t = TrainingTarget( + name=name, + date=date, + manager=themanager, + notes=notes) + + t.save() + t.rowers.add(therower) t.save() elif request.method == 'POST' and 'startdate' in request.POST: @@ -16185,7 +16188,14 @@ def rower_create_trainingplan(request,userid=0): - targets = TrainingTarget.objects.filter(rower=therower).order_by("date") + targets2 = TrainingTarget.objects.filter(rower=therower).order_by("date") + for target in targets2: + if target.rower is not None: + target.rowers.add(target.rower) + target.rower = None + target.save() + + targets = TrainingTarget.objects.filter(rowers=therower).order_by("date") targetform = TrainingTargetForm() plans = TrainingPlan.objects.filter(rower=therower).order_by("-startdate") @@ -16193,7 +16203,7 @@ def rower_create_trainingplan(request,userid=0): plans = plans | plans2 - form = TrainingPlanForm(targets=targets) + form = TrainingPlanForm(targets=targets,initial={'status':False}) breadcrumbs = [ { @@ -17022,22 +17032,53 @@ class TrainingTargetUpdate(UpdateView): 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() - plan = form.save() + target = form.save() return super(TrainingTargetUpdate, self).form_valid(form) def get_object(self, *args, **kwargs): obj = super(TrainingTargetUpdate, self).get_object(*args, **kwargs) + if obj.rower is not None: + obj.rowers.add(obj.rower) + obj.rower = None + obj.save() if obj.manager is not None and self.request.user.rower != obj.manager: raise PermissionDenied('You are not allowed to edit this training plan cycle') - if not checkaccessuser(self.request.user,obj.rower): - raise PermissionDenied('You are not allowed to edit this training plan target') return obj def allsundays(startdate,enddate): From 0e650fe0dfbf8dda10a6531a4eede9d70d797cbc Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 29 Oct 2018 20:37:45 +0100 Subject: [PATCH 3/3] template details --- rowers/templates/trainingplan.html | 2 +- rowers/templates/trainingplan_create.html | 12 ++++++++++-- rowers/views.py | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/rowers/templates/trainingplan.html b/rowers/templates/trainingplan.html index ad728fb0..072dd756 100644 --- a/rowers/templates/trainingplan.html +++ b/rowers/templates/trainingplan.html @@ -366,7 +366,7 @@

Click on the cycle to fold out its contents.

-

Click on the plan cycles to edit their names, start and end dates. +

The gray "filler" cycles are generated, adjusted and deleted automatically to ensure the entire plan diff --git a/rowers/templates/trainingplan_create.html b/rowers/templates/trainingplan_create.html index 2ec6d3d1..69086bde 100644 --- a/rowers/templates/trainingplan_create.html +++ b/rowers/templates/trainingplan_create.html @@ -72,9 +72,17 @@ {{ plan.enddate }} {{ plan.name }} {% if plan.status %} active {% else %} inactive {% endif %} - Edit + + {% if request.user == plan.manager %} + Edit + {% endif %} + Plan - Delete + + {% if request.user == plan.manager %} + Delete + {% endif %} + {% endfor %} diff --git a/rowers/views.py b/rowers/views.py index 2b8220a7..3fe9813a 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -16588,7 +16588,8 @@ def rower_trainingplan_view(request, r = getrequestrower(request,userid=userid) if not checkaccessuser(request.user,plan.manager): - raise PermissionDenied("Access denied") + if request.user.rower not in plan.rowers.all(): + raise PermissionDenied("Access denied") createmacrofillers(plan) macrocycles = TrainingMacroCycle.objects.filter(