Merge branch 'release/v18.6.6'
This commit is contained in:
@@ -905,6 +905,7 @@ class Rower(models.Model):
|
|||||||
clubsize = models.IntegerField(default=0)
|
clubsize = models.IntegerField(default=0)
|
||||||
protrialexpires = models.DateField(default=datetime.date(1970, 1, 1))
|
protrialexpires = models.DateField(default=datetime.date(1970, 1, 1))
|
||||||
plantrialexpires = models.DateField(default=datetime.date(1970, 1, 1))
|
plantrialexpires = models.DateField(default=datetime.date(1970, 1, 1))
|
||||||
|
coachtrialexpires = models.DateField(default=datetime.date(1970, 1, 1))
|
||||||
offercoaching = models.BooleanField(
|
offercoaching = models.BooleanField(
|
||||||
default=False, verbose_name='Offer Remote Coaching')
|
default=False, verbose_name='Offer Remote Coaching')
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,13 @@ def user_is_not_basic(user):
|
|||||||
if user.rower.protrialexpires >= timezone.now().date():
|
if user.rower.protrialexpires >= timezone.now().date():
|
||||||
return True # pragma: no cover
|
return True # pragma: no cover
|
||||||
|
|
||||||
|
if user.rower.plantrialexpires >= timezone.now().date():
|
||||||
|
return True # pragma: no cover
|
||||||
|
|
||||||
|
if user.rower.coachtrialexpires >= timezone.now().date():
|
||||||
|
return True # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@rules.predicate
|
@rules.predicate
|
||||||
@@ -116,6 +123,13 @@ def can_start_plantrial(user):
|
|||||||
|
|
||||||
return user.rower.plantrialexpires == datetime.date(1970, 1, 1)
|
return user.rower.plantrialexpires == datetime.date(1970, 1, 1)
|
||||||
|
|
||||||
|
@rules.predicate
|
||||||
|
def can_start_coachtrial(user):
|
||||||
|
if user.is_anonymous: # pragma: no cover
|
||||||
|
return False
|
||||||
|
|
||||||
|
return user.rower.coachtrialexpires == datetime.date(1970, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
@rules.predicate
|
@rules.predicate
|
||||||
def is_staff(user): # pragma: no cover
|
def is_staff(user): # pragma: no cover
|
||||||
@@ -171,11 +185,23 @@ def is_protrial(user):
|
|||||||
|
|
||||||
return False # pragma: no cover
|
return False # pragma: no cover
|
||||||
|
|
||||||
|
@rules.predicate
|
||||||
|
def is_coachtrial(user):
|
||||||
|
try:
|
||||||
|
r = user.rower
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if r.rowerplan == 'basic':
|
||||||
|
return r.coachtrialexpires >= timezone.now().date()
|
||||||
|
|
||||||
|
return False # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
ispromember = is_promember | is_protrial
|
ispromember = is_promember | is_protrial
|
||||||
|
|
||||||
|
|
||||||
can_have_teams = ispromember | is_coach
|
can_have_teams = ispromember | is_coach | is_coachtrial
|
||||||
|
|
||||||
|
|
||||||
@rules.predicate
|
@rules.predicate
|
||||||
@@ -188,6 +214,9 @@ def can_add_team(user):
|
|||||||
if otherteams.count() == 0:
|
if otherteams.count() == 0:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
if is_coachtrial(user):
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -222,10 +251,12 @@ def is_plantrial(user):
|
|||||||
|
|
||||||
isplanmember = is_planmember | is_plantrial
|
isplanmember = is_planmember | is_plantrial
|
||||||
|
|
||||||
|
iscoachmember = is_coach | is_coachtrial
|
||||||
|
|
||||||
|
|
||||||
@rules.predicate
|
@rules.predicate
|
||||||
def can_add_session(user):
|
def can_add_session(user):
|
||||||
return isplanmember(user) or is_coach(user)
|
return isplanmember(user) or is_coach(user) or is_coachtrial(user)
|
||||||
|
|
||||||
# User / Coach relationships (Rower object)
|
# User / Coach relationships (Rower object)
|
||||||
|
|
||||||
@@ -237,7 +268,7 @@ def can_plan(user):
|
|||||||
if user.rower.rowerplan in ['plan', 'coach']:
|
if user.rower.rowerplan in ['plan', 'coach']:
|
||||||
return True
|
return True
|
||||||
if user.rower.rowerplan in ['basic', 'pro']:
|
if user.rower.rowerplan in ['basic', 'pro']:
|
||||||
return user.rower.plantrialexpires >= timezone.now().date()
|
return user.rower.plantrialexpires >= timezone.now().date() or user.rower.coachtrialexpires >= timezone.now().date()
|
||||||
if user.rower.rowerplan == 'freecoach': # pragma: no cover
|
if user.rower.rowerplan == 'freecoach': # pragma: no cover
|
||||||
if user.rower.mycoachgroup is not None:
|
if user.rower.mycoachgroup is not None:
|
||||||
return len(user.rower.mycoachgroup) >= 4
|
return len(user.rower.mycoachgroup) >= 4
|
||||||
@@ -620,7 +651,7 @@ def can_view_session(user, session):
|
|||||||
return True
|
return True
|
||||||
# coach users can view sessions created by their team members
|
# coach users can view sessions created by their team members
|
||||||
# below untested
|
# below untested
|
||||||
if is_coach(user): # pragma: no cover
|
if is_coach(user) or is_coachtrial(user): # pragma: no cover
|
||||||
teams = user.rower.get_managed_teams()
|
teams = user.rower.get_managed_teams()
|
||||||
for t in teams:
|
for t in teams:
|
||||||
teamusers = [member.u for member in t.rower.all()]
|
teamusers = [member.u for member in t.rower.all()]
|
||||||
@@ -711,7 +742,7 @@ def is_team_member(user, team): # pragma: no cover
|
|||||||
def can_view_team(user, team):
|
def can_view_team(user, team):
|
||||||
# user based - below untested
|
# user based - below untested
|
||||||
if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'coach': # pragma: no cover
|
if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'coach': # pragma: no cover
|
||||||
return is_plantrial(user) or is_protrial(user)
|
return is_plantrial(user) or is_protrial(user) or is_coachtrial(user)
|
||||||
# team is public
|
# team is public
|
||||||
if team.private == 'open':
|
if team.private == 'open':
|
||||||
return True
|
return True
|
||||||
|
|||||||
34
rowers/templates/coachtrialwelcome.html
Normal file
34
rowers/templates/coachtrialwelcome.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{% extends "emailbase.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<p>Dear <strong>{{ first_name }}</strong>,</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Welcome on the trial for the Coach plan. You are now able to test coaching
|
||||||
|
functionality for two weeks, with two coachees.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
As the developer of the Rowsandall.com site I am very interested to know
|
||||||
|
what you think of Rowsandall.com.
|
||||||
|
Especially, I'd like to understand how you started using the site,
|
||||||
|
what you are looking for, and what you think could be improved.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
I'd also love to hear a bit about your rowing background.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
So don't hesitate to respond to this email and let me know. I will read and respond to each
|
||||||
|
email.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Thank you very much for your help and for supporting <a href="rowsandall.com">rowsandall.com</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Best Regards, the Rowsandall Team
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
||||||
@@ -249,7 +249,21 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
{% if user.is_anonymous %}
|
||||||
|
<button style="width:100%">
|
||||||
|
<a href="/rowers/startcoachtrial/">Free COACH trial</a>
|
||||||
|
</button>
|
||||||
|
{% elif rower and rower.rowerplan == 'basic' and rower.coachtrialexpires|date_dif == 1 %}
|
||||||
|
<button style="width:100%">
|
||||||
|
<a href="/rowers/startcoachtrial/">Free COACH trial</a>
|
||||||
|
</button>
|
||||||
|
{% elif rower and rower.rowerplan == 'pro' and rower.coachtrialexpires|date_dif == 1 %}
|
||||||
|
<button style="width:100%">
|
||||||
|
<a href="/rowers/startcoachtrial/">Free COACH trial</a>
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -848,6 +848,8 @@ urlpatterns = [
|
|||||||
re_path(r'^starttrial/$', views.start_trial_view, name='start_trial_view'),
|
re_path(r'^starttrial/$', views.start_trial_view, name='start_trial_view'),
|
||||||
re_path(r'^startplantrial/$', views.start_plantrial_view,
|
re_path(r'^startplantrial/$', views.start_plantrial_view,
|
||||||
name='start_plantrial_view'),
|
name='start_plantrial_view'),
|
||||||
|
re_path(r'^startcoachtrial/$', views.start_coachtrial_view,
|
||||||
|
name='start_coachtrial_view'),
|
||||||
re_path(r'^legal', TemplateView.as_view(
|
re_path(r'^legal', TemplateView.as_view(
|
||||||
template_name='legal.html'), name='legal'),
|
template_name='legal.html'), name='legal'),
|
||||||
re_path(r'^register/$', views.rower_register_view,
|
re_path(r'^register/$', views.rower_register_view,
|
||||||
|
|||||||
@@ -1289,7 +1289,7 @@ def plannedsessions_coach_view(request,
|
|||||||
else:
|
else:
|
||||||
theteam = False
|
theteam = False
|
||||||
|
|
||||||
if 'coach' in request.user.rower.rowerplan:
|
if is_coach(request.user) or is_coachtrial(request.user):
|
||||||
sps = get_sessions_manager(request.user, teamid=teamid,
|
sps = get_sessions_manager(request.user, teamid=teamid,
|
||||||
enddate=enddate,
|
enddate=enddate,
|
||||||
startdate=startdate)
|
startdate=startdate)
|
||||||
@@ -1303,7 +1303,7 @@ def plannedsessions_coach_view(request,
|
|||||||
rowers = []
|
rowers = []
|
||||||
|
|
||||||
for ps in sps:
|
for ps in sps:
|
||||||
if 'coach' in request.user.rower.rowerplan:
|
if is_coach(request.user) or is_coachtrial(request.user):
|
||||||
rowers += ps.rower.all().exclude(rowerplan='freecoach')
|
rowers += ps.rower.all().exclude(rowerplan='freecoach')
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
rowers += ps.rower.filter(
|
rowers += ps.rower.filter(
|
||||||
@@ -1539,8 +1539,9 @@ def plannedsessions_view(request,
|
|||||||
totals['actualtrimp'] += thetrimp
|
totals['actualtrimp'] += thetrimp
|
||||||
|
|
||||||
if not sps and request.user.rower.rowerplan == 'basic': # pragma: no cover
|
if not sps and request.user.rower.rowerplan == 'basic': # pragma: no cover
|
||||||
messages.error(request,
|
if user_is_basic(request.user):
|
||||||
"You must purchase Coach or Self-coach plans or be part of a team to get planned sessions")
|
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:
|
for ps in sps:
|
||||||
ratio, status, cdate = is_session_complete(r, ps)
|
ratio, status, cdate = is_session_complete(r, ps)
|
||||||
|
|||||||
@@ -77,8 +77,9 @@ from rowers.rower_rules import (
|
|||||||
can_view_plan, can_change_plan, can_delete_plan,
|
can_view_plan, can_change_plan, can_delete_plan,
|
||||||
can_view_cycle, can_change_cycle, can_delete_cycle,
|
can_view_cycle, can_change_cycle, can_delete_cycle,
|
||||||
can_add_workout_member, can_plan_user, is_paid_coach,
|
can_add_workout_member, can_plan_user, is_paid_coach,
|
||||||
can_start_trial, can_start_plantrial, can_plan, is_workout_team,
|
can_start_trial, can_start_plantrial, can_start_coachtrial,
|
||||||
is_promember,
|
can_plan, is_workout_team,
|
||||||
|
is_promember,user_is_basic, is_coachtrial, is_coach
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ def get_teams(request):
|
|||||||
private='open').exclude(
|
private='open').exclude(
|
||||||
rower=r).exclude(manager=request.user).order_by('name')
|
rower=r).exclude(manager=request.user).order_by('name')
|
||||||
|
|
||||||
if r.rowerplan == 'basic':
|
if user_is_basic(request.user):
|
||||||
otherteams = otherteams.filter(manager__rower__rowerplan='coach')
|
otherteams = otherteams.filter(manager__rower__rowerplan='coach')
|
||||||
|
|
||||||
return myteams, memberteams, otherteams
|
return myteams, memberteams, otherteams
|
||||||
@@ -234,7 +234,7 @@ def rower_teams_view(request): # pragma: no cover
|
|||||||
|
|
||||||
coachees = teams.coach_getcoachees(request.user.rower)
|
coachees = teams.coach_getcoachees(request.user.rower)
|
||||||
|
|
||||||
if request.user.rower.rowerplan == 'coach':
|
if is_coach(request.user) or is_coachtrial(request.user):
|
||||||
potentialathletes = Rower.objects.filter(
|
potentialathletes = Rower.objects.filter(
|
||||||
team__in=myteams).exclude(
|
team__in=myteams).exclude(
|
||||||
user__in=invitedathletes).exclude(
|
user__in=invitedathletes).exclude(
|
||||||
@@ -471,7 +471,7 @@ def team_requestmembership_view(request, teamid, userid):
|
|||||||
def request_coaching_view(request, coachid):
|
def request_coaching_view(request, coachid):
|
||||||
coach = User.objects.get(id=coachid).rower
|
coach = User.objects.get(id=coachid).rower
|
||||||
|
|
||||||
if 'coach' in coach.rowerplan:
|
if is_coach(coach.user) or is_coachtrial(request.user):
|
||||||
res, text = teams.create_coaching_request(coach, request.user)
|
res, text = teams.create_coaching_request(coach, request.user)
|
||||||
if res:
|
if res:
|
||||||
messages.info(request, text)
|
messages.info(request, text)
|
||||||
|
|||||||
@@ -143,6 +143,40 @@ def survey(request): # pragma: no cover
|
|||||||
|
|
||||||
return render(request, 'survey.html', context)
|
return render(request, 'survey.html', context)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def start_coachtrial_view(request):
|
||||||
|
r = getrower(request.user)
|
||||||
|
|
||||||
|
if not can_start_coachtrial(request.user): # pragma: no cover
|
||||||
|
messages.error(request, 'You do not qualify for a coach trial')
|
||||||
|
url = '/rowers/paidplans'
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
r.coachtrialexpires = timezone.now()+datetime.timedelta(13)
|
||||||
|
r.clubsize = 2
|
||||||
|
r.save()
|
||||||
|
|
||||||
|
url = reverse('workouts_view')
|
||||||
|
|
||||||
|
messages.info(request, 'We have started your 14 day coach trial period')
|
||||||
|
|
||||||
|
subject2 = "User started Coach Trial"
|
||||||
|
message2 = "User Started Coach Trial.\n"
|
||||||
|
message2 += request.user.email + "\n"
|
||||||
|
message2 += "User name: "+request.user.username
|
||||||
|
|
||||||
|
send_mail(subject2, message2,
|
||||||
|
'Rowsandall Server <info@rowsandall.com>',
|
||||||
|
['roosendaalsander@gmail.com'])
|
||||||
|
|
||||||
|
send_template_email('Rowsandall <info@rowsandall.com>',
|
||||||
|
[r.user.email],
|
||||||
|
'Welcome to the Rowsandall Coach Trial',
|
||||||
|
'coachtrialwelcome.html',
|
||||||
|
{'first_name': r.user.first_name,
|
||||||
|
'last_name': r.user.last_name})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def start_trial_view(request):
|
def start_trial_view(request):
|
||||||
|
|||||||
@@ -261,6 +261,13 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if user.rower.coachtrialexpires and user.rower.coachtrialexpires|is_future_date and user.rower.rowerplan != 'coach' %}
|
||||||
|
<li class="grid_4">
|
||||||
|
<p class="successmessage">
|
||||||
|
{{ user.rower.coachtrialexpires|date_dif|ddays }} days left of your Coach trial - Would you like to <a href="/rowers/paidplans/">upgrade now?</a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.rower.emailbounced %}
|
{% if user.rower.emailbounced %}
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
|||||||
Reference in New Issue
Block a user