From 53cbd91e8db77a66e03fb2f92e30ae3edfde07bf Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 1 Jun 2024 15:44:03 +0200
Subject: [PATCH] adding bulk action assign rowers
---
rowers/forms.py | 10 +++++
rowers/tasks.py | 44 ++++++++++++++++++++++
rowers/templates/workout_bulk_actions.html | 5 +++
rowers/templatetags/rowerfilters.py | 2 +-
rowers/views/statements.py | 4 +-
rowers/views/workoutviews.py | 13 +++++++
6 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/rowers/forms.py b/rowers/forms.py
index 4d6740c3..311f1fa5 100644
--- a/rowers/forms.py
+++ b/rowers/forms.py
@@ -1213,6 +1213,7 @@ class ForceCurveMultipleCompareForm(forms.Form):
bulkactions = (
('remove','remove'),
('export','export'),
+ ('rower assign','rower assign'),
)
destinations = (
('C2','C2'),
@@ -1230,6 +1231,15 @@ class ExportChoices(forms.Form):
choices=destinations, label='Destination', required=False, initial='strava'
)
+class AssignChoices(forms.Form):
+ remove_workout = forms.BooleanField(initial=False, required=False)
+ destination = forms.ModelMultipleChoiceField(label='Rowers', required=False,
+ queryset=Rower.objects.filter(), widget=forms.CheckboxSelectMultiple())
+
+ def __init__(self, *args, **kwargs):
+ super(AssignChoices, self).__init__(*args, **kwargs)
+ self.fields['destination'].queryset = Rower.objects.filter()
+
class WorkoutMultipleCompareForm(forms.Form):
workouts = forms.ModelMultipleChoiceField(
queryset=Workout.objects.filter(),
diff --git a/rowers/tasks.py b/rowers/tasks.py
index dbf562d4..bb4f04bd 100644
--- a/rowers/tasks.py
+++ b/rowers/tasks.py
@@ -324,6 +324,50 @@ def summaryfromsplitdata(splitdata, data, filename, sep='|', workouttype='rower'
return sums, sa, results
+@app.task
+def handle_assignworkouts(workouts, rowers, remove_workout, debug=False, **kwargs):
+ for workout in workouts:
+ uploadoptions = {
+ 'secret': UPLOAD_SERVICE_SECRET,
+ 'title': workout.name,
+ 'boattype': workout.boattype,
+ 'workouttype': workout.workouttype,
+ 'inboard': workout.inboard,
+ 'oarlength': workout.oarlength,
+ 'summary': workout.summary,
+ 'elapsedTime': 3600.*workout.duration.hour+60*workout.duration.minute+workout.duration.second,
+ 'totalDistance': workout.distance,
+ 'useImpeller': workout.impeller,
+ 'seatNumber': workout.seatnumber,
+ 'boatName': workout.boatname,
+ 'portStarboard': workout.empowerside,
+ }
+ for rower in rowers:
+ failed = False
+ csvfilename = 'media/{code}.csv'.format(code=uuid4().hex[:16])
+ try:
+ with open(csvfilename,'wb') as f:
+ shutil.copy(workout.csvfilename,csvfilename)
+ except FileNotFoundError:
+ try:
+ with open(csvfilename,'wb') as f:
+ csvfilename = csvfilename+'.gz'
+ shutil.copy(workout.csvfilename+'.gz', csvfilename)
+ except:
+ failed = True
+ if not failed:
+ uploadoptions['user'] = rower.user.id
+ uploadoptions['file'] = csvfilename
+ session = requests.session()
+ newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
+ session.headers.update(newHeaders)
+ response = session.post(UPLOAD_SERVICE_URL, json=uploadoptions)
+ print(response.text)
+ if remove_workout:
+ workout.delete()
+
+ return 1
+
@app.task
def handle_post_workout_api(uploadoptions, debug=False, **kwargs): # pragma: no cover
session = requests.session()
diff --git a/rowers/templates/workout_bulk_actions.html b/rowers/templates/workout_bulk_actions.html
index 4fcb356b..0c50413c 100644
--- a/rowers/templates/workout_bulk_actions.html
+++ b/rowers/templates/workout_bulk_actions.html
@@ -23,6 +23,11 @@
{{ exportchoice.as_p }}
{% endif %}
+ {% if action == 'rower assign' %}
+
+ {{ assignchoices.as_p }}
+
+ {% endif %}
{% csrf_token %}
diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py
index 77eb7a12..2d4af95e 100644
--- a/rowers/templatetags/rowerfilters.py
+++ b/rowers/templatetags/rowerfilters.py
@@ -770,7 +770,7 @@ def team_rowers(user): # pragma: no cover
teams = Team.objects.filter(manager=user)
members = Rower.objects.filter(
team__in=teams).distinct().order_by(
- "user__last_name", "user__last_name").exclude(
+ "user__last_name", "user__first_name").exclude(
rowerplan='freecoach')
return members
except TypeError:
diff --git a/rowers/views/statements.py b/rowers/views/statements.py
index fd7c2d99..d134013d 100644
--- a/rowers/views/statements.py
+++ b/rowers/views/statements.py
@@ -116,7 +116,8 @@ from rowers.forms import (
StravaChartForm, FitnessFitForm, PerformanceManagerForm,
TrainingPlanBillingForm, InstantPlanSelectForm,
TrainingZonesForm, InstrokeForm, InStrokeMultipleCompareForm,
- ForceCurveMultipleCompareForm, PlanByRscoreForm
+ ForceCurveMultipleCompareForm, PlanByRscoreForm,
+ AssignChoices,
)
from django.urls import reverse, reverse_lazy
@@ -267,6 +268,7 @@ from rowers.tasks import (
handle_send_email_instantplan_notification,
handle_nk_async_workout,
check_tp_workout_id,
+ handle_assignworkouts,
)
from scipy.signal import savgol_filter
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 288614a2..ced60404 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -2031,6 +2031,12 @@ def workouts_bulk_actions(request):
'Export to {destination} of workout {id} failed'.format(
id=encoder.encode_hex(w.id),
destination=destination))
+ elif action == 'rower assign':
+ assignchoices = AssignChoices(request.POST)
+ if assignchoices.is_valid():
+ remove_workout = assignchoices.cleaned_data['remove_workout']
+ rowers = assignchoices.cleaned_data['destination']
+ _ = myqueue(queuehigh, handle_assignworkouts, workouts, rowers, remove_workout)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
else: # pragma: no cover
@@ -2041,6 +2047,12 @@ def workouts_bulk_actions(request):
exportchoice = ExportChoices()
actionform = WorkoutBulkActions()
actionform.fields["action"].initial = action
+ assignchoices = AssignChoices()
+ teams = Team.objects.filter(manager=request.user)
+ assignchoices.fields["destination"].queryset = Rower.objects.filter(
+ team__in=teams
+ ).distinct().order_by("user__last_name", "user__first_name").exclude(rowerplan='freecoach')
+ assignchoices.fields["destination"].initial = []
form = WorkoutMultipleCompareForm()
form.fields["workouts"].queryset = Workout.objects.filter(id__in=[w.id for w in workouts])
form.fields["workouts"].initial = workouts
@@ -2049,6 +2061,7 @@ def workouts_bulk_actions(request):
{'action':action,
'exportchoice':exportchoice,
'actionform':actionform,
+ 'assignchoices': assignchoices,
'form':form,
'workouts':workouts})