from rowers.rower_rules import is_team_manager, is_team_member, is_coach, user_is_basic from rowers.models import ValidationError, PlannedSession from rowers.tasks import ( handle_sendemail_invite, handle_sendemail_request, handle_sendemail_member_dropped, handle_sendemail_request_accept, handle_sendemail_request_reject, handle_sendemail_invite_reject, handle_sendemail_invite_accept, handle_sendemail_team_removed, handle_sendemail_coachrequest, handle_sendemail_coacheerequest, handle_sendemail_coachoffer_rejected, handle_sendemail_coachoffer_accepted, handle_sendemail_coachrequest_rejected, handle_sendemail_coachrequest_accepted, handle_sendemail_message, ) from rowers.models import ( Rower, Workout, Team, TeamInvite, User, TeamRequest, CoachRequest, CoachOffer, CoachingGroup ) # All the Team related methods # Python from django.utils import timezone from datetime import datetime from datetime import date as ddate from datetime import timedelta import time from django.db import IntegrityError import uuid from django.conf import settings from rowers.utils import myqueue import django_rq queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') # Low level functions - to be called by higher level methods inviteduration = 14 # days from rowers.tasks import handle_remove_workouts_team, handle_add_workouts_team def update_team(t, name, manager, private, notes, viewing): if not is_team_manager(manager, t): return (0, 'You are not the manager of this team') try: t.name = name t.manager = manager t.private = private t.notes = notes t.viewing = viewing t.save() except IntegrityError: return (0, 'Team name duplication') return (1, 'Team Updated') def create_team(name, manager, private='open', notes='', viewing='allmembers'): # needs some error testing if user_is_basic(manager.rower.user): # pragma: no cover return (0, 'You need to upgrade to a paid plan to establish a team') if not is_coach(manager): ts = Team.objects.filter(manager=manager) if len(ts) >= 1: # pragma: no cover return (0, 'You need to upgrade to the Coach plan to have more than one team') try: t = Team(name=name, manager=manager, notes=notes, private=private, viewing=viewing) t.save() r = Rower.objects.get(user=manager) _ = add_member(t.id, r) except IntegrityError: return (0, 'Team name duplication') return (t.id, 'Team created') def remove_team(id): t = Team.objects.get(id=id) for r in Rower.objects.filter(team=t): send_team_delete_mail(t, r) return t.delete() return (1, 'Updated rower team expiry') # pragma: no cover def add_coach(coach, rower): # get coaching group coachgroup = coach.mycoachgroup if coachgroup is None: # pragma: no cover coachgroup = CoachingGroup(name=coach.user.first_name) coachgroup.save() coach.mycoachgroup = coachgroup coach.save() if get_coach_club_size(coach) < coach.clubsize: rower.coachinggroups.add(coach.mycoachgroup) return (1, "Added Coach") else: # pragma: no cover return (0, "Maximum number of athletes reached") def add_member(id, rower): t = Team.objects.get(id=id) try: rower.team.add(t) except ValidationError as e: # pragma: no cover 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 ws = Workout.objects.filter(user=rower) _ = myqueue( queuehigh, handle_add_workouts_team, ws, t) # code to add plannedsessions plannedsessions = PlannedSession.objects.filter( team=t, enddate__gte=timezone.now().date()) for ps in plannedsessions: # pragma: no cover _ = ps.rower.add(rower) # set_teamplanexpires(rower) # code for Stuck At Home Team (temporary) if id == 52 and rower.rowerplan == 'basic': # pragma: no cover rower.protrialexpires = ddate(2020, 9, 1) rower.save() return (id, 'Member added') def remove_member(id, rower): t = Team.objects.get(id=id) rower.team.remove(t) # remove the team from rower's workouts: ws = Workout.objects.filter(user=rower, team=t) _ = myqueue(queuehigh,handle_remove_workouts_team,ws, t) # set_teamplanexpires(rower) return (id, 'Member removed') def remove_coach(coach, rower): # pragma: no cover try: coachgroup = coach.mycoachgroup except CoachingGroup.DoesNotExist: # pragma: no cover coachgroup = CoachingGroup() coachgroup.save() coach.mycoachgroup = coachgroup coach.save() rower.coachinggroups.remove(coachgroup) return (1, 'Coach removed') def rower_get_managers(rower): managers = [] for team in rower.team.all(): managers.append(team.manager.rower) return managers def rower_get_coaches(rower): return rower.get_coaches() def coach_getcoachees(coach): rowers = [] if coach.mycoachgroup and is_coach(coach.user): rs = Rower.objects.filter( coachinggroups__in=[coach.mycoachgroup] ).distinct().order_by("user__last_name", "user__first_name") for r in rs: rowers.append(r) return rowers def coach_remove_athlete(coach, rower): try: coachgroup = coach.mycoachgroup except CoachingGroup.DoesNotExist: # pragma: no cover coachgroup = CoachingGroup() coachgroup.save() coach.mycoachgroup = coachgroup coach.save() rower.coachinggroups.remove(coachgroup) return (1, 'Coach removed') def mgr_remove_member(id, manager, rower): t = Team.objects.get(id=id) if is_team_manager(manager, t): remove_member(id, rower) send_email_member_dropped(id, rower) return (id, 'Member removed') else: # pragma: no cover return (0, 'You are not the team manager') return (0, '') # pragma: no cover def count_invites(manager): # pragma: no cover ts = Team.objects.filter(manager=manager) count = 0 for t in ts: count += TeamInvite.objects.filter(team=t).count() return count def count_club_members(manager): # pragma: no cover ts = Team.objects.filter(manager=manager) return Rower.objects.filter(team__in=ts).distinct().count() # Medium level functionality # request by user to be coached by coach def create_coaching_request(coach, user): # pragma: no cover if coach in rower_get_coaches(user.rower): return (0, 'Already coached by that coach') codes = [i.code for i in CoachRequest.objects.all()] code = uuid.uuid4().hex[:10].upper() while code in codes: # pragma: no cover code = uuid.uuid4().hex[:10].upper() if 'coach' in coach.rowerplan: rekwest = CoachRequest(coach=coach, user=user, code=code) rekwest.save() send_coachrequest_email(rekwest) return (rekwest.id, 'The request was created') else: # pragma: no cover return (0, 'That person is not a coach') def send_coachrequest_email(rekwest): name = rekwest.user.first_name + " " + rekwest.user.last_name email = rekwest.coach.user.email code = rekwest.code coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name _ = myqueue(queuehigh, handle_sendemail_coachrequest, email, name, code, coachname) def send_coacheerequest_email(rekwest): name = rekwest.user.first_name + " " + rekwest.user.last_name email = rekwest.user.email code = rekwest.code coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name _ = myqueue(queuehigh, handle_sendemail_coacheerequest, email, name, code, coachname) def create_request(team, user): r2 = Rower.objects.get(user=user) if r2 in Rower.objects.filter(team=team): # pragma: no cover return (0, 'Already a member of that team') # if count_club_members(team.manager)+count_invites(team.manager) <= r.clubsize: codes = [i.code for i in TeamRequest.objects.all()] code = uuid.uuid4().hex[:10].upper() # prevent duplicates while code in codes: # pragma: no cover code = uuid.uuid4().hex[:10].upper() u = User.objects.get(id=user) rekwest = TeamRequest(team=team, user=u, code=code) rekwest.save() send_request_email(rekwest) return (rekwest.id, 'The request was created') return (0, 'Something went wrong in create_request') # pragma: no cover def get_coach_club_size(coach): rs = Rower.objects.filter(coachinggroups__in=[coach.mycoachgroup]) rekwests = CoachOffer.objects.filter(coach=coach) result = len(rs)+len(rekwests) return result # request by coach to coach user def create_coaching_offer(coach, user): if coach in rower_get_coaches(user.rower): # pragma: no cover return (0, 'You are already coaching this person.') codes = [i.code for i in CoachOffer.objects.all()] code = uuid.uuid4().hex[:10].upper() while code in codes: # pragma: no cover code = uuid.uuid4().hex[:10].upper() if is_coach(coach.user) and get_coach_club_size(coach) < coach.clubsize: rekwest = CoachOffer(coach=coach, user=user, code=code) rekwest.save() send_coacheerequest_email(rekwest) return (rekwest.id, 'The request was created') elif get_coach_club_size(coach) >= coach.clubsize: # pragma: no cover return(0, 'You have reached the maximum number of athletes') else: # pragma: no cover return (0, 'You are not a coach') def create_invite(team, manager, user=None, email=''): if not is_team_manager(manager, team): return (0, 'Not the team manager') if user: try: r2 = Rower.objects.get(user=user) email = r2.user.email except Rower.DoesNotExist: # pragma: no cover return (0, 'Rower does not exist') if r2 in Rower.objects.filter(team=team): return (0, 'Already member of that team') elif email is None or email == '': # pragma: no cover return (0, 'Invalid request - missing email or user') else: try: r2 = Rower.objects.get(user__email=email) user = User.objects.get(rower=r2) except Rower.DoesNotExist: # pragma: no cover user = None except Rower.MultipleObjectsReturned: # pragma: no cover return (0, 'There is more than one user with that email address') # if count_club_members(team.manager)+count_invites(team.manager) <= r.clubsize: codes = [i.code for i in TeamInvite.objects.all()] code = uuid.uuid4().hex[:10].upper() # prevent duplicates while code in codes: # pragma: no cover code = uuid.uuid4().hex[:10].upper() invite = TeamInvite(team=team, code=code, user=user, email=email) invite.save() return (invite.id, 'Invitation created') return (0, 'Nothing done') # pragma: no cover def revoke_request(user, id): try: rekwest = TeamRequest.objects.get(id=id) except TeamRequest.DoesNotExist: # pragma: no cover return (0, 'The request is invalid') if rekwest.user == user: rekwest.delete() return (1, 'Request revoked') return (0, 'You are not the requestor') # pragma: no cover def reject_revoke_coach_offer(user, id): try: rekwest = CoachOffer.objects.get(id=id) except CoachOffer.DoesNotExist: # pragma: no cover return (0, 'The request is invalid') if rekwest.coach.user == user: rekwest.delete() return (1, 'Request removed') elif rekwest.user == user: send_coachoffer_rejected_email(rekwest) rekwest.delete() return (1, 'Request removed') else: # pragma: no cover return (0, 'Not permitted') def reject_revoke_coach_request(user, id): try: rekwest = CoachRequest.objects.get(id=id) except CoachRequest.DoesNotExist: # pragma: no cover return (0, 'The request is invalid') if rekwest.coach.user == user: send_coachrequest_rejected_email(rekwest) rekwest.delete() return (1, 'Request rejected') elif rekwest.user == user: rekwest.delete() return (1, 'Request rejected') else: # pragma: no cover return (0, 'Not permitted') def revoke_invite(manager, id): try: invite = TeamInvite.objects.get(id=id) except TeamInvite.DoesNotExist: # pragma: no cover return (0, 'The invitation is invalid') if is_team_manager(manager, invite.team): invite.delete() return (1, 'Invitation revoked') else: # pragma: no cover return (0, 'You are not the team manager') def reject_request(manager, id): try: rekwest = TeamRequest.objects.get(id=id) except TeamRequest.DoesNotExist: # pragma: no cover return (0, 'The request is invalid') if is_team_manager(manager, rekwest.team): send_request_reject_email(rekwest) rekwest.delete() return (1, 'Request rejected') else: # pragma: no cover return (0, 'You are not the manager for this request') def reject_invitation(user, id): try: invite = TeamInvite.objects.get(id=id) except TeamInvite.DoesNotExist: # pragma: no cover return (0, 'The invitation is invalid') if invite.user == user: send_invite_reject_email(invite) invite.delete() return (1, 'Invitation rejected') else: # pragma: no cover return (0, 'This request was not for you') def send_invite_email(id): try: invitation = TeamInvite.objects.get(id=id) except TeamInvite.DoesNotExist: # pragma: no cover return (0, 'Invitation doesn not exist') if invitation.user: email = invitation.user.email name = invitation.user.first_name + " " + invitation.user.last_name else: # pragma: no cover email = invitation.email name = '' code = invitation.code teamname = invitation.team.name manager = invitation.team.manager.first_name + \ ' '+invitation.team.manager.last_name _ = myqueue(queuehigh, handle_sendemail_invite, email, name, code, teamname, manager) return (1, 'Invitation email sent') def send_team_delete_mail(t, rower): u = rower.user teamname = t.name email = u.email name = u.first_name+' '+u.last_name manager = t.manager.first_name+' '+t.manager.last_name _ = myqueue(queuehigh, handle_sendemail_team_removed, email, name, teamname, manager) return (1, 'Team delete email sent') def send_email_member_dropped(teamid, rower): t = Team.objects.get(id=teamid) u = rower.user teamname = t.name email = u.email name = u.first_name+' '+u.last_name manager = t.manager.first_name+' '+t.manager.last_name _ = myqueue(queuehigh, handle_sendemail_member_dropped, email, name, teamname, manager) return (1, 'Member dropped email sent') def send_request_accept_email(rekwest): # pragma: no cover email = rekwest.user.email teamname = rekwest.team.name name = rekwest.user.first_name+' '+rekwest.user.last_name manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name _ = myqueue(queuehigh, handle_sendemail_request_accept, email, name, teamname, manager) return (1, 'Invitation email sent') def send_request_reject_email(rekwest): teamname = rekwest.team.name email = rekwest.user.email name = rekwest.user.first_name+' '+rekwest.user.last_name manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name _ = myqueue(queuehigh, handle_sendemail_request_reject, email, name, teamname, manager) return (1, 'Invitation email sent') def send_invite_reject_email(invitation): email = invitation.team.manager.email if invitation.user: name = invitation.user.first_name+' '+invitation.user.last_name else: # pragma: no cover name = invitation.email teamname = invitation.team.name manager = invitation.team.manager.first_name + \ ' '+invitation.team.manager.last_name _ = myqueue(queuehigh, handle_sendemail_invite_reject, email, name, teamname, manager) return (1, 'Invitation email sent') def send_invite_accept_email(invitation): # pragma: no cover email = invitation.team.manager.email if invitation.user: name = invitation.user.first_name+' '+invitation.user.last_name else: name = invitation.email teamname = invitation.team.name manager = invitation.team.manager.first_name + \ ' '+invitation.team.manager.last_name _ = myqueue(queuehigh, handle_sendemail_invite_accept, email, name, teamname, manager) return (1, 'Invitation email sent') def send_team_message(team, message): # pragma: no cover rowers = team.rower.all() managername = team.manager.first_name + " " + team.manager.last_name for rower in rowers: rowername = rower.user.first_name + " " + rower.user.last_name _ = myqueue(queuehigh, handle_sendemail_message, rower.user.email, team.manager.email, rowername, message, team.name, managername) return (1, 'message sent') def send_request_email(rekwest): email = rekwest.team.manager.email id = rekwest.id name = rekwest.team.manager.first_name + " " + rekwest.team.manager.last_name code = rekwest.code teamname = rekwest.team.name requestor = rekwest.user.first_name+' '+rekwest.user.last_name _ = myqueue(queuehigh, handle_sendemail_request, email, name, code, teamname, requestor, id) return (1, 'Invitation email sent') def process_request_code(manager, code): # pragma: no cover code = code.upper() try: rekwest = TeamRequest.objects.get(code=code) except TeamRequest.DoesNotExist: return (0, 'The request has been revoked or the code is invalid') r = Rower.objects.get(user=rekwest.user) t = rekwest.team if rekwest.team.manager != manager: return (0, 'You are not the manager of this team') result, comment = add_member(t.id, r) if not result: return (result, "The member couldn't be added") send_request_accept_email(rekwest) rekwest.delete() return (result, 'The member was added') def process_invite_code(user, code): # pragma: no cover code = code.upper() try: invitation = TeamInvite.objects.get(code=code) except TeamInvite.DoesNotExist: return (0, 'The invitation has expired or the code is invalid') r = Rower.objects.get(user=user) nu = datetime.date(timezone.now()) if nu > invitation.issuedate+timedelta(days=inviteduration): revoke_invite(invitation.team.manager, invitation.id) return (0, 'The invitation has expired') t = invitation.team result, comment = add_member(t.id, r) if not result: return (result, "The member couldn't be added") send_invite_accept_email(invitation) invitation.delete() return (result, 'You were added to the team') def remove_expired_invites(): # pragma: no cover issuedate = timezone.now()-timedelta(days=inviteduration) issuedate = datetime.date(issuedate) invitations = TeamInvite.objects.filter(issuedate__lt=issuedate) for i in invitations: revoke_invite(i.team.manager, i.id) return (1, 'Expired invitations deleted') def process_coachrequest_code(coach, code): code = code.upper() try: rekwest = CoachRequest.objects.get(code=code) except CoachRequest.DoesNotExist: # pragma: no cover return (0, 'The request has been revoked or is invalid') if rekwest.coach != coach: # pragma: no cover return (0, 'The request is invalid') result = add_coach(coach, rekwest.user.rower) if not result: # pragma: no cover return result else: send_coachrequest_accepted_email(rekwest) rekwest.delete() return result def process_coachoffer_code(user, code): code = code.upper() try: rekwest = CoachOffer.objects.get(code=code) except CoachOffer.DoesNotExist: # pragma: no cover return (0, 'The request has been revoked or is invalid') if rekwest.user != user: # pragma: no cover return (0, 'The request is invalid') result = add_coach(rekwest.coach, rekwest.user.rower) if not result: # pragma: no cover return result else: send_coachoffer_accepted_email(rekwest) rekwest.delete() return result def send_coachoffer_rejected_email(rekwest): coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name coachemail = rekwest.coach.user.email name = rekwest.user.first_name + " " + rekwest.user.last_name _ = myqueue(queuehigh, handle_sendemail_coachoffer_rejected, coachemail, coachname, name) def send_coachrequest_rejected_email(rekwest): coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name email = rekwest.user.email name = rekwest.user.first_name + " " + rekwest.user.last_name _ = myqueue(queuehigh, handle_sendemail_coachrequest_rejected, email, coachname, name) def send_coachrequest_accepted_email(rekwest): coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name email = rekwest.user.email name = rekwest.user.first_name + " " + rekwest.user.last_name _ = myqueue(queuehigh, handle_sendemail_coachrequest_accepted, email, coachname, name) def send_coachoffer_accepted_email(rekwest): coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name coachemail = rekwest.coach.user.email name = rekwest.user.first_name + " " + rekwest.user.last_name _ = myqueue(queuehigh, handle_sendemail_coachoffer_accepted, coachemail, coachname, name)