1509 lines
40 KiB
Python
1509 lines
40 KiB
Python
""" Background tasks done by Celery (develop) or QR (production) """
|
|
import os
|
|
import time
|
|
import gc
|
|
import gzip
|
|
import shutil
|
|
import numpy as np
|
|
import re
|
|
|
|
from scipy import optimize
|
|
|
|
import rowingdata
|
|
|
|
from rowingdata import rowingdata as rdata
|
|
from datetime import timedelta
|
|
from sqlalchemy import create_engine
|
|
|
|
from celery import app
|
|
import datetime
|
|
import pytz
|
|
import iso8601
|
|
|
|
from matplotlib.backends.backend_agg import FigureCanvas
|
|
#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib import path
|
|
|
|
from rowsandall_app.settings import SITE_URL
|
|
from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV
|
|
from rowsandall_app.settings import PROGRESS_CACHE_SECRET
|
|
from rowsandall_app.settings import SETTINGS_NAME
|
|
|
|
|
|
import pandas as pd
|
|
|
|
from django_rq import job
|
|
from django.utils import timezone
|
|
from django.utils.html import strip_tags
|
|
|
|
from utils import deserialize_list
|
|
|
|
from rowers.dataprepnodjango import (
|
|
update_strokedata, new_workout_from_file,
|
|
getsmallrowdata_db, updatecpdata_sql,
|
|
update_agegroup_db,fitnessmetric_to_sql,
|
|
add_c2_stroke_data_db,totaltime_sec_to_string,
|
|
create_c2_stroke_data_db,update_empower,
|
|
database_url_debug,database_url,
|
|
)
|
|
|
|
|
|
from django.core.mail import (
|
|
send_mail,
|
|
EmailMessage,EmailMultiAlternatives,
|
|
)
|
|
|
|
from django.template import Context
|
|
from django.db.utils import OperationalError
|
|
from jinja2 import Template,Environment,FileSystemLoader
|
|
env = Environment(loader = FileSystemLoader(["rowers/templates"]))
|
|
|
|
import datautils
|
|
import utils
|
|
import requests
|
|
import longtask
|
|
import arrow
|
|
|
|
siteurl = SITE_URL
|
|
|
|
# testing task
|
|
|
|
from rowers.emails import send_template_email
|
|
from rowers.courseutils import coursetime_paths, coursetime_first, time_in_path
|
|
|
|
@app.task
|
|
def add(x, y):
|
|
return x + y
|
|
|
|
|
|
@app.task
|
|
def handle_c2_import_stroke_data(c2token,
|
|
c2id,workoutid,
|
|
starttimeunix,
|
|
csvfilename,debug=True,**kwargs):
|
|
|
|
authorizationstring = str('Bearer ' + c2token)
|
|
headers = {'Authorization': authorizationstring,
|
|
'user-agent': 'sanderroosendaal',
|
|
'Content-Type': 'application/json'}
|
|
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
|
|
s = requests.get(url,headers=headers)
|
|
if s.status_code == 200:
|
|
strokedata = pd.DataFrame.from_dict(s.json()['data'])
|
|
result = add_c2_stroke_data_db(
|
|
strokedata,workoutid,starttimeunix,
|
|
csvfilename,debug=debug,
|
|
)
|
|
|
|
return 1
|
|
else:
|
|
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)
|
|
s = requests.get(url,headers=headers)
|
|
|
|
if s.status_code == 200:
|
|
workoutdata = s.json()['data']
|
|
distance = workoutdata['distance']
|
|
c2id = workoutdata['id']
|
|
workouttype = workoutdata['type']
|
|
verified = workoutdata['verified']
|
|
startdatetime = iso8601.parse_date(workoutdata['date'])
|
|
weightclass = workoutdata['weight_class']
|
|
weightcategory = 'hwt'
|
|
if weightclass == "L":
|
|
weightcategory = 'lwt'
|
|
totaltime = workoutdata['time']/10.
|
|
duration = totaltime_sec_to_string(totaltime)
|
|
duration = datetime.datetime.strptime(duration,'%H:%M:%S.%f').time()
|
|
|
|
try:
|
|
timezone_str = tz(workoutdata['timezone'])
|
|
except:
|
|
timezone_str = 'UTC'
|
|
|
|
workoutdate = startdatetime.astimezone(
|
|
pytz.timezone(timezone_str)
|
|
).strftime('%Y-%m-%d')
|
|
starttime = startdatetime.astimezone(
|
|
pytz.timezone(timezone_str)
|
|
).strftime('%H:%M:%S')
|
|
|
|
result = create_c2_stroke_data_db(
|
|
distance,duration,workouttype,
|
|
workoutid,starttimeunix,
|
|
csvfilename,debug=debug,
|
|
)
|
|
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
return 0
|
|
|
|
def getagegrouprecord(age,sex='male',weightcategory='hwt',
|
|
distance=2000,duration=None,indf=pd.DataFrame()):
|
|
|
|
if not duration:
|
|
df = indf[indf['distance'] == distance]
|
|
else:
|
|
duration = 60*int(duration)
|
|
df = indf[indf['duration'] == duration]
|
|
|
|
if not df.empty:
|
|
ages = df['age']
|
|
powers = df['power']
|
|
|
|
#poly_coefficients = np.polyfit(ages,powers,6)
|
|
fitfunc = lambda pars, x: np.abs(pars[0])*(1-x/max(120,pars[1]))-np.abs(pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50,pars[5])))
|
|
errfunc = lambda pars, x,y: fitfunc(pars,x)-y
|
|
|
|
p0 = [700,120,700,10,100,100]
|
|
|
|
p1, success = optimize.leastsq(errfunc,p0[:],
|
|
args = (ages,powers))
|
|
|
|
if success:
|
|
power = fitfunc(p1, float(age))
|
|
|
|
#power = np.polyval(poly_coefficients,age)
|
|
|
|
power = 0.5*(np.abs(power)+power)
|
|
else:
|
|
power = 0
|
|
else:
|
|
power = 0
|
|
|
|
return power
|
|
|
|
def polygon_to_path(polygon,debug=True):
|
|
pid = polygon[0]
|
|
query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid} ORDER BY order_in_poly ASC".format(
|
|
pid=pid
|
|
)
|
|
if debug:
|
|
engine = create_engine(database_url_debug, echo=False)
|
|
else:
|
|
engine = create_engine(database_url, echo=False)
|
|
with engine.connect() as conn, conn.begin():
|
|
result = conn.execute(query)
|
|
points = result.fetchall()
|
|
|
|
conn.close()
|
|
engine.dispose()
|
|
s = []
|
|
|
|
for point in points:
|
|
s.append([point[1],point[2]])
|
|
|
|
p = path.Path(s[:-1])
|
|
|
|
return p
|
|
|
|
@app.task(bind=True)
|
|
def handle_check_race_course(self,
|
|
f1,workoutid,courseid,
|
|
recordid,**kwargs):
|
|
|
|
if 'debug' in kwargs:
|
|
debug = kwargs['debug']
|
|
else:
|
|
debug = False
|
|
|
|
if 'splitsecond' in kwargs:
|
|
splitsecond = kwargs['splitsecond']
|
|
else:
|
|
splitsecond = 0
|
|
|
|
mode = 'race'
|
|
if 'mode' in kwargs:
|
|
mode = kwargs['mode']
|
|
|
|
columns = ['time',' latitude',' longitude','cum_dist']
|
|
|
|
try:
|
|
row = rdata(csvfile=f1)
|
|
except IOError:
|
|
try:
|
|
row = rdata(f1 + '.csv')
|
|
except IOError:
|
|
try:
|
|
row = rdata(f1 + '.gz')
|
|
except IOError:
|
|
return 0
|
|
|
|
|
|
rowdata = row.df
|
|
|
|
try:
|
|
s = rowdata[' latitude']
|
|
except KeyError:
|
|
return 0
|
|
|
|
rowdata.rename(columns = {
|
|
' latitude':'latitude',
|
|
' longitude':'longitude',
|
|
' ElapsedTime (sec)': 'time',
|
|
}, inplace=True)
|
|
|
|
rowdata.fillna(method='backfill',inplace=True)
|
|
|
|
rowdata['time'] = rowdata['time']-rowdata.ix[0,'time']
|
|
rowdata = rowdata[rowdata['time']>splitsecond]
|
|
# we may want to expand the time (interpolate)
|
|
rowdata['dt'] = rowdata['time'].apply(
|
|
lambda x: timedelta(seconds=x)
|
|
)
|
|
rowdata = rowdata.resample('100ms',on='dt').mean()
|
|
rowdata = rowdata.interpolate()
|
|
|
|
# initiate database engine
|
|
|
|
if debug:
|
|
engine = create_engine(database_url_debug, echo=False)
|
|
else:
|
|
engine = create_engine(database_url, echo=False)
|
|
|
|
# get polygons
|
|
query = "SELECT id FROM rowers_geopolygon WHERE course_id = {courseid} ORDER BY order_in_course ASC".format(
|
|
courseid=courseid
|
|
)
|
|
|
|
with engine.connect() as conn, conn.begin():
|
|
result = conn.execute(query)
|
|
polygons = result.fetchall()
|
|
|
|
conn.close()
|
|
engine.dispose()
|
|
|
|
paths = []
|
|
for polygon in polygons:
|
|
path = polygon_to_path(polygon,debug=debug)
|
|
paths.append(path)
|
|
|
|
# check how many times went through start polygon
|
|
entrytimes,entrydistances = time_in_path(rowdata,paths[0],maxmin='max',getall=True)
|
|
|
|
cseconds = []
|
|
cmeters = []
|
|
ccomplete = []
|
|
|
|
for startt in entrytimes:
|
|
|
|
rowdata2 = rowdata[rowdata['time']>(startt-10.)]
|
|
|
|
(
|
|
coursetimeseconds,
|
|
coursemeters,
|
|
coursecompleted,
|
|
|
|
) = coursetime_paths(rowdata2,paths)
|
|
(
|
|
coursetimefirst,
|
|
coursemetersfirst,
|
|
firstcompleted
|
|
) = coursetime_first(
|
|
rowdata2,paths)
|
|
|
|
|
|
|
|
coursetimeseconds = coursetimeseconds-coursetimefirst
|
|
coursemeters = coursemeters-coursemetersfirst
|
|
|
|
cseconds.append(coursetimeseconds)
|
|
cmeters.append(coursemeters)
|
|
ccomplete.append(coursecompleted)
|
|
|
|
|
|
records = pd.DataFrame({
|
|
'coursetimeseconds':cseconds,
|
|
'coursecompleted': ccomplete,
|
|
'coursemeters': cmeters
|
|
})
|
|
|
|
records = records[records['coursecompleted'] == True]
|
|
|
|
if len(records):
|
|
coursecompleted = True
|
|
mintime = records['coursetimeseconds'].min()
|
|
coursetimeseconds = records[records['coursetimeseconds'] == mintime]['coursetimeseconds'].min()
|
|
coursemeters = records[records['coursetimeseconds'] == mintime]['coursemeters'].min()
|
|
else:
|
|
coursecompleted = False
|
|
|
|
|
|
if coursecompleted:
|
|
query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid} WHERE id={recordid}'.format(
|
|
recordid=recordid,
|
|
duration=totaltime_sec_to_string(coursetimeseconds),
|
|
distance=int(coursemeters),
|
|
workoutid=workoutid,
|
|
)
|
|
|
|
if mode == 'coursetest':
|
|
query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid} WHERE id={recordid}'.format(
|
|
recordid=recordid,
|
|
duration=totaltime_sec_to_string(coursetimeseconds),
|
|
distance=int(coursemeters),
|
|
workoutid=workoutid,
|
|
)
|
|
|
|
|
|
with engine.connect() as conn, conn.begin():
|
|
result = conn.execute(query)
|
|
|
|
conn.close()
|
|
engine.dispose()
|
|
|
|
return 1
|
|
|
|
else:
|
|
return 2
|
|
|
|
return 0
|
|
|
|
|
|
@app.task(bind=True)
|
|
def handle_getagegrouprecords(self,
|
|
df,
|
|
distances,durations,
|
|
age,sex,weightcategory,
|
|
**kwargs):
|
|
wcdurations = []
|
|
wcpower = []
|
|
|
|
if 'debug' in kwargs:
|
|
debug = kwargs['debug']
|
|
else:
|
|
debug = False
|
|
|
|
|
|
df = pd.read_json(df)
|
|
|
|
if sex == 'not specified':
|
|
return 0
|
|
|
|
for distance in distances:
|
|
worldclasspower = getagegrouprecord(
|
|
age,
|
|
sex=sex,
|
|
distance=distance,
|
|
weightcategory=weightcategory,indf=df,
|
|
)
|
|
velo = (worldclasspower/2.8)**(1./3.)
|
|
try:
|
|
duration = distance/velo
|
|
wcdurations.append(duration)
|
|
wcpower.append(worldclasspower)
|
|
except ZeroDivisionError:
|
|
pass
|
|
|
|
|
|
|
|
for duration in durations:
|
|
worldclasspower = getagegrouprecord(
|
|
age,
|
|
sex=sex,
|
|
duration=duration,
|
|
weightcategory=weightcategory,indf=df
|
|
)
|
|
try:
|
|
velo = (worldclasspower/2.8)**(1./3.)
|
|
distance = int(60*duration*velo)
|
|
wcdurations.append(60.*duration)
|
|
wcpower.append(worldclasspower)
|
|
except ValueError:
|
|
pass
|
|
|
|
update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower,
|
|
debug=debug)
|
|
|
|
return 1
|
|
|
|
|
|
@app.task(bind=True)
|
|
def long_test_task(self,aantal,debug=False,job=None,session_key=None):
|
|
job = self.request
|
|
|
|
return longtask.longtask(aantal,jobid=job.id,debug=debug,
|
|
session_key=session_key)
|
|
|
|
@app.task(bind=True)
|
|
def long_test_task2(self,aantal,**kwargs):
|
|
#debug=False,job=None,jobid='aap'):
|
|
job = self.request
|
|
job_id = job.id
|
|
|
|
if 'jobkey' in kwargs:
|
|
job_id = kwargs.pop('jobkey')
|
|
|
|
kwargs['jobid'] = job_id
|
|
|
|
return longtask.longtask2(aantal,**kwargs)
|
|
|
|
|
|
|
|
|
|
# create workout
|
|
@app.task
|
|
def handle_new_workout_from_file(r, f2,
|
|
workouttype='rower',
|
|
boattype='1x',
|
|
makeprivate=False,
|
|
notes='',debug=False):
|
|
return new_workout_from_file(r, f2, workouttype,
|
|
title, makeprivate, notes)
|
|
|
|
# process and update workouts
|
|
|
|
@app.task(bind=True)
|
|
def handle_update_empower(self,
|
|
useremail,
|
|
workoutdicts,
|
|
debug=False, **kwargs):
|
|
|
|
job = self.request
|
|
job_id = job.id
|
|
|
|
if 'jobkey' in kwargs:
|
|
job_id = kwargs.pop('jobkey')
|
|
|
|
aantal = len(workoutdicts)
|
|
counter = 0
|
|
|
|
for workoutdict in workoutdicts:
|
|
wid = workoutdict['id']
|
|
inboard = workoutdict['inboard']
|
|
oarlength = workoutdict['oarlength']
|
|
boattype = workoutdict['boattype']
|
|
f1 = workoutdict['filename']
|
|
|
|
# oarlength consistency checks will be done in view
|
|
|
|
havedata = 1
|
|
try:
|
|
rowdata = rdata(f1)
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.csv')
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.gz')
|
|
except IOError:
|
|
havedata = 0
|
|
|
|
progressurl = SITE_URL
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
progressurl = SITE_URL_DEV
|
|
siteurl = SITE_URL_DEV
|
|
secret = PROGRESS_CACHE_SECRET
|
|
|
|
kwargs['job_id'] = job_id
|
|
|
|
progressurl += "/rowers/record-progress/"
|
|
progressurl += job_id
|
|
|
|
if havedata:
|
|
success = update_empower(wid, inboard, oarlength, boattype,
|
|
rowdata.df, f1, debug=debug)
|
|
|
|
counter += 1
|
|
|
|
progress = 100.*float(counter)/float(aantal)
|
|
|
|
post_data = {
|
|
"secret":secret,
|
|
"value":progress,
|
|
}
|
|
|
|
s = requests.post(progressurl, data=post_data)
|
|
status_code = s.status_code
|
|
|
|
subject = "Rowsandall.com Your Old Empower Oarlock data have been corrected"
|
|
message = """
|
|
We have updated Power and Work per Stroke data according to the instructions by Nielsen-Kellerman.
|
|
"""
|
|
|
|
email = EmailMessage(subject, message,
|
|
'Rowsandall <info@rowsandall.com>',
|
|
[useremail])
|
|
|
|
if 'emailbounced' in kwargs:
|
|
emailbounced = kwargs['emailbounced']
|
|
else:
|
|
emailbounced = False
|
|
|
|
if not emailbounced:
|
|
res = email.send()
|
|
return 1
|
|
|
|
@app.task
|
|
def handle_updatedps(useremail, workoutids, debug=False,**kwargs):
|
|
for wid, f1 in workoutids:
|
|
havedata = 1
|
|
try:
|
|
rowdata = rdata(f1)
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.csv')
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.gz')
|
|
except IOError:
|
|
havedata = 0
|
|
|
|
if havedata:
|
|
update_strokedata(wid, rowdata.df, debug=debug)
|
|
|
|
|
|
subject = "Rowsandall.com Your Distance per Stroke metric has been updated"
|
|
message = "All your workouts now have Distance per Stroke"
|
|
|
|
email = EmailMessage(subject, message,
|
|
'Rowsandall <info@rowsandall.com>',
|
|
[useremail])
|
|
|
|
if 'emailbounced' in kwargs:
|
|
emailbounced = kwargs['emailbounced']
|
|
else:
|
|
emailbounced = False
|
|
|
|
if not emailbounced:
|
|
res = email.send()
|
|
|
|
return 1
|
|
|
|
# send email when a breakthrough workout is uploaded
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_breakthrough(workoutid, useremail,
|
|
userfirstname, userlastname,
|
|
btvalues=pd.DataFrame().to_json(),
|
|
**kwargs):
|
|
|
|
if 'debug' in kwargs:
|
|
debug = kwargs['debug']
|
|
else:
|
|
debug = False
|
|
|
|
btvalues = pd.read_json(btvalues)
|
|
btvalues.sort_values('delta', axis=0, inplace=True)
|
|
|
|
tablevalues = [
|
|
{'delta': t.delta,
|
|
'cpvalue': t.cpvalues,
|
|
'pwr': t.pwr
|
|
} for t in btvalues.itertuples()
|
|
]
|
|
|
|
# send email with attachment
|
|
subject = "A breakthrough workout on rowsandall.com"
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
d = {
|
|
'first_name':userfirstname,
|
|
'siteurl':siteurl,
|
|
'workoutid':workoutid,
|
|
'btvalues':tablevalues,
|
|
}
|
|
|
|
|
|
|
|
res = send_template_email(from_email,[useremail],
|
|
subject,'breakthroughemail.html',
|
|
d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
# send email when a breakthrough workout is uploaded
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_hard(workoutid, useremail,
|
|
userfirstname, userlastname,
|
|
btvalues=pd.DataFrame().to_json(),
|
|
debug=False,**kwargs):
|
|
|
|
if 'debug' in kwargs:
|
|
debug = kwargs['debug']
|
|
else:
|
|
debug = False
|
|
|
|
|
|
btvalues = pd.read_json(btvalues)
|
|
btvalues.sort_values('delta', axis=0, inplace=True)
|
|
|
|
tablevalues = [
|
|
{'delta': t.delta,
|
|
'cpvalue': t.cpvalues,
|
|
'pwr': t.pwr
|
|
} for t in btvalues.itertuples()
|
|
]
|
|
|
|
# send email with attachment
|
|
subject = "That was a pretty hard workout on rowsandall.com"
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
d = {
|
|
'first_name':userfirstname,
|
|
'siteurl':siteurl,
|
|
'workoutid':workoutid,
|
|
'btvalues':tablevalues,
|
|
}
|
|
|
|
res = send_template_email(from_email,[useremail],
|
|
subject,'hardemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
# send email when user deletes account
|
|
@app.task
|
|
def handle_sendemail_userdeleted(name, email, debug=False, **kwargs):
|
|
fullemail = 'roosendaalsander@gmail.com'
|
|
subject = 'User account deleted'
|
|
message = 'Sander,\n\n'
|
|
message += 'The user {name} ({email}) has just deleted his account'.format(
|
|
name=name,
|
|
email=email
|
|
)
|
|
email = EmailMessage(subject,message,
|
|
'Rowsandall <info@rowsandall.com>',
|
|
[fullemail])
|
|
|
|
if 'emailbounced' in kwargs:
|
|
emailbounced = kwargs['emailbounced']
|
|
else:
|
|
emailbounced = False
|
|
|
|
if not emailbounced:
|
|
res = email.send()
|
|
|
|
|
|
return 1
|
|
|
|
# send email to me when an unrecognized file is uploaded
|
|
@app.task
|
|
def handle_sendemail_unrecognized(unrecognizedfile, useremail,
|
|
debug=False,**kwargs):
|
|
|
|
# send email with attachment
|
|
fullemail = 'roosendaalsander@gmail.com'
|
|
subject = "Unrecognized file from Rowsandall.com"
|
|
message = "Dear Sander,\n\n"
|
|
message += "Please find attached a file that someone tried to upload to rowsandall.com. The file was not recognized as a valid file type.\n\n"
|
|
message += "User Email " + useremail + "\n\n"
|
|
message += "Best Regards, the Rowsandall Team"
|
|
|
|
email = EmailMessage(subject, message,
|
|
'Rowsandall <info@rowsandall.com>',
|
|
[fullemail])
|
|
|
|
try:
|
|
email.attach_file(unrecognizedfile)
|
|
except IOError:
|
|
pass
|
|
|
|
if 'emailbounced' in kwargs:
|
|
emailbounced = kwargs['emailbounced']
|
|
else:
|
|
emailbounced = False
|
|
|
|
if not emailbounced:
|
|
res = email.send()
|
|
|
|
|
|
# remove tcx file
|
|
try:
|
|
os.remove(unrecognizedfile)
|
|
except:
|
|
pass
|
|
|
|
return 1
|
|
|
|
|
|
# send email to owner when an unrecognized file is uploaded
|
|
@app.task
|
|
def handle_sendemail_unrecognizedowner(useremail, userfirstname,
|
|
debug=False,**kwargs):
|
|
|
|
# send email with attachment
|
|
fullemail = useremail
|
|
subject = "Unrecognized file from Rowsandall.com"
|
|
|
|
|
|
d = {
|
|
'first_name':userfirstname,
|
|
'siteurl':siteurl,
|
|
}
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'unrecognizedemail.html',d,
|
|
**kwargs)
|
|
|
|
return 1
|
|
|
|
@app.task
|
|
def handle_sendemailkml(first_name, last_name, email, kmlfile,**kwargs):
|
|
|
|
# send email with attachment
|
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
|
subject = "File from Rowsandall.com"
|
|
|
|
|
|
d = {'first_name':first_name,
|
|
'siteurl':siteurl,
|
|
}
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'kmlemail.html',d,
|
|
attach_file=kmlfile,**kwargs)
|
|
|
|
os.remove(kmlfile)
|
|
return 1
|
|
|
|
# Send email with TCX attachment
|
|
@app.task
|
|
def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs):
|
|
|
|
# send email with attachment
|
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
|
subject = "File from Rowsandall.com"
|
|
|
|
|
|
d = {'first_name':first_name,
|
|
'siteurl':siteurl,
|
|
}
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'tcxemail.html',d,
|
|
attach_file=tcxfile,**kwargs)
|
|
|
|
os.remove(tcxfile)
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_zip_file(emailfrom, subject, file,**kwargs):
|
|
message = "... zip processing ... "
|
|
try:
|
|
debug = kwargs['debug']
|
|
except KeyError:
|
|
debug = False
|
|
|
|
if debug:
|
|
print message
|
|
|
|
email = EmailMessage(subject, message,
|
|
emailfrom,
|
|
['workouts@rowsandall.com'])
|
|
email.attach_file(file)
|
|
if debug:
|
|
print "attaching"
|
|
|
|
|
|
res = email.send()
|
|
|
|
|
|
if debug:
|
|
print "sent"
|
|
time.sleep(60)
|
|
return 1
|
|
|
|
# Send email with CSV attachment
|
|
|
|
@app.task
|
|
def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs):
|
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
|
subject = "File from Rowsandall.com"
|
|
|
|
|
|
d = {'first_name':first_name,
|
|
'siteurl':siteurl,
|
|
}
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'summarymail.html',d,
|
|
attach_file=csvfile,
|
|
**kwargs)
|
|
|
|
try:
|
|
os.remove(csvfile)
|
|
except:
|
|
pass
|
|
|
|
return 1
|
|
|
|
#from rowers.emails import sendemail
|
|
|
|
@app.task
|
|
def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs):
|
|
|
|
|
|
# send email with attachment
|
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
|
subject = "File from Rowsandall.com"
|
|
|
|
d = {'first_name':first_name,
|
|
'siteurl':siteurl,
|
|
}
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'csvemail.html',d,
|
|
attach_file=csvfile,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
# Calculate wind and stream corrections for OTW rowing
|
|
|
|
|
|
@app.task(bind=True)
|
|
def handle_otwsetpower(self,f1, boattype, weightvalue,
|
|
first_name, last_name, email, workoutid,
|
|
**kwargs):
|
|
|
|
job = self.request
|
|
job_id = job.id
|
|
|
|
if 'jobkey' in kwargs:
|
|
job_id = kwargs.pop('jobkey')
|
|
if 'ps' in kwargs:
|
|
ps = kwargs['ps']
|
|
else:
|
|
ps = [1,1,1,1]
|
|
|
|
if 'ratio' in kwargs:
|
|
ratio = kwargs['ratio']
|
|
else:
|
|
ratio = 1.0
|
|
if 'debug' in kwargs:
|
|
debug = kwargs['debug']
|
|
else:
|
|
debug = False
|
|
|
|
if 'quick_calc' in kwargs:
|
|
usetable = kwargs['quick_calc']
|
|
else:
|
|
usetable = False
|
|
|
|
kwargs['jobid'] = job_id
|
|
|
|
|
|
try:
|
|
rowdata = rdata(f1)
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.csv')
|
|
except IOError:
|
|
rowdata = rdata(f1 + '.gz')
|
|
|
|
weightvalue = float(weightvalue)
|
|
|
|
# do something with boat type
|
|
boatfile = {
|
|
'1x': 'static/rigging/1x.txt',
|
|
'2x': 'static/rigging/2x.txt',
|
|
'2-': 'static/rigging/2-.txt',
|
|
'4x': 'static/rigging/4x.txt',
|
|
'4-': 'static/rigging/4-.txt',
|
|
'8+': 'static/rigging/8+.txt',
|
|
}
|
|
try:
|
|
rg = rowingdata.getrigging(boatfile[boattype])
|
|
except KeyError:
|
|
rg = rowingdata.getrigging('static/rigging/1x.txt')
|
|
|
|
# do calculation, but do not overwrite NK Empower Power data
|
|
powermeasured = False
|
|
try:
|
|
w = rowdata.df['wash']
|
|
if w.mean() != 0:
|
|
powermeasured = True
|
|
except KeyError:
|
|
pass
|
|
|
|
progressurl = SITE_URL
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
progressurl = SITE_URL_DEV
|
|
siteurl = SITE_URL_DEV
|
|
secret = PROGRESS_CACHE_SECRET
|
|
|
|
progressurl += "/rowers/record-progress/"
|
|
progressurl += job_id
|
|
|
|
# determine cache file name
|
|
physics_cache = 'media/'+str(boattype)+'_'+str(int(weightvalue))
|
|
|
|
|
|
rowdata.otw_setpower(skiprows=5, mc=weightvalue, rg=rg,
|
|
powermeasured=powermeasured,
|
|
progressurl=progressurl,
|
|
secret=secret,
|
|
silent=True,
|
|
usetable=usetable,storetable=physics_cache,
|
|
)
|
|
|
|
# save data
|
|
rowdata.write_csv(f1, gzip=True)
|
|
update_strokedata(workoutid, rowdata.df, debug=debug)
|
|
|
|
totaltime = rowdata.df['TimeStamp (sec)'].max(
|
|
) - rowdata.df['TimeStamp (sec)'].min()
|
|
try:
|
|
totaltime = totaltime + rowdata.df.ix[0, ' ElapsedTime (sec)']
|
|
except KeyError:
|
|
pass
|
|
df = getsmallrowdata_db(
|
|
['power', 'workoutid', 'time'], ids=[workoutid],
|
|
debug=debug)
|
|
thesecs = totaltime
|
|
maxt = 1.05 * thesecs
|
|
logarr = datautils.getlogarr(maxt)
|
|
dfgrouped = df.groupby(['workoutid'])
|
|
delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr)
|
|
|
|
#delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df)
|
|
res, btvalues, res2 = utils.isbreakthrough(
|
|
delta, cpvalues, ps[0], ps[1], ps[2], ps[3], ratio)
|
|
if res:
|
|
handle_sendemail_breakthrough(
|
|
workoutid, email,
|
|
first_name,
|
|
last_name, btvalues=btvalues.to_json())
|
|
|
|
|
|
subject = "Your OTW Physics Calculations are ready"
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
|
|
|
|
|
d = {
|
|
'first_name':first_name,
|
|
'siteurl':siteurl,
|
|
'workoutid':workoutid,
|
|
}
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'otwpoweremail.html',d,
|
|
**kwargs)
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs):
|
|
therows = []
|
|
for f1 in workoutfilenames:
|
|
try:
|
|
rowdata = rdata(f1)
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.csv')
|
|
except IOError:
|
|
try:
|
|
rowdata = rdata(f1 + '.gz')
|
|
except IOError:
|
|
rowdata = 0
|
|
|
|
if rowdata != 0:
|
|
therows.append(rowdata)
|
|
|
|
cpdata = rowingdata.cumcpdata(therows)
|
|
cpdata.columns = cpdata.columns.str.lower()
|
|
|
|
updatecpdata_sql(rower_id,cpdata['delta'],cpdata['cp'],
|
|
table='ergcpdata',distance=cpdata['distance'],
|
|
debug=debug)
|
|
|
|
return 1
|
|
|
|
def cp_from_workoutids(workoutids,debug=False):
|
|
columns = ['power','workoutid','time']
|
|
df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)
|
|
df.dropna(inplace=True,axis=0)
|
|
|
|
if df.empty:
|
|
# change this
|
|
return 0,0,0
|
|
|
|
# df is not empty. We continue
|
|
dfgrouped = df.groupby(['workoutid'])
|
|
maxt = 1.05*df['time'].max()/1000.
|
|
|
|
logarr = datautils.getlogarr(maxt)
|
|
|
|
delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
|
|
|
|
powerdf = pd.DataFrame({
|
|
'Delta':delta,
|
|
'CP':cpvalue,
|
|
})
|
|
|
|
powerdf = powerdf[powerdf['CP']>0]
|
|
powerdf.dropna(axis=0,inplace=True)
|
|
powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
|
|
powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True)
|
|
|
|
p1,fitt,fitpower,ratio = datautils.cpfit(powerdf)
|
|
# This is code duplication from datautils -- correct asap
|
|
fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3])))
|
|
|
|
powerfourmin = fitfunc(p1,240.)
|
|
powerhour = fitfunc(p1,3600.)
|
|
|
|
# 2k power
|
|
velofourmin = (powerfourmin/2.8)**(1./3.)
|
|
dfourmin = 240.*velofourmin
|
|
dratio = 2000./dfourmin
|
|
pacefourmin = 500./velofourmin
|
|
|
|
# assume 5 sec per doubling drop
|
|
pace2k = pacefourmin + 5.*np.log10(dratio)/np.log10(2.)
|
|
velo2k = 500./pace2k
|
|
t2k = 2000./velo2k
|
|
pwr2k = fitfunc(p1,t2k)
|
|
velo2 = (pwr2k/2.8)**(1./3.)
|
|
if np.isnan(velo2) or velo2 <= 0:
|
|
velo2 = 1.0
|
|
|
|
t2 = 2000./velo2
|
|
|
|
pwr2k = fitfunc(p1,t2)
|
|
|
|
velo3 = (pwr2k/2.8)**(1./3.)
|
|
|
|
t3 = 2000./velo3
|
|
|
|
power2k = fitfunc(p1,t3)
|
|
|
|
return powerfourmin,power2k,powerhour
|
|
|
|
|
|
@app.task
|
|
def handle_updatefitnessmetric(user_id,mode,workoutids,debug=False,
|
|
**kwargs):
|
|
|
|
powerfourmin = -1
|
|
power2k = -1
|
|
powerhour = -1
|
|
|
|
mdict = {
|
|
'user_id': user_id,
|
|
'PowerFourMin': powerfourmin,
|
|
'PowerTwoK': power2k,
|
|
'PowerOneHour': powerhour,
|
|
'workoutmode': mode,
|
|
'last_workout': max(workoutids),
|
|
'date': timezone.now().strftime('%Y-%m-%d'),
|
|
}
|
|
|
|
result = fitnessmetric_to_sql(mdict,debug=debug,doclean=False)
|
|
|
|
powerfourmin,power2k,powerhour = cp_from_workoutids(workoutids,debug=debug)
|
|
|
|
if powerfourmin > 0 and power2k > 0 and powerhour > 0:
|
|
|
|
mdict = {
|
|
'user_id': user_id,
|
|
'PowerFourMin': powerfourmin,
|
|
'PowerTwoK': power2k,
|
|
'PowerOneHour': powerhour,
|
|
'workoutmode': mode,
|
|
'last_workout': max(workoutids),
|
|
'date': timezone.now().strftime('%Y-%m-%d'),
|
|
}
|
|
|
|
result = fitnessmetric_to_sql(mdict,debug=debug,doclean=True)
|
|
else:
|
|
result = 0
|
|
|
|
return result
|
|
|
|
@app.task
|
|
def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs):
|
|
columns = ['power','workoutid','time']
|
|
df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)
|
|
dfgrouped = df.groupby(['workoutid'])
|
|
|
|
if not df.empty:
|
|
maxt = 1.05*df['time'].max()/1000.
|
|
else:
|
|
maxt = 1000.
|
|
|
|
logarr = datautils.getlogarr(maxt)
|
|
|
|
|
|
delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
|
|
|
|
updatecpdata_sql(rower_id,delta,cpvalue,debug=debug,table=table)
|
|
|
|
return 1
|
|
|
|
@app.task
|
|
def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename,
|
|
debug=False,**kwargs):
|
|
|
|
hrmax = hrdata['hrmax']
|
|
hrut2 = hrdata['hrut2']
|
|
hrut1 = hrdata['hrut1']
|
|
hrat = hrdata['hrat']
|
|
hrtr = hrdata['hrtr']
|
|
hran = hrdata['hran']
|
|
ftp = hrdata['ftp']
|
|
powerzones = deserialize_list(hrdata['powerzones'])
|
|
powerperc = np.array(deserialize_list(hrdata['powerperc'])).astype(int)
|
|
|
|
rr = rowingdata.rower(hrmax=hrmax, hrut2=hrut2,
|
|
hrut1=hrut1, hrat=hrat,
|
|
hrtr=hrtr, hran=hran,
|
|
ftp=ftp, powerperc=powerperc,
|
|
powerzones=powerzones)
|
|
try:
|
|
row = rdata(f2, rower=rr)
|
|
except IOError:
|
|
row = rdata(f2 + '.gz', rower=rr)
|
|
|
|
haspower = row.df[' Power (watts)'].mean() > 50
|
|
|
|
nr_rows = len(row.df)
|
|
if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200):
|
|
bin = int(nr_rows / 1200.)
|
|
df = row.df.groupby(lambda x: x / bin).mean()
|
|
row.df = df
|
|
nr_rows = len(row.df)
|
|
if (plotnr == 1):
|
|
fig1 = row.get_timeplot_erg(t)
|
|
elif (plotnr == 2):
|
|
fig1 = row.get_metersplot_erg(t)
|
|
elif (plotnr == 3):
|
|
t += ' - Heart Rate Distribution'
|
|
fig1 = row.get_piechart(t)
|
|
elif (plotnr == 4):
|
|
if haspower:
|
|
fig1 = row.get_timeplot_otwempower(t)
|
|
else:
|
|
fig1 = row.get_timeplot_otw(t)
|
|
elif (plotnr == 5):
|
|
if haspower:
|
|
fig1 = row.get_metersplot_otwempower(t)
|
|
else:
|
|
fig1 = row.get_metersplot_otw(t)
|
|
elif (plotnr == 6):
|
|
t += ' - Heart Rate Distribution'
|
|
fig1 = row.get_piechart(t)
|
|
elif (plotnr == 7) or (plotnr == 10):
|
|
fig1 = row.get_metersplot_erg2(t)
|
|
elif (plotnr == 8) or (plotnr == 11):
|
|
fig1 = row.get_timeplot_erg2(t)
|
|
elif (plotnr == 9) or (plotnr == 12):
|
|
fig1 = row.get_time_otwpower(t)
|
|
elif (plotnr == 13) or (plotnr == 16):
|
|
t += ' - Power Distribution'
|
|
fig1 = row.get_power_piechart(t)
|
|
|
|
canvas = FigureCanvas(fig1)
|
|
|
|
# plt.savefig('static/plots/'+imagename,format='png')
|
|
canvas.print_figure('static/plots/' + imagename)
|
|
# plt.imsave(fname='static/plots/'+imagename)
|
|
plt.close(fig1)
|
|
fig1.clf()
|
|
gc.collect()
|
|
|
|
return imagename
|
|
|
|
# Team related remote tasks
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_invite(email, name, code, teamname, manager,
|
|
debug=False,**kwargs):
|
|
fullemail = name + ' <' + email + '>'
|
|
subject = 'Invitation to join team ' + teamname
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'name':name,
|
|
'manager':manager,
|
|
'code':code,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl
|
|
}
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
res = send_template_email(from_email,[fullemail],
|
|
subject,'teaminviteemail.html',d,
|
|
**kwargs)
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemailnewresponse(first_name, last_name,
|
|
email,
|
|
commenter_first_name,
|
|
commenter_last_name,
|
|
comment,
|
|
workoutname, workoutid, commentid,
|
|
debug=False,**kwargs):
|
|
fullemail = first_name + ' ' + last_name + ' <' + email + '>'
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
subject = 'New comment on workout ' + workoutname
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
|
|
d = {
|
|
'first_name':first_name,
|
|
'commenter_first_name':commenter_first_name,
|
|
'commenter_last_name':commenter_last_name,
|
|
'comment':comment,
|
|
'workoutname':workoutname,
|
|
'siteurl':siteurl,
|
|
'workoutid':workoutid,
|
|
'commentid':commentid
|
|
}
|
|
|
|
res = send_template_email(from_email,[fullemail],subject,'teamresponseemail.html',d,**kwargs)
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemailnewcomment(first_name,
|
|
last_name,
|
|
email,
|
|
commenter_first_name,
|
|
commenter_last_name,
|
|
comment, workoutname,
|
|
workoutid,
|
|
debug=False,**kwargs):
|
|
|
|
|
|
|
|
fullemail = first_name + ' ' + last_name + ' <' + email + '>'
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
subject = 'New comment on workout ' + workoutname
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
|
|
d = {
|
|
'first_name':first_name,
|
|
'commenter_first_name':commenter_first_name,
|
|
'commenter_last_name':commenter_last_name,
|
|
'comment':comment,
|
|
'workoutname':workoutname,
|
|
'siteurl':siteurl,
|
|
'workoutid':workoutid,
|
|
}
|
|
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teamresponseemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_request(email, name, code, teamname, requestor, id,
|
|
debug=False,**kwargs):
|
|
fullemail = name + ' <' + email + '>'
|
|
subject = 'Request to join team ' + teamname
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'requestor':requestor,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
'id':id,
|
|
'first_name':name,
|
|
}
|
|
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teamrequestemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_request_accept(email, name, teamname, managername,
|
|
debug=False,**kwargs):
|
|
fullemail = name + ' <' + email + '>'
|
|
subject = 'Welcome to ' + teamname
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'first_name':name,
|
|
'managername':managername,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
}
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teamwelcomeemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_request_reject(email, name, teamname, managername,
|
|
debug=False,**kwargs):
|
|
fullemail = name + ' <' + email + '>'
|
|
subject = 'Your application to ' + teamname + ' was rejected'
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'first_name':name,
|
|
'managername':managername,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
}
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teamrejectemail.html',d,**kwargs)
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_member_dropped(email, name, teamname, managername,
|
|
debug=False,**kwargs):
|
|
fullemail = name + ' <' + email + '>'
|
|
subject = 'You were removed from ' + teamname
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'first_name':name,
|
|
'managername':managername,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
}
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teamdropemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_team_removed(email, name, teamname, managername,
|
|
debug=False,**kwargs):
|
|
|
|
fullemail = name + ' <' + email + '>'
|
|
subject = 'You were removed from ' + teamname
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'first_name':name,
|
|
'managername':managername,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
}
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teamremoveemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_invite_reject(email, name, teamname, managername,
|
|
debug=False,**kwargs):
|
|
fullemail = managername + ' <' + email + '>'
|
|
subject = 'Your invitation to ' + name + ' was rejected'
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'first_name':name,
|
|
'managername':managername,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
}
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teaminviterejectemail.html',d,**kwargs)
|
|
|
|
return 1
|
|
|
|
|
|
@app.task
|
|
def handle_sendemail_invite_accept(email, name, teamname, managername,
|
|
debug=False,**kwargs):
|
|
fullemail = managername + ' <' + email + '>'
|
|
subject = 'Your invitation to ' + name + ' was accepted'
|
|
|
|
from_email = 'Rowsandall <info@rowsandall.com>'
|
|
|
|
siteurl = SITE_URL
|
|
if debug:
|
|
siteurl = SITE_URL_DEV
|
|
|
|
d = {
|
|
'first_name':name,
|
|
'managername':managername,
|
|
'teamname':teamname,
|
|
'siteurl':siteurl,
|
|
}
|
|
res = send_template_email(from_email,[fullemail],subject,
|
|
'teaminviteacceptemail.html',d,**kwargs)
|
|
|
|
|
|
return 1
|
|
|
|
|
|
# Another simple task for debugging purposes
|
|
def add2(x, y,debug=False,**kwargs):
|
|
return x + y
|