From 92d577f1aa39d7ab645d67da63e7bd00b44f9e8c Mon Sep 17 00:00:00 2001 From: mariusrklein <47218379+mariusrklein@users.noreply.github.com> Date: Fri, 11 Apr 2025 18:05:13 +0200 Subject: [PATCH 1/4] fix(members/excursion): fix seminar day calculation and add verbosity in finance overview --- .../members/locale/de/LC_MESSAGES/django.po | 14 +++++++- jdav_web/members/models.py | 35 ++++++++++++++----- .../admin/freizeit_finance_overview.html | 20 +++++++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/jdav_web/members/locale/de/LC_MESSAGES/django.po b/jdav_web/members/locale/de/LC_MESSAGES/django.po index 108b36f..5ec8724 100644 --- a/jdav_web/members/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/members/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-11 00:56+0200\n" +"POT-Creation-Date: 2025-04-11 18:02+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1411,6 +1411,18 @@ msgstr "" "Um den zu erhalten, musst du den LJP-Antrag innerhalb von 3 Wochen nach der " "Ausfahrt beim Jugendreferat einreichen und formal genehmigt bekommen." +#: members/templates/admin/freizeit_finance_overview.html +msgid "Seminar hours" +msgstr "Seminar-Stunden" + +#: members/templates/admin/freizeit_finance_overview.html +msgid "Seminar days" +msgstr "Seminar-Tage" + +#: members/templates/admin/freizeit_finance_overview.html +msgid "Sum" +msgstr "Summe" + #: members/templates/admin/freizeit_finance_overview.html msgid "The LJP contributions are configured to be paid to:" msgstr "Die LJP-Zuschüsse werden ausgezahlt an:" diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index aedcf49..a8b7bfb 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -8,7 +8,7 @@ import csv from django.db import models from django.db.models import TextField, ManyToManyField, ForeignKey, Count,\ Sum, Case, Q, F, When, Value, IntegerField, Subquery, OuterRef -from django.db.models.functions import TruncDate +from django.db.models.functions import Cast from django.utils.translation import gettext_lazy as _ from django.utils import timezone from django.utils.html import format_html @@ -1293,20 +1293,37 @@ class Freizeit(CommonModel): """calculate seminar days based on intervention hours in every day""" # TODO: add tests for this if hasattr(self, 'ljpproposal'): - hours_per_day = ( - self.ljpproposal.intervention_set - .annotate(day=TruncDate('date_start')) # Extract the date (without time) - .values('day') # Group by day - .annotate(total_duration=Sum('duration')) # Sum durations for each day - .order_by('day') # Sort results by date - ) + hours_per_day = self.seminar_time_per_day # Calculate the total number of seminar days # Each day is counted as 1 if total_duration is >= 5 hours, as 0.5 if total_duration is >= 2.5 # otherwise 0 - return sum([min(math.floor(h['total_duration']/cvt_to_decimal(2.5))/2, 1) for h in hours_per_day]) + sum_days = sum([h['sum_days'] for h in hours_per_day]) + print(hours_per_day) + print(sum_days) + return sum_days else: return 0 + + @property + def seminar_time_per_day(self): + if hasattr(self, 'ljpproposal'): + return ( + self.ljpproposal.intervention_set + .annotate(day=Cast('date_start', output_field=models.DateField())) # Force it to date + .values('day') # Group by day + .annotate(total_duration=Sum('duration'))# Sum durations for each day + .annotate( + sum_days=Case( + When(total_duration__gt=5.0, then=Value(1.0)), + When(total_duration__gt=2.5, then=Value(0.5)), + default=Value(0.0),) + ) + .order_by('day') # Sort results by date + ) + else: + return [] + @property def ljp_duration(self): """calculate the duration in days for the LJP""" diff --git a/jdav_web/members/templates/admin/freizeit_finance_overview.html b/jdav_web/members/templates/admin/freizeit_finance_overview.html index aecc588..875b743 100644 --- a/jdav_web/members/templates/admin/freizeit_finance_overview.html +++ b/jdav_web/members/templates/admin/freizeit_finance_overview.html @@ -141,6 +141,26 @@ This results in a total contribution of {{ ljp_contributions }}€. To receive them, you need to submit the LJP-Proposal within 3 weeks after your excursion and have it approved by the finance office.{% endblocktrans %}

