From 4fb2ef26d06a107b9b450e08671715418f2a0e77 Mon Sep 17 00:00:00 2001 From: mipel Date: Mon, 26 Jul 2021 10:23:09 +0200 Subject: [PATCH] Payments add modal form * adds modal form for adding payments * generalizes generic_table_form.html for table-form-like usage in modal_form.html * adds css enhancements for focused input fields * adds BaseModalForm as specification to BaseForm, which inherits the BSModalForm class as well * adds translations --- compensation/forms.py | 54 ++++++++++- compensation/urls.py | 2 +- compensation/views.py | 43 ++++++++- .../templates/intervention/detail-view.html | 16 ++- intervention/views.py | 2 +- konova/forms.py | 12 ++- konova/static/css/konova.css | 2 +- konova/templates/konova/form.html | 2 +- locale/de/LC_MESSAGES/django.mo | Bin 8437 -> 8749 bytes locale/de/LC_MESSAGES/django.po | 91 +++++++++++------- templates/modal/modal_form.html | 3 + templates/{ => table}/generic_table_form.html | 20 +--- templates/table/generic_table_form_body.html | 20 ++++ user/templates/user/notifications.html | 2 +- 14 files changed, 194 insertions(+), 75 deletions(-) rename templates/{ => table}/generic_table_form.html (52%) create mode 100644 templates/table/generic_table_form_body.html diff --git a/compensation/forms.py b/compensation/forms.py index 1e0853ab..30b03046 100644 --- a/compensation/forms.py +++ b/compensation/forms.py @@ -5,10 +5,60 @@ Contact: michel.peltriaux@sgdnord.rlp.de Created on: 04.12.20 """ -from konova.forms import BaseForm +from django import forms +from django.db import transaction +from django.utils.translation import gettext_lazy as _ + +from compensation.models import Payment +from konova.forms import BaseForm, BaseModalForm class NewCompensationForm(BaseForm): def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) \ No newline at end of file + super().__init__(*args, **kwargs) + + +class NewPaymentForm(BaseModalForm): + amount = forms.FloatField( + min_value=0.01, + label=_("Amount"), + label_suffix=_(""), + ) + due = forms.DateField( + required=False, + label=_("Due on"), + label_suffix=_(""), + widget=forms.DateInput( + attrs={ + "type": "date", + "data-provide": "datepicker", + }, + format="%d.%m.%Y" + ) + ) + transfer_note = forms.CharField( + max_length=1000, + required=False, + label_suffix=_(""), + label=_("Transfer note") + ) + + def __init__(self, *args, **kwargs): + self.user = kwargs.pop("request", None).user + self.intervention = kwargs.pop("intervention", None) + super().__init__(*args, **kwargs) + + self.form_title = _("Payment") + self.form_caption = _("Add a payment for intervention '{}'").format(self.intervention.title) + + def save(self): + with transaction.atomic(): + pay = Payment.objects.create( + created_by=self.user, + amount=self.cleaned_data.get("amount", -1), + due_on=self.cleaned_data.get("due", None), + comment=self.cleaned_data.get("transfer_note", None), + intervention=self.intervention, + ) + return pay \ No newline at end of file diff --git a/compensation/urls.py b/compensation/urls.py index 5e470926..c22f0322 100644 --- a/compensation/urls.py +++ b/compensation/urls.py @@ -19,7 +19,7 @@ urlpatterns = [ path('/remove', remove_view, name='remove'), # Payment - path('pay/new', new_view, name='pay-new'), + 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'), diff --git a/compensation/views.py b/compensation/views.py index 1c047e70..482ab537 100644 --- a/compensation/views.py +++ b/compensation/views.py @@ -1,9 +1,12 @@ from django.contrib.auth.decorators import login_required from django.http import HttpRequest -from django.shortcuts import render +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.tables import CompensationTable, EcoAccountTable +from intervention.models import Intervention from konova.contexts import BaseContext from konova.decorators import * @@ -108,3 +111,41 @@ def account_open_view(request: HttpRequest, id: str): def account_remove_view(request: HttpRequest, id: str): # ToDo pass + + +@login_required +def new_payment_view(request: HttpRequest, intervention_id: str): + """ Renders a modal view for adding new payments + + Args: + request (HttpRequest): The incoming request + intervention_id (str): The intervention's id for which a new payment shall be added + + Returns: + + """ + template = "modal/modal_form.html" + intervention = get_object_or_404(Intervention, id=intervention_id) + form = NewPaymentForm(request.POST or None, intervention=intervention, request=request) + if request.method == "POST": + if form.is_valid(): + payment = form.save() + messages.success( + request, + _("Payment added") + ) + 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 25d99bd0..c3e1fb70 100644 --- a/intervention/templates/intervention/detail-view.html +++ b/intervention/templates/intervention/detail-view.html @@ -211,12 +211,10 @@
- - - +
@@ -264,7 +262,7 @@ -{% with 'del-btn' as btn_class %} +{% with 'btn-modal' as btn_class %} {% include 'modal/modal_form_script.html' %} {% endwith %} diff --git a/intervention/views.py b/intervention/views.py index 49ae0c3f..131acbde 100644 --- a/intervention/views.py +++ b/intervention/views.py @@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _ from django.http import HttpRequest from django.shortcuts import render, get_object_or_404 -from intervention.forms import NewInterventionForm, EditInterventionForm, OpenInterventionForm +from intervention.forms import NewInterventionForm, EditInterventionForm from intervention.models import Intervention from intervention.tables import InterventionTable from konova.contexts import BaseContext diff --git a/konova/forms.py b/konova/forms.py index 15966cd7..0ee4187c 100644 --- a/konova/forms.py +++ b/konova/forms.py @@ -8,12 +8,11 @@ Created on: 16.11.20 from abc import abstractmethod -from bootstrap_modal_forms.forms import BSModalModelForm, BSModalForm +from bootstrap_modal_forms.forms import BSModalForm from django import forms from django.contrib.auth.models import User from django.contrib.gis.forms import GeometryField, OSMWidget from django.contrib.gis.geos import Polygon -from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -99,6 +98,13 @@ class RemoveForm(BaseForm): return self.object_to_remove +class BaseModalForm(BaseForm, BSModalForm): + """ A specialzed form class for modal form handling + + """ + is_modal_form = True + + class SimpleGeomForm(BaseForm): """ A geometry form for rendering geometry read-only using a widget @@ -131,7 +137,7 @@ class SimpleGeomForm(BaseForm): self.area = geom.area -class RemoveDocumentForm(BaseForm, BSModalForm): +class RemoveDocumentForm(BaseModalForm): confirm = forms.BooleanField( label=_("Confirm"), label_suffix=_(""), diff --git a/konova/static/css/konova.css b/konova/static/css/konova.css index 04cb9af1..d4ca9d39 100644 --- a/konova/static/css/konova.css +++ b/konova/static/css/konova.css @@ -168,7 +168,7 @@ a { } input:focus, textarea:focus, select:focus{ - border: 1px solid var(--rlp-red) !important; + border-color: var(--rlp-red) !important; box-shadow: 0 0 3px var(--rlp-red) !important; -moz-box-shadow: 0 0 3px var(--rlp-red) !important; -webkit-box-shadow: 0 0 3px var(--rlp-red) !important; diff --git a/konova/templates/konova/form.html b/konova/templates/konova/form.html index 850c1b00..8b339f8d 100644 --- a/konova/templates/konova/form.html +++ b/konova/templates/konova/form.html @@ -3,6 +3,6 @@ {% block body %}
- {% include 'generic_table_form.html' %} + {% include 'table/generic_table_form.html' %}
{% endblock %} \ No newline at end of file diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index 70111a9e75a26bdf02533b9768a0930c42a85f66..83f9726b3a15dbbc15d3cd9aacf52852edc38fa5 100644 GIT binary patch delta 3201 zcmZA3eN5F=9LMnkC?=pH_=H@&zkCSfA(J#yLQ_%0N0L%}NW03ta1}0gxu~FcNt48~ zEgi0yLvvQ*^bfn%(#ka1noDcW{3oZDv#i!^E338H>ixO*xVg^m_rA_KzlU?q_xyer z{+M#KID9RwTbrS@5-y^mn=zl_kq7vq97;B3H+Etg7Nr=Ih^5#A7vXSRf&FkRrs5me z2RktVPoS>*1o@aQzPMl5T%?jj$4%4;zhXZAiNkP2uh>8{F`f2&+g^p7V%8uZv%&Va zpw4^Ewhy4zav0qhL5*_>lNjH8Lxqp|p0ED+JL-g zNivI&B$`#&7pqX2YeZ#iC+dD}n92C2gGzTiiJJLoRO-IQQFs$IP;WYQV|KlX8Im#;E(L_)2JJDq4xSq zd;B^MqA{+mD(iotpU?eZ8z$87HT2m?D0vqe|BH;uL~B_p$z!!i8ZK+tV2F#CtsS-K8!v@ z*g^Xe>bfAy(~28V1Gge`GOwc+b^w*ZBdGI_q3-u#*jCPC5gp&6W;&FkdM2_^7v`h- z3s5U6L`}Q|9bAYba6Rg}z19P$i5x;*cLH_4&r$aapQrK=mCLA=-Nhm3VqbD_BI-mh zsy~2Z@m19EGnj|Jpw7!+gX3`+Y9b?18OX({aclv;OM3(9&DQ(xu#vj3#JT`S(_V@i z@D&`4ov3G^3$=o)s8rrSrT!<>v+_5x29wUo8aN9xaSUpqb5Y}k(53gkiHc5aN2T;2 z^2V8CsMqT>>V{vS_Vzkz;9Kb6ZPZ)ShtYN8bYvHe3pMf4wtp7ter2ffmg7LiH&wQy z*`Bb&+GhLr+xB79MBYbb<{WCmw@^PkcaZExN7Y0JF#32LiptPJRAzms<9jfyJ?fyM zlpeGPI#DY*hHR@ji7e85g_`+~s1^QZ?M{Bx9)!wFF6#OM)cp&sQ&1C~i5jmgll&`n z<#g!jT!u>hYI|Y>vM93+weo$ar#XUpJ-bi?U$NdsWhRclWE#kg+Vfl-g$wWz+=Tgf z)J6W4k}GtK!DO!107a;k&O@cR9F;OJDkC+hlx{&yd>1P9`%x4605ySg*2}23>pRqh z;)ce~%MMe~fkM21OHrvCMJK;4rU2D0w(Ys70alMp#B`v4{ccC)0*LoDSg{M$Y_h(2l%>`7Zenu8; z{>5=Pqtwq9oKtM~s!8k=p0*lO!jv4ogTEG9Hbl?gG-OIChwq7TS8pUSix@$u=qX=7cnO|K;}9zel`X^^ zB1H|#dLomUMAQ>;HsEA!Y|4sUOFk2qSX}RQY6FpuURUFLn^Jqer=r4J5vfaUiBAc7 z0(Cxb&jq`va9hzt0!Ft5f9S}+bV#6L=5W(b?H2;1TTY=$SWIew2hcowtqPt3xmEknq_T=e-o zvf&^0vU zq0X3vj?)JjI1I#Aj30(m$>qYt_`n=&L3<(E!SZ-N5wF)EeTQwxV#6LJX<;9>!2{?D zzeX2u9_^jDPks z3(deHbYj)$#NI+DT#NR%Ka2d|LggzixOb;84=>}b*n-i#-xX5>p&gZ>sjWZ6}XpW7JQThSHQqR;I?`~5VV{JUqzxZnip(8F>C-^I4v^oO4ya|-*=fsZ1OgcImW z&Y>B*gg*Z}+TXQkCg~VTyE8h08R!|9o1o$k7seZl(V4GASM~}PU=4Q1&(I&9ik?F! zaslnDh4( zlFg8h&b)8DUW#@&1s$*g`DvIR+tu;@tFgT$w%|E*`4q)(q%Y|PPh&|f8in({U_R*Wtx#L zXa|Mp0R5ta(1{L32ONWDYyx_CC!r~yi9T0_bRAZqE3ZKh?amJI{ol_8CvYYQ@w%^jQFt#dLNl`qUC~K&fFIBSPNNICfP5xW*Pg>}#3JeaC+_>kSYQF>9E z$@r-B%8&)}$wo dw%eMKe53vKv}8@*iHzjB{9YN!g9TM-{{y=5^nCyT diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index e2b4ab4b..63ad9ffa 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -3,15 +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 #: intervention/filters.py:25 intervention/filters.py:31 #: intervention/filters.py:38 intervention/filters.py:39 konova/forms.py:73 -#: konova/forms.py:137 user/forms.py:38 +#: konova/forms.py:144 user/forms.py:38 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-07-23 18:26+0200\n" +"POT-Creation-Date: 2021-07-26 10:18+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -21,6 +22,27 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#: compensation/forms.py:26 +#: intervention/templates/intervention/detail-view.html:227 +msgid "Amount" +msgstr "Betrag" + +#: compensation/forms.py:31 +msgid "Due on" +msgstr "Fällig am" + +#: compensation/forms.py:45 +msgid "Transfer note" +msgstr "Verwendungszweck" + +#: compensation/forms.py:53 +msgid "Payment" +msgstr "Zahlung" + +#: compensation/forms.py:54 +msgid "Add a payment for intervention '{}'" +msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen" + #: compensation/tables.py:18 compensation/tables.py:71 intervention/forms.py:26 #: intervention/tables.py:23 #: intervention/templates/intervention/detail-view.html:179 @@ -31,7 +53,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:281 +#: intervention/templates/intervention/detail-view.html:279 msgid "Title" msgstr "Bezeichnung" @@ -72,6 +94,14 @@ msgstr "Lösche {}" msgid "Eco Accounts" msgstr "Ökokonten" +#: compensation/views.py:135 +msgid "Payment added" +msgstr "Zahlung hinzugefügt" + +#: compensation/views.py:141 konova/views.py:137 +msgid "There was an error on this form." +msgstr "Es gab einen Fehler im Formular." + #: intervention/filters.py:24 msgid "Show all" msgstr "Alle anzeigen" @@ -291,31 +321,27 @@ msgstr "Ersatzzahlungen" msgid "Add new payment" msgstr "Neue Zahlung hinzufügen" -#: intervention/templates/intervention/detail-view.html:229 -msgid "Amount" -msgstr "Betrag" - -#: intervention/templates/intervention/detail-view.html:232 +#: intervention/templates/intervention/detail-view.html:230 msgid "Transfer comment" msgstr "Verwendungszweck" -#: intervention/templates/intervention/detail-view.html:261 +#: intervention/templates/intervention/detail-view.html:259 msgid "Documents" msgstr "Dokumente" -#: intervention/templates/intervention/detail-view.html:266 +#: intervention/templates/intervention/detail-view.html:264 msgid "Add new document" msgstr "Neues Dokument hinzufügen" -#: intervention/templates/intervention/detail-view.html:284 +#: intervention/templates/intervention/detail-view.html:282 msgid "Comment" msgstr "Kommentar" -#: intervention/templates/intervention/detail-view.html:287 +#: intervention/templates/intervention/detail-view.html:285 msgid "Action" msgstr "Aktionen" -#: intervention/templates/intervention/detail-view.html:301 konova/forms.py:145 +#: intervention/templates/intervention/detail-view.html:299 konova/forms.py:152 msgid "Remove document" msgstr "Dokument löschen" @@ -357,7 +383,7 @@ msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!" msgid "Not editable" msgstr "Nicht editierbar" -#: konova/forms.py:72 konova/forms.py:136 +#: konova/forms.py:72 konova/forms.py:143 msgid "Confirm" msgstr "Bestätige" @@ -369,7 +395,7 @@ msgstr "Entferne" msgid "You are about to remove {} {}" msgstr "Sie sind dabei {} {} zu löschen" -#: konova/forms.py:146 +#: konova/forms.py:153 msgid "This will remove '{}'. Are you sure?" msgstr "Hiermit wird '{}' gelöscht. Sind Sie sicher?" @@ -425,14 +451,10 @@ msgstr "Ökokonto" msgid "Withdraw" msgstr "Abbuchen" -#: konova/views.py:133 +#: konova/views.py:131 msgid "Document '{}' deleted" msgstr "Dokument '{}' gelöscht" -#: konova/views.py:139 -msgid "There was an error on this form." -msgstr "Es gab einen Fehler im Formular." - #: news/templates/news/dashboard-news.html:12 news/templates/news/index.html:19 msgid "Published on" msgstr "Veröffentlicht am" @@ -461,19 +483,7 @@ msgstr "" msgid "Contact" msgstr "Kontakt" -#: templates/generic_table_form.html:37 -msgid "Fields with * are required." -msgstr "* sind Pflichtfelder." - -#: templates/generic_table_form.html:41 -msgid "Cancel" -msgstr "Abbrechen" - -#: templates/generic_table_form.html:45 -msgid "Save" -msgstr "Speichern" - -#: templates/modal/modal_form.html:30 +#: templates/modal/modal_form.html:33 msgid "Continue" msgstr "Weiter" @@ -549,6 +559,18 @@ msgstr "" msgid "Apply filter" msgstr "Filter anwenden" +#: templates/table/generic_table_form.html:23 +msgid "Cancel" +msgstr "Abbrechen" + +#: templates/table/generic_table_form.html:27 +msgid "Save" +msgstr "Speichern" + +#: templates/table/generic_table_form_body.html:20 +msgid "Fields with * are required." +msgstr "* sind Pflichtfelder." + #: user/forms.py:23 msgid "Notifications" msgstr "Benachrichtigungen" @@ -1816,9 +1838,6 @@ msgstr "" #~ msgid "Last login on" #~ msgstr "Zuletzt eingeloggt am" -#~ msgid "Add new intervention" -#~ msgstr "Neuen Eingriff hinzufügen" - #~ msgid "Delete intervention" #~ msgstr "Eingriff löschen" diff --git a/templates/modal/modal_form.html b/templates/modal/modal_form.html index 82e65c37..93b28317 100644 --- a/templates/modal/modal_form.html +++ b/templates/modal/modal_form.html @@ -15,6 +15,7 @@