diff --git a/jdav_web/finance/locale/de/LC_MESSAGES/django.po b/jdav_web/finance/locale/de/LC_MESSAGES/django.po index 9f6d9e3..d1fb9d9 100644 --- a/jdav_web/finance/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/finance/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-01-19 14:26+0100\n" +"POT-Creation-Date: 2025-01-25 11:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -32,6 +32,10 @@ msgstr "" "Rechnung %(name)s erfolgreich eingereicht. Das Finanzreferat wird auf dich " "sobald wie möglich zukommen." +#: finance/admin.py +msgid "Finance overview" +msgstr "Kostenübersicht" + #: finance/admin.py msgid "Submit statement" msgstr "Rechnung einreichen" @@ -182,13 +186,10 @@ msgid "Pay allowance to" msgstr "Aufwandsentschädigung auszahlen an" #: finance/models.py -msgid "" -"The youth leaders to which an allowance should be paid. The count must match " -"the number of permitted youth leaders." +msgid "The youth leaders to which an allowance should be paid." msgstr "" "Die Jugendleiter*innen an die eine Aufwandsentschädigung ausgezahlt werden " -"soll. Die Anzahl muss mit der Anzahl an zugelassenen Jugendleiter*innen " -"übereinstimmen. " +"soll." #: finance/models.py msgid "Pay subsidy to" @@ -412,8 +413,8 @@ msgstr "Ausfahrt" #, python-format msgid "This excursion featured %(staff_count)s youth leader(s), each costing" msgstr "" -"Diese Ausfahrt hatte %(staff_count)s genehmigte Jugendleiter*innen. Auf " -"jede*n entfallen die folgenden Kosten:" +"Diese Ausfahrt hatte %(staff_count)s genehmigte Jugendleiter*innen. Für " +"jede*n besteht ein Anspruch auf folgende Zuschüsse und Aufwandsentschädigungen:" #: finance/templates/admin/overview_submitted_statement.html #, python-format @@ -427,29 +428,33 @@ msgstr "" #: finance/templates/admin/overview_submitted_statement.html #, python-format msgid "" -"%(duration)s days for %(allowance_per_day)s€ per day making a total of " -"%(allowance_per_yl)s€." +"%(kilometers_traveled)s km by %(means_of_transport)s (%(euro_per_km)s € / " +"km) making a total of %(transportation_per_yl)s€." msgstr "" -"%(duration)s Tage für %(allowance_per_day)s€ pro Tag. Das ergibt eine " -"Gesamtsumme von %(allowance_per_yl)s€." +"%(kilometers_traveled)s km mit %(means_of_transport)s (%(euro_per_km)s€ / " +"km). Das ergibt eine Gesamtsumme von %(transportation_per_yl)s€." #: finance/templates/admin/overview_submitted_statement.html #, python-format msgid "" -"%(kilometers_traveled)s km by %(means_of_transport)s (%(euro_per_km)s € / " -"km) making a total of %(transportation_per_yl)s€." +"%(duration)s days for %(allowance_per_day)s€ per day making a total of " +"%(allowance_per_yl)s€." msgstr "" -"%(kilometers_traveled)s km mit %(means_of_transport)s (%(euro_per_km)s€ / " -"km). Das ergibt eine Gesamtsumme von %(transportation_per_yl)s€." +"%(duration)s Tage für %(allowance_per_day)s€ pro Tag. Das ergibt eine " +"Gesamtsumme von %(allowance_per_yl)s€." #: finance/templates/admin/overview_submitted_statement.html #, python-format msgid "" "In total this is %(total_per_yl)s€ times %(staff_count)s, giving " -"%(total_staff)s€." +"%(theoretical_total_staff)s€." msgstr "" "Insgesamt sind das Kosten von %(total_per_yl)s€ mal %(staff_count)s, " -"insgesamt also %(total_staff)s€." +"insgesamt also maximal %(theoretical_total_staff)s€." + +#: finance/templates/admin/overview_submitted_statement.html +msgid "Payment of subsidies and allowances" +msgstr "Auszahlung von Sektionszuschüssen und Aufwandsentschädigungen" #: finance/templates/admin/overview_submitted_statement.html #, python-format @@ -458,6 +463,27 @@ msgstr "" "Die Aufwandsentschädigung von %(allowance_per_yl)s€ pro Person soll " "ausgezahlt werden an:" +#: finance/templates/admin/overview_submitted_statement.html +#: finance/templates/admin/submit_statement.html +msgid "IBAN valid" +msgstr "IBAN gültig" + +#: finance/templates/admin/overview_submitted_statement.html +#, python-format +msgid "" +"Only %(allowances_paid)s of the %(real_staff_count)s youth leaders have " +"requested the outpayment of their allowance." +msgstr "" +"Achtung: Nur für %(allowances_paid)s der %(real_staff_count)s " +"Jugendleiter*innen wird die Aufwandsentschädigung abgerufen." + +#: finance/templates/admin/overview_submitted_statement.html +msgid "" +"No receivers of the allowance were provided. Allowance will not be used." +msgstr "" +"Keine Empfänger*innen für eine Aufwandsentschädigung angegeben. Es wird " +"daher keine Aufwandsentschädigung ausbezahlt." + #: finance/templates/admin/overview_submitted_statement.html #, python-format msgid "" @@ -465,7 +491,14 @@ msgid "" "should be paid to:" msgstr "" "Die Zuschüsse für Übernachtungs- und Fahrtkosten von %(total_subsidies)s€ " -"sollen ausgezahlt werden an:" +"für alle Jugendleiter*innen sollen ausgezahlt werden an:" + +#: finance/templates/admin/overview_submitted_statement.html +msgid "" +"No receivers of the subsidies were provided. Subsidies will not be used." +msgstr "" +"Keine Empfänger*innen für Sektionszuschüsse angegeben. Es werden daher keine " +"Sektionszuschüsse ausbezahlt." #: finance/templates/admin/overview_submitted_statement.html #, python-format @@ -542,10 +575,6 @@ msgstr "" "Bitte überprüfe, ob alle Ausgaben korrekt erfasst sind und ob alle " "auslegenden Personen eine gültige IBAN haben." -#: finance/templates/admin/submit_statement.html -msgid "IBAN valid" -msgstr "IBAN gültig" - #: finance/templates/admin/submit_statement.html msgid "" "Do you want to submit the statement for further processing by the finance " diff --git a/jdav_web/finance/migrations/0008_alter_statement_allowance_to_and_more.py b/jdav_web/finance/migrations/0008_alter_statement_allowance_to_and_more.py new file mode 100644 index 0000000..faf7504 --- /dev/null +++ b/jdav_web/finance/migrations/0008_alter_statement_allowance_to_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 4.0.1 on 2025-01-23 22:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0033_freizeit_approved_extra_youth_leader_count'), + ('finance', '0007_alter_statement_allowance_to'), + ] + + operations = [ + migrations.AlterField( + model_name='statement', + name='allowance_to', + field=models.ManyToManyField(blank=True, help_text='The youth leaders to which an allowance should be paid.', related_name='receives_allowance_for_statements', to='members.Member', verbose_name='Pay allowance to'), + ), + migrations.AlterField( + model_name='statement', + name='subsidy_to', + field=models.ForeignKey(blank=True, help_text='The person that should receive the subsidy for night and travel costs. Typically the person who paid for them.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='receives_subsidy_for_statements', to='members.member', verbose_name='Pay subsidy to'), + ), + ] diff --git a/jdav_web/finance/models.py b/jdav_web/finance/models.py index 8be4291..5fb1aa9 100644 --- a/jdav_web/finance/models.py +++ b/jdav_web/finance/models.py @@ -62,9 +62,10 @@ class Statement(CommonModel): allowance_to = models.ManyToManyField(Member, verbose_name=_('Pay allowance to'), related_name='receives_allowance_for_statements', blank=True, - help_text=_('The youth leaders to which an allowance should be paid. The count must match the number of permitted youth leaders.')) + help_text=_('The youth leaders to which an allowance should be paid.')) subsidy_to = models.ForeignKey(Member, verbose_name=_('Pay subsidy to'), null=True, + blank=True, on_delete=models.SET_NULL, related_name='receives_subsidy_for_statements', help_text=_('The person that should receive the subsidy for night and travel costs. Typically the person who paid for them.')) @@ -163,7 +164,8 @@ class Statement(CommonModel): @property def allowance_to_valid(self): """Checks if the configured `allowance_to` field matches the regulations.""" - if self.allowance_to.count() != self.real_staff_count: + if self.allowances_paid > self.real_staff_count: + # it is allowed that less allowances are utilized than youth leaders are enlisted return False if self.excursion is not None: yls = self.excursion.jugendleiter.all() @@ -239,8 +241,7 @@ class Statement(CommonModel): if self.subsidy_to: ref = _("Night and travel costs for %(excu)s") % {'excu': self.excursion.name} Transaction(statement=self, member=self.subsidy_to, amount=self.total_subsidies, confirmed=False, reference=ref).save() - else: - return False + return True def reduce_transactions(self): @@ -299,9 +300,13 @@ class Statement(CommonModel): return cvt_to_decimal(self.excursion.duration * settings.ALLOWANCE_PER_DAY) + @property + def allowances_paid(self): + return self.allowance_to.count() + @property def total_allowance(self): - return self.allowance_per_yl * self.real_staff_count + return self.allowance_per_yl * self.allowances_paid @property def total_transportation(self): @@ -341,11 +346,24 @@ class Statement(CommonModel): The total amount of subsidies excluding the allowance, i.e. the transportation and night costs per youth leader multiplied with the real number of youth leaders. """ - return (self.transportation_per_yl + self.nights_per_yl) * self.real_staff_count + if self.subsidy_to: + return (self.transportation_per_yl + self.nights_per_yl) * self.real_staff_count + else: + return cvt_to_decimal(0) + + @property + def theoretical_total_staff(self): + """ + the sum of subsidies and allowances if all eligible youth leaders would collect them. + """ + return self.total_per_yl * self.real_staff_count @property def total_staff(self): - return self.total_per_yl * self.real_staff_count + """ + the sum of subsidies and allowances that youth leaders are actually collecting + """ + return self.total_allowance + self.total_subsidies @property def real_staff_count(self): @@ -397,11 +415,14 @@ class Statement(CommonModel): 'means_of_transport': self.excursion.get_tour_approach(), 'euro_per_km': self.euro_per_km, 'allowance_per_day': settings.ALLOWANCE_PER_DAY, + 'allowances_paid': self.allowances_paid, 'nights_per_yl': self.nights_per_yl, 'allowance_per_yl': self.allowance_per_yl, 'transportation_per_yl': self.transportation_per_yl, 'total_per_yl': self.total_per_yl, 'total_staff': self.total_staff, + 'theoretical_total_staff': self.theoretical_total_staff, + 'real_staff_count': self.real_staff_count, 'total_subsidies': self.total_subsidies, } return dict(context, **excursion_context) diff --git a/jdav_web/finance/templates/admin/overview_submitted_statement.html b/jdav_web/finance/templates/admin/overview_submitted_statement.html index 0546b81..e6196de 100644 --- a/jdav_web/finance/templates/admin/overview_submitted_statement.html +++ b/jdav_web/finance/templates/admin/overview_submitted_statement.html @@ -71,27 +71,47 @@

