diff --git a/rowers/tasks.py b/rowers/tasks.py index 14a6753d..7011b5b8 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -1148,6 +1148,37 @@ def handle_send_disqualification_email( return 1 +@app.task +def handle_send_withdraw_email( + useremail,username,reason,message, racename, **kwargs): + + if 'debug' in kwargs: + debug = kwargs['debug'] + else: + debug = True + + subject = "Your result for {n} has been disqualified on rowsandall.com".format( + n = racename + ) + + from_email = 'Rowsandall ' + + d = { + 'username':username, + 'reason':reason, + 'siteurl':siteurl, + 'message': htmlstrip(message), + 'racename':racename, + } + + res = send_template_email(from_email,[useremail], + subject, + 'withdraw_email.html', + d,**kwargs) + + return 1 + + @app.task def handle_sendemail_expired(useremail,userfirstname,userlastname,expireddate, **kwargs): diff --git a/rowers/templates/disqualification_view.html b/rowers/templates/disqualification_view.html index b2a7ef4f..f1b696c4 100644 --- a/rowers/templates/disqualification_view.html +++ b/rowers/templates/disqualification_view.html @@ -114,7 +114,7 @@

Please select a reason and add a comment (mandatory). - Pressing 'Reject' disqualifies the submitted result. + Pressing 'Reject' removes the submitted result. An email will be sent to the rower. There is no "undo".

diff --git a/rowers/templates/virtualevent.html b/rowers/templates/virtualevent.html index 5c8a7c86..9e4187c2 100644 --- a/rowers/templates/virtualevent.html +++ b/rowers/templates/virtualevent.html @@ -313,6 +313,13 @@   {% endif %} + + {% if result.userid == request.user.rower.id and not race|is_final %} + + Remove + + {% endif %} + {% endfor %} {% for result in dns %} diff --git a/rowers/templates/withdraw_email.html b/rowers/templates/withdraw_email.html new file mode 100644 index 00000000..acf069b2 --- /dev/null +++ b/rowers/templates/withdraw_email.html @@ -0,0 +1,30 @@ +{% extends "emailbase.html" %} +{% block body %} +

Dear {{ username }},

+ +

+ The result that you have submitted for the virtual challenge {{ racename }} has been + removed. +

+ +

+ The reason for the removal was: {{ reason }}. +

+ +

+ You added the following explanation: +

+ +

+ {{ message }} +

+ + +

+ You are still registered for the challenge and can submit a result. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/withdraw_view.html b/rowers/templates/withdraw_view.html new file mode 100644 index 00000000..9bd3ba04 --- /dev/null +++ b/rowers/templates/withdraw_view.html @@ -0,0 +1,138 @@ +{% extends "newbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} +{% block scripts %} +{% include "monitorjobs.html" %} +{% endblock %} + +{% block title %}{{ workout.name }} {% endblock %} +{% block og_title %}{{ workout.name }} {% endblock %} +{% block description %}{{ workout.name }} +{{ workout.date }} - {{ workout.distance }}m - {{ workout.duration |durationprint:"%H:%M:%S.%f" }}{% endblock %} +{% block og_description %}{{ workout.name }} +{{ workout.date }} - {{ workout.distance }}m - {{ workout.duration |durationprint:"%H:%M:%S.%f" }}{% endblock %} +{% if graphs1 %} +{% endif %} +{% for graph in graphs1 %} +{% block og_image %} +{% if graphs1 %} +{% for graph in graphs %} + + + + +{% endfor %} +{% else %} + + +{% endif %} +{% endblock %} +{% block image_src %} +{% for graph in graphs %} + +{% endfor %} +{% endblock %} + +{% endfor %} +{% block main %} + +

Do you want to withdraw this result?

+
    +
  • +

    + Before you reject this challenge result, please carefully review it + using the information below. If you still want to reject the entry, + scroll down to the rejection form. +

    +
  • +
  • + + + + + + + + + + + + + + + + + + + + +
    Rower:{{ record.username }}
    Name:{{ workout.name }}
    Date:{{ workout.date }}
    Time:{{ workout.starttime }}
    Distance:{{ workout.distance }}m
    Duration:{{ workout.duration |durationprint:"%H:%M:%S.%f" }}
    Type:{{ workout.workouttype }}
    Weight Category:{{ workout.weightcategory }}
    +
  • +
  • +

    Workout Summary

    + +

    +

    +        {{ workout.summary }}
    +      
    +

    +
  • + {% for graph in graphs %} +
  • + + {{ graph.filename }} + +
  • + {% endfor %} + {% if mapdiv %} +
  • +
    + + {{ mapdiv|safe }} + + + {{ mapscript|safe }} +
    +
  • + {% endif %} +
  • + + + + {{ interactiveplot |safe }} + + {{ the_div|safe }} + +
  • +
  • +

    + Yes, I want to reject this entry +

    +

    + Please select a reason and add a comment (mandatory). + Pressing 'Reject' removes the submitted result. + An email will be sent to the rower. There is no "undo". +

    +

    +

    + + {{ form.as_table }} +
    +

    +

    + {% csrf_token %} + +

    +
    +
  • +
+ +{% endblock %} + +{% block sidebar %} +{% include 'menu_racing.html' %} +{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 5df0f9ba..097ad88c 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -195,6 +195,8 @@ urlpatterns = [ views.virtualevent_submit_result_view,name='virtualevent_submit_result_view'), re_path(r'^virtualevent/(?P\d+)/disqualify/(?P\d+)/', views.virtualevent_disqualify_view,name='virtualevent_disqualify_view'), + re_path(r'^virtualevent/(?P\d+)/withdrawresult/(?P\d+)/', + views.virtualevent_withdrawresult_view,name='virtualevent_withdrawresult_view'), re_path(r'^list-workouts/$',views.workouts_view,name='workouts_view'), re_path(r'^list-courses/$',views.courses_view,name='courses_view'), re_path(r'^courses/upload/$',views.course_upload_view,name='course_upload_view'), diff --git a/rowers/views/racesviews.py b/rowers/views/racesviews.py index 845a79cf..b0d2c9d7 100644 --- a/rowers/views/racesviews.py +++ b/rowers/views/racesviews.py @@ -647,7 +647,7 @@ def virtualevent_disqualify_view(request,id=0,recordid=0): }, { 'url':reverse(virtualevent_disqualify_view, - kwargs={'raceid':raceid, + kwargs={'id':id, 'recordid':recordid}), 'name': 'Disqualify Entry' }, @@ -688,6 +688,149 @@ def virtualevent_disqualify_view(request,id=0,recordid=0): 'record':record, }) +@login_required() +def virtualevent_withdrawresult_view(request,id=0,recordid=0): + + r = getrower(request.user) + race = get_object_or_404(VirtualRace,pk=id) + + + if race.sessiontype == 'race': + recordobj = VirtualRaceResult + else: + recordobj = IndoorVirtualRaceResult + + # datum moet voor race evaluation date zijn (ook in template controleren) + + try: + record = recordobj.objects.get(id=recordid) + except recordobj.DoesNotExist: + messages.error(request,"We couldn't find the record") + + if r.id != record.userid: + raise PermissionDenied("You are not the owner of this result") + + if timezone.now() > race.evaluation_closure+datetime.timedelta(hours=1): + messages.error(request,"The evaluation is already closed and the results are official") + url = reverse('virtualevent_view',kwargs={'id':raceid}) + + return HttpResponseRedirect(url) + + if request.method == 'POST': + form = DisqualificationForm(request.POST) + if form.is_valid(): + message = form.cleaned_data['message'] + reason = form.cleaned_data['reason'] + disqualifier = disqualifiers[reason] + + r = Rower.objects.get(id=record.userid) + name = record.username + + job = myqueue(queue,handle_send_withdraw_email, + r.user.email, name, + disqualifier,message,race.name) + + messages.info(request,"We have invalidated the result for: "+str(record)) + + record.coursecompleted = False + record.save() + + url = reverse('virtualevent_view',kwargs={'id':id}) + + return HttpResponseRedirect(url) + + else: + form = DisqualificationForm(request.POST) + + workout = Workout.objects.get(id=record.workoutid) + + g = GraphImage.objects.filter(workout=workout).order_by("-creationdatetime") + for i in g: + try: + width,height = Image.open(i.filename).size + i.width = width + i.height = height + i.save() + except: + pass + + script, div = interactive_chart(record.workoutid) + + f1 = workout.csvfilename + rowdata = rdata(f1) + hascoordinates = 1 + if rowdata != 0: + try: + latitude = rowdata.df[' latitude'] + if not latitude.std(): + hascoordinates = 0 + except (KeyError, AttributeError): + hascoordinates = 0 + else: + hascoordinates = 0 + + if hascoordinates: + mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'], + rowdata.df[' longitude'], + workout.name) + else: + mapscript = "" + mapdiv = "" + + breadcrumbs = [ + { + 'url':reverse('virtualevents_view'), + 'name': 'Challenges' + }, + { + 'url':reverse('virtualevent_view', + kwargs={'id':race.id}), + 'name': race.name + }, + { + 'url':reverse(virtualevent_disqualify_view, + kwargs={'id':id, + 'recordid':recordid}), + 'name': 'Disqualify Entry' + }, + ] + + buttons = [] + + if not request.user.is_anonymous: + if race_can_register(r,race): + buttons += ['registerbutton'] + + if race_can_adddiscipline(r,race): + buttons += ['adddisciplinebutton'] + + if race_can_submit(r,race): + buttons += ['submitbutton'] + + if race_can_resubmit(r,race): + buttons += ['resubmitbutton'] + + if race_can_withdraw(r,race): + buttons += ['withdrawbutton'] + + if race_can_edit(r,race): + buttons += ['editbutton'] + + return render(request,"withdraw_view.html", + {'workout':workout, + 'active':'nav-racing', + 'graphs':g, + 'buttons':buttons, + 'interactiveplot':script, + 'the_div':div, + 'mapscript':mapscript, + 'mapdiv':mapdiv, + 'form':form, + 'race':race, + 'record':record, + }) + + def virtualevent_view(request,id=0): results = []