fix(members/excursion): fix seminar day calculation and add verbosity in finance overview (#153)

Reviewed-on: #153
Reviewed-by: Christian Merten <christian@merten.dev>
Co-authored-by: marius.klein <marius.klein@alpenverein-heidelberg.de>
Co-committed-by: marius.klein <marius.klein@alpenverein-heidelberg.de>
pull/149/head
marius.klein 8 months ago committed by Christian Merten
parent fd4770d295
commit 05f924cdef

@ -412,6 +412,10 @@ class Statement(CommonModel):
@property @property
def paid_ljp_contributions(self): def paid_ljp_contributions(self):
if hasattr(self.excursion, 'ljpproposal') and self.ljp_to: if hasattr(self.excursion, 'ljpproposal') and self.ljp_to:
if self.excursion.theoretic_ljp_participant_count < 5:
return 0
return cvt_to_decimal( return cvt_to_decimal(
min( min(
(1-settings.LJP_TAX) * settings.LJP_CONTRIBUTION_PER_DAY * self.excursion.ljp_participant_count * self.excursion.ljp_duration, (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, 'allowance_to': self.allowance_to,
'paid_ljp_contributions': self.paid_ljp_contributions, 'paid_ljp_contributions': self.paid_ljp_contributions,
'ljp_to': self.ljp_to, 'ljp_to': self.ljp_to,
'theoretic_ljp_participant_count': self.excursion.theoretic_ljp_participant_count,
'participant_count': self.excursion.participant_count, 'participant_count': self.excursion.participant_count,
'total_seminar_days': self.excursion.total_seminar_days, 'total_seminar_days': self.excursion.total_seminar_days,
'ljp_tax': settings.LJP_TAX * 100, 'ljp_tax': settings.LJP_TAX * 100,

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-11 00:56+0200\n" "POT-Creation-Date: 2025-04-15 22:36+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -1411,6 +1411,18 @@ msgstr ""
"Um den zu erhalten, musst du den LJP-Antrag innerhalb von 3 Wochen nach der " "Um den zu erhalten, musst du den LJP-Antrag innerhalb von 3 Wochen nach der "
"Ausfahrt beim Jugendreferat einreichen und formal genehmigt bekommen." "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 #: members/templates/admin/freizeit_finance_overview.html
msgid "The LJP contributions are configured to be paid to:" msgid "The LJP contributions are configured to be paid to:"
msgstr "Die LJP-Zuschüsse werden ausgezahlt an:" msgstr "Die LJP-Zuschüsse werden ausgezahlt an:"
@ -1420,20 +1432,31 @@ msgstr "Die LJP-Zuschüsse werden ausgezahlt an:"
msgid "" msgid ""
"By submitting a seminar report, you may apply for LJP contributions. In this " "By submitting a seminar report, you may apply for LJP contributions. In this "
"case,\n" "case,\n"
"you may obtain up to 25€ times %(duration)s days for %(participant_count)s " "you may obtain up to 25€ times %(duration)s days for "
"participants but only up to\n" "%(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€. " "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 " "If you have created a seminar report, you need to specify who should receive "
"the contributions in order to make use of them." "the contributions in order to make use of them."
msgstr "" msgstr ""
"Indem du einen Seminarbericht anfertigst, kannst du Landesjugendplan (LJP) " "Indem du einen Seminarbericht anfertigst, kannst du Landesjugendplan (LJP) "
"Zuschüsse beantragen. In diesem Fall kannst du bis zu 25€ mal %(duration)s " "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 " "Gesamtausgaben erhalten. Das resultiert in einem Gesamtzuschuss von "
"%(ljp_contributions)s€. Wenn du schon einen Seminarbericht erstellt hast, " "%(ljp_contributions)s€. Wenn du schon einen Seminarbericht erstellt hast, "
"musst du im Tab 'Abrechnungen' noch angeben, an wen die LJP-Zuschüsse " "musst du im Tab 'Abrechnungen' noch angeben, an wen die LJP-Zuschüsse "
"ausgezahlt werden sollen." "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 #: members/templates/admin/freizeit_finance_overview.html
msgid "Summary" msgid "Summary"
msgstr "Zusammenfassung" msgstr "Zusammenfassung"
@ -1793,13 +1816,13 @@ msgstr ""
msgid "Echo" msgid "Echo"
msgstr "Rückmeldung" msgstr "Rückmeldung"
#: members/templates/members/echo.html #: members/templates/members/echo.html members/tests.py
msgid "" msgid ""
"Here is your current data. Please check if it is up to date and change " "Here is your current data. Please check if it is up to date and change "
"accordingly." "accordingly."
msgstr "" msgstr ""
"Hier siehst du deine aktuellen Daten. Bitte überprüfe alles und passe es " "Hier siehst du deine aktuellen Daten. Bitte überprüfe alles und passe es bei "
"bei Bedarf an." "Bedarf an."
#: members/templates/members/echo_failed.html members/tests.py #: members/templates/members/echo_failed.html members/tests.py
msgid "Echo failed" msgid "Echo failed"
@ -2228,12 +2251,6 @@ msgstr "ungültig"
msgid "expired" msgid "expired"
msgstr "abgelaufen" 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 #: members/views.py
msgid "Prename of the member." msgid "Prename of the member."
msgstr "Vorname des*der Teilnehmenden" msgstr "Vorname des*der Teilnehmenden"

@ -8,7 +8,7 @@ import csv
from django.db import models from django.db import models
from django.db.models import TextField, ManyToManyField, ForeignKey, Count,\ from django.db.models import TextField, ManyToManyField, ForeignKey, Count,\
Sum, Case, Q, F, When, Value, IntegerField, Subquery, OuterRef 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.translation import gettext_lazy as _
from django.utils import timezone from django.utils import timezone
from django.utils.html import format_html from django.utils.html import format_html
@ -1293,20 +1293,36 @@ class Freizeit(CommonModel):
"""calculate seminar days based on intervention hours in every day""" """calculate seminar days based on intervention hours in every day"""
# TODO: add tests for this # TODO: add tests for this
if hasattr(self, 'ljpproposal'): if hasattr(self, 'ljpproposal'):
hours_per_day = ( hours_per_day = self.seminar_time_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
)
# Calculate the total number of seminar days # 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 # Each day is counted as 1 if total_duration is >= 5 hours, as 0.5 if total_duration is >= 2.5
# otherwise 0 # 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])
return sum_days
else: else:
return 0 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__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
)
else:
return []
@property @property
def ljp_duration(self): def ljp_duration(self):
"""calculate the duration in days for the LJP""" """calculate the duration in days for the LJP"""

@ -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 %} 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 %}
</p> </p>
<table>
<tr>
<td></td>
<td>{% trans "Seminar hours" %}</td>
<td>{% trans "Seminar days" %}</td>
</tr>
{% for day in memberlist.seminar_time_per_day %}
<tr>
<td>{{ day.day }}</td>
<td>{{ day.total_duration }}</td>
<td>{{ day.sum_days }}</td>
</tr>
{% endfor %}
<tr>
<td><b>{% trans "Sum" %}</b></td>
<td></td>
<td>{{ total_seminar_days }}</td>
</tr>
</table>
<p> <p>
{% blocktrans %}The LJP contributions are configured to be paid to:{% endblocktrans %} {% blocktrans %}The LJP contributions are configured to be paid to:{% endblocktrans %}
<table> <table>
@ -157,12 +177,18 @@ To receive them, you need to submit the LJP-Proposal within 3 weeks after your e
{% else %} {% else %}
<p> <p>
{% blocktrans %}By submitting a seminar report, you may apply for LJP contributions. In this case, {% 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 %} 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 %}
</p> </p>
{% endif %} {% endif %}
{% if memberlist.theoretic_ljp_participant_count < 5 %}
<p>
{% 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 %}
</p>
{% endif %}
<h3>{% trans "Summary" %}</h3> <h3>{% trans "Summary" %}</h3>
<p> <p>

Loading…
Cancel
Save