diff --git a/compensation/admin.py b/compensation/admin.py index 1c15be75..656b5240 100644 --- a/compensation/admin.py +++ b/compensation/admin.py @@ -41,7 +41,9 @@ class PaymentAdmin(admin.ModelAdmin): list_display = [ "id", "amount", - "due_on" + "due_on", + "created_by", + "created_on", ] diff --git a/compensation/forms.py b/compensation/forms.py index 30b03046..9c435644 100644 --- a/compensation/forms.py +++ b/compensation/forms.py @@ -20,15 +20,18 @@ class NewCompensationForm(BaseForm): class NewPaymentForm(BaseModalForm): - amount = forms.FloatField( - min_value=0.01, + amount = forms.DecimalField( + min_value=0.00, + decimal_places=2, label=_("Amount"), label_suffix=_(""), + help_text=_("Amount in Euro"), + localize=True, ) due = forms.DateField( - required=False, label=_("Due on"), label_suffix=_(""), + help_text=_("Due on which date"), widget=forms.DateInput( attrs={ "type": "date", @@ -41,14 +44,13 @@ class NewPaymentForm(BaseModalForm): max_length=1000, required=False, label_suffix=_(""), - label=_("Transfer note") + label=_("Transfer note"), + help_text=_("Note for money transfer") ) def __init__(self, *args, **kwargs): - self.user = kwargs.pop("request", None).user - self.intervention = kwargs.pop("intervention", None) super().__init__(*args, **kwargs) - + self.intervention = self.instance self.form_title = _("Payment") self.form_caption = _("Add a payment for intervention '{}'").format(self.intervention.title) diff --git a/compensation/urls.py b/compensation/urls.py index c22f0322..c51d026f 100644 --- a/compensation/urls.py +++ b/compensation/urls.py @@ -22,7 +22,7 @@ urlpatterns = [ path('pay//new', new_payment_view, name='pay-new'), path('pay/', open_view, name='pay-open'), path('pay//edit', edit_view, name='pay-edit'), - path('pay//remove', remove_view, name='pay-remove'), + path('pay//remove', payment_remove_view, name='pay-remove'), # Eco-account path("acc/", account_index_view, name="acc-index"), diff --git a/compensation/views.py b/compensation/views.py index 482ab537..507aa2e0 100644 --- a/compensation/views.py +++ b/compensation/views.py @@ -4,11 +4,12 @@ from django.shortcuts import render, get_object_or_404 from django.utils.translation import gettext_lazy as _ from compensation.forms import NewPaymentForm -from compensation.models import Compensation, EcoAccount +from compensation.models import Compensation, EcoAccount, Payment from compensation.tables import CompensationTable, EcoAccountTable from intervention.models import Intervention from konova.contexts import BaseContext from konova.decorators import * +from konova.forms import RemoveModalForm @login_required @@ -126,7 +127,7 @@ def new_payment_view(request: HttpRequest, intervention_id: str): """ template = "modal/modal_form.html" intervention = get_object_or_404(Intervention, id=intervention_id) - form = NewPaymentForm(request.POST or None, intervention=intervention, request=request) + form = NewPaymentForm(request.POST or None, instance=intervention, user=request.user) if request.method == "POST": if form.is_valid(): payment = form.save() @@ -149,3 +150,41 @@ def new_payment_view(request: HttpRequest, intervention_id: str): return render(request, template, context) else: raise NotImplementedError + + +@login_required +def payment_remove_view(request: HttpRequest, id: str): + """ Renders a modal view for adding new payments + + Args: + request (HttpRequest): The incoming request + id (str): The payment's id + + Returns: + + """ + template = "modal/modal_form.html" + payment = get_object_or_404(Payment, id=id) + form = RemoveModalForm(request.POST or None, instance=payment, user=request.user) + if request.method == "POST": + if form.is_valid(): + form.save() + messages.success( + request, + _("Payment removed") + ) + return redirect(request.META.get("HTTP_REFERER", "home")) + else: + messages.info( + request, + _("There was an error on this form.") + ) + return redirect(request.META.get("HTTP_REFERER", "home")) + elif request.method == "GET": + context = { + "form": form, + } + context = BaseContext(request, context).context + return render(request, template, context) + else: + raise NotImplementedError diff --git a/intervention/templates/intervention/detail-view.html b/intervention/templates/intervention/detail-view.html index c3e1fb70..444a0f2d 100644 --- a/intervention/templates/intervention/detail-view.html +++ b/intervention/templates/intervention/detail-view.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n static fontawesome_5 %} +{% load i18n l10n static fontawesome_5 humanize %} {% block head %} @@ -129,7 +129,7 @@ {% trans 'Last modified' %} - {{intervention.created_on|default_if_none:""}} + {{intervention.created_on|default_if_none:""|naturalday}}
{% trans 'by' %} {{intervention.created_by|default_if_none:""}} @@ -171,7 +171,7 @@ -
+
@@ -219,16 +219,22 @@ -
+
+ + @@ -236,10 +242,16 @@ + + {% endfor %} @@ -271,7 +283,7 @@ -
+
{% trans 'Amount' %} + {% trans 'Due on' %} + {% trans 'Transfer comment' %} + {% trans 'Action' %} +
- {{ pay.amount }} + {{ pay.amount|floatformat:2 }} € {{ pay.due_on }} {{ pay.comment }} + +
diff --git a/konova/forms.py b/konova/forms.py index 0ee4187c..b1a9a294 100644 --- a/konova/forms.py +++ b/konova/forms.py @@ -29,6 +29,7 @@ class BaseForm(forms.Form): def __init__(self, *args, **kwargs): self.instance = kwargs.pop("instance", None) + self.user = kwargs.pop("user", None) super().__init__(*args, **kwargs) @abstractmethod @@ -137,6 +138,34 @@ class SimpleGeomForm(BaseForm): self.area = geom.area +class RemoveModalForm(BaseModalForm): + """ Generic removing modal form + + Can be used for anything, where removing shall be confirmed by the user a second time. + + """ + confirm = forms.BooleanField( + label=_("Confirm"), + label_suffix=_(""), + widget=forms.CheckboxInput(), + required=True, + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form_title = _("Remove") + self.form_caption = _("Are you sure?") + + def save(self): + if hasattr(self.instance, "deleted_on"): + self.instance.deleted_on = timezone.now() + self.instance.deleted_by = self.user + self.instance.save() + else: + # If the class does not provide restorable delete functionality, we must delete the entry finally + self.instance.delete() + + class RemoveDocumentForm(BaseModalForm): confirm = forms.BooleanField( label=_("Confirm"), diff --git a/konova/static/css/konova.css b/konova/static/css/konova.css index d4ca9d39..c3854362 100644 --- a/konova/static/css/konova.css +++ b/konova/static/css/konova.css @@ -194,4 +194,13 @@ input:focus, textarea:focus, select:focus{ .page-item.active > .page-link{ background-color: var(--rlp-red); border-color: var(--rlp-red); +} + +.label-required{ + color: var(--rlp-red); +} + +.scroll-300{ + max-height: 300px; + overflow: auto; } \ No newline at end of file diff --git a/konova/sub_settings/django_settings.py b/konova/sub_settings/django_settings.py index 0f54ef8c..ece5d073 100644 --- a/konova/sub_settings/django_settings.py +++ b/konova/sub_settings/django_settings.py @@ -53,6 +53,7 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.gis', + 'django.contrib.humanize', 'simple_sso.sso_server', 'django_tables2', 'bootstrap_modal_forms', @@ -143,9 +144,12 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/3.1/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = 'de' + +USE_THOUSAND_SEPARATOR = True DEFAULT_DATE_TIME_FORMAT = '%d.%m.%Y %H:%M:%S' +DATE_FORMAT = '%d.%m.%Y' TIME_ZONE = 'Europe/Berlin' diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index 83f9726b..acf03ddb 100644 Binary files a/locale/de/LC_MESSAGES/django.mo and b/locale/de/LC_MESSAGES/django.mo differ diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index 63ad9ffa..f68d970d 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -3,16 +3,16 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#: compensation/forms.py:27 compensation/forms.py:32 compensation/forms.py:44 +#: compensation/forms.py:26 compensation/forms.py:32 compensation/forms.py:45 #: intervention/filters.py:25 intervention/filters.py:31 #: intervention/filters.py:38 intervention/filters.py:39 konova/forms.py:73 -#: konova/forms.py:144 user/forms.py:38 +#: konova/forms.py:149 konova/forms.py:172 user/forms.py:38 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-07-26 10:18+0200\n" +"POT-Creation-Date: 2021-07-26 10:44+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,24 +22,36 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: compensation/forms.py:26 +#: compensation/forms.py:25 #: intervention/templates/intervention/detail-view.html:227 msgid "Amount" msgstr "Betrag" +#: compensation/forms.py:27 +msgid "Amount in Euro" +msgstr "Betrag in Euro" + #: compensation/forms.py:31 msgid "Due on" msgstr "Fällig am" -#: compensation/forms.py:45 +#: compensation/forms.py:33 +msgid "Due on which date" +msgstr "Zahlung wird an diesem Datum erwartet" + +#: compensation/forms.py:46 msgid "Transfer note" msgstr "Verwendungszweck" -#: compensation/forms.py:53 +#: compensation/forms.py:47 +msgid "Note for money transfer" +msgstr "Verwendungszweck für Überweisung" + +#: compensation/forms.py:55 msgid "Payment" msgstr "Zahlung" -#: compensation/forms.py:54 +#: compensation/forms.py:56 msgid "Add a payment for intervention '{}'" msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen" @@ -53,7 +65,7 @@ msgstr "Kennung" #: intervention/tables.py:28 #: intervention/templates/intervention/detail-view.html:62 #: intervention/templates/intervention/detail-view.html:182 -#: intervention/templates/intervention/detail-view.html:279 +#: intervention/templates/intervention/detail-view.html:287 msgid "Title" msgstr "Bezeichnung" @@ -94,14 +106,18 @@ msgstr "Lösche {}" msgid "Eco Accounts" msgstr "Ökokonten" -#: compensation/views.py:135 +#: compensation/views.py:136 msgid "Payment added" msgstr "Zahlung hinzugefügt" -#: compensation/views.py:141 konova/views.py:137 +#: compensation/views.py:142 compensation/views.py:180 konova/views.py:137 msgid "There was an error on this form." msgstr "Es gab einen Fehler im Formular." +#: compensation/views.py:174 +msgid "Payment removed" +msgstr "Zahlung gelöscht" + #: intervention/filters.py:24 msgid "Show all" msgstr "Alle anzeigen" @@ -325,23 +341,28 @@ msgstr "Neue Zahlung hinzufügen" msgid "Transfer comment" msgstr "Verwendungszweck" -#: intervention/templates/intervention/detail-view.html:259 -msgid "Documents" -msgstr "Dokumente" - -#: intervention/templates/intervention/detail-view.html:264 -msgid "Add new document" -msgstr "Neues Dokument hinzufügen" - -#: intervention/templates/intervention/detail-view.html:282 -msgid "Comment" -msgstr "Kommentar" - -#: intervention/templates/intervention/detail-view.html:285 +#: intervention/templates/intervention/detail-view.html:233 +#: intervention/templates/intervention/detail-view.html:293 msgid "Action" msgstr "Aktionen" -#: intervention/templates/intervention/detail-view.html:299 konova/forms.py:152 +#: intervention/templates/intervention/detail-view.html:247 +msgid "Remove payment" +msgstr "Zahlung entfernen" + +#: intervention/templates/intervention/detail-view.html:267 +msgid "Documents" +msgstr "Dokumente" + +#: intervention/templates/intervention/detail-view.html:272 +msgid "Add new document" +msgstr "Neues Dokument hinzufügen" + +#: intervention/templates/intervention/detail-view.html:290 +msgid "Comment" +msgstr "Kommentar" + +#: intervention/templates/intervention/detail-view.html:307 konova/forms.py:180 msgid "Remove document" msgstr "Dokument löschen" @@ -383,19 +404,23 @@ msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!" msgid "Not editable" msgstr "Nicht editierbar" -#: konova/forms.py:72 konova/forms.py:143 +#: konova/forms.py:72 konova/forms.py:148 konova/forms.py:171 msgid "Confirm" msgstr "Bestätige" -#: konova/forms.py:84 +#: konova/forms.py:84 konova/forms.py:156 msgid "Remove" -msgstr "Entferne" +msgstr "Löschen" #: konova/forms.py:86 msgid "You are about to remove {} {}" msgstr "Sie sind dabei {} {} zu löschen" -#: konova/forms.py:153 +#: konova/forms.py:157 +msgid "Are you sure?" +msgstr "" + +#: konova/forms.py:181 msgid "This will remove '{}'. Are you sure?" msgstr "Hiermit wird '{}' gelöscht. Sind Sie sicher?" @@ -483,7 +508,7 @@ msgstr "" msgid "Contact" msgstr "Kontakt" -#: templates/modal/modal_form.html:33 +#: templates/modal/modal_form.html:24 msgid "Continue" msgstr "Weiter" @@ -1923,9 +1948,6 @@ msgstr "" #~ "Eingriffe müssen zu einem Vorgang gehören. Bitte geben SIe die fehlenden " #~ "Daten für den Vorgang ein." -#~ msgid "Intervention {} removed" -#~ msgstr "Eingriff {} gelöscht" - #~ msgid "You are working as" #~ msgstr "Sie arbeiten gerade als " diff --git a/templates/base.html b/templates/base.html index f1a713cb..65487e21 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,5 @@ -{% load static i18n fontawesome_5 bootstrap4 %} +{% load static i18n l10n fontawesome_5 bootstrap4 %} diff --git a/templates/modal/modal_form.html b/templates/modal/modal_form.html index 93b28317..79f347ff 100644 --- a/templates/modal/modal_form.html +++ b/templates/modal/modal_form.html @@ -1,4 +1,4 @@ -{% load i18n %} +{% load i18n l10n %} {% comment %} A generic modal form template which is based on django-bootstrap-modal-forms package https://pypi.org/project/django-bootstrap-modal-forms/ @@ -15,18 +15,9 @@