-{% blocktrans %}In total this is {{ total_per_yl }}€ times {{ staff_count }}, giving {{ total_staff }}€.{% endblocktrans %} +{% blocktrans %}In total this is {{ total_per_yl }}€ times {{ staff_count }}, giving {{ theoretical_total_staff }}€.{% endblocktrans %}

- +

{% trans "Payment of subsidies and allowances" %}

+{% if allowances_paid > 0 %}

{% blocktrans %}The allowance of {{ allowance_per_yl }}€ per person should be paid to:{% endblocktrans %} -

+{% if allowances_paid > 0 %} {% blocktrans %}The allowance of {{ allowance_per_yl }}€ per person is configured to be paid to:{% endblocktrans %}
@@ -99,6 +100,14 @@ cost plan! {% endfor %}

+{% if memberlist.statement.allowances_paid < memberlist.statement.real_staff_count %} +

{% blocktrans %}Only {{ allowances_paid }} of the {{ real_staff_count }} youth leaders have requested the outpayment of their allowance.{% endblocktrans %}

+{% endif %} + +{% else %} +

{% blocktrans %}No receivers of the allowance were provided. Allowance will not be used.{% endblocktrans %}

+{% endif %} +{% if memberlist.statement.subsidy_to %}

{% blocktrans %}The subsidies for night and transportation costs of {{ total_subsidies }}€ is configured to be paid to:{% endblocktrans %} @@ -111,6 +120,10 @@ cost plan!

+{% else %} +

{% blocktrans %}No receivers of the subsidies were provided. Subsidies will not be used.{% endblocktrans %}

+ +{% endif %} {% if not memberlist.statement.allowance_to_valid %}

{% blocktrans %}Warning: The configured recipients of the allowance don't match the regulations. This might be because the number of recipients is bigger then the number of admissable youth leaders for this excursion.{% endblocktrans %}