Merge branch 'feature/nomailbox' into develop
This commit is contained in:
@@ -73,7 +73,7 @@ def process_webhook(notification):
|
|||||||
if notification.kind == 'subscription_charged_successfully':
|
if notification.kind == 'subscription_charged_successfully':
|
||||||
subscription = notification.subscription
|
subscription = notification.subscription
|
||||||
rs = Rower.objects.filter(subscription_id=subscription.id)
|
rs = Rower.objects.filter(subscription_id=subscription.id)
|
||||||
if rs.count() == 0:
|
if rs.count() == 0: # pragma: no cover
|
||||||
dologging('braintreewebhooks.log','Could not find rowers with subscription ID {id}'.format(
|
dologging('braintreewebhooks.log','Could not find rowers with subscription ID {id}'.format(
|
||||||
id=subscription.id
|
id=subscription.id
|
||||||
))
|
))
|
||||||
@@ -209,7 +209,7 @@ def make_payment(rower,data):
|
|||||||
if 'plan' in data:
|
if 'plan' in data:
|
||||||
theplan = data['plan']
|
theplan = data['plan']
|
||||||
additional_text = 'Rowsandall Purchase Plan nr {theplan}'.format(theplan=theplan)
|
additional_text = 'Rowsandall Purchase Plan nr {theplan}'.format(theplan=theplan)
|
||||||
else:
|
else: # pragma: no cover
|
||||||
additional_text = 'Rowsandall Purchase'
|
additional_text = 'Rowsandall Purchase'
|
||||||
|
|
||||||
result = gateway.transaction.sale({
|
result = gateway.transaction.sale({
|
||||||
|
|||||||
+7
-7
@@ -4,16 +4,16 @@ class InsufficientCreditError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def upgrade(amount, rower):
|
def upgrade(amount, rower):
|
||||||
if rower.eurocredits > amount:
|
if rower.eurocredits > amount: # pragma: no cover
|
||||||
return rower.eurocredits
|
return rower.eurocredits
|
||||||
else:
|
else:
|
||||||
rower.eurocredits = amount
|
rower.eurocredits = amount
|
||||||
rower.save()
|
rower.save()
|
||||||
return rower.eurocredits
|
return rower.eurocredits
|
||||||
return rower.eurocredits
|
return rower.eurocredits # pragma: no cover
|
||||||
|
|
||||||
def withdraw(amount, rower):
|
def withdraw(amount, rower):
|
||||||
if rower.eurocredits < amount:
|
if rower.eurocredits < amount: # pragma: no cover
|
||||||
rower.eurocredits = 0
|
rower.eurocredits = 0
|
||||||
rower.save()
|
rower.save()
|
||||||
raise InsufficientCreditError
|
raise InsufficientCreditError
|
||||||
@@ -22,9 +22,9 @@ def withdraw(amount, rower):
|
|||||||
rower.save()
|
rower.save()
|
||||||
return rower.eurocredits
|
return rower.eurocredits
|
||||||
|
|
||||||
return rower.eurocredits
|
return rower.eurocredits # pragma: no cover
|
||||||
|
|
||||||
def discount(amount,rower):
|
def discount(amount,rower): # pragma: no cover
|
||||||
if amount < rower.eurocredits:
|
if amount < rower.eurocredits:
|
||||||
return amount
|
return amount
|
||||||
else:
|
else:
|
||||||
@@ -33,9 +33,9 @@ def discount(amount,rower):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def discounted(amount,rower):
|
def discounted(amount,rower):
|
||||||
if amount > rower.eurocredits:
|
if amount > rower.eurocredits: # pragma: no cover
|
||||||
return amount-rower.eurocredits
|
return amount-rower.eurocredits
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
return 0
|
return 0 # pragma: no cover
|
||||||
|
|||||||
+30
-18
@@ -28,7 +28,8 @@ from rowingdata import (
|
|||||||
|
|
||||||
from rowers.tasks import (
|
from rowers.tasks import (
|
||||||
handle_sendemail_unrecognized,handle_setcp,
|
handle_sendemail_unrecognized,handle_setcp,
|
||||||
handle_getagegrouprecords, handle_update_wps
|
handle_getagegrouprecords, handle_update_wps,
|
||||||
|
handle_request_post
|
||||||
)
|
)
|
||||||
from rowers.tasks import handle_zip_file
|
from rowers.tasks import handle_zip_file
|
||||||
|
|
||||||
@@ -42,7 +43,9 @@ from pyarrow.lib import ArrowInvalid
|
|||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.timezone import get_current_timezone
|
from django.utils.timezone import get_current_timezone
|
||||||
from django_mailbox.models import Message,Mailbox,MessageAttachment
|
from django.urls import reverse
|
||||||
|
import requests
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from time import strftime
|
from time import strftime
|
||||||
@@ -74,6 +77,7 @@ allowedcolumns = [key for key,value in strokedatafields.items()]
|
|||||||
#from async_messages import messages as a_messages
|
#from async_messages import messages as a_messages
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from zipfile import BadZipFile
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import itertools
|
import itertools
|
||||||
@@ -2024,8 +2028,7 @@ def handle_nonpainsled(f2, fileformat, summary='',startdatetime='',empowerfirmwa
|
|||||||
return (f2, summary, oarlength, inboard, fileformat, impeller)
|
return (f2, summary, oarlength, inboard, fileformat, impeller)
|
||||||
|
|
||||||
# Create new workout from file and store it in the database
|
# Create new workout from file and store it in the database
|
||||||
# This routine should be used everywhere in views.py and mailprocessing.py
|
# This routine should be used everywhere in views.py
|
||||||
# Currently there is code duplication
|
|
||||||
|
|
||||||
def get_workouttype_from_fit(filename,workouttype='water'):
|
def get_workouttype_from_fit(filename,workouttype='water'):
|
||||||
try:
|
try:
|
||||||
@@ -2102,21 +2105,30 @@ def new_workout_from_file(r, f2,
|
|||||||
|
|
||||||
# Save zip files to email box for further processing
|
# Save zip files to email box for further processing
|
||||||
if len(fileformat) == 3 and fileformat[0] == 'zip': # pragma: no cover
|
if len(fileformat) == 3 and fileformat[0] == 'zip': # pragma: no cover
|
||||||
uploadoptions['fromuploadform'] = True
|
uploadoptions['secret'] = settings.UPLOAD_SERVICE_SECRET
|
||||||
bodyyaml = yaml.safe_dump(uploadoptions,default_flow_style=False)
|
uploadoptions['user'] = r.user.id
|
||||||
f_to_be_deleted = f2
|
uploadoptions['title'] = title
|
||||||
|
try:
|
||||||
|
zip_file = zipfile.ZipFile(f2)
|
||||||
|
for id,filename in enumerate(zip_file.namelist()):
|
||||||
|
datafile = zip_file.extract(filename, path='media/')
|
||||||
|
if id>0:
|
||||||
|
uploadoptions['title'] = title+' ('+str(id+1)+')'
|
||||||
|
else:
|
||||||
|
uploadoptions['title'] = title
|
||||||
|
|
||||||
|
uploadoptions['file'] = datafile
|
||||||
|
url = settings.UPLOAD_SERVICE_URL
|
||||||
|
|
||||||
|
job = myqueue(queuehigh,
|
||||||
|
handle_request_post,
|
||||||
|
url,
|
||||||
|
uploadoptions
|
||||||
|
)
|
||||||
|
|
||||||
|
except BadZipFile: # pragma: no cover
|
||||||
|
pass
|
||||||
|
|
||||||
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
|
|
||||||
msg = Message(mailbox=workoutsbox,
|
|
||||||
from_header=r.user.email,
|
|
||||||
subject = title,body=bodyyaml)
|
|
||||||
msg.save()
|
|
||||||
f3 = 'media/mailbox_attachments/'+f2[6:]
|
|
||||||
copyfile(f2,f3)
|
|
||||||
f3 = f3[6:]
|
|
||||||
a = MessageAttachment(message=msg,document=f3)
|
|
||||||
a.save()
|
|
||||||
message = "Zip file was stored for offline processing"
|
|
||||||
|
|
||||||
return -1, message, f2
|
return -1, message, f2
|
||||||
|
|
||||||
|
|||||||
@@ -120,3 +120,21 @@ def send_template_email(from_email,to_email,subject,
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def send_confirm(user, name, link, options): # pragma: no cover
|
||||||
|
d = {
|
||||||
|
'first_name':user.first_name,
|
||||||
|
'name':name,
|
||||||
|
'link':link,
|
||||||
|
}
|
||||||
|
|
||||||
|
fullemail = user.email
|
||||||
|
subject = 'New Workout Added: '+name
|
||||||
|
|
||||||
|
res = send_template_email('Rowsandall <info@rowsandall.com>',
|
||||||
|
[fullemail],
|
||||||
|
subject,'confirmemail.html',
|
||||||
|
d
|
||||||
|
)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|||||||
+1
-1
@@ -1486,7 +1486,7 @@ class RaceResultFilterForm(forms.Form):
|
|||||||
|
|
||||||
if records:
|
if records:
|
||||||
# group
|
# group
|
||||||
if groups:
|
if groups: # pragma: no cover
|
||||||
thecategories = [record.entrycategory for record in records]
|
thecategories = [record.entrycategory for record in records]
|
||||||
thecategories = list(set(thecategories))
|
thecategories = list(set(thecategories))
|
||||||
if len(thecategories) <= 1:
|
if len(thecategories) <= 1:
|
||||||
|
|||||||
@@ -2429,7 +2429,7 @@ def get_map_script_course(
|
|||||||
longend,
|
longend,
|
||||||
scoordinates,
|
scoordinates,
|
||||||
course,
|
course,
|
||||||
):
|
): # pragma: no cover
|
||||||
latmean,lonmean,coordinates = course_coord_center(course)
|
latmean,lonmean,coordinates = course_coord_center(course)
|
||||||
lat_min, lat_max, long_min, long_max = course_coord_maxmin(course)
|
lat_min, lat_max, long_min, long_max = course_coord_maxmin(course)
|
||||||
|
|
||||||
@@ -2742,7 +2742,7 @@ def leaflet_chart(lat,lon,name="",raceresult=0):
|
|||||||
longend,
|
longend,
|
||||||
scoordinates,
|
scoordinates,
|
||||||
)
|
)
|
||||||
else:
|
else: # pragma: no cover
|
||||||
record = VirtualRaceResult.objects.get(id=raceresult)
|
record = VirtualRaceResult.objects.get(id=raceresult)
|
||||||
course = record.course
|
course = record.course
|
||||||
script = get_map_script_course(
|
script = get_map_script_course(
|
||||||
@@ -7010,7 +7010,7 @@ def get_zones_report(rower,startdate,enddate,trainingzones='hr',date_agg='week',
|
|||||||
|
|
||||||
def interactive_zoneschart(rower,data,startdate,enddate,trainingzones='hr',date_agg='week',
|
def interactive_zoneschart(rower,data,startdate,enddate,trainingzones='hr',date_agg='week',
|
||||||
yaxis='time'):
|
yaxis='time'):
|
||||||
if startdate >= enddate:
|
if startdate >= enddate: # pragma: no cover
|
||||||
st = startdate
|
st = startdate
|
||||||
startdate = enddate
|
startdate = enddate
|
||||||
enddate = st
|
enddate = st
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
# Processes emails sent to workouts@rowsandall.com
|
|
||||||
""" Processes emails sent to workouts@rowsandall.com """
|
|
||||||
import shutil
|
|
||||||
import time
|
|
||||||
from django.conf import settings
|
|
||||||
from rowers.tasks import (
|
|
||||||
handle_sendemail_unrecognized,
|
|
||||||
handle_sendemail_unrecognizedowner
|
|
||||||
)
|
|
||||||
from django_mailbox.models import Message, MessageAttachment,Mailbox
|
|
||||||
|
|
||||||
#workoutmailbox = Mailbox.objects.get(name='workouts')
|
|
||||||
#failedmailbox = Mailbox.objects.get(name='Failed')
|
|
||||||
|
|
||||||
|
|
||||||
from rowers.models import User, Rower, RowerForm
|
|
||||||
|
|
||||||
from django.core.mail import EmailMessage
|
|
||||||
|
|
||||||
from rowingdata import rower as rrower
|
|
||||||
|
|
||||||
from rowingdata import rowingdata as rrdata
|
|
||||||
|
|
||||||
from rowingdata import get_file_type
|
|
||||||
|
|
||||||
import zipfile
|
|
||||||
import os
|
|
||||||
import rowers.dataprep as dataprep
|
|
||||||
|
|
||||||
import django_rq
|
|
||||||
queue = django_rq.get_queue('default')
|
|
||||||
queuelow = django_rq.get_queue('low')
|
|
||||||
queuehigh = django_rq.get_queue('default')
|
|
||||||
|
|
||||||
# Sends a confirmation with a link to the workout
|
|
||||||
from rowers.emails import send_template_email
|
|
||||||
|
|
||||||
def send_confirm(user, name, link, options): # pragma: no cover
|
|
||||||
d = {
|
|
||||||
'first_name':user.first_name,
|
|
||||||
'name':name,
|
|
||||||
'link':link,
|
|
||||||
}
|
|
||||||
|
|
||||||
fullemail = user.email
|
|
||||||
subject = 'New Workout Added: '+name
|
|
||||||
|
|
||||||
res = send_template_email('Rowsandall <info@rowsandall.com>',
|
|
||||||
[fullemail],
|
|
||||||
subject,'confirmemail.html',
|
|
||||||
d
|
|
||||||
)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Reads a "rowingdata" object, plus some error protections
|
|
||||||
|
|
||||||
|
|
||||||
def rdata(file, rower=rrower()):
|
|
||||||
""" Reads rowingdata data or returns 0 on Error """
|
|
||||||
try:
|
|
||||||
result = rrdata(csvfile=file, rower=rower)
|
|
||||||
except IOError: # pragma: no cover
|
|
||||||
try:
|
|
||||||
result = rrdata(csvfile=file + '.gz', rower=rower)
|
|
||||||
except IOError:
|
|
||||||
result = 0
|
|
||||||
except TypeError: # pragma: no cover
|
|
||||||
try:
|
|
||||||
result = rrdata(csvfile=file)
|
|
||||||
except IOError:
|
|
||||||
try:
|
|
||||||
result = rrdata(csvfile=file+'.gz', rower=rower)
|
|
||||||
except IOError:
|
|
||||||
result = 0
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
|
|
||||||
""" This one is used in processemail """
|
|
||||||
workouttype = 'rower'
|
|
||||||
impeller = False
|
|
||||||
|
|
||||||
try: # pragma: no cover
|
|
||||||
datafilename = datafile.name
|
|
||||||
fileformat = get_file_type('media/' + datafilename)
|
|
||||||
raise ValueError
|
|
||||||
except IOError: # pragma: no cover
|
|
||||||
datafilename = datafile.name + '.gz'
|
|
||||||
fileformat = get_file_type('media/' + datafilename)
|
|
||||||
except AttributeError:
|
|
||||||
datafilename = datafile
|
|
||||||
fileformat = get_file_type('media/' + datafile)
|
|
||||||
|
|
||||||
if len(fileformat) == 3 and fileformat[0] == 'zip': # pragma: no cover
|
|
||||||
with zipfile.ZipFile('media/' + datafilename) as zip_file:
|
|
||||||
datafilename = zip_file.extract(
|
|
||||||
zip_file.namelist()[0],
|
|
||||||
path='media/')[6:]
|
|
||||||
fileformat = fileformat[2]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
f,e = os.path.splitext(datafilename)
|
|
||||||
if fileformat == 'unknown' and 'txt' not in e:
|
|
||||||
fcopy = "media/"+datafilename
|
|
||||||
if not testing: # pragma: no cover
|
|
||||||
if settings.CELERY:
|
|
||||||
res = handle_sendemail_unrecognized.delay(
|
|
||||||
fcopy,
|
|
||||||
rower.user.email
|
|
||||||
)
|
|
||||||
res = handle_sendemail_unrecognizedowner.delay(
|
|
||||||
rower.user.email,
|
|
||||||
rower.user.first_name
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
res = queuehigh.enqueue(handle_sendemail_unrecognized,
|
|
||||||
fcopy,
|
|
||||||
rower.user.email)
|
|
||||||
res = queuehigh.enqueue(handle_sendemail_unrecognizedowner,
|
|
||||||
rower.user.email,
|
|
||||||
rower.user.first_name
|
|
||||||
)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
summary = ''
|
|
||||||
|
|
||||||
|
|
||||||
# handle non-Painsled
|
|
||||||
if fileformat == 'att':
|
|
||||||
return 0
|
|
||||||
if fileformat != 'csv':
|
|
||||||
filename_mediadir, summary, oarlength, inboard,fileformat,impeller = dataprep.handle_nonpainsled(
|
|
||||||
'media/' + datafilename, fileformat, summary)
|
|
||||||
if not filename_mediadir: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
filename_mediadir = 'media/' + datafilename
|
|
||||||
inboard = 0.88
|
|
||||||
oarlength = 2.89
|
|
||||||
|
|
||||||
row = rdata(filename_mediadir)
|
|
||||||
if row == 0: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# change filename
|
|
||||||
if datafilename[:5] != 'media':
|
|
||||||
timestr = time.strftime("%Y%m%d-%H%M%S")
|
|
||||||
datafilename = 'media/' + timestr + str(cntr) + 'o.csv'
|
|
||||||
|
|
||||||
try:
|
|
||||||
avglat = row.df[' latitude'].mean()
|
|
||||||
avglon = row.df[' longitude'].mean()
|
|
||||||
if avglat != 0 or avglon != 0:
|
|
||||||
workouttype = 'water'
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
row.write_csv(datafilename, gzip=True)
|
|
||||||
dosummary = (fileformat != 'fit' and 'speedcoach2' not in fileformat)
|
|
||||||
dosummary = dosummary or summary == ''
|
|
||||||
|
|
||||||
if name == '': # pragma: no cover
|
|
||||||
name = 'Workout from Background Queue'
|
|
||||||
|
|
||||||
id, message = dataprep.save_workout_database(
|
|
||||||
datafilename, rower,
|
|
||||||
workouttype=workouttype,
|
|
||||||
dosummary=dosummary,
|
|
||||||
summary=summary,
|
|
||||||
inboard=inboard,
|
|
||||||
oarlength=oarlength,
|
|
||||||
title=name,
|
|
||||||
dosmooth=rower.dosmooth,
|
|
||||||
workoutsource=fileformat,
|
|
||||||
notes='',impeller=impeller,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
return id
|
|
||||||
@@ -18,7 +18,7 @@ import json
|
|||||||
import io
|
import io
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django_mailbox.models import Message, MessageAttachment,Mailbox
|
#from django_mailbox.models import Message, MessageAttachment,Mailbox
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ from rowingdata import rower as rrower
|
|||||||
from rowingdata import rowingdata as rrdata
|
from rowingdata import rowingdata as rrdata
|
||||||
|
|
||||||
import rowers.uploads as uploads
|
import rowers.uploads as uploads
|
||||||
from rowers.mailprocessing import make_new_workout_from_email, send_confirm
|
|
||||||
import rowers.polarstuff as polarstuff
|
import rowers.polarstuff as polarstuff
|
||||||
import rowers.c2stuff as c2stuff
|
import rowers.c2stuff as c2stuff
|
||||||
import rowers.rp3stuff as rp3stuff
|
import rowers.rp3stuff as rp3stuff
|
||||||
@@ -37,8 +37,7 @@ import rowers.stravastuff as stravastuff
|
|||||||
import rowers.nkstuff as nkstuff
|
import rowers.nkstuff as nkstuff
|
||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
|
|
||||||
from rowers.models import User,VirtualRace,Workout
|
from rowers.models import User,Workout
|
||||||
from rowers.plannedsessions import email_submit_race
|
|
||||||
from rowers.rower_rules import user_is_not_basic
|
from rowers.rower_rules import user_is_not_basic
|
||||||
from rowers.utils import dologging
|
from rowers.utils import dologging
|
||||||
|
|
||||||
@@ -60,102 +59,6 @@ def rdata(file_obj, rower=rrower()): # pragma: no cover
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def processattachment(rower, fileobj, title, uploadoptions,testing=False):
|
|
||||||
try:
|
|
||||||
filename = fileobj.name
|
|
||||||
# filename = os.path.abspath(fileobj.name)
|
|
||||||
except AttributeError:
|
|
||||||
filename = fileobj[6:]
|
|
||||||
|
|
||||||
|
|
||||||
# test if file exists and is not empty
|
|
||||||
try:
|
|
||||||
with io.open('media/'+filename,'rb') as fop:
|
|
||||||
line = fop.readline()
|
|
||||||
except (IOError, UnicodeEncodeError): # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
# set user
|
|
||||||
if rower.user.is_staff and 'username' in uploadoptions:
|
|
||||||
users = User.objects.filter(username=uploadoptions['username'])
|
|
||||||
if len(users)==1:
|
|
||||||
therower = users[0].rower
|
|
||||||
elif uploadoptions['username'] == '': # pragma: no cover
|
|
||||||
therower = rower
|
|
||||||
else: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
therower = rower
|
|
||||||
|
|
||||||
|
|
||||||
uploadoptions['secret'] = settings.UPLOAD_SERVICE_SECRET
|
|
||||||
uploadoptions['user'] = therower.user.id
|
|
||||||
uploadoptions['file'] = 'media/'+filename
|
|
||||||
uploadoptions['title'] = title
|
|
||||||
|
|
||||||
url = settings.UPLOAD_SERVICE_URL
|
|
||||||
if not testing: # pragma: no cover
|
|
||||||
response = requests.post(url,data=uploadoptions)
|
|
||||||
# print("Upload response status code",response.status_code, response.json())
|
|
||||||
if response.status_code == 200:
|
|
||||||
response_json = response.json()
|
|
||||||
workoutid = [int(response_json['id'])]
|
|
||||||
else:
|
|
||||||
workoutid = [0]
|
|
||||||
|
|
||||||
# this is ugly and needs to be done better
|
|
||||||
if testing:
|
|
||||||
workoutid = [
|
|
||||||
make_new_workout_from_email(therower, filename, title,testing=testing)
|
|
||||||
]
|
|
||||||
if workoutid[0] and uploadoptions and not 'error' in uploadoptions:
|
|
||||||
workout = Workout.objects.get(id=workoutid[0])
|
|
||||||
uploads.make_private(workout, uploadoptions)
|
|
||||||
uploads.set_workouttype(workout, uploadoptions)
|
|
||||||
uploads.do_sync(workout, uploadoptions)
|
|
||||||
|
|
||||||
|
|
||||||
if 'raceid' in uploadoptions and workoutid[0] and rower.user.is_staff:
|
|
||||||
if testing and workoutid[0]:
|
|
||||||
w = Workout.objects.get(id = workoutid[0])
|
|
||||||
w.startdatetime = timezone.now()
|
|
||||||
w.date = timezone.now().date()
|
|
||||||
w.save()
|
|
||||||
try:
|
|
||||||
race = VirtualRace.objects.get(id=uploadoptions['raceid'])
|
|
||||||
if race.manager == rower.user:
|
|
||||||
result = email_submit_race(therower,race,workoutid[0])
|
|
||||||
except VirtualRace.DoesNotExist: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
return workoutid
|
|
||||||
|
|
||||||
def get_from_address(message):
|
|
||||||
|
|
||||||
from_address = message.from_address[0].lower()
|
|
||||||
|
|
||||||
if message.encoded: # pragma: no cover
|
|
||||||
body = message.text.splitlines()
|
|
||||||
else:
|
|
||||||
body = message.get_body().splitlines()
|
|
||||||
|
|
||||||
try:
|
|
||||||
first_line = body[0].lower()
|
|
||||||
except IndexError: # pragma: no cover
|
|
||||||
first_line = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
first_line = first_line.decode('utf-8')
|
|
||||||
except AttributeError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
if "quiske" in first_line: # pragma: no cover
|
|
||||||
match = re.search(r'[\w\.-]+@[\w\.-]+', first_line)
|
|
||||||
return match.group(0)
|
|
||||||
|
|
||||||
return from_address
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
@@ -182,21 +85,11 @@ class Command(BaseCommand):
|
|||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
testing = False
|
testing = False
|
||||||
|
|
||||||
if 'mailbox' in options:
|
|
||||||
workoutmailbox = Mailbox.objects.get(name=options['mailbox'])
|
|
||||||
else: # pragma: no cover
|
|
||||||
workoutmailbox = Mailbox.objects.get(name='workouts')
|
|
||||||
|
|
||||||
if 'failedmailbox' in options: # pragma: no cover
|
|
||||||
failedmailbox = Mailbox.objects.get(name=options['failedmailbox'])
|
|
||||||
else: # pragma: no cover
|
|
||||||
failedmailbox = Mailbox.objects.get(name='Failed')
|
|
||||||
|
|
||||||
# Polar
|
# Polar
|
||||||
try:
|
try:
|
||||||
polar_available = polarstuff.get_polar_notifications()
|
polar_available = polarstuff.get_polar_notifications()
|
||||||
res = polarstuff.get_all_new_workouts(polar_available)
|
res = polarstuff.get_all_new_workouts(polar_available)
|
||||||
except:
|
except: # pragma: no cover
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||||
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
||||||
@@ -207,7 +100,7 @@ class Command(BaseCommand):
|
|||||||
for r in rowers: # pragma: no cover
|
for r in rowers: # pragma: no cover
|
||||||
if user_is_not_basic(r.user):
|
if user_is_not_basic(r.user):
|
||||||
c2stuff.get_c2_workouts(r)
|
c2stuff.get_c2_workouts(r)
|
||||||
except:
|
except: # pragma: no cover
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||||
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
||||||
@@ -218,7 +111,7 @@ class Command(BaseCommand):
|
|||||||
for r in rowers: # pragma: no cover
|
for r in rowers: # pragma: no cover
|
||||||
if user_is_not_basic(r.user):
|
if user_is_not_basic(r.user):
|
||||||
res = rp3stuff.get_rp3_workouts(r)
|
res = rp3stuff.get_rp3_workouts(r)
|
||||||
except:
|
except: # pragma: no cover
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||||
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
||||||
@@ -230,105 +123,11 @@ class Command(BaseCommand):
|
|||||||
s = 'Starting NK Auto Import for user {id}'.format(id=r.user.id)
|
s = 'Starting NK Auto Import for user {id}'.format(id=r.user.id)
|
||||||
dologging('nklog.log',s)
|
dologging('nklog.log',s)
|
||||||
res = nkstuff.get_nk_workouts(r)
|
res = nkstuff.get_nk_workouts(r)
|
||||||
except:
|
except: # pragma: no cover
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||||
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
dologging('processemail.log',''.join('!! ' + line for line in lines))
|
||||||
|
|
||||||
|
|
||||||
messages = Message.objects.filter(mailbox_id = workoutmailbox.id)
|
|
||||||
message_ids = [m.id for m in messages]
|
|
||||||
attachments = MessageAttachment.objects.filter(
|
|
||||||
message_id__in=message_ids
|
|
||||||
)
|
|
||||||
cntr = 0
|
|
||||||
for attachment in attachments:
|
|
||||||
filename, extension = os.path.splitext(attachment.document.name)
|
|
||||||
extension = extension.lower()
|
|
||||||
# extension = attachment.document.name[-3:].lower()
|
|
||||||
try:
|
|
||||||
message = Message.objects.get(id=attachment.message_id)
|
|
||||||
if message.encoded: # pragma: no cover
|
|
||||||
# if message.text:
|
|
||||||
body = "\n".join(message.text.splitlines())
|
|
||||||
else:
|
|
||||||
body = message.get_body()
|
|
||||||
|
|
||||||
uploadoptions = uploads.upload_options(body)
|
|
||||||
|
|
||||||
from_address = get_from_address(message)
|
|
||||||
|
|
||||||
name = message.subject
|
|
||||||
# get a list of users
|
|
||||||
# theusers = User.objects.filter(email=from_address)
|
|
||||||
rowers = [
|
|
||||||
r for r in Rower.objects.all() if r.user.email.lower() == from_address
|
|
||||||
]
|
|
||||||
try: # pragma: no cover
|
|
||||||
rowers2 = [
|
|
||||||
r for r in Rower.objects.all() if from_address in r.emailalternatives
|
|
||||||
]
|
|
||||||
rowers = rowers+rowers2
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
except IOError: # pragma: no cover
|
|
||||||
rowers = []
|
|
||||||
except Message.DoesNotExist: # pragma: no cover
|
|
||||||
try:
|
|
||||||
attachment.delete()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
for rower in rowers:
|
|
||||||
if 'zip' in extension:
|
|
||||||
try:
|
|
||||||
zip_file = zipfile.ZipFile(attachment.document)
|
|
||||||
for id,filename in enumerate(zip_file.namelist()):
|
|
||||||
datafile = zip_file.extract(
|
|
||||||
filename, path='media/')
|
|
||||||
if id>0:
|
|
||||||
title = name+' ('+str(id+1)+')'
|
|
||||||
else:
|
|
||||||
title = name
|
|
||||||
workoutid = processattachment(
|
|
||||||
rower, datafile, title, uploadoptions,
|
|
||||||
testing=testing
|
|
||||||
)
|
|
||||||
except BadZipFile: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
else:
|
|
||||||
# move attachment and make workout
|
|
||||||
|
|
||||||
workoutid = processattachment(
|
|
||||||
rower, attachment.document, name, uploadoptions,
|
|
||||||
testing=testing
|
|
||||||
)
|
|
||||||
|
|
||||||
# We're done with the attachment. It can be deleted
|
|
||||||
try:
|
|
||||||
attachment.delete()
|
|
||||||
except IOError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
except WindowsError: # pragma: no cover
|
|
||||||
if not testing:
|
|
||||||
time.sleep(2)
|
|
||||||
try:
|
|
||||||
attachment.delete()
|
|
||||||
except WindowsError:
|
|
||||||
pass
|
|
||||||
except: # pragma: no cover
|
|
||||||
message.mailbox = failedmailbox
|
|
||||||
message.save()
|
|
||||||
|
|
||||||
if message.attachments.exists() is False:
|
|
||||||
# no attachments, so can be deleted
|
|
||||||
message.delete()
|
|
||||||
|
|
||||||
messages = Message.objects.all()
|
|
||||||
for message in messages:
|
|
||||||
if message.attachments.exists() is False:
|
|
||||||
message.delete()
|
|
||||||
|
|
||||||
# Strava
|
# Strava
|
||||||
#rowers = Rower.objects.filter(strava_auto_import=True)
|
#rowers = Rower.objects.filter(strava_auto_import=True)
|
||||||
#for r in rowers:
|
#for r in rowers:
|
||||||
|
|||||||
+9
-9
@@ -103,22 +103,22 @@ smoothingchoices = (
|
|||||||
def half_year_from_now(ttz=None):
|
def half_year_from_now(ttz=None):
|
||||||
if ttz is None:
|
if ttz is None:
|
||||||
return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=182)).date()
|
return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=182)).date()
|
||||||
return (datetime.datetime.utcnow()+timezone.timedelta(days=182)).astimezone(pytz.timezone(ttz)).date()
|
return (datetime.datetime.utcnow()+timezone.timedelta(days=182)).astimezone(pytz.timezone(ttz)).date() # pragma: no cover
|
||||||
|
|
||||||
def a_week_from_now(ttz=None):
|
def a_week_from_now(ttz=None):
|
||||||
if ttz is None:
|
if ttz is None:
|
||||||
return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=7)).date()
|
return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=7)).date()
|
||||||
return (datetime.datetime.utcnow()+timezone.timedelta(days=7)).astimezone(pytz.timezone(ttz)).date()
|
return (datetime.datetime.utcnow()+timezone.timedelta(days=7)).astimezone(pytz.timezone(ttz)).date() # pragma: no cover
|
||||||
|
|
||||||
def current_day(ttz=None):
|
def current_day(ttz=None):
|
||||||
if ttz is None:
|
if ttz is None:
|
||||||
return (datetime.datetime.now(tz=timezone.utc)).date()
|
return (datetime.datetime.now(tz=timezone.utc)).date()
|
||||||
return datetime.datetime.utcnow().astimezone(pytz.timezone(ttz)).date()
|
return datetime.datetime.utcnow().astimezone(pytz.timezone(ttz)).date() # pragma: no cover
|
||||||
|
|
||||||
def current_time(ttz=None): # pragma: no cover
|
def current_time(ttz=None): # pragma: no cover
|
||||||
if ttz is None:
|
if ttz is None:
|
||||||
return datetime.datetime.now(tz=timezone.utc)
|
return datetime.datetime.now(tz=timezone.utc)
|
||||||
return (datetime.datetime.utcnow()).astimezone(pytz.timezone(ttz))
|
return (datetime.datetime.utcnow()).astimezone(pytz.timezone(ttz)) # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
class UserFullnameChoiceField(forms.ModelChoiceField):
|
class UserFullnameChoiceField(forms.ModelChoiceField):
|
||||||
@@ -2188,7 +2188,7 @@ class TrainingMesoCycle(models.Model):
|
|||||||
|
|
||||||
if not self.enddate <= self.startdate:
|
if not self.enddate <= self.startdate:
|
||||||
super(TrainingMesoCycle,self).save(*args, **kwargs)
|
super(TrainingMesoCycle,self).save(*args, **kwargs)
|
||||||
else:
|
else: # pragma: no cover
|
||||||
self.enddate = self.startdate
|
self.enddate = self.startdate
|
||||||
super(TrainingMesoCycle,self).save(*args, **kwargs)
|
super(TrainingMesoCycle,self).save(*args, **kwargs)
|
||||||
|
|
||||||
@@ -2512,18 +2512,18 @@ class PlannedSession(models.Model):
|
|||||||
elif self.sessiontype != 'coursetest' and self.sessiontype != 'race':
|
elif self.sessiontype != 'coursetest' and self.sessiontype != 'race':
|
||||||
self.course = None
|
self.course = None
|
||||||
|
|
||||||
if self.enddate < self.startdate:
|
if self.enddate < self.startdate: # pragma: no cover
|
||||||
self.enddate = self.startdate
|
self.enddate = self.startdate
|
||||||
|
|
||||||
if self.preferreddate > self.enddate:
|
if self.preferreddate > self.enddate: # pragma: no cover
|
||||||
self.preferreddate = self.enddate
|
self.preferreddate = self.enddate
|
||||||
if self.preferreddate < self.startdate:
|
if self.preferreddate < self.startdate: # pragma: no cover
|
||||||
self.preferreddate = self.startdate
|
self.preferreddate = self.startdate
|
||||||
|
|
||||||
#super(PlannedSession,self).save(*args, **kwargs)
|
#super(PlannedSession,self).save(*args, **kwargs)
|
||||||
if self.steps:
|
if self.steps:
|
||||||
steps = self.steps
|
steps = self.steps
|
||||||
elif self.fitfile:
|
elif self.fitfile: # pragma: no cover
|
||||||
steps = steps_read_fit(os.path.join(settings.MEDIA_ROOT,self.fitfile.name))
|
steps = steps_read_fit(os.path.join(settings.MEDIA_ROOT,self.fitfile.name))
|
||||||
self.steps = steps
|
self.steps = steps
|
||||||
|
|
||||||
|
|||||||
+3
-126
@@ -1145,10 +1145,10 @@ def update_indoorvirtualrace(ps,cd):
|
|||||||
|
|
||||||
ps.timezone = timezone_str
|
ps.timezone = timezone_str
|
||||||
|
|
||||||
if ps.sessiontype == 'fastest_distance':
|
if ps.sessiontype == 'fastest_distance': # pragma: no cover
|
||||||
ps.approximate_distance = ps.sessionvalue
|
ps.approximate_distance = ps.sessionvalue
|
||||||
|
|
||||||
if ps.course is not None:
|
if ps.course is not None: # pragma: no cover
|
||||||
ps.approximate_distance = ps.course.distance
|
ps.approximate_distance = ps.course.distance
|
||||||
|
|
||||||
ps.save()
|
ps.save()
|
||||||
@@ -1204,7 +1204,7 @@ def update_virtualrace(ps,cd):
|
|||||||
|
|
||||||
ps.timezone = timezone_str
|
ps.timezone = timezone_str
|
||||||
|
|
||||||
if ps.sessiontype == 'fastest_distance':
|
if ps.sessiontype == 'fastest_distance': # pragma: no cover
|
||||||
ps.approximate_distance = ps.sessionvalue
|
ps.approximate_distance = ps.sessionvalue
|
||||||
|
|
||||||
if ps.course is not None:
|
if ps.course is not None:
|
||||||
@@ -1403,129 +1403,6 @@ def race_can_withdraw(r,race):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def email_submit_race(r,race,workoutid):
|
|
||||||
try:
|
|
||||||
w = Workout.objects.get(id=workoutid)
|
|
||||||
except Workout.DoesNotExist: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if race.sessionmode == 'time':
|
|
||||||
wduration = timefield_to_seconds_duration(w.duration)
|
|
||||||
delta = wduration - (60.*race.sessionvalue)
|
|
||||||
|
|
||||||
if delta > -2 and delta < 2:
|
|
||||||
w.duration = totaltime_sec_to_string(60.*race.sessionvalue)
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
|
|
||||||
elif race.sessionmode == 'distance': # pragma: no cover
|
|
||||||
delta = w.distance - race.sessionvalue
|
|
||||||
|
|
||||||
if delta > -5 and delta < 5:
|
|
||||||
w.distance = race.sessionvalue
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
|
|
||||||
if race_can_register(r,race):
|
|
||||||
teamname = ''
|
|
||||||
weightcategory = w.weightcategory
|
|
||||||
sex = r.sex
|
|
||||||
if sex == 'not specified':
|
|
||||||
sex = 'male'
|
|
||||||
|
|
||||||
if not r.birthdate: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
age = calculate_age(r.birthdate)
|
|
||||||
|
|
||||||
adaptiveclass = r.adaptiveclass
|
|
||||||
boatclass = w.workouttype
|
|
||||||
|
|
||||||
record = IndoorVirtualRaceResult(
|
|
||||||
userid = r.id,
|
|
||||||
teamname=teamname,
|
|
||||||
race=race,
|
|
||||||
username = u'{f} {l}'.format(
|
|
||||||
f = r.user.first_name,
|
|
||||||
l = r.user.last_name
|
|
||||||
),
|
|
||||||
weightcategory=weightcategory,
|
|
||||||
adaptiveclass=adaptiveclass,
|
|
||||||
duration=dt.time(0,0),
|
|
||||||
boatclass=boatclass,
|
|
||||||
coursecompleted=False,
|
|
||||||
sex=sex,
|
|
||||||
age=age
|
|
||||||
)
|
|
||||||
|
|
||||||
record.save()
|
|
||||||
|
|
||||||
result = add_rower_race(r,race)
|
|
||||||
|
|
||||||
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
|
||||||
race = race)
|
|
||||||
|
|
||||||
|
|
||||||
for otherrecord in otherrecords:
|
|
||||||
otheruser = Rower.objects.get(id=otherrecord.userid)
|
|
||||||
othername = otheruser.user.first_name+' '+otheruser.user.last_name
|
|
||||||
registeredname = r.user.first_name+' '+r.user.last_name
|
|
||||||
if otherrecord.emailnotifications:
|
|
||||||
job = myqueue(
|
|
||||||
queue,
|
|
||||||
handle_sendemail_raceregistration,
|
|
||||||
otheruser.user.email, othername,
|
|
||||||
registeredname,
|
|
||||||
race.name,
|
|
||||||
race.id
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if race_can_submit(r,race):
|
|
||||||
records = IndoorVirtualRaceResult.objects.filter(
|
|
||||||
userid = r.id,
|
|
||||||
race=race
|
|
||||||
)
|
|
||||||
|
|
||||||
if not records: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
record = records[0]
|
|
||||||
|
|
||||||
workouts = Workout.objects.filter(id=w.id)
|
|
||||||
|
|
||||||
result,comments,errors,jobid = add_workout_indoorrace(
|
|
||||||
workouts,race,r,recordid=record.id
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if result:
|
|
||||||
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
|
||||||
race = race)
|
|
||||||
|
|
||||||
for otherrecord in otherrecords:
|
|
||||||
otheruser = Rower.objects.get(id=otherrecord.userid)
|
|
||||||
othername = otheruser.user.first_name+' '+otheruser.user.last_name
|
|
||||||
registeredname = r.user.first_name+' '+r.user.last_name
|
|
||||||
if otherrecord.emailnotifications:
|
|
||||||
job = myqueue(
|
|
||||||
queue,
|
|
||||||
handle_sendemail_racesubmission,
|
|
||||||
otheruser.user.email, othername,
|
|
||||||
registeredname,
|
|
||||||
race.name,
|
|
||||||
race.id
|
|
||||||
)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return 0 # pragma: no cover
|
|
||||||
else: # pragma: no cover
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
return 0 # pragma: no cover
|
|
||||||
|
|
||||||
|
|
||||||
def race_can_register(r,race):
|
def race_can_register(r,race):
|
||||||
if race.sessiontype in ['race']:
|
if race.sessiontype in ['race']:
|
||||||
|
|||||||
+17
-11
@@ -38,6 +38,7 @@ from django.contrib.auth.decorators import login_required
|
|||||||
from rowingdata import rowingdata
|
from rowingdata import rowingdata
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from rowers.models import Rower,Workout
|
from rowers.models import Rower,Workout
|
||||||
|
from rowers.tasks import handle_request_post
|
||||||
|
|
||||||
import rowers.dataprep as dataprep
|
import rowers.dataprep as dataprep
|
||||||
from rowers.dataprep import columndict
|
from rowers.dataprep import columndict
|
||||||
@@ -47,8 +48,6 @@ from io import StringIO
|
|||||||
import stravalib
|
import stravalib
|
||||||
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
|
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
|
||||||
|
|
||||||
from django_mailbox.models import Message,Mailbox,MessageAttachment
|
|
||||||
|
|
||||||
from rowsandall_app.settings import (
|
from rowsandall_app.settings import (
|
||||||
POLAR_CLIENT_ID, POLAR_REDIRECT_URI, POLAR_CLIENT_SECRET,
|
POLAR_CLIENT_ID, POLAR_REDIRECT_URI, POLAR_CLIENT_SECRET,
|
||||||
)
|
)
|
||||||
@@ -115,7 +114,7 @@ def make_authorization_url(): # pragma: no cover
|
|||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
def get_polar_notifications():
|
def get_polar_notifications(): # pragma: no cover
|
||||||
url = baseurl+'/notifications'
|
url = baseurl+'/notifications'
|
||||||
state = str(uuid4())
|
state = str(uuid4())
|
||||||
auth_string = '{id}:{secret}'.format(
|
auth_string = '{id}:{secret}'.format(
|
||||||
@@ -197,7 +196,6 @@ def get_polar_workouts(user):
|
|||||||
|
|
||||||
if response.status_code == 201:
|
if response.status_code == 201:
|
||||||
|
|
||||||
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
|
|
||||||
uploadoptions = {
|
uploadoptions = {
|
||||||
'makeprivate':False,
|
'makeprivate':False,
|
||||||
}
|
}
|
||||||
@@ -231,15 +229,23 @@ def get_polar_workouts(user):
|
|||||||
with open(filename,'wb') as fop:
|
with open(filename,'wb') as fop:
|
||||||
fop.write(response.content)
|
fop.write(response.content)
|
||||||
|
|
||||||
msg = Message(mailbox=workoutsbox,
|
# post file to upload api
|
||||||
from_header=user.email,
|
json_data = {
|
||||||
subject = '',
|
'title':'',
|
||||||
body=bodyyaml)
|
'workouttype':'',
|
||||||
|
'user':user.id,
|
||||||
|
'secret':settings.UPLOAD_SERVICE_SECRET,
|
||||||
|
'file':filename,
|
||||||
|
}
|
||||||
|
url = reverse('workout_upload_api')
|
||||||
|
|
||||||
msg.save()
|
|
||||||
|
|
||||||
a = MessageAttachment(message=msg,document=filename[6:])
|
job = myqueue(queuehigh,
|
||||||
a.save()
|
handle_request_post,
|
||||||
|
url,
|
||||||
|
json_data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
exercise_dict['filename'] = filename
|
exercise_dict['filename'] = filename
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import time
|
|||||||
from time import strftime
|
from time import strftime
|
||||||
|
|
||||||
|
|
||||||
from django_mailbox.models import Message,Mailbox,MessageAttachment
|
|
||||||
|
|
||||||
import django_rq
|
import django_rq
|
||||||
queue = django_rq.get_queue('default')
|
queue = django_rq.get_queue('default')
|
||||||
queuelow = django_rq.get_queue('low')
|
queuelow = django_rq.get_queue('low')
|
||||||
@@ -212,157 +210,6 @@ def get_strava_workout_list(user,limit_n=0):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
# gets all new Strava workouts for a rower
|
|
||||||
def get_strava_workouts(rower): # pragma: no cover
|
|
||||||
try:
|
|
||||||
thetoken = strava_open(rower.user)
|
|
||||||
except NoTokenError:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
res = get_strava_workout_list(rower.user,limit_n=10)
|
|
||||||
|
|
||||||
if (res.status_code != 200):
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
stravaids = [int(item['id']) for item in res.json()]
|
|
||||||
stravadata = [{
|
|
||||||
'id':int(item['id']),
|
|
||||||
'elapsed_time':item['elapsed_time'],
|
|
||||||
'start_date':item['start_date'],
|
|
||||||
} for item in res.json()]
|
|
||||||
|
|
||||||
alldata = {}
|
|
||||||
for item in res.json():
|
|
||||||
alldata[item['id']] = item
|
|
||||||
|
|
||||||
|
|
||||||
wfailed = Workout.objects.filter(user=rower,uploadedtostrava=-1)
|
|
||||||
|
|
||||||
for w in wfailed:
|
|
||||||
for item in stravadata:
|
|
||||||
elapsed_time = item['elapsed_time']
|
|
||||||
start_date = item['start_date']
|
|
||||||
stravaid = item['id']
|
|
||||||
|
|
||||||
if arrow.get(start_date) == arrow.get(w.startdatetime):
|
|
||||||
dd = datetime.min + timedelta(
|
|
||||||
seconds=int(elapsed_time)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
delta = datetime.combine(datetime.min,datetime.time(dd))-datetime.combine(datetime.min,w.duration)
|
|
||||||
|
|
||||||
if delta < timedelta(minutes=2):
|
|
||||||
w.uploadedtostrava = int(stravaid)
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
knownstravaids = [
|
|
||||||
w.uploadedtostrava for w in Workout.objects.filter(user=rower)
|
|
||||||
]
|
|
||||||
|
|
||||||
tombstones = [
|
|
||||||
t.uploadedtostrava for t in TombStone.objects.filter(user=rower)
|
|
||||||
]
|
|
||||||
|
|
||||||
knownstravaids = uniqify(knownstravaids+tombstones)
|
|
||||||
|
|
||||||
newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids]
|
|
||||||
|
|
||||||
for stravaid in newids:
|
|
||||||
result = create_async_workout(alldata,rower.user,stravaid)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def create_async_workout(alldata,user,stravaid,debug=False):
|
|
||||||
data = alldata[stravaid]
|
|
||||||
r = Rower.objects.get(user=user)
|
|
||||||
distance = data['distance']
|
|
||||||
stravaid = data['id']
|
|
||||||
try:
|
|
||||||
workouttype = mytypes.stravamappinginv[data['type']]
|
|
||||||
except: # pragma: no cover
|
|
||||||
workouttype = 'other'
|
|
||||||
|
|
||||||
if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover
|
|
||||||
workouttype = 'other'
|
|
||||||
|
|
||||||
if workouttype.lower() == 'rowing': # pragma: no cover
|
|
||||||
workouttype = 'rower'
|
|
||||||
if 'summary_polyline' in data['map']:
|
|
||||||
workouttype = 'water'
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
comments = data['comments']
|
|
||||||
except:
|
|
||||||
comments = ' '
|
|
||||||
|
|
||||||
try:
|
|
||||||
thetimezone = tz(data['timezone'])
|
|
||||||
except:
|
|
||||||
thetimezone = 'UTC'
|
|
||||||
|
|
||||||
try:
|
|
||||||
rowdatetime = iso8601.parse_date(data['date_utc'])
|
|
||||||
except KeyError:
|
|
||||||
rowdatetime = iso8601.parse_date(data['start_date'])
|
|
||||||
except ParseError: # pragma: no cover
|
|
||||||
rowdatetime = iso8601.parse_date(data['date'])
|
|
||||||
|
|
||||||
try:
|
|
||||||
c2intervaltype = data['workout_type']
|
|
||||||
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
c2intervaltype = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
title = data['name']
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
title = ""
|
|
||||||
try:
|
|
||||||
t = data['comments'].split('\n', 1)[0]
|
|
||||||
title += t[:20]
|
|
||||||
except:
|
|
||||||
title = ''
|
|
||||||
|
|
||||||
workoutdate = rowdatetime.astimezone(
|
|
||||||
pytz.timezone(thetimezone)
|
|
||||||
).strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
starttime = rowdatetime.astimezone(
|
|
||||||
pytz.timezone(thetimezone)
|
|
||||||
).strftime('%H:%M:%S')
|
|
||||||
|
|
||||||
totaltime = data['elapsed_time']
|
|
||||||
duration = dataprep.totaltime_sec_to_string(totaltime)
|
|
||||||
|
|
||||||
weightcategory = 'hwt'
|
|
||||||
|
|
||||||
# Create CSV file name and save data to CSV file
|
|
||||||
csvfilename ='media/mailbox_attachments/{code}_{importid}.csv'.format(
|
|
||||||
importid=stravaid,
|
|
||||||
code = uuid4().hex[:16]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check if workout has stroke data, and get the stroke data
|
|
||||||
|
|
||||||
starttimeunix = arrow.get(rowdatetime).timestamp()
|
|
||||||
|
|
||||||
result = handle_strava_import_stroke_data(
|
|
||||||
title,
|
|
||||||
user.email,
|
|
||||||
r.stravatoken,
|
|
||||||
stravaid,
|
|
||||||
starttimeunix,
|
|
||||||
csvfilename,
|
|
||||||
workouttype = workouttype,
|
|
||||||
boattype = '1x'
|
|
||||||
)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
from rowers.utils import get_strava_stream
|
from rowers.utils import get_strava_stream
|
||||||
|
|
||||||
def async_get_workout(user,stravaid):
|
def async_get_workout(user,stravaid):
|
||||||
@@ -559,174 +406,3 @@ def workout_strava_upload(user,w, quick=False,asynchron=True):
|
|||||||
os.remove(tcxfile)
|
os.remove(tcxfile)
|
||||||
return message,stravaid
|
return message,stravaid
|
||||||
return message,stravaid # pragma: no cover
|
return message,stravaid # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def handle_strava_import_stroke_data(title,
|
|
||||||
useremail,
|
|
||||||
stravatoken,
|
|
||||||
stravaid,
|
|
||||||
starttimeunix,
|
|
||||||
csvfilename,debug=True,
|
|
||||||
workouttype = 'rower',
|
|
||||||
boattype = '1x',
|
|
||||||
**kwargs):
|
|
||||||
# ready to fetch. Hurray
|
|
||||||
|
|
||||||
fetchresolution = 'high'
|
|
||||||
series_type = 'time'
|
|
||||||
authorizationstring = str('Bearer ' + stravatoken)
|
|
||||||
headers = {'Authorization': authorizationstring,
|
|
||||||
'user-agent': 'sanderroosendaal',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'resolution': 'medium',}
|
|
||||||
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)
|
|
||||||
workoutsummary = requests.get(url,headers=headers).json()
|
|
||||||
|
|
||||||
workoutsummary['timezone'] = "Etc/UTC"
|
|
||||||
startdatetime = workoutsummary['start_date']
|
|
||||||
|
|
||||||
r = type('Rower', (object,), {"stravatoken": stravatoken})
|
|
||||||
|
|
||||||
spm = get_strava_stream(r,'cadence',stravaid)
|
|
||||||
t = get_strava_stream(r,'time',stravaid)
|
|
||||||
|
|
||||||
try:
|
|
||||||
hr = get_strava_stream(r,'heartrate',stravaid)
|
|
||||||
except JSONDecodeError: # pragma: no cover
|
|
||||||
hr = 0*spm
|
|
||||||
|
|
||||||
try:
|
|
||||||
velo = get_strava_stream(r,'velocity_smooth',stravaid)
|
|
||||||
except JSONDecodeError: # pragma: no cover
|
|
||||||
velo = 0*t
|
|
||||||
|
|
||||||
try:
|
|
||||||
d = get_strava_stream(r,'distance',stravaid)
|
|
||||||
except JSONDecodeError: # pragma: no cover
|
|
||||||
d = 0*t
|
|
||||||
|
|
||||||
try:
|
|
||||||
coords = get_strava_stream(r,'latlng',stravaid)
|
|
||||||
except JSONDecodeError: # pragma: no cover
|
|
||||||
coords = 0*t
|
|
||||||
try:
|
|
||||||
power = get_strava_stream(r,'watts',stravaid)
|
|
||||||
except JSONDecodeError: # pragma: no cover
|
|
||||||
power = 0*t
|
|
||||||
|
|
||||||
if t is not None:
|
|
||||||
nr_rows = len(t)
|
|
||||||
else: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if nr_rows == 0: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if d is None: # pragma: no cover
|
|
||||||
d = 0*t
|
|
||||||
|
|
||||||
if spm is None: # pragma: no cover
|
|
||||||
spm = np.zeros(nr_rows)
|
|
||||||
|
|
||||||
if power is None: # pragma: no cover
|
|
||||||
power = np.zeros(nr_rows)
|
|
||||||
|
|
||||||
if hr is None: # pragma: no cover
|
|
||||||
hr = np.zeros(nr_rows)
|
|
||||||
|
|
||||||
if velo is None: # pragma: no cover
|
|
||||||
velo = np.zeros(nr_rows)
|
|
||||||
|
|
||||||
|
|
||||||
f = np.diff(t).mean()
|
|
||||||
if f != 0:
|
|
||||||
windowsize = 2*(int(10./(f)))+1
|
|
||||||
else: # pragma: no cover
|
|
||||||
windowsize = 1
|
|
||||||
|
|
||||||
if windowsize > 3 and windowsize < len(velo):
|
|
||||||
velo2 = savgol_filter(velo,windowsize,3)
|
|
||||||
else: # pragma: no cover
|
|
||||||
velo2 = velo
|
|
||||||
|
|
||||||
if coords is not None:
|
|
||||||
try:
|
|
||||||
lat = coords[:,0]
|
|
||||||
lon = coords[:,1]
|
|
||||||
if lat.std() == 0 and lon.std() == 0 and workouttype == 'water': # pragma: no cover
|
|
||||||
workouttype = 'rower'
|
|
||||||
except IndexError: # pragma: no cover
|
|
||||||
lat = np.zeros(len(t))
|
|
||||||
lon = np.zeros(len(t))
|
|
||||||
if workouttype == 'water':
|
|
||||||
workouttype = 'rower'
|
|
||||||
else: # pragma: no cover
|
|
||||||
lat = np.zeros(len(t))
|
|
||||||
lon = np.zeros(len(t))
|
|
||||||
if workouttype == 'water':
|
|
||||||
workouttype = 'rower'
|
|
||||||
|
|
||||||
strokelength = velo*60./(spm)
|
|
||||||
strokelength[np.isinf(strokelength)] = 0.0
|
|
||||||
|
|
||||||
pace = 500./(1.0*velo2)
|
|
||||||
pace[np.isinf(pace)] = 0.0
|
|
||||||
|
|
||||||
unixtime = starttimeunix+t
|
|
||||||
|
|
||||||
strokedistance = 60.*velo2/spm
|
|
||||||
|
|
||||||
if workouttype == 'rower' and pd.Series(power).mean() == 0: # pragma: no cover
|
|
||||||
power = 2.8*(velo2**3)
|
|
||||||
|
|
||||||
nr_strokes = len(t)
|
|
||||||
|
|
||||||
df = pd.DataFrame({'TimeStamp (sec)':unixtime,
|
|
||||||
' ElapsedTime (sec)':t,
|
|
||||||
' Horizontal (meters)':d,
|
|
||||||
' Stroke500mPace (sec/500m)':pace,
|
|
||||||
' Cadence (stokes/min)':spm,
|
|
||||||
' HRCur (bpm)':hr,
|
|
||||||
' latitude':lat,
|
|
||||||
' longitude':lon,
|
|
||||||
' StrokeDistance (meters)':strokelength,
|
|
||||||
'cum_dist':d,
|
|
||||||
' DragFactor':np.zeros(nr_strokes),
|
|
||||||
' DriveLength (meters)':np.zeros(nr_strokes),
|
|
||||||
' StrokeDistance (meters)':strokedistance,
|
|
||||||
' DriveTime (ms)':np.zeros(nr_strokes),
|
|
||||||
' StrokeRecoveryTime (ms)':np.zeros(nr_strokes),
|
|
||||||
' AverageDriveForce (lbs)':np.zeros(nr_strokes),
|
|
||||||
' PeakDriveForce (lbs)':np.zeros(nr_strokes),
|
|
||||||
' lapIdx':np.zeros(nr_strokes),
|
|
||||||
' Power (watts)':power,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
df.sort_values(by='TimeStamp (sec)',ascending=True)
|
|
||||||
|
|
||||||
res = df.to_csv(csvfilename,index_label='index')
|
|
||||||
|
|
||||||
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
|
|
||||||
|
|
||||||
body = """stravaid {stravaid}
|
|
||||||
workouttype {workouttype}
|
|
||||||
boattype {boattype}""".format(
|
|
||||||
stravaid=stravaid,
|
|
||||||
workouttype=workouttype,
|
|
||||||
boattype=boattype
|
|
||||||
)
|
|
||||||
|
|
||||||
msg = Message(mailbox=workoutsbox,
|
|
||||||
from_header=useremail,
|
|
||||||
subject=title,
|
|
||||||
body=body)
|
|
||||||
msg.save()
|
|
||||||
|
|
||||||
a = MessageAttachment(message=msg,document=csvfilename[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
return res
|
|
||||||
|
|||||||
+14
-7
@@ -284,6 +284,12 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
|
|||||||
return sums,sa,results
|
return sums,sa,results
|
||||||
|
|
||||||
|
|
||||||
|
@app.task
|
||||||
|
def handle_request_post(url, data,debug=False, **kwargs): # pragma: no cover
|
||||||
|
response = requests.post(url,data)
|
||||||
|
return response.status_code
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def add(x, y): # pragma: no cover
|
def add(x, y): # pragma: no cover
|
||||||
return x + y
|
return x + y
|
||||||
@@ -1363,7 +1369,8 @@ def handle_send_email_transaction(
|
|||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_send_email_instantplan_notification(
|
def handle_send_email_instantplan_notification(
|
||||||
username, useremail, amount, planname,startdate, enddate, **kwargs):
|
username, useremail, amount, planname,startdate, enddate, **kwargs
|
||||||
|
): # pragma: no cover
|
||||||
|
|
||||||
if 'debug' in kwargs: # pragma: no cover
|
if 'debug' in kwargs: # pragma: no cover
|
||||||
debug = kwargs['debug']
|
debug = kwargs['debug']
|
||||||
@@ -1531,7 +1538,7 @@ def handle_sendemail_raceregistration(
|
|||||||
|
|
||||||
def handle_sendemail_coursesucceed(
|
def handle_sendemail_coursesucceed(
|
||||||
useremail, username, logfile, workoutid, **kwargs
|
useremail, username, logfile, workoutid, **kwargs
|
||||||
):
|
): # pragma: no cover
|
||||||
if 'debug' in kwargs: # pragma: no cover
|
if 'debug' in kwargs: # pragma: no cover
|
||||||
debug = kwargs['debug']
|
debug = kwargs['debug']
|
||||||
else:
|
else:
|
||||||
@@ -3240,7 +3247,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
|
|||||||
splitdata = None
|
splitdata = None
|
||||||
|
|
||||||
distance = data['distance']
|
distance = data['distance']
|
||||||
try:
|
try: # pragma: no cover
|
||||||
rest_distance = data['rest_distance']
|
rest_distance = data['rest_distance']
|
||||||
rest_time = data['rest_time']/10.
|
rest_time = data['rest_time']/10.
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -3319,7 +3326,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
|
|||||||
#dologging('debuglog.log',json.dumps(s.json()))
|
#dologging('debuglog.log',json.dumps(s.json()))
|
||||||
try:
|
try:
|
||||||
strokedata = pd.DataFrame.from_dict(s.json()['data'])
|
strokedata = pd.DataFrame.from_dict(s.json()['data'])
|
||||||
except AttributeError:
|
except AttributeError: # pragma: no cover
|
||||||
dologging('debuglog.log','No stroke data in stroke data')
|
dologging('debuglog.log','No stroke data in stroke data')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -3327,7 +3334,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
|
|||||||
res = make_cumvalues(0.1*strokedata['t'])
|
res = make_cumvalues(0.1*strokedata['t'])
|
||||||
cum_time = res[0]
|
cum_time = res[0]
|
||||||
lapidx = res[1]
|
lapidx = res[1]
|
||||||
except KeyError:
|
except KeyError: # pragma: no cover
|
||||||
dologging('debuglog.log','No time values in stroke data')
|
dologging('debuglog.log','No time values in stroke data')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -3633,7 +3640,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu
|
|||||||
'power':power,
|
'power':power,
|
||||||
'strokelength':strokelength,
|
'strokelength':strokelength,
|
||||||
})
|
})
|
||||||
except ValueError:
|
except ValueError: # pragma: no cover
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -3648,7 +3655,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu
|
|||||||
try:
|
try:
|
||||||
if 'summary_polyline' in workoutsummary['map'] and workouttype=='rower': # pragma: no cover
|
if 'summary_polyline' in workoutsummary['map'] and workouttype=='rower': # pragma: no cover
|
||||||
workouttype = 'water'
|
workouttype = 'water'
|
||||||
except KeyError:
|
except KeyError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -8,15 +8,6 @@
|
|||||||
<h1>Available on Strava</h1>
|
<h1>Available on Strava</h1>
|
||||||
{% if workouts %}
|
{% if workouts %}
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li>
|
|
||||||
<a href="/rowers/workout/stravaimport/all/" class="blue button">Import all NEW</a>
|
|
||||||
</li>
|
|
||||||
<li class="grid_3">
|
|
||||||
<p>This imports all workouts that have not been imported to rowsandall.com.
|
|
||||||
The action may take a longer time to process, so please be patient. Click on Import in the list below to import an individual workout.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<form enctype="multipart/form-data" method="post">
|
<form enctype="multipart/form-data" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ from rowers.dataprep import delete_strokedata
|
|||||||
from redis import StrictRedis
|
from redis import StrictRedis
|
||||||
redis_connection = StrictRedis()
|
redis_connection = StrictRedis()
|
||||||
|
|
||||||
from django_mailbox.models import Mailbox,MessageAttachment,Message
|
|
||||||
|
|
||||||
def mocked_grpc(*args, **kwargs):
|
def mocked_grpc(*args, **kwargs):
|
||||||
class insecure_channel:
|
class insecure_channel:
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ from importlib import import_module
|
|||||||
from redis import StrictRedis
|
from redis import StrictRedis
|
||||||
redis_connection = StrictRedis()
|
redis_connection = StrictRedis()
|
||||||
|
|
||||||
from django_mailbox.models import Mailbox,MessageAttachment,Message
|
|
||||||
|
|
||||||
from rowers.tests.mocks import *
|
from rowers.tests.mocks import *
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ class OwnApi(TestCase):
|
|||||||
gdproptindate=timezone.now(),
|
gdproptindate=timezone.now(),
|
||||||
rowerplan='coach',subscription_id=1)
|
rowerplan='coach',subscription_id=1)
|
||||||
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
self.c = Client()
|
self.c = Client()
|
||||||
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
|
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
|
||||||
|
|||||||
@@ -69,10 +69,6 @@ class BraintreeUnits(TestCase):
|
|||||||
gdproptindate=timezone.now(),
|
gdproptindate=timezone.now(),
|
||||||
rowerplan='coach',subscription_id=1)
|
rowerplan='coach',subscription_id=1)
|
||||||
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
self.pp = PaidPlan.objects.create(price=0,paymentprocessor='braintree')
|
self.pp = PaidPlan.objects.create(price=0,paymentprocessor='braintree')
|
||||||
self.p2 = PaidPlan.objects.create(price=25,paymentprocessor='braintree')
|
self.p2 = PaidPlan.objects.create(price=25,paymentprocessor='braintree')
|
||||||
|
|||||||
+10
-388
@@ -29,18 +29,7 @@ class EmailUpload(TestCase):
|
|||||||
rowerplan='coach')
|
rowerplan='coach')
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
nu = datetime.datetime.now()
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts1')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = "run",
|
|
||||||
body = """
|
|
||||||
workout run
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/colin3.csv'
|
a2 = 'media/mailbox_attachments/colin3.csv'
|
||||||
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
||||||
a3 = 'media/mailbox_attachments/colin4.csv'
|
a3 = 'media/mailbox_attachments/colin4.csv'
|
||||||
@@ -52,8 +41,6 @@ workout run
|
|||||||
a6 = 'media/mailbox_attachments/colin7.csv'
|
a6 = 'media/mailbox_attachments/colin7.csv'
|
||||||
copy('rowers/tests/testdata/emails/colin.csv',a6)
|
copy('rowers/tests/testdata/emails/colin.csv',a6)
|
||||||
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for filename in os.listdir('media/mailbox_attachments'):
|
for filename in os.listdir('media/mailbox_attachments'):
|
||||||
@@ -64,6 +51,7 @@ workout run
|
|||||||
except (IOError,FileNotFoundError,OSError):
|
except (IOError,FileNotFoundError,OSError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
||||||
def test_uploadapi(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_uploadapi(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
||||||
@@ -168,266 +156,7 @@ workout run
|
|||||||
self.assertEqual(response.status_code,403)
|
self.assertEqual(response.status_code,403)
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.polarstuff.get_polar_notifications')
|
|
||||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
|
||||||
def test_emailupload(
|
|
||||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts1')
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(name="run")
|
|
||||||
|
|
||||||
self.assertEqual(len(ws),1)
|
|
||||||
w = ws[0]
|
|
||||||
self.assertEqual(w.workouttype,'Run')
|
|
||||||
|
|
||||||
@override_settings(TESTING=True)
|
|
||||||
class ZipEmailUpload(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
redis_connection.publish('tasks','KILL')
|
|
||||||
u = User.objects.create_user('john',
|
|
||||||
'sander@ds.ds',
|
|
||||||
'koeinsloot')
|
|
||||||
r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now()
|
|
||||||
)
|
|
||||||
|
|
||||||
self.theadmin = UserFactory(is_staff=True)
|
|
||||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
|
||||||
birthdate = faker.profile()['birthdate'],
|
|
||||||
gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now(),
|
|
||||||
rowerplan='coach')
|
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts1')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = "Sprint",
|
|
||||||
body = """
|
|
||||||
workout water
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/zipfile.zip'
|
|
||||||
copy('rowers/tests/testdata/zipfile.zip',a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
for filename in os.listdir('media/mailbox_attachments'):
|
|
||||||
path = os.path.join('media/mailbox_attachments/',filename)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except (IOError,FileNotFoundError,OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.polarstuff.get_polar_notifications')
|
|
||||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
|
||||||
def test_emailupload(
|
|
||||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts1')
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|
||||||
ws = Workout.objects.all()
|
|
||||||
|
|
||||||
self.assertEqual(len(ws),5)
|
|
||||||
w = ws[4]
|
|
||||||
self.assertEqual(w.name,'Sprint (5)')
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(TESTING=True)
|
|
||||||
class EmailUniCodeUpload(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
redis_connection.publish('tasks','KILL')
|
|
||||||
u = User.objects.create_user('john',
|
|
||||||
'sander@ds.ds',
|
|
||||||
'koeinsloot')
|
|
||||||
r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now()
|
|
||||||
)
|
|
||||||
|
|
||||||
self.theadmin = UserFactory(is_staff=True)
|
|
||||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
|
||||||
birthdate = faker.profile()['birthdate'],
|
|
||||||
gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now(),
|
|
||||||
rowerplan='coach')
|
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts2')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = "Třeboň",
|
|
||||||
body = """
|
|
||||||
workout water
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/colin4a.csv'
|
|
||||||
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
filename = 'colin4a.csv'
|
|
||||||
path = os.path.join('media/mailbox_attachments/',filename)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except (IOError,FileNotFoundError,OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.polarstuff.get_polar_notifications')
|
|
||||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
|
||||||
def test_emailupload(
|
|
||||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts2')
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(name="Třeboň")
|
|
||||||
|
|
||||||
self.assertEqual(len(ws),1)
|
|
||||||
w = ws[0]
|
|
||||||
self.assertEqual(w.workouttype,'water')
|
|
||||||
|
|
||||||
@override_settings(TESTING=True)
|
|
||||||
class EmailBikeErgUpload(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
redis_connection.publish('tasks','KILL')
|
|
||||||
u = User.objects.create_user('john',
|
|
||||||
'sander@ds.ds',
|
|
||||||
'koeinsloot')
|
|
||||||
r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now()
|
|
||||||
)
|
|
||||||
|
|
||||||
self.theadmin = UserFactory(is_staff=True)
|
|
||||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
|
||||||
birthdate = faker.profile()['birthdate'],
|
|
||||||
gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now(),
|
|
||||||
rowerplan='coach')
|
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts2')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = "bikeerg",
|
|
||||||
body = """
|
|
||||||
workout bikeerg
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/colin3.csv'
|
|
||||||
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
filename = 'colin3.csv'
|
|
||||||
path = os.path.join('media/mailbox_attachments/',filename)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except (IOError,FileNotFoundError,OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.polarstuff.get_polar_notifications')
|
|
||||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
|
||||||
def test_emailupload(
|
|
||||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts2')
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(name="bikeerg")
|
|
||||||
|
|
||||||
self.assertEqual(len(ws),1)
|
|
||||||
w = ws[0]
|
|
||||||
self.assertEqual(w.workouttype,'bikeerg')
|
|
||||||
|
|
||||||
@override_settings(TESTING=True)
|
|
||||||
class EmailBikeUpload(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
redis_connection.publish('tasks','KILL')
|
|
||||||
u = User.objects.create_user('john',
|
|
||||||
'sander@ds.ds',
|
|
||||||
'koeinsloot')
|
|
||||||
r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now()
|
|
||||||
)
|
|
||||||
|
|
||||||
self.theadmin = UserFactory(is_staff=True)
|
|
||||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
|
||||||
birthdate = faker.profile()['birthdate'],
|
|
||||||
gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now(),
|
|
||||||
rowerplan='coach')
|
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts3')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = "bike",
|
|
||||||
body = """
|
|
||||||
workout bike
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/colin4.csv'
|
|
||||||
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
filename = 'colin4.csv'
|
|
||||||
path = os.path.join('media/mailbox_attachments/',filename)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except (IOError,FileNotFoundError,OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.polarstuff.get_polar_notifications')
|
|
||||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
|
||||||
def test_emailupload(
|
|
||||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts3')
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(name="bike")
|
|
||||||
|
|
||||||
self.assertEqual(len(ws),1)
|
|
||||||
w = ws[0]
|
|
||||||
self.assertEqual(w.workouttype,'bike')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -451,48 +180,17 @@ class EmailTests(TestCase):
|
|||||||
rowerplan='coach')
|
rowerplan='coach')
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
nu = datetime.datetime.now()
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts4')
|
a2 = 'media/mailbox_attachments/colin3.csv'
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
|
|
||||||
for filename in os.listdir(u'rowers/tests/testdata/emails'):
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = filename,
|
|
||||||
body="""
|
|
||||||
---
|
|
||||||
workouttype: water
|
|
||||||
boattype: 4x
|
|
||||||
...
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/'+filename
|
|
||||||
copy(u'rowers/tests/testdata/emails/'+filename,a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = "3x(5min/2min)/r2 \r2",
|
|
||||||
body = """
|
|
||||||
workout water
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/colin2.csv'
|
|
||||||
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
copy('rowers/tests/testdata/emails/colin.csv',a2)
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
a3 = 'media/mailbox_attachments/colin4.csv'
|
||||||
a.save()
|
copy('rowers/tests/testdata/emails/colin.csv',a3)
|
||||||
|
a4 = 'media/mailbox_attachments/colin5.csv'
|
||||||
|
copy('rowers/tests/testdata/emails/colin.csv',a4)
|
||||||
|
a5 = 'media/mailbox_attachments/colin6.csv'
|
||||||
|
copy('rowers/tests/testdata/emails/colin.csv',a5)
|
||||||
|
a6 = 'media/mailbox_attachments/colin7.csv'
|
||||||
|
copy('rowers/tests/testdata/emails/colin.csv',a6)
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = self.theadmin.email,
|
|
||||||
subject = "johnsworkout",
|
|
||||||
body = """
|
|
||||||
user john
|
|
||||||
race 1
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for filename in os.listdir('media/mailbox_attachments'):
|
for filename in os.listdir('media/mailbox_attachments'):
|
||||||
@@ -512,79 +210,3 @@ race 1
|
|||||||
out = StringIO()
|
out = StringIO()
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts4')
|
call_command('processemail', stdout=out,testing=True,mailbox='workouts4')
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
self.assertIn('Successfully processed email attachments',out.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(TESTING=True)
|
|
||||||
class EmailAdminUpload(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
redis_connection.publish('tasks','KILL')
|
|
||||||
u = User.objects.create_user('john',
|
|
||||||
'sander@ds.ds',
|
|
||||||
'koeinsloot')
|
|
||||||
r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now(),
|
|
||||||
birthdate = faker.profile()['birthdate']
|
|
||||||
)
|
|
||||||
|
|
||||||
self.theadmin = UserFactory(is_staff=True)
|
|
||||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
|
||||||
birthdate = faker.profile()['birthdate'],
|
|
||||||
gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now(),
|
|
||||||
rowerplan='coach')
|
|
||||||
|
|
||||||
self.race = RaceFactory(manager = self.theadmin)
|
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts5')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = self.theadmin.email,
|
|
||||||
subject = "johnsworkout",
|
|
||||||
body = """
|
|
||||||
user john
|
|
||||||
race 1
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/minute.csv'
|
|
||||||
copy('rowers/tests/testdata/minute.csv',a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
for filename in os.listdir('media/mailbox_attachments'):
|
|
||||||
path = os.path.join('media/mailbox_attachments/',filename)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except (IOError,FileNotFoundError,OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.polarstuff.get_polar_notifications')
|
|
||||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
|
||||||
def test_email_admin_upload(
|
|
||||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out,testing=True,mailbox='workouts5')
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(name="johnsworkout")
|
|
||||||
|
|
||||||
self.assertEqual(len(ws),1)
|
|
||||||
|
|
||||||
w = ws[0]
|
|
||||||
self.assertEqual(w.user.user.username,u'john')
|
|
||||||
|
|
||||||
results = IndoorVirtualRaceResult.objects.filter(
|
|
||||||
race=self.race)
|
|
||||||
|
|
||||||
self.assertEqual(len(results),1)
|
|
||||||
result = results[0]
|
|
||||||
|
|
||||||
self.assertTrue(result.coursecompleted)
|
|
||||||
|
|||||||
@@ -1258,62 +1258,3 @@ class TPObjects(DjangoTestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.url, '/rowers/workout/'+encoded1+'/edit/')
|
self.assertEqual(response.url, '/rowers/workout/'+encoded1+'/edit/')
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
|
|
||||||
#@pytest.mark.django_db
|
|
||||||
@override_settings(TESTING=True)
|
|
||||||
class AutoExportTests(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
redis_connection.publish('tasks','KILL')
|
|
||||||
u = User.objects.create_user('john',
|
|
||||||
'sander@ds.ds',
|
|
||||||
'koeinsloot')
|
|
||||||
r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
|
|
||||||
gdproptindate=timezone.now()
|
|
||||||
)
|
|
||||||
|
|
||||||
r.c2_auto_export = True
|
|
||||||
r.sporttracks_auto_export = True
|
|
||||||
r.mapmyfitness_auto_export = True
|
|
||||||
r.trainingpeaks_auto_export = True
|
|
||||||
|
|
||||||
r.save()
|
|
||||||
|
|
||||||
nu = datetime.datetime.now()
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
filename = 'testdata.csv'
|
|
||||||
|
|
||||||
m = Message(mailbox=workoutsbox,
|
|
||||||
from_header = u.email,
|
|
||||||
subject = filename,
|
|
||||||
body="""
|
|
||||||
---
|
|
||||||
workouttype: water
|
|
||||||
boattype: 2x
|
|
||||||
...
|
|
||||||
""")
|
|
||||||
m.save()
|
|
||||||
a2 = 'media/mailbox_attachments/'+filename
|
|
||||||
copy('rowers/tests/testdata/'+filename,a2)
|
|
||||||
a = MessageAttachment(message=m,document=a2[6:])
|
|
||||||
a.save()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
for filename in os.listdir('media/mailbox_attachments'):
|
|
||||||
path = os.path.join('media/mailbox_attachments/',filename)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except (FileNotFoundError,OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.tpstuff.requests.post', side_effect=mocked_requests)
|
|
||||||
@patch('rowers.tpstuff.requests.get', side_effect=mocked_requests)
|
|
||||||
def test_emailprocessing(self, mock_post, mock_get):
|
|
||||||
out = StringIO()
|
|
||||||
call_command('processemail', stdout=out, testing=True)
|
|
||||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
|
||||||
|
|||||||
@@ -586,6 +586,10 @@ class ChallengesTest(TestCase):
|
|||||||
'course': self.ThyroBaantje.id
|
'course': self.ThyroBaantje.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form = CourseSelectForm(formdata)
|
||||||
|
|
||||||
|
self.assertTrue(form.is_valid())
|
||||||
|
|
||||||
response = self.c.post(url, formdata, follow=True)
|
response = self.c.post(url, formdata, follow=True)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
@@ -813,6 +817,7 @@ class ChallengesTest(TestCase):
|
|||||||
'yparam': 'spm',
|
'yparam': 'spm',
|
||||||
'plottype': 'line',
|
'plottype': 'line',
|
||||||
'teamid':0,
|
'teamid':0,
|
||||||
|
'course':self.ThyroBaantje.id,
|
||||||
}
|
}
|
||||||
form = ChartParamChoiceForm(form_data)
|
form = ChartParamChoiceForm(form_data)
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
@@ -829,6 +834,7 @@ class ChallengesTest(TestCase):
|
|||||||
'yparam': 'spm',
|
'yparam': 'spm',
|
||||||
'plottype': 'line',
|
'plottype': 'line',
|
||||||
'teamid':0,
|
'teamid':0,
|
||||||
|
'course':self.ThyroBaantje.id
|
||||||
}
|
}
|
||||||
form = ChartParamChoiceForm(form_data)
|
form = ChartParamChoiceForm(form_data)
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ class OtherUnitTests(TestCase):
|
|||||||
defaulttimezone='US/Pacific',
|
defaulttimezone='US/Pacific',
|
||||||
rowerplan='coach')
|
rowerplan='coach')
|
||||||
|
|
||||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
|
||||||
workoutsbox.save()
|
|
||||||
failbox = Mailbox.objects.create(name='Failed')
|
|
||||||
failbox.save()
|
|
||||||
|
|
||||||
# Test get_dates_timeperiod
|
# Test get_dates_timeperiod
|
||||||
def test_get_dates_timeperiod(self):
|
def test_get_dates_timeperiod(self):
|
||||||
@@ -99,20 +95,6 @@ class OtherUnitTests(TestCase):
|
|||||||
self.assertTrue('US/Pacific' in str(startdate.tzinfo))
|
self.assertTrue('US/Pacific' in str(startdate.tzinfo))
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.tasks.requests.get',side_effect=mocked_requests)
|
|
||||||
def test_strava_asyncworkout(self,mock_get):
|
|
||||||
with open('rowers/tests/testdata/stravaworkoutlist.txt','r') as f:
|
|
||||||
s = f.read()
|
|
||||||
|
|
||||||
jsondata = json.loads(s)
|
|
||||||
alldata = {}
|
|
||||||
for item in jsondata:
|
|
||||||
alldata[item['id']] = item
|
|
||||||
|
|
||||||
theid = jsondata[0]['id']
|
|
||||||
|
|
||||||
workoutid = stravastuff.create_async_workout(alldata,self.r.user,theid)
|
|
||||||
self.assertEqual(workoutid,1)
|
|
||||||
|
|
||||||
def test_summaryfromsplitdata(self):
|
def test_summaryfromsplitdata(self):
|
||||||
with open('rowers/tests/testdata/c2splits.json','r') as f:
|
with open('rowers/tests/testdata/c2splits.json','r') as f:
|
||||||
|
|||||||
@@ -132,6 +132,46 @@ class ViewTest(TestCase):
|
|||||||
except (FileNotFoundError,OSError):
|
except (FileNotFoundError,OSError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@patch('rowers.dataprep.create_engine')
|
||||||
|
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
||||||
|
def test_upload_view_sled_bg(self, mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
||||||
|
login = self.c.login(username='john',password='koeinsloot')
|
||||||
|
self.assertTrue(login)
|
||||||
|
|
||||||
|
filename = 'rowers/tests/testdata/testdata.csv'
|
||||||
|
f = open(filename,'rb')
|
||||||
|
file_data = {'file': f}
|
||||||
|
form_data = {
|
||||||
|
'title':'test',
|
||||||
|
'workouttype':'rower',
|
||||||
|
'boattype':'1x',
|
||||||
|
'notes':'aap noot mies',
|
||||||
|
'rpe':4,
|
||||||
|
'make_plot':False,
|
||||||
|
'rpe':6,
|
||||||
|
'upload_to_c2':False,
|
||||||
|
'plottype':'timeplot',
|
||||||
|
'landingpage':'workout_edit_view',
|
||||||
|
'raceid':0,
|
||||||
|
'file': f,
|
||||||
|
'offline': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
request = RequestFactory()
|
||||||
|
request.user = self.u
|
||||||
|
form = DocumentsForm(form_data,file_data)
|
||||||
|
|
||||||
|
optionsform = UploadOptionsForm(form_data,request=request)
|
||||||
|
self.assertTrue(optionsform.is_valid())
|
||||||
|
|
||||||
|
response = self.c.post('/rowers/workout/upload/', form_data, follow=True)
|
||||||
|
|
||||||
|
self.assertRedirects(response, expected_url=reverse('workout_upload_view'),
|
||||||
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -87,9 +87,7 @@
|
|||||||
97,114,workout_undo_smoothenpace_view,unsmoothen pace,TRUE,403,pro,302,302,pro,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
97,114,workout_undo_smoothenpace_view,unsmoothen pace,TRUE,403,pro,302,302,pro,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
98,115,workout_c2import_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
98,115,workout_c2import_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
||||||
99,120,workout_stravaimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
99,120,workout_stravaimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
||||||
100,122,workout_getc2workout_all,gets all C2 workouts (now redirects due to NoTokenError,TRUE,302,basic,302,302,FALSE,302,302,FALSE,302,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
|
||||||
101,124,workout_getimportview,imports a workout from third party,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
101,124,workout_getimportview,imports a workout from third party,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
102,125,workout_getstravaworkout_all,gets all C2 workouts (now redirects due to NoTokenError,TRUE,302,basic,302,302,FALSE,302,302,FALSE,302,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
|
||||||
103,126,workout_getstravaworkout_next,gets all strava workouts,TRUE,302,basic,302,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
103,126,workout_getstravaworkout_next,gets all strava workouts,TRUE,302,basic,302,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
104,127,workout_sporttracksimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
104,127,workout_sporttracksimport_view,list workouts to be imported (test stops at notokenerror),TRUE,302,basic,302,302,basic,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
||||||
105,129,workout_getsporttracksworkout_all,gets all C2 workouts (now redirects due to NoTokenError,TRUE,302,basic,302,302,FALSE,302,302,FALSE,302,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
105,129,workout_getsporttracksworkout_all,gets all C2 workouts (now redirects due to NoTokenError,TRUE,302,basic,302,302,FALSE,302,302,FALSE,302,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
|
|||||||
|
+2
-377
@@ -48,360 +48,11 @@ from rowers.utils import (
|
|||||||
str2bool,range_to_color_hex,absolute,myqueue,NoTokenError
|
str2bool,range_to_color_hex,absolute,myqueue,NoTokenError
|
||||||
)
|
)
|
||||||
|
|
||||||
def cleanbody(body):
|
|
||||||
try:
|
|
||||||
body = body.decode('utf-8')
|
|
||||||
except AttributeError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
regex = r".*---\n([\s\S]*?)\.\.\..*"
|
|
||||||
matches = re.finditer(regex,body)
|
|
||||||
|
|
||||||
for m in matches:
|
|
||||||
|
|
||||||
if m != None:
|
|
||||||
body = m.group(0)
|
|
||||||
|
|
||||||
return body
|
|
||||||
|
|
||||||
|
|
||||||
sources = [s for s,name in workoutsources]
|
sources = [s for s,name in workoutsources]
|
||||||
|
|
||||||
def matchsource(line):
|
|
||||||
results = []
|
|
||||||
for s in sources:
|
|
||||||
testert = '^source.*(%s)' % s
|
|
||||||
tester = re.compile(testert)
|
|
||||||
|
|
||||||
if tester.match(line.lower()): # pragma: no cover
|
|
||||||
return tester.match(line.lower()).group(1)
|
|
||||||
|
|
||||||
# currently only matches one chart
|
|
||||||
def matchchart(line):
|
|
||||||
results = []
|
|
||||||
testert = '^((chart)|(plot))'
|
|
||||||
tester2t = testert+'(.*)(dist)'
|
|
||||||
tester3t = testert+'(.*)(time)'
|
|
||||||
tester4t = testert+'(.*)(pie)'
|
|
||||||
|
|
||||||
tester = re.compile(testert)
|
|
||||||
tester2 = re.compile(tester2t)
|
|
||||||
tester3 = re.compile(tester3t)
|
|
||||||
tester4 = re.compile(tester4t)
|
|
||||||
|
|
||||||
if tester.match(line.lower()): # pragma: no cover
|
|
||||||
if tester2.match(line.lower()):
|
|
||||||
return 'distanceplot'
|
|
||||||
if tester3.match(line.lower()):
|
|
||||||
return 'timeplot'
|
|
||||||
if tester3.match(line.lower()):
|
|
||||||
return 'pieplot'
|
|
||||||
|
|
||||||
def matchuser(line):
|
|
||||||
testert = '^(user)'
|
|
||||||
tester = re.compile(testert)
|
|
||||||
if tester.match(line.lower()):
|
|
||||||
words = line.split()
|
|
||||||
return words[1]
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def matchrace(line):
|
|
||||||
testert = '^(race)'
|
|
||||||
tester = re.compile(testert)
|
|
||||||
if tester.match(line.lower()):
|
|
||||||
words = line.split()
|
|
||||||
try:
|
|
||||||
return int(words[1])
|
|
||||||
except: # pragma: no cover
|
|
||||||
return None
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def matchsync(line):
|
|
||||||
results = []
|
|
||||||
tester = '((sync)|(synchronization)|(export))'
|
|
||||||
tester2 = tester+'(.*)((c2)|(concept2)|(logbook))'
|
|
||||||
tester3 = tester+'(.*)((tp)|(trainingpeaks))'
|
|
||||||
tester4 = tester+'(.*)(strava)'
|
|
||||||
tester5 = tester+'(.*)((st)|(sporttracks))'
|
|
||||||
|
|
||||||
tester = re.compile(tester)
|
|
||||||
|
|
||||||
if tester.match(line.lower()): # pragma: no cover
|
|
||||||
testers = [
|
|
||||||
('upload_to_C2',re.compile(tester2)),
|
|
||||||
('upload_totp',re.compile(tester3)),
|
|
||||||
('upload_to_Strava',re.compile(tester4)),
|
|
||||||
('upload_to_SportTracks',re.compile(tester5)),
|
|
||||||
('upload_to_MapMyFitness',re.compile(tester7)),
|
|
||||||
]
|
|
||||||
for t in testers:
|
|
||||||
if t[1].match(line.lower()):
|
|
||||||
results.append(t[0])
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
def getstravaid(uploadoptions,body):
|
|
||||||
stravaid = 0
|
|
||||||
tester = re.compile('^(stravaid)(.*?)(\d+)')
|
|
||||||
for line in body.splitlines():
|
|
||||||
if tester.match(line.lower()): # pragma: no cover
|
|
||||||
stravaid = tester.match(line.lower()).group(3)
|
|
||||||
|
|
||||||
uploadoptions['stravaid'] = int(stravaid)
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def gettypeoptions_body2(uploadoptions,body):
|
|
||||||
tester = re.compile('^(workout)')
|
|
||||||
testerb = re.compile('^(boat)')
|
|
||||||
for line in body.splitlines():
|
|
||||||
if tester.match(line.lower()):
|
|
||||||
for typ,verb in workouttypes_ordered.items():
|
|
||||||
str1 = '^(workout)(.*)({a})'.format(
|
|
||||||
a = typ.lower()
|
|
||||||
)
|
|
||||||
testert = re.compile(str1)
|
|
||||||
if testert.match(line.lower()):
|
|
||||||
uploadoptions['workouttype'] = typ
|
|
||||||
break
|
|
||||||
if testerb.match(line.lower()):
|
|
||||||
for typ,verb in boattypes:
|
|
||||||
str1 = '^(boat)(.*)({a})'.format(
|
|
||||||
a = typ.replace('+','\+')
|
|
||||||
)
|
|
||||||
testert = re.compile(str1)
|
|
||||||
if testert.match(line.lower()):
|
|
||||||
uploadoptions['boattype'] = typ
|
|
||||||
break
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getprivateoptions_body2(uploadoptions,body):
|
|
||||||
tester = re.compile('^(priva)')
|
|
||||||
for line in body.splitlines():
|
|
||||||
if tester.match(line.lower()): # pragma: no cover
|
|
||||||
v = True
|
|
||||||
negs = ['false','False','None','no']
|
|
||||||
for neg in negs:
|
|
||||||
tstr = re.compile('^(.*)'+neg)
|
|
||||||
|
|
||||||
if tstr.match(line.lower()):
|
|
||||||
v = False
|
|
||||||
|
|
||||||
uploadoptions['makeprivate'] = v
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getworkoutsources(uploadoptions,body):
|
|
||||||
for line in body.splitlines():
|
|
||||||
workoutsource = matchsource(line)
|
|
||||||
if workoutsource: # pragma: no cover
|
|
||||||
uploadoptions['workoutsource'] = workoutsource
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getplotoptions_body2(uploadoptions,body):
|
|
||||||
for line in body.splitlines():
|
|
||||||
chart = matchchart(line)
|
|
||||||
if chart: # pragma: no cover
|
|
||||||
uploadoptions['make_plot'] = True
|
|
||||||
uploadoptions['plottype'] = chart
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getuseroptions_body2(uploadoptions,body):
|
|
||||||
for line in body.splitlines():
|
|
||||||
user = matchuser(line)
|
|
||||||
if user:
|
|
||||||
uploadoptions['username'] = user
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getraceoptions_body2(uploadoptions,body):
|
|
||||||
for line in body.splitlines():
|
|
||||||
raceid = matchrace(line)
|
|
||||||
if raceid:
|
|
||||||
uploadoptions['raceid'] = raceid
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getsyncoptions_body2(uploadoptions,body):
|
|
||||||
result = []
|
|
||||||
for line in body.splitlines():
|
|
||||||
result = result+matchsync(line)
|
|
||||||
|
|
||||||
result = list(set(result))
|
|
||||||
|
|
||||||
for r in result: # pragma: no cover
|
|
||||||
uploadoptions[r] = True
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getsyncoptions(uploadoptions,values): # pragma: no cover
|
|
||||||
try:
|
|
||||||
value = values.lower()
|
|
||||||
values = [values]
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
for v in values:
|
|
||||||
try:
|
|
||||||
v = v.lower()
|
|
||||||
|
|
||||||
if v in ['c2','concept2','logbook']:
|
|
||||||
uploadoptions['upload_to_C2'] = True
|
|
||||||
if v in ['tp','trainingpeaks']:
|
|
||||||
uploadoptions['upload_totp'] = True
|
|
||||||
if v in ['strava']:
|
|
||||||
uploadoptions['upload_to_Strava'] = True
|
|
||||||
if v in ['st','sporttracks']:
|
|
||||||
uploadoptions['upload_to_SportTracks'] = True
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getplotoptions(uploadoptions,value): # pragma: no cover
|
|
||||||
try:
|
|
||||||
v = value.lower()
|
|
||||||
if v in ['pieplot','timeplot','distanceplot']:
|
|
||||||
uploadoptions['make_plot'] = True
|
|
||||||
uploadoptions['plottype'] = v
|
|
||||||
elif 'pie' in v:
|
|
||||||
uploadoptions['make_plot'] = True
|
|
||||||
uploadoptions['plottype'] = 'pieplot'
|
|
||||||
elif 'distance' in v:
|
|
||||||
uploadoptions['make_plot'] = True
|
|
||||||
uploadoptions['plottype'] = 'distanceplot'
|
|
||||||
elif 'time' in v:
|
|
||||||
uploadoptions['make_plot'] = True
|
|
||||||
uploadoptions['plottype'] = 'timeplot'
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
|
|
||||||
def gettype(uploadoptions,value,key): # pragma: no cover
|
|
||||||
workouttype = 'rower'
|
|
||||||
for typ,verb in workouttypes_ordered.items():
|
|
||||||
if value == typ:
|
|
||||||
workouttype = typ
|
|
||||||
break
|
|
||||||
if value == verb:
|
|
||||||
workouttype = typ
|
|
||||||
break
|
|
||||||
|
|
||||||
uploadoptions[key] = workouttype
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getboattype(uploadoptions,value,key): # pragma: no cover
|
|
||||||
boattype = '1x'
|
|
||||||
for type,verb in boattypes:
|
|
||||||
if value == type:
|
|
||||||
boattype = type
|
|
||||||
if value == verb:
|
|
||||||
boattype = type
|
|
||||||
|
|
||||||
uploadoptions[key] = boattype
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getuser(uploadoptions,value,key): # pragma: no cover
|
|
||||||
uploadoptions['username'] = value
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getrace(uploadoptions,value,key): # pragma: no cover
|
|
||||||
try:
|
|
||||||
raceid = int(value)
|
|
||||||
uploadoptions['raceid'] = raceid
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getsource(uploadoptions,value,key): # pragma: no cover
|
|
||||||
workoutsource = 'unknown'
|
|
||||||
for type,verb in workoutsources:
|
|
||||||
if value == type:
|
|
||||||
workoutsource = type
|
|
||||||
if value == verb:
|
|
||||||
workoutsource = type
|
|
||||||
|
|
||||||
uploadoptions[key] = workoutsource
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def getboolean(uploadoptions,value,key): # pragma: no cover
|
|
||||||
b = True
|
|
||||||
if not value:
|
|
||||||
b = False
|
|
||||||
if value in [False,'false','False',None,'no']:
|
|
||||||
b = False
|
|
||||||
|
|
||||||
uploadoptions[key] = b
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def upload_options(body):
|
|
||||||
uploadoptions = {
|
|
||||||
'boattype':'1x',
|
|
||||||
'workouttype': 'rower',
|
|
||||||
}
|
|
||||||
body = cleanbody(body)
|
|
||||||
try:
|
|
||||||
yml = (yaml.safe_load(body))
|
|
||||||
if yml and 'fromuploadform' in yml: # pragma: no cover
|
|
||||||
return yml
|
|
||||||
try:
|
|
||||||
for key, value in yml.iteritems(): # pragma: no cover
|
|
||||||
lowkey = key.lower()
|
|
||||||
if lowkey == 'sync' or lowkey == 'synchronization' or lowkey == 'export':
|
|
||||||
uploadoptions = getsyncoptions(uploadoptions,value)
|
|
||||||
if lowkey == 'chart' or lowkey == 'static' or lowkey == 'plot':
|
|
||||||
uploadoptions = getplotoptions(uploadoptions,value)
|
|
||||||
if 'priva' in lowkey:
|
|
||||||
uploadoptions = getboolean(uploadoptions,value,'makeprivate')
|
|
||||||
if 'workout' in lowkey:
|
|
||||||
uploadoptions = gettype(uploadoptions,value,'workouttype')
|
|
||||||
if 'boat' in lowkey:
|
|
||||||
uploadoptions = getboattype(uploadoptions,value,'boattype')
|
|
||||||
if 'source' in lowkey:
|
|
||||||
uploadoptions = getsource(uploadoptions,value,'workoutsource')
|
|
||||||
if 'username' in lowkey:
|
|
||||||
uploadoptions = getuser(uploadoptions,value,'username')
|
|
||||||
if 'raceid' in lowkey:
|
|
||||||
uploadoptions = getraceid(uploadoptions,value,'raceid')
|
|
||||||
except AttributeError:
|
|
||||||
#pass
|
|
||||||
raise yaml.YAMLError
|
|
||||||
except yaml.YAMLError as exc:
|
|
||||||
try:
|
|
||||||
uploadoptions = getplotoptions_body2(uploadoptions,body)
|
|
||||||
uploadoptions = getsyncoptions_body2(uploadoptions,body)
|
|
||||||
uploadoptions = getprivateoptions_body2(uploadoptions,body)
|
|
||||||
uploadoptions = gettypeoptions_body2(uploadoptions,body)
|
|
||||||
uploadoptions = getstravaid(uploadoptions,body)
|
|
||||||
uploadoptions = getworkoutsources(uploadoptions,body)
|
|
||||||
uploadoptions = getuseroptions_body2(uploadoptions,body)
|
|
||||||
uploadoptions = getraceoptions_body2(uploadoptions,body)
|
|
||||||
except IOError: # pragma: no cover
|
|
||||||
pm = exc.problem_mark
|
|
||||||
strpm = str(pm)
|
|
||||||
pbm = "Your email has an issue on line {} at position {}. The error is: ".format(
|
|
||||||
pm.line+1,
|
|
||||||
pm.column+1,
|
|
||||||
)+strpm
|
|
||||||
return {'error':pbm}
|
|
||||||
|
|
||||||
if uploadoptions == {}: # pragma: no cover
|
|
||||||
uploadoptions['message'] = 'No parsing issue. No valid commands detected'
|
|
||||||
|
|
||||||
return uploadoptions
|
|
||||||
|
|
||||||
def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0):
|
def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0):
|
||||||
if imagename == '':
|
if imagename == '':
|
||||||
@@ -489,33 +140,7 @@ import rowers.tpstuff as tpstuff
|
|||||||
|
|
||||||
from rowers.rower_rules import is_promember
|
from rowers.rower_rules import is_promember
|
||||||
|
|
||||||
def set_workouttype(w,options):
|
|
||||||
try:
|
|
||||||
w.workouttype = options['workouttype']
|
|
||||||
w.save()
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
w.boattype = options['boattype']
|
|
||||||
w.save()
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def set_workoutsource(w,options): # pragma: no cover
|
|
||||||
try:
|
|
||||||
w.workoutsource = options['workoutsource']
|
|
||||||
w.save()
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
def make_private(w,options): # pragma: no cover
|
|
||||||
if 'makeprivate' in options and options['makeprivate']:
|
|
||||||
w.privacy = 'hidden'
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def do_sync(w,options, quick=False):
|
def do_sync(w,options, quick=False):
|
||||||
|
|
||||||
@@ -587,7 +212,7 @@ def do_sync(w,options, quick=False):
|
|||||||
if w.duplicate:
|
if w.duplicate:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if do_c2_export:
|
if do_c2_export: # pragma: no cover
|
||||||
try:
|
try:
|
||||||
message,id = c2stuff.workout_c2_upload(w.user.user,w,asynchron=True)
|
message,id = c2stuff.workout_c2_upload(w.user.user,w,asynchron=True)
|
||||||
except NoTokenError:
|
except NoTokenError:
|
||||||
@@ -628,7 +253,7 @@ def do_sync(w,options, quick=False):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
upload_to_tp = False
|
upload_to_tp = False
|
||||||
|
|
||||||
if do_tp_export:
|
if do_tp_export: # pragma: no cover
|
||||||
try:
|
try:
|
||||||
message,id = sporttracksstuff.workout_sporttracks_upload(
|
message,id = sporttracksstuff.workout_sporttracks_upload(
|
||||||
w.user.user,w,asynchron=True,
|
w.user.user,w,asynchron=True,
|
||||||
|
|||||||
+1
-1
@@ -510,7 +510,7 @@ urlpatterns = [
|
|||||||
re_path(r'^workout/rp3import/all/$',views.workout_getrp3workout_all,name='workout_getrp3workout_all'),
|
re_path(r'^workout/rp3import/all/$',views.workout_getrp3workout_all,name='workout_getrp3workout_all'),
|
||||||
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/$',views.workout_getimportview,name='workout_getimportview'),
|
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/$',views.workout_getimportview,name='workout_getimportview'),
|
||||||
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/async/$',views.workout_getimportview,{'do_async':True},name='workout_getimportview'),
|
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/async/$',views.workout_getimportview,{'do_async':True},name='workout_getimportview'),
|
||||||
re_path(r'^workout/stravaimport/all/$',views.workout_getstravaworkout_all,name='workout_getstravaworkout_all'),
|
# re_path(r'^workout/stravaimport/all/$',views.workout_getstravaworkout_all,name='workout_getstravaworkout_all'),
|
||||||
re_path(r'^workout/stravaimport/next/$',views.workout_getstravaworkout_next,name='workout_getstravaworkout_next'),
|
re_path(r'^workout/stravaimport/next/$',views.workout_getstravaworkout_next,name='workout_getstravaworkout_next'),
|
||||||
re_path(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'),
|
re_path(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'),
|
||||||
re_path(r'^workout/sporttracksimport/user/(?P<userid>\d+)/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'),
|
re_path(r'^workout/sporttracksimport/user/(?P<userid>\d+)/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'),
|
||||||
|
|||||||
+4
-4
@@ -120,7 +120,7 @@ def dologging(filename,s):
|
|||||||
f.write(' ')
|
f.write(' ')
|
||||||
f.write(s)
|
f.write(s)
|
||||||
|
|
||||||
def to_pace(pace):
|
def to_pace(pace): # pragma: no cover
|
||||||
minutes, seconds = divmod(pace,60)
|
minutes, seconds = divmod(pace,60)
|
||||||
seconds, rest = divmod(seconds, 1)
|
seconds, rest = divmod(seconds, 1)
|
||||||
tenths = int(rest*10)
|
tenths = int(rest*10)
|
||||||
@@ -518,7 +518,7 @@ def custom_exception_handler(exc,message):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high',authorizationstring=''):
|
def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high',authorizationstring=''):
|
||||||
if r is not None:
|
if r is not None: # pragma: no cover
|
||||||
authorizationstring = str('Bearer ' + r.stravatoken)
|
authorizationstring = str('Bearer ' + r.stravatoken)
|
||||||
headers = {'Authorization': authorizationstring,
|
headers = {'Authorization': authorizationstring,
|
||||||
'user-agent': 'sanderroosendaal',
|
'user-agent': 'sanderroosendaal',
|
||||||
@@ -569,7 +569,7 @@ def allsundays(startdate,enddate):
|
|||||||
yield d
|
yield d
|
||||||
d += datetime.timedelta(days=7)
|
d += datetime.timedelta(days=7)
|
||||||
|
|
||||||
def steps_read_fit(filename,name='',sport='Custom'):
|
def steps_read_fit(filename,name='',sport='Custom'): # pragma: no cover
|
||||||
authorizationstring = 'Bearer '+settings.WORKOUTS_FIT_TOKEN
|
authorizationstring = 'Bearer '+settings.WORKOUTS_FIT_TOKEN
|
||||||
url = settings.WORKOUTS_FIT_URL+"/tojson"
|
url = settings.WORKOUTS_FIT_URL+"/tojson"
|
||||||
headers = {'Authorization':authorizationstring}
|
headers = {'Authorization':authorizationstring}
|
||||||
@@ -622,7 +622,7 @@ def step_to_time_dist(step,avgspeed = 3.2,ftp=200,ftspm=25,ftv=3.7):
|
|||||||
distance = avgspeed*seconds
|
distance = avgspeed*seconds
|
||||||
rscore = 60.*seconds/3600.
|
rscore = 60.*seconds/3600.
|
||||||
|
|
||||||
if targettype == 'Speed':
|
if targettype == 'Speed': # pragma: no cover
|
||||||
value = step.get('targetValue',0)
|
value = step.get('targetValue',0)
|
||||||
valuelow = step.get('targetValueLow',0)
|
valuelow = step.get('targetValueLow',0)
|
||||||
valuehigh = step.get('targetValueHigh',0)
|
valuehigh = step.get('targetValueHigh',0)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from rowers.views.statements import *
|
from rowers.views.statements import *
|
||||||
from rowers.tasks import handle_calctrimp
|
from rowers.tasks import handle_calctrimp
|
||||||
from rowers.mailprocessing import send_confirm
|
|
||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@@ -637,7 +637,7 @@ def workout_nkimport_view(request,userid=0,after=0,before=0):
|
|||||||
|
|
||||||
workouts = workouts[::-1]
|
workouts = workouts[::-1]
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST': # pragma: no cover
|
||||||
try:
|
try:
|
||||||
tdict = dict(request.POST.lists())
|
tdict = dict(request.POST.lists())
|
||||||
ids = tdict['workoutid']
|
ids = tdict['workoutid']
|
||||||
@@ -1053,7 +1053,7 @@ def workout_stravaimport_view(request,message="",userid=0):
|
|||||||
messages.info(request,'Your Strava workouts will be imported in the background. It may take a few minutes before it appears.'.format(stravaid=stravaid))
|
messages.info(request,'Your Strava workouts will be imported in the background. It may take a few minutes before it appears.'.format(stravaid=stravaid))
|
||||||
url = reverse('workouts_view')
|
url = reverse('workouts_view')
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except KeyError:
|
except KeyError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
@@ -1133,7 +1133,7 @@ def strava_webhook_view(request):
|
|||||||
except Rower.DoesNotExist: # pragma: no cover
|
except Rower.DoesNotExist: # pragma: no cover
|
||||||
dologging('strava_webhooks.log','Rower not found')
|
dologging('strava_webhooks.log','Rower not found')
|
||||||
return HttpResponse(status=200)
|
return HttpResponse(status=200)
|
||||||
except MultipleObjectsReturned:
|
except MultipleObjectsReturned: # pragma: no cover
|
||||||
s = 'Multiple rowers found for strava ID {id}'.format(id=strava_owner)
|
s = 'Multiple rowers found for strava ID {id}'.format(id=strava_owner)
|
||||||
dologging('strava_webhooks.log',s)
|
dologging('strava_webhooks.log',s)
|
||||||
rs = Rower.objects.filter(strava_owner_id=strava_owner)
|
rs = Rower.objects.filter(strava_owner_id=strava_owner)
|
||||||
@@ -1164,7 +1164,7 @@ def strava_webhook_view(request):
|
|||||||
except Rower.DoesNotExist: # pragma: no cover
|
except Rower.DoesNotExist: # pragma: no cover
|
||||||
dologging('strava_webhooks.log','Rower not found')
|
dologging('strava_webhooks.log','Rower not found')
|
||||||
return HttpResponse(status=200)
|
return HttpResponse(status=200)
|
||||||
except MultipleObjectsReturned:
|
except MultipleObjectsReturned: # pragma: no cover
|
||||||
rs = Rower.objects.filter(strava_owner_id=strava_owner)
|
rs = Rower.objects.filter(strava_owner_id=strava_owner)
|
||||||
r = rs[0]
|
r = rs[0]
|
||||||
if r.strava_auto_delete: # pragma: no cover
|
if r.strava_auto_delete: # pragma: no cover
|
||||||
@@ -1619,7 +1619,7 @@ def workout_c2import_view(request,page=1,userid=0,message=""):
|
|||||||
messages.info(request,'Your Concept2 workouts will be imported in the background. It may take a few minutes before it appears.'.format(c2id=c2id))
|
messages.info(request,'Your Concept2 workouts will be imported in the background. It may take a few minutes before it appears.'.format(c2id=c2id))
|
||||||
url = reverse('workouts_view')
|
url = reverse('workouts_view')
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except KeyError:
|
except KeyError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -1768,18 +1768,6 @@ def workout_getsporttracksworkout_all(request):
|
|||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
# Imports all new workouts from SportTracks
|
|
||||||
@login_required()
|
|
||||||
def workout_getstravaworkout_all(request):
|
|
||||||
r = getrower(request.user)
|
|
||||||
res = stravastuff.get_strava_workouts(r)
|
|
||||||
if res == 1: # pragma: no cover
|
|
||||||
messages.info(request,"Your workouts are being imported and should appear on the site in the next 15 minutes")
|
|
||||||
else:
|
|
||||||
messages.error(request,"Couldn't import Strava workouts ")
|
|
||||||
|
|
||||||
url = reverse('workouts_view')
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
|
|
||||||
# Imports all new workouts from SportTracks
|
# Imports all new workouts from SportTracks
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ def buy_trainingplan_view(request,id=0):
|
|||||||
status = True
|
status = True
|
||||||
|
|
||||||
# get target and set enddate
|
# get target and set enddate
|
||||||
try:
|
try: # pragma: no cover
|
||||||
targetid = cd['target']
|
targetid = cd['target']
|
||||||
target = TrainingTarget.objects.get(id=int(targetid))
|
target = TrainingTarget.objects.get(id=int(targetid))
|
||||||
except (KeyError,ValueError):
|
except (KeyError,ValueError):
|
||||||
@@ -192,7 +192,7 @@ def purchase_checkouts_view(request):
|
|||||||
})
|
})
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if r.rowerplan == 'freecoach':
|
if r.rowerplan == 'freecoach': # pragma: no cover
|
||||||
messages.error(request,'You cannot purchase this training plan as a free coach member')
|
messages.error(request,'You cannot purchase this training plan as a free coach member')
|
||||||
url = reverse('rower_view_instantplan',kwargs={
|
url = reverse('rower_view_instantplan',kwargs={
|
||||||
'id':plan.uuid,
|
'id':plan.uuid,
|
||||||
@@ -230,7 +230,7 @@ def purchase_checkouts_view(request):
|
|||||||
startdate = enddate-datetime.timedelta(days=plan.duration)
|
startdate = enddate-datetime.timedelta(days=plan.duration)
|
||||||
|
|
||||||
# upgrade rower
|
# upgrade rower
|
||||||
if r.rowerplan == 'basic':
|
if r.rowerplan == 'basic': # pragma: no cover
|
||||||
messages.info(request,'You have been upgraded to the Self-Coach plan for the duration of the plan')
|
messages.info(request,'You have been upgraded to the Self-Coach plan for the duration of the plan')
|
||||||
r.rowerplan = 'plan'
|
r.rowerplan = 'plan'
|
||||||
r.planexpires = enddate
|
r.planexpires = enddate
|
||||||
@@ -280,7 +280,7 @@ def purchase_checkouts_view(request):
|
|||||||
messages.error(request,"There was an error in the payment form")
|
messages.error(request,"There was an error in the payment form")
|
||||||
url = reverse("purchase_checkouts_view")
|
url = reverse("purchase_checkouts_view")
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
else:
|
else: # pragma: no cover
|
||||||
messages.error(request,"There was an error in the payment form")
|
messages.error(request,"There was an error in the payment form")
|
||||||
|
|
||||||
url = reverse('rower_select_instantplan') # pragma: no cover
|
url = reverse('rower_select_instantplan') # pragma: no cover
|
||||||
|
|||||||
@@ -234,14 +234,14 @@ def course_view(request,id=0):
|
|||||||
|
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
notsharing = Rower.objects.filter(share_course_results=False).exclude(id=r.id)
|
notsharing = Rower.objects.filter(share_course_results=False).exclude(id=r.id)
|
||||||
else:
|
else: # pragma: no cover
|
||||||
notsharing = Rower.objects.filter(share_course_results=False)
|
notsharing = Rower.objects.filter(share_course_results=False)
|
||||||
|
|
||||||
notsharing_ids = [o.user.id for o in notsharing]
|
notsharing_ids = [o.user.id for o in notsharing]
|
||||||
|
|
||||||
records = records.exclude(userid__in=notsharing_ids)
|
records = records.exclude(userid__in=notsharing_ids)
|
||||||
|
|
||||||
if 'onlyme' in request.GET:
|
if 'onlyme' in request.GET: # pragma: no cover
|
||||||
onlyme = request.GET.get('onlyme',False)
|
onlyme = request.GET.get('onlyme',False)
|
||||||
if onlyme == 'true':
|
if onlyme == 'true':
|
||||||
onlyme = True
|
onlyme = True
|
||||||
@@ -253,7 +253,7 @@ def course_view(request,id=0):
|
|||||||
|
|
||||||
|
|
||||||
form = RaceResultFilterForm(records=records,groups=False)
|
form = RaceResultFilterForm(records=records,groups=False)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST': # pragma: no cover
|
||||||
form = RaceResultFilterForm(request.POST,records=records,groups=False)
|
form = RaceResultFilterForm(request.POST,records=records,groups=False)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
cd = form.cleaned_data
|
cd = form.cleaned_data
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ from rowers.plannedsessions import *
|
|||||||
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
|
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
|
||||||
from rowers.tasks import (
|
from rowers.tasks import (
|
||||||
handle_sendemail_unrecognized,handle_sendemailnewcomment,
|
handle_sendemail_unrecognized,handle_sendemailnewcomment,
|
||||||
|
handle_request_post,
|
||||||
handle_sendemailsummary,
|
handle_sendemailsummary,
|
||||||
handle_rp3_async_workout,
|
handle_rp3_async_workout,
|
||||||
handle_send_template_email,
|
handle_send_template_email,
|
||||||
@@ -242,7 +243,7 @@ import pandas as pd
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
from rowers.emails import send_template_email,htmlstrip
|
from rowers.emails import send_template_email,htmlstrip, send_confirm
|
||||||
from rowers.alerts import *
|
from rowers.alerts import *
|
||||||
|
|
||||||
from pytz import timezone as tz,utc
|
from pytz import timezone as tz,utc
|
||||||
@@ -271,7 +272,6 @@ from rq import Queue,cancel_job
|
|||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django_mailbox.models import Message,Mailbox,MessageAttachment
|
|
||||||
|
|
||||||
from rules.contrib.views import permission_required, objectgetter
|
from rules.contrib.views import permission_required, objectgetter
|
||||||
|
|
||||||
@@ -703,7 +703,7 @@ from rest_framework.permissions import IsAuthenticated
|
|||||||
from rowers.permissions import IsOwnerOrNot, IsCompetitorOrNot
|
from rowers.permissions import IsOwnerOrNot, IsCompetitorOrNot
|
||||||
|
|
||||||
import rowers.plots as plots
|
import rowers.plots as plots
|
||||||
import rowers.mailprocessing as mailprocessing
|
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from scipy.special import lambertw
|
from scipy.special import lambertw
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ def rower_exportsettings_view(request,userid=0):
|
|||||||
def rower_edit_view(request,rowerid=0,userid=0,message=""):
|
def rower_edit_view(request,rowerid=0,userid=0,message=""):
|
||||||
r = getrequestrowercoachee(request,rowerid=rowerid,userid=userid,notpermanent=True)
|
r = getrequestrowercoachee(request,rowerid=rowerid,userid=userid,notpermanent=True)
|
||||||
|
|
||||||
if 'courseshare' in request.GET:
|
if 'courseshare' in request.GET: # pragma: no cover
|
||||||
courseshare = request.GET.get('courseshare',"ok")
|
courseshare = request.GET.get('courseshare',"ok")
|
||||||
if courseshare == 'true':
|
if courseshare == 'true':
|
||||||
r.share_course_results = True
|
r.share_course_results = True
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from rowers.views.statements import *
|
|||||||
import rowers.teams as teams
|
import rowers.teams as teams
|
||||||
import rowers.mytypes as mytypes
|
import rowers.mytypes as mytypes
|
||||||
import numpy
|
import numpy
|
||||||
from rowers.mailprocessing import send_confirm
|
|
||||||
import rowers.uploads as uploads
|
import rowers.uploads as uploads
|
||||||
import rowers.utils as utils
|
import rowers.utils as utils
|
||||||
from rowers.utils import intervals_to_string
|
from rowers.utils import intervals_to_string
|
||||||
@@ -1738,7 +1737,7 @@ def course_compare_view(request,id=0):
|
|||||||
'teamid':0
|
'teamid':0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if request.method == 'POST' and 'workouts' in request.POST:
|
if request.method == 'POST' and 'workouts' in request.POST: # pragma: no cover
|
||||||
form = WorkoutMultipleCompareForm(request.POST)
|
form = WorkoutMultipleCompareForm(request.POST)
|
||||||
form.fields["workouts"].queryset = Workout.objects.filter(id__in=workoutids)
|
form.fields["workouts"].queryset = Workout.objects.filter(id__in=workoutids)
|
||||||
chartform = ChartParamChoiceForm(request.POST)
|
chartform = ChartParamChoiceForm(request.POST)
|
||||||
@@ -1752,7 +1751,7 @@ def course_compare_view(request,id=0):
|
|||||||
teamid = chartform.cleaned_data['teamid']
|
teamid = chartform.cleaned_data['teamid']
|
||||||
ids = [int(w.id) for w in workouts]
|
ids = [int(w.id) for w in workouts]
|
||||||
request.session['ids'] = ids
|
request.session['ids'] = ids
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST': # pragma: no cover
|
||||||
form = WorkoutMultipleCompareForm()
|
form = WorkoutMultipleCompareForm()
|
||||||
form.fields["workouts"].queryset = Workout.objects.filter(id__in=workoutids)
|
form.fields["workouts"].queryset = Workout.objects.filter(id__in=workoutids)
|
||||||
request.session['ids'] = workoutids
|
request.session['ids'] = workoutids
|
||||||
@@ -1924,7 +1923,7 @@ def virtualevent_compare_view(request,id=0):
|
|||||||
'teamid':0
|
'teamid':0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if request.method == 'POST' and 'workouts' in request.POST:
|
if request.method == 'POST' and 'workouts' in request.POST: # pragma: no cover
|
||||||
form = WorkoutMultipleCompareForm(request.POST)
|
form = WorkoutMultipleCompareForm(request.POST)
|
||||||
form.fields["workouts"].queryset = Workout.objects.filter(id__in=workoutids)
|
form.fields["workouts"].queryset = Workout.objects.filter(id__in=workoutids)
|
||||||
chartform = ChartParamChoiceForm(request.POST)
|
chartform = ChartParamChoiceForm(request.POST)
|
||||||
@@ -5435,26 +5434,19 @@ def workout_upload_view(request,
|
|||||||
title = t,
|
title = t,
|
||||||
notes=notes,
|
notes=notes,
|
||||||
)
|
)
|
||||||
else: # pragma: no cover
|
else:
|
||||||
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
|
uploadoptions['secret'] = settings.UPLOAD_SERVICE_SECRET
|
||||||
uploadoptions['fromuploadform'] = True
|
uploadoptions['user'] = r.user.id
|
||||||
bodyyaml = yaml.safe_dump(
|
uploadoptions['title'] = t
|
||||||
uploadoptions,
|
uploadoptions['file'] = f2
|
||||||
default_flow_style=False
|
|
||||||
)
|
url = settings.UPLOAD_SERVICE_URL
|
||||||
msg = Message(mailbox=workoutsbox,
|
|
||||||
from_header=r.user.email,
|
job = myqueue(queuehigh,
|
||||||
subject = t,body=bodyyaml)
|
handle_request_post,
|
||||||
msg.save()
|
url,
|
||||||
f3 = 'media/mailbox_attachments/'+f2[6:]
|
uploadoptions
|
||||||
copyfile(f2,f3)
|
)
|
||||||
f3 = f3[6:]
|
|
||||||
a = MessageAttachment(message=msg,document=f3)
|
|
||||||
try:
|
|
||||||
a.save()
|
|
||||||
except DataError:
|
|
||||||
pass
|
|
||||||
os.remove(f2)
|
|
||||||
|
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
@@ -6563,7 +6555,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
course=course,
|
course=course,
|
||||||
workoutid=row.id
|
workoutid=row.id
|
||||||
)
|
)
|
||||||
if records:
|
if records: # pragma: no cover
|
||||||
record = records[0]
|
record = records[0]
|
||||||
else:
|
else:
|
||||||
# create record
|
# create record
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ INSTALLED_APPS = [
|
|||||||
'django_rq',
|
'django_rq',
|
||||||
# 'django_rq_dashboard',
|
# 'django_rq_dashboard',
|
||||||
# 'translation_manager',
|
# 'translation_manager',
|
||||||
'django_mailbox',
|
# 'django_mailbox',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'datetimewidget',
|
'datetimewidget',
|
||||||
'rest_framework_swagger',
|
'rest_framework_swagger',
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Including another URLconf
|
|||||||
1. Import the include() function: from django.conf.urls import url, include
|
1. Import the include() function: from django.conf.urls import url, include
|
||||||
2. Add a URL to urlpatterns: re_path(r'^blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: re_path(r'^blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from django.conf.urls import url,include
|
from django.conf.urls import include
|
||||||
from django.urls import path, re_path
|
from django.urls import path, re_path
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
|||||||
Reference in New Issue
Block a user