+ + + + + + +{% for day in memberlist.seminar_time_per_day %} + + + + + + {% endfor %} + + + + + +
{% trans "Seminar hours" %}{% trans "Seminar days" %}
{{ day.day }}{{ day.total_duration }}{{ day.sum_days }}
{% trans "Sum" %}{{ total_seminar_days }}
+

{% blocktrans %}The LJP contributions are configured to be paid to:{% endblocktrans %} -- 2.38.4 From cc1fae2bdd175518b1a4557ecbb6ba6ae3db49e1 Mon Sep 17 00:00:00 2001 From: mariusrklein <47218379+mariusrklein@users.noreply.github.com> Date: Fri, 11 Apr 2025 18:08:40 +0200 Subject: [PATCH 2/4] remove print statements --- jdav_web/members/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index a8b7bfb..cffe0fd 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -1298,8 +1298,7 @@ class Freizeit(CommonModel): # Each day is counted as 1 if total_duration is >= 5 hours, as 0.5 if total_duration is >= 2.5 # otherwise 0 sum_days = sum([h['sum_days'] for h in hours_per_day]) - print(hours_per_day) - print(sum_days) + return sum_days else: return 0 -- 2.38.4 From 95b900db1ec7139f2d0a3c0eb42f84a5fc95af9f Mon Sep 17 00:00:00 2001 From: mariusrklein <47218379+mariusrklein@users.noreply.github.com> Date: Tue, 15 Apr 2025 22:39:55 +0200 Subject: [PATCH 3/4] fix: Auszahlung LJP bei zu wenigen TN verhindern und warnen --- jdav_web/finance/models.py | 5 +++ .../members/locale/de/LC_MESSAGES/django.po | 31 +++++++++++-------- .../admin/freizeit_finance_overview.html | 8 ++++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/jdav_web/finance/models.py b/jdav_web/finance/models.py index 5765aef..92a4c08 100644 --- a/jdav_web/finance/models.py +++ b/jdav_web/finance/models.py @@ -412,6 +412,10 @@ class Statement(CommonModel): @property def paid_ljp_contributions(self): if hasattr(self.excursion, 'ljpproposal') and self.ljp_to: + + if self.excursion.theoretic_ljp_participant_count < 5: + return 0 + return cvt_to_decimal( min( (1-settings.LJP_TAX) * settings.LJP_CONTRIBUTION_PER_DAY * self.excursion.ljp_participant_count * self.excursion.ljp_duration, @@ -472,6 +476,7 @@ class Statement(CommonModel): 'allowance_to': self.allowance_to, 'paid_ljp_contributions': self.paid_ljp_contributions, 'ljp_to': self.ljp_to, + 'theoretic_ljp_participant_count': self.excursion.theoretic_ljp_participant_count, 'participant_count': self.excursion.participant_count, 'total_seminar_days': self.excursion.total_seminar_days, 'ljp_tax': settings.LJP_TAX * 100, diff --git a/jdav_web/members/locale/de/LC_MESSAGES/django.po b/jdav_web/members/locale/de/LC_MESSAGES/django.po index 5ec8724..4d6f6dd 100644 --- a/jdav_web/members/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/members/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-11 18:02+0200\n" +"POT-Creation-Date: 2025-04-15 22:36+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1432,20 +1432,31 @@ msgstr "Die LJP-Zuschüsse werden ausgezahlt an:" msgid "" "By submitting a seminar report, you may apply for LJP contributions. In this " "case,\n" -"you may obtain up to 25€ times %(duration)s days for %(participant_count)s " -"participants but only up to\n" +"you may obtain up to 25€ times %(duration)s days for " +"%(theoretic_ljp_participant_count)s participants but only up to\n" "90%% of the total costs. This results in a total of %(ljp_contributions)s€. " "If you have created a seminar report, you need to specify who should receive " "the contributions in order to make use of them." msgstr "" "Indem du einen Seminarbericht anfertigst, kannst du Landesjugendplan (LJP) " "Zuschüsse beantragen. In diesem Fall kannst du bis zu 25€ mal %(duration)s " -"Tage für %(participant_count)s Teilnehmende, aber nicht mehr als 90%% der " +"Tage für %(theoretic_ljp_participant_count)s Teilnehmende, aber nicht mehr als 90%% der " "Gesamtausgaben erhalten. Das resultiert in einem Gesamtzuschuss von " "%(ljp_contributions)s€. Wenn du schon einen Seminarbericht erstellt hast, " "musst du im Tab 'Abrechnungen' noch angeben, an wen die LJP-Zuschüsse " "ausgezahlt werden sollen." +#: members/templates/admin/freizeit_finance_overview.html +#, python-format +msgid "" +" Warning: LJP contributions can only be claimed for activities with at least " +"5 participants and one leader. This activity currently has only " +"%(theoretic_ljp_participant_count)s participants." +msgstr "" +"Achtung: Nur für Aktivitäten mit mindestens 5 Teilnehmenden und einer " +"Leitungsperson kann ein LJP-Antrag gestellt werden. Diese Ausfahrt hat " +"aktuell nur %(theoretic_ljp_participant_count)s Teilnehmende." + #: members/templates/admin/freizeit_finance_overview.html msgid "Summary" msgstr "Zusammenfassung" @@ -1805,13 +1816,13 @@ msgstr "" msgid "Echo" msgstr "Rückmeldung" -#: members/templates/members/echo.html +#: members/templates/members/echo.html members/tests.py msgid "" "Here is your current data. Please check if it is up to date and change " "accordingly." msgstr "" -"Hier siehst du deine aktuellen Daten. Bitte überprüfe alles und passe es " -"bei Bedarf an." +"Hier siehst du deine aktuellen Daten. Bitte überprüfe alles und passe es bei " +"Bedarf an." #: members/templates/members/echo_failed.html members/tests.py msgid "Echo failed" @@ -2240,12 +2251,6 @@ msgstr "ungültig" msgid "expired" msgstr "abgelaufen" -#: members/tests.py -msgid "Thanks for echoing back. Here is your current data:" -msgstr "" -"Vielen Dank, dass du dich rückmeldest. Hier siehst du deine aktuellen Daten. " -"Falls sich etwas geändert hat, trage das bitte hier ein." - #: members/views.py msgid "Prename of the member." msgstr "Vorname des*der Teilnehmenden" diff --git a/jdav_web/members/templates/admin/freizeit_finance_overview.html b/jdav_web/members/templates/admin/freizeit_finance_overview.html index 875b743..31c98e6 100644 --- a/jdav_web/members/templates/admin/freizeit_finance_overview.html +++ b/jdav_web/members/templates/admin/freizeit_finance_overview.html @@ -177,12 +177,18 @@ To receive them, you need to submit the LJP-Proposal within 3 weeks after your e {% else %}

