From ff689290c2e2f77ee115292bd1138296beed349d Mon Sep 17 00:00:00 2001 From: Berehum Date: Mon, 8 Jan 2024 21:10:54 +0100 Subject: [PATCH] Added new form type which has a period and keyword. Also changed the old activities field, so that it uses this form. It will look through the summary and decription for this keyword. --- amelie/activities/views.py | 92 +++++++++++++++++++++++++++----------- amelie/tools/forms.py | 25 +++++++++++ 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/amelie/activities/views.py b/amelie/activities/views.py index 3ae53b4..2c05179 100644 --- a/amelie/activities/views.py +++ b/amelie/activities/views.py @@ -52,7 +52,7 @@ from amelie.members.query_forms import MailingForm from amelie.tools import amelie_messages, types from amelie.tools.decorators import require_actief, require_lid, require_committee, require_board -from amelie.tools.forms import PeriodForm, ExportForm +from amelie.tools.forms import PeriodForm, ExportForm, PeriodKeywordForm from amelie.tools.calendar import ical_calendar from amelie.tools.mixins import RequireActiveMemberMixin, DeleteMessageMixin, PassesTestMixin, RequireBoardMixin, \ RequireCommitteeMixin @@ -126,7 +126,6 @@ def activities(request): new_activities = [a.as_leaf_class() for a in new_activities] only_open_enrollments = 'openEnrollments' in request.GET - return render(request, "activity_list.html", locals()) @@ -134,14 +133,16 @@ def activities_old(request): """ Gives an overview of past activities. - You can filter on a date. + You can filter on a date and on a few keywords. """ - form = PeriodForm(to_date_required=False, data=request.GET or None) + form = PeriodKeywordForm(to_date_required=False, keywords_required=False, data=request.GET or None) if form.is_valid(): + keywords = form.cleaned_data['keywords'] start_date = form.cleaned_data['from_date'] end_date = form.cleaned_data['to_date'] or timezone.now() else: + keywords = "" start_date = form.fields['from_date'].initial end_date = form.fields['to_date'].initial @@ -149,8 +150,17 @@ def activities_old(request): start_datetime = timezone.make_aware(datetime.datetime.combine(start_date, datetime.time())) end_datetime = timezone.make_aware(datetime.datetime.combine(end_date, datetime.time())) + # Filter for activities in tim range old_activities = Activity.objects.filter_public(request).filter(end__range=(start_datetime, end_datetime)) \ .order_by('-end') + + if 'keywords' in form.data.keys(): + # Filter for activities with keyword + old_activities = old_activities.filter(Q(summary_en__icontains=keywords) | + Q(description_en__icontains=keywords) | + Q(summary_nl__icontains=keywords) | + Q(description_nl__icontains=keywords)) + return render(request, "activity_old.html", { 'form': form, 'old_activities': old_activities, @@ -193,11 +203,16 @@ def activity(request, pk, deanonymise=False): for restaurant in restaurants: restaurant.dishes = DishPrice.objects \ .filter(enrollmentoptionfoodanswer__enrollmentoption__activity=activity, - dish__restaurant=restaurant, enrollmentoptionfoodanswer__enrollment__waiting_list=False)\ - .annotate(amount=Count('enrollmentoptionfoodanswer', filter=Q(enrollmentoptionfoodanswer__enrollment__waiting_list=False)), - total_price=Sum('price', filter=Q(enrollmentoptionfoodanswer__enrollment__waiting_list=False))) - total_price = sum([(restaurant.dishes.aggregate(Sum('total_price')).get('total_price__sum')) if restaurant.dishes.aggregate(Sum('total_price')).get('total_price__sum') is not None else 0 for restaurant in restaurants]) - total_amount = sum([restaurant.dishes.aggregate(Sum('amount')).get('amount__sum') for restaurant in restaurants]) + dish__restaurant=restaurant, enrollmentoptionfoodanswer__enrollment__waiting_list=False) \ + .annotate(amount=Count('enrollmentoptionfoodanswer', + filter=Q(enrollmentoptionfoodanswer__enrollment__waiting_list=False)), + total_price=Sum('price', + filter=Q(enrollmentoptionfoodanswer__enrollment__waiting_list=False))) + total_price = sum([(restaurant.dishes.aggregate(Sum('total_price')).get( + 'total_price__sum')) if restaurant.dishes.aggregate(Sum('total_price')).get( + 'total_price__sum') is not None else 0 for restaurant in restaurants]) + total_amount = sum( + [restaurant.dishes.aggregate(Sum('amount')).get('amount__sum') for restaurant in restaurants]) can_view_photos = activity.photos.filter_public(request).count() > 0 obj = activity # Template laziness @@ -206,11 +221,14 @@ def activity(request, pk, deanonymise=False): participation_set = activity.participation_set.order_by('added_on') if only_show_underage: - confirmed_participation_set = [x for x in activity.participation_set.filter(waiting_list=False).order_by('added_on') if x.person.age(at=activity.begin) < 18] - confirmed_participation_set_turns_18_during_event = [x for x in confirmed_participation_set if x.person.age(at=activity.end) >= 18] + confirmed_participation_set = [x for x in + activity.participation_set.filter(waiting_list=False).order_by('added_on') if + x.person.age(at=activity.begin) < 18] + confirmed_participation_set_turns_18_during_event = [x for x in confirmed_participation_set if + x.person.age(at=activity.end) >= 18] else: confirmed_participation_set = activity.participation_set.filter(waiting_list=False).order_by('added_on') - + waiting_participation_set = activity.participation_set.filter(waiting_list=True).order_by('added_on') if hasattr(request, 'person') and waiting_participation_set.filter(person=request.person).exists(): @@ -264,7 +282,8 @@ def activity_delete(request, pk): # Undo transactions and remove participations from amelie.personal_tab import transactions for participation in obj.participation_set.all(): - transactions.participation_transaction(participation, "Cancelled event", cancel=True, added_by=request.person) + transactions.participation_transaction(participation, "Cancelled event", cancel=True, + added_by=request.person) # Remove the participation participation.delete() @@ -299,7 +318,8 @@ def activity_enrollment(request, pk): if obj.enrollmentoption_set.count() == 0 and obj.price == 0: # Simple enrollment: no questions or costs participation = Participation(person=request.person, event=obj, - payment_method=Participation.PaymentMethodChoices.NONE, added_by=request.person, waiting_list=enrollment_full) + payment_method=Participation.PaymentMethodChoices.NONE, added_by=request.person, + waiting_list=enrollment_full) participation.save() # Send mail if preference asks for it @@ -358,6 +378,7 @@ def activity_unenrollment_self(request, pk): # Redirect back to the activity return redirect(obj) + def activity_editenrollment(request, participation, obj): # If necessary, compensate the enrollment costs. from amelie.personal_tab import transactions @@ -381,6 +402,7 @@ def activity_editenrollment(request, participation, obj): participation.delete() activity_enrollment_form(request, obj, person=None) + @require_lid @transaction.atomic def activity_editenrollment_self(request, pk): @@ -405,10 +427,12 @@ def activity_editenrollment_self(request, pk): return redirect(obj) else: enrollmentoptions_forms = _build_enrollmentoptionsanswers_forms(obj, - request.POST if request.POST else None, request.user) + request.POST if request.POST else None, + request.user) update = True return render(request, "activity_enrollment_form.html", locals()) + @require_board @transaction.atomic def activity_editenrollment_other(request, pk, person_id): @@ -432,10 +456,12 @@ def activity_editenrollment_other(request, pk, person_id): return redirect(obj) else: enrollmentoptions_forms = _build_enrollmentoptionsanswers_forms(obj, - request.POST if request.POST else None, person.user) + request.POST if request.POST else None, + person.user) update = True return render(request, "activity_enrollment_form.html", locals()) + @require_board @transaction.atomic def activity_unenrollment(request, pk, person_id): @@ -539,24 +565,30 @@ def _build_enrollmentoptionsanswers_forms(activity, data, user): try: if form_type == EnrollmentoptionCheckboxAnswerForm: participation = Participation.objects.get(person__user=user, event=activity) - unit = EnrollmentoptionCheckboxAnswer.objects.get(enrollmentoption=enrollmentoption, enrollment=participation) + unit = EnrollmentoptionCheckboxAnswer.objects.get(enrollmentoption=enrollmentoption, + enrollment=participation) checked = unit.answer elif form_type == EnrollmentoptionNumericAnswerForm: participation = Participation.objects.get(person__user=user, event=activity) - unit = EnrollmentoptionNumericAnswer.objects.get(enrollmentoption=enrollmentoption, enrollment=participation) + unit = EnrollmentoptionNumericAnswer.objects.get(enrollmentoption=enrollmentoption, + enrollment=participation) checked = unit.answer > 0 - except (EnrollmentoptionCheckboxAnswer.DoesNotExist, EnrollmentoptionNumericAnswer.DoesNotExist, Participation.DoesNotExist): + except (EnrollmentoptionCheckboxAnswer.DoesNotExist, EnrollmentoptionNumericAnswer.DoesNotExist, + Participation.DoesNotExist): pass # If no data is given for this form, fill it from the database if possible initial = None try: participation = Participation.objects.get(person__user=user, event=activity) - initial = {"answer": answer_type.objects.get(enrollmentoption=enrollmentoption, enrollment=participation).answer} + initial = { + "answer": answer_type.objects.get(enrollmentoption=enrollmentoption, enrollment=participation).answer} except (Participation.DoesNotExist, answer_type.DoesNotExist): pass - forms.append(form_type(enrollmentoption=enrollmentoption, checked=checked, data=data, prefix=prefix, instance=instance, initial=initial)) + forms.append( + form_type(enrollmentoption=enrollmentoption, checked=checked, data=data, prefix=prefix, instance=instance, + initial=initial)) return forms @@ -591,7 +623,8 @@ def activity_enrollment_form(request, activity, person=None): per_mandate = (request.is_board or settings.PERSONAL_TAB_COMMITTEE_CAN_AUTHORIZE) \ and person.has_mandate_activities() - enrollmentoptions_forms = _build_enrollmentoptionsanswers_forms(activity, request.POST if request.POST else None, person.user) + enrollmentoptions_forms = _build_enrollmentoptionsanswers_forms(activity, request.POST if request.POST else None, + person.user) if request.method == 'POST': if indirect: @@ -638,7 +671,8 @@ def activity_enrollment_form(request, activity, person=None): participation.save() # Make transactions if there is a mandate - if participation.payment_method == Participation.PaymentMethodChoices.AUTHORIZATION and (force_skip_waiting_list or not activity_full): + if participation.payment_method == Participation.PaymentMethodChoices.AUTHORIZATION and ( + force_skip_waiting_list or not activity_full): from amelie.personal_tab import transactions transactions.add_participation(participation, request.person) @@ -1116,7 +1150,8 @@ def get(self, request, *args, **kwargs): activity_ins = self.get_activity() if activity_ins.participants.exists(): - messages.error(request, _("This activity already has enrollments, therefore options can no longer be added!")) + messages.error(request, + _("This activity already has enrollments, therefore options can no longer be added!")) return HttpResponseRedirect(activity_ins.get_absolute_url()) else: return super(EnrollmentoptionCreateView, self).get(self, request, args, kwargs) @@ -1294,9 +1329,11 @@ def get_context_data(self, **kwargs): context['ia_event_email'] = settings.EVENT_DESK_NOTICES_DISPLAY_EMAIL - current_activities = Activity.objects.filter(begin__gte=now).prefetch_related('eventdeskregistrationmessage_set').order_by("begin") + current_activities = Activity.objects.filter(begin__gte=now).prefetch_related( + 'eventdeskregistrationmessage_set').order_by("begin") context['current_activities'] = [x for x in current_activities if x.can_edit(self.request.person)] - past_activities = Activity.objects.filter(begin__gte=one_week_ago, end__lte=now).prefetch_related('eventdeskregistrationmessage_set').order_by("-begin") + past_activities = Activity.objects.filter(begin__gte=one_week_ago, end__lte=now).prefetch_related( + 'eventdeskregistrationmessage_set').order_by("-begin") context['past_activities'] = [x for x in past_activities if x.can_edit(self.request.person)] unmatched_messages = EventDeskRegistrationMessage.objects.filter(activity__isnull=True)[:15] @@ -1337,7 +1374,8 @@ def get_context_data(self, **kwargs): scopes=settings.CLAUDIA_GSUITE['SCOPES']['GMAIL_API'] ) # Retrieve the message from Google - msg_details = gmail_api.users().messages().get(id=self.object.message_id, userId='me', format='metadata').execute() + msg_details = gmail_api.users().messages().get(id=self.object.message_id, userId='me', + format='metadata').execute() msg_raw = gmail_api.users().messages().get(id=self.object.message_id, userId='me', format='raw').execute() # Get the message from diff --git a/amelie/tools/forms.py b/amelie/tools/forms.py index bb4364b..cd3f51a 100644 --- a/amelie/tools/forms.py +++ b/amelie/tools/forms.py @@ -49,6 +49,31 @@ def __init__(self, *args, **kwargs): inject_style(PeriodForm) +class PeriodKeywordForm(forms.Form): + keywords = forms.CharField(max_length=20, label=_('Keywords')) + from_date = forms.DateField(label='Begin date:', initial=timezone.now().date() - timedelta(days=365)) + to_date = forms.DateField(label='End date:', initial=timezone.now().date()) + + def __init__(self, *args, **kwargs): + if 'to_date_required' in kwargs: + to_date_required = kwargs['to_date_required'] + del kwargs['to_date_required'] + else: + to_date_required = True + + if 'keywords_required' in kwargs: + keywords_required = kwargs['keywords_required'] + del kwargs['keywords_required'] + else: + keywords_required = True + + super(PeriodKeywordForm, self).__init__(*args, **kwargs) + + self.fields["to_date"].required = to_date_required + self.fields["keywords"].required = keywords_required + + +inject_style(PeriodKeywordForm) class PeriodTimeForm(forms.Form): datetime_from = forms.SplitDateTimeField(label='Begin:', initial=timezone.now() - timedelta(days=365), widget=DateTimeSelector)