Private
Public Access
1
0

fixes for coach trial

This commit is contained in:
Sander Roosendaal
2022-09-04 17:53:16 +02:00
parent 936a524804
commit 86890a8a73
15 changed files with 97 additions and 54 deletions

View File

@@ -531,6 +531,13 @@ class TeamInviteForm(ModelForm):
user = UserFullnameChoiceField(queryset=User.objects.all(), required=False) user = UserFullnameChoiceField(queryset=User.objects.all(), required=False)
email = forms.EmailField(required=False) email = forms.EmailField(required=False)
def __init__(self, *args, **kwargs):
userid = kwargs.pop('userid',0)
super(TeamInviteForm, self).__init__(*args, **kwargs)
if userid:
self.fields['user'].initial = userid
class Meta: class Meta:
model = TeamInvite model = TeamInvite
fields = ['user', 'email'] fields = ['user', 'email']

View File

@@ -138,6 +138,12 @@ def is_staff(user): # pragma: no cover
@rules.predicate @rules.predicate
def is_coach(user): def is_coach(user):
if user is None:
return False
if user.is_anonymous:
return False
if user.rower.coachtrialexpires >= timezone.now().date():
return True
return user.rower.rowerplan in ['coach', 'freecoach'] return user.rower.rowerplan in ['coach', 'freecoach']
@@ -157,6 +163,9 @@ def is_planmember(user):
except AttributeError: # pragma: no cover except AttributeError: # pragma: no cover
return False return False
if user.rower.coachtrialexpires >= timezone.now().date():
return True
return r.rowerplan in ['coach', 'plan'] # freecoach? return r.rowerplan in ['coach', 'plan'] # freecoach?
@@ -198,7 +207,7 @@ def is_coachtrial(user):
return False # pragma: no cover return False # pragma: no cover
ispromember = is_promember | is_protrial ispromember = is_promember | is_protrial | is_coach | is_coachtrial
can_have_teams = ispromember | is_coach | is_coachtrial can_have_teams = ispromember | is_coach | is_coachtrial
@@ -251,7 +260,7 @@ def is_plantrial(user):
isplanmember = is_planmember | is_plantrial isplanmember = is_planmember | is_plantrial
iscoachmember = is_coach | is_coachtrial iscoachmember = is_coachtrial | is_coach
@rules.predicate @rules.predicate

View File

@@ -314,6 +314,21 @@ def summaryfromsplitdata(splitdata, data, filename, sep='|', workouttype='rower'
return sums, sa, results return sums, sa, results
@app.task
def handle_remove_workouts_team(ws, t, debug=False, **kwargs):
for w in ws:
w.team.remove(t)
return 1
@app.task
def handle_add_workouts_team(ws, t, debug=False, **kwargs):
for w in ws:
w.team.add(t)
return 1
@app.task @app.task
def check_tp_workout_id(workout, location, attempts=5, debug=False, **kwargs): def check_tp_workout_id(workout, location, attempts=5, debug=False, **kwargs):
authorizationstring = str('Bearer ' + workout.user.tptoken) authorizationstring = str('Bearer ' + workout.user.tptoken)

View File

@@ -42,20 +42,7 @@ queuehigh = django_rq.get_queue('low')
inviteduration = 14 # days inviteduration = 14 # days
from rowers.tasks import handle_remove_workouts_team, handle_add_workouts_team
def handle_remove_workouts_team(ws, t):
for w in ws:
w.team.remove(t)
return 1
def handle_add_workouts_team(ws, t):
for w in ws:
w.team.add(t)
return 1
def update_team(t, name, manager, private, notes, viewing): def update_team(t, name, manager, private, notes, viewing):
@@ -128,10 +115,17 @@ def add_member(id, rower):
except ValidationError as e: # pragma: no cover except ValidationError as e: # pragma: no cover
return(0, "Couldn't add member: "+str(e.message)) return(0, "Couldn't add member: "+str(e.message))
# if team manager is coach
if is_coach(t.manager):
result = add_coach(t.manager.rower, rower)
# code to add all workouts # code to add all workouts
ws = Workout.objects.filter(user=rower) ws = Workout.objects.filter(user=rower)
_ = handle_add_workouts_team(ws, t) _ = myqueue(
queuehigh,
handle_add_workouts_team,
ws, t)
# code to add plannedsessions # code to add plannedsessions
plannedsessions = PlannedSession.objects.filter( plannedsessions = PlannedSession.objects.filter(
@@ -154,7 +148,8 @@ def remove_member(id, rower):
# remove the team from rower's workouts: # remove the team from rower's workouts:
ws = Workout.objects.filter(user=rower, team=t) ws = Workout.objects.filter(user=rower, team=t)
_ = handle_remove_workouts_team(ws, t)
_ = myqueue(queuehigh,handle_remove_workouts_team,ws, t)
# set_teamplanexpires(rower) # set_teamplanexpires(rower)
return (id, 'Member removed') return (id, 'Member removed')

View File

@@ -25,7 +25,7 @@
<div id="id_drop-files" class="drop-files"> <div id="id_drop-files" class="drop-files">
<form id="file_form" enctype="multipart/form-data" action="{{ formloc }}" method="post"> <form id="file_form" enctype="multipart/form-data" action="{{ formloc }}" method="post">
<h1>Upload Workout File</h1> <h1>Upload Workout File</h1>
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|coach_rowers %}
<p>Looking for <a href="/rowers/workout/upload/team/">Team Manager <p>Looking for <a href="/rowers/workout/upload/team/">Team Manager
Upload?</a></p> Upload?</a></p>
{% endif %} {% endif %}

View File

@@ -115,6 +115,7 @@
{% if user.is_authenticated and user|is_manager and rower %} {% if user.is_authenticated and user|is_manager and rower %}
<p>&nbsp;</p> <p>&nbsp;</p>
{% endif %}
{% if user|coach_rowers %} {% if user|coach_rowers %}
<ul class="cd-accordion-menu animated"> <ul class="cd-accordion-menu animated">
@@ -137,7 +138,6 @@
</li> </li>
</ul> </ul>
{% endif %} {% endif %}
{% endif %}
{% if user|user_teams %} {% if user|user_teams %}
<p>&nbsp;</p> <p>&nbsp;</p>

View File

@@ -65,6 +65,7 @@
{% if user.is_authenticated and user|is_manager and rower %} {% if user.is_authenticated and user|is_manager and rower %}
<p>&nbsp;</p> <p>&nbsp;</p>
{% endif %}
{% if user|coach_rowers %} {% if user|coach_rowers %}
<ul class="cd-accordion-menu animated"> <ul class="cd-accordion-menu animated">
@@ -87,7 +88,6 @@
</li> </li>
</ul> </ul>
{% endif %} {% endif %}
{% endif %}
{% if teams %} {% if teams %}
<p>&nbsp;</p> <p>&nbsp;</p>

View File

@@ -49,7 +49,6 @@ from six import string_types
register = template.Library() register = template.Library()
@register.filter @register.filter
def workoutdate(id): # pragma: no cover def workoutdate(id): # pragma: no cover
try: try:
@@ -711,6 +710,7 @@ def team_members(user):
try: try:
therower = Rower.objects.get(user=user) therower = Rower.objects.get(user=user)
if therower.rowerplan == 'basic': # pragma: no cover if therower.rowerplan == 'basic': # pragma: no cover
if therower.coachtrialexpires < timezone.now().date():
return [] return []
teams = Team.objects.filter(manager=user) teams = Team.objects.filter(manager=user)
members = Rower.objects.filter( members = Rower.objects.filter(
@@ -757,13 +757,20 @@ def team_rowers(user): # pragma: no cover
return [] return []
@register.filter
def length(l):
return len(l)
@register.filter @register.filter
def coach_rowers(user): def coach_rowers(user):
if user.is_anonymous:
return []
if user.rower.rowerplan != 'freecoach': if user.rower.rowerplan != 'freecoach':
thelist = [user.rower]+[c for c in coach_getcoachees(user.rower)] thelist = [user.rower]+[c for c in coach_getcoachees(user.rower)]
else: # pragma: no cover else: # pragma: no cover
thelist = [c for c in coach_getcoachees(user.rower)] thelist = [c for c in coach_getcoachees(user.rower)]
return thelist return thelist

View File

@@ -69,6 +69,7 @@ class OwnApi(TestCase):
# response must be json # response must be json
strokedata = json.loads(response.content) strokedata = json.loads(response.content)
df = pd.DataFrame(strokedata) df = pd.DataFrame(strokedata)
self.assertFalse(df.empty) self.assertFalse(df.empty)
form_data = { form_data = {

View File

@@ -261,8 +261,12 @@ urlpatterns = [
name='rower_update_empower_view'), name='rower_update_empower_view'),
re_path(r'^agegroupcp/(?P<age>\d+)/$', re_path(r'^agegroupcp/(?P<age>\d+)/$',
views.agegroupcpview, name='agegroupcpview'), views.agegroupcpview, name='agegroupcpview'),
re_path(r'^agegroupcp/(?P<age>\d+)/user/(?P<userid>\d+)/$',
views.agegroupcpview, name='agegroupcpview'),
re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/$', re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/$',
views.agegroupcpview, name='agegroupcpview'), views.agegroupcpview, name='agegroupcpview'),
re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/user/(?P<userid>\d+)/$',
views.agegroupcpview, name='agegroupcpview'),
re_path(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)/$', re_path(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)/$',
views.ajax_agegrouprecords, name='ajax_agegrouprecords'), views.ajax_agegrouprecords, name='ajax_agegrouprecords'),
re_path(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m/$', re_path(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m/$',
@@ -429,6 +433,8 @@ urlpatterns = [
name='workout_toggle_ranking'), name='workout_toggle_ranking'),
re_path(r'^workout/upload/team/$', views.team_workout_upload_view, re_path(r'^workout/upload/team/$', views.team_workout_upload_view,
name='team_workout_upload_view'), name='team_workout_upload_view'),
re_path(r'^workout/upload/team/user/(?P<userid>\d+)/$', views.team_workout_upload_view,
name='team_workout_upload_view'),
re_path(r'^workout/upload/(?P<raceid>\d+)/$', re_path(r'^workout/upload/(?P<raceid>\d+)/$',
views.workout_upload_view, name='workout_upload_view'), views.workout_upload_view, name='workout_upload_view'),
re_path(r'^workout/upload/$', views.workout_upload_view, re_path(r'^workout/upload/$', views.workout_upload_view,

View File

@@ -1763,7 +1763,7 @@ def otwcp_toadmin_view(request, theuser=0,
return response return response
def agegroupcpview(request, age, normalize=0): def agegroupcpview(request, age, normalize=0, userid=0):
script, div = interactive_agegroupcpchart(age, normalized=normalize) script, div = interactive_agegroupcpchart(age, normalized=normalize)
response = render(request, 'agegroupcp.html', response = render(request, 'agegroupcp.html',

View File

@@ -763,7 +763,7 @@ def workout_nkimport_view(request, userid=0, after=0, before=0):
messages.info( messages.info(
request, request,
'Your NK logbook workouts will be imported in the background.' 'Your NK logbook workouts will be imported in the background.'
' It may take a few minutes before it appears.') ' It may take a few minutes before they appear.')
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
except KeyError: except KeyError:
@@ -1270,7 +1270,7 @@ def workout_stravaimport_view(request, message="", userid=0):
# done, redirect to workouts list # done, redirect to workouts list
messages.info(request, messages.info(request,
'Your Strava workouts will be imported in the background.' 'Your Strava workouts will be imported in the background.'
' It may take a few minutes before it appears.') ' It may take a few minutes before they appear.')
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
@@ -1815,7 +1815,7 @@ def workout_c2import_view(request, page=1, userid=0, message=""):
messages.info( messages.info(
request, request,
'Your Concept2 workouts will be imported in the background.' 'Your Concept2 workouts will be imported in the background.'
' It may take a few minutes before it appears.') ' It may take a few minutes before they appear.')
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
except KeyError: # pragma: no cover except KeyError: # pragma: no cover

View File

@@ -811,7 +811,7 @@ def useractivate(request, uidb64, token): # pragma: no cover
['roosendaalsander@gmail.com']) ['roosendaalsander@gmail.com'])
messages.info( messages.info(
request, 'Thank you for your email confirmation. YOu are now signed in to your account.') request, 'Thank you for your email confirmation. You are now signed in to your account.')
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0]) login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])
url = reverse('workouts_view') url = reverse('workouts_view')
# if user.rower.rowerplan == 'freecoach': # if user.rower.rowerplan == 'freecoach':

View File

@@ -1235,11 +1235,14 @@ def iscoachmember(user):
r = Rower(user=user) r = Rower(user=user)
r.save() r.save()
result = user.is_authenticated and ('coach' in r.rowerplan) if user.is_authenticated:
else: # pragma: no cover if 'coach' in r.rowerplan:
result = False return True
elif r.coachtrialexpires >= timezone.now().date():
return True
return result
return False
# More User/Rower utils # More User/Rower utils

View File

@@ -5398,7 +5398,7 @@ def workout_upload_view(request,
# This is the main view for processing uploaded files # This is the main view for processing uploaded files
@user_passes_test(iscoachmember, login_url="/rowers/paidplans", redirect_field_name=None, @user_passes_test(iscoachmember, login_url="/rowers/paidplans", redirect_field_name=None,
message="This functionality requires a Coach plan or higher") message="This functionality requires a Coach plan or higher")
def team_workout_upload_view(request, message="", def team_workout_upload_view(request, userid=0, message="",
successmessage="", successmessage="",
uploadoptions={ uploadoptions={
'make_plot': False, 'make_plot': False,
@@ -5572,7 +5572,7 @@ def team_workout_upload_view(request, message="",
else: else:
form = DocumentsForm() form = DocumentsForm()
optionsform = TeamUploadOptionsForm(initial=uploadoptions) optionsform = TeamUploadOptionsForm(initial=uploadoptions)
rowerform = TeamInviteForm() rowerform = TeamInviteForm(userid=userid)
rowerform.fields.pop('email') rowerform.fields.pop('email')
rowers = Rower.objects.filter( rowers = Rower.objects.filter(