{% blocktrans %}By submitting a seminar report, you may apply for LJP contributions. In this case, -you may obtain up to 25€ times {{ duration }} days for {{ participant_count }} participants but only up to +you may obtain up to 25€ times {{ duration }} days for {{ theoretic_ljp_participant_count }} participants but only up to 90% of the total costs. This results in a total of {{ ljp_contributions }}€. If you have created a seminar report, you need to specify who should receive the contributions in order to make use of them.{% endblocktrans %}

{% endif %} +{% if memberlist.theoretic_ljp_participant_count < 5 %} +

+ {% blocktrans %} Warning: LJP contributions can only be claimed for activities with at least 5 participants and one leader. This activity currently has only {{ theoretic_ljp_participant_count }} participants.{% endblocktrans %} +

+{% endif %} +

{% trans "Summary" %}

-- 2.38.4 From 31eec46f71e43c73307eb68a925dac36e4ac4094 Mon Sep 17 00:00:00 2001 From: mariusrklein <47218379+mariusrklein@users.noreply.github.com> Date: Sun, 27 Apr 2025 13:42:52 +0200 Subject: [PATCH 4/4] fixed seminar day calculation again --- jdav_web/members/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index cffe0fd..16ec653 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -1314,8 +1314,8 @@ class Freizeit(CommonModel): .annotate(total_duration=Sum('duration'))# Sum durations for each day .annotate( sum_days=Case( - When(total_duration__gt=5.0, then=Value(1.0)), - When(total_duration__gt=2.5, then=Value(0.5)), + When(total_duration__gte=5.0, then=Value(1.0)), + When(total_duration__gte=2.5, then=Value(0.5)), default=Value(0.0),) ) .order_by('day') # Sort results by date -- 2.38.4