Compensation action

* adds compensation action to compensation detail view
* adds adding/removing logic for compensation action
* adds bootstrap style to select fields in forms
* refactors UnitEnum into UnitChoices using models.TextChoices (Django 3.x)
* adds translations
This commit is contained in:
mipel 2021-08-04 10:44:02 +02:00
parent c6fe944701
commit e2ed39c900
8 changed files with 333 additions and 70 deletions

View File

@ -12,7 +12,7 @@ from django.http import HttpRequest
from django.shortcuts import redirect, render
from django.utils.translation import gettext_lazy as _
from compensation.models import Payment, CompensationState
from compensation.models import Payment, CompensationState, CompensationAction, UnitChoices
from konova.contexts import BaseContext
from konova.forms import BaseForm, BaseModalForm
from konova.models import Deadline, DeadlineType
@ -156,7 +156,12 @@ class NewDeadlineModalForm(BaseModalForm):
label_suffix="",
required=True,
help_text=_("Select the deadline type"),
choices=DeadlineType.choices
choices=DeadlineType.choices,
widget=forms.Select(
attrs={
"class": "custom-select"
}
)
)
date = forms.DateField(
label=_("Date"),
@ -193,7 +198,7 @@ class NewDeadlineModalForm(BaseModalForm):
with transaction.atomic():
action = UserActionLogEntry.objects.create(
user=self.user,
action=UserAction.CREATED.value
action=UserAction.CREATED
)
deadline = Deadline.objects.create(
type=self.cleaned_data["type"],
@ -204,3 +209,64 @@ class NewDeadlineModalForm(BaseModalForm):
self.instance.deadlines.add(deadline)
return deadline
class NewActionModalForm(BaseModalForm):
action_type = forms.CharField(
label=_("Action Type"),
label_suffix="",
required=True,
help_text=_("Select the deadline type"),
)
unit = forms.ChoiceField(
label=_("Unit"),
label_suffix="",
required=True,
help_text=_("Select the unit"),
choices=UnitChoices.choices,
widget=forms.Select(
attrs={
"class": "custom-select"
}
)
)
amount = forms.DecimalField(
label=_("Amount"),
label_suffix="",
required=True,
help_text=_("Insert the amount"),
decimal_places=2,
min_value=0.00,
)
comment = forms.CharField(
required=False,
label=_("Comment"),
label_suffix=_(""),
help_text=_("Additional comment"),
widget=forms.Textarea(
attrs={
"cols": 30,
"rows": 5,
}
)
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_title = _("New action")
self.form_caption = _("Insert data for the new action")
def save(self):
with transaction.atomic():
user_action = UserActionLogEntry.objects.create(
user=self.user,
action=UserAction.CREATED
)
comp_action = CompensationAction.objects.create(
action_type=self.cleaned_data["action_type"],
amount=self.cleaned_data["amount"],
unit=self.cleaned_data["unit"],
created=user_action,
)
self.instance.actions.add(comp_action)
return comp_action

View File

@ -11,6 +11,7 @@ from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import transaction
from django.utils import timezone
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from compensation.settings import COMPENSATION_IDENTIFIER_LENGTH, COMPENSATION_IDENTIFIER_TEMPLATE
from intervention.models import Intervention, ResponsibilityData
@ -63,18 +64,45 @@ class CompensationState(UuidModel):
return "{} | {}".format(self.biotope_type, self.surface)
class UnitChoices(models.TextChoices):
"""
Predefines units for selection
"""
cm = "cm", _("cm")
m = "m", _("m")
km = "km", _("km")
qm = "qm", _("")
ha = "ha", _("ha")
st = "pcs", _("Pieces") # pieces
class CompensationAction(BaseResource):
"""
Compensations include actions like planting trees, refreshing rivers and so on.
"""
action_type = models.CharField(max_length=500, null=True, blank=True)
amount = models.FloatField()
unit = models.CharField(max_length=100, null=True, blank=True)
unit = models.CharField(max_length=100, null=True, blank=True, choices=UnitChoices.choices)
control = models.ForeignKey(CompensationControl, on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return "{} | {} {}".format(self.action_type, self.amount, self.unit)
@property
def unit_humanize(self):
""" Returns humanized version of enum
Used for template rendering
Returns:
"""
choices = UnitChoices.choices
for choice in choices:
if choice[0] == self.unit:
return choice[1]
return None
class AbstractCompensation(BaseObject):
"""

View File

@ -0,0 +1,61 @@
{% load i18n l10n fontawesome_5 %}
<div id="related-documents" class="card">
<div class="card-header rlp-r">
<div class="row">
<div class="col-sm-6">
<h5>
<span class="badge badge-light">{{comp.actions.count}}</span>
{% trans 'Actions' context 'Compensation' %}
</h5>
</div>
<div class="col-sm-6">
<div class="d-flex justify-content-end">
{% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:new-action' comp.id %}" title="{% trans 'Add new action' %}">
{% fa5_icon 'plus' %}
{% fa5_icon 'seedling' %}
</button>
{% endif %}
</div>
</div>
</div>
</div>
<div class="card-body scroll-300">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">
{% trans 'Action type' %}
</th>
<th scope="col">
{% trans 'Amount' context 'Compensation' %}
</th>
<th scope="col">
{% trans 'Unit' %}
</th>
<th scope="col">
{% trans 'Action' %}
</th>
</tr>
</thead>
<tbody>
{% for action in comp.actions.all %}
<tr>
<td class="align-middle">
{{ action.action_type }}
</td>
<td class="align-middle">{{ action.amount }}</td>
<td class="align-middle">{{ action.unit_humanize }}</td>
<td>
{% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:action-remove' action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %}
</button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>

View File

@ -18,6 +18,7 @@ urlpatterns = [
path('<id>/edit', edit_view, name='edit'),
path('<id>/remove', remove_view, name='remove'),
path('<id>/state/new', state_new_view, name='new-state'),
path('<id>/action/new', action_new_view, name='new-action'),
path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
# Documents
@ -41,4 +42,7 @@ urlpatterns = [
# Generic state routes
path('state/<id>/remove', state_remove_view, name='state-remove'),
# Generic action routes
path('action/<id>/remove', action_remove_view, name='action-remove'),
]

View File

@ -5,8 +5,8 @@ from django.http import HttpRequest, Http404
from django.shortcuts import render, get_object_or_404
from django.utils.translation import gettext_lazy as _
from compensation.forms import NewPaymentForm, NewStateModalForm, NewDeadlineModalForm
from compensation.models import Compensation, EcoAccount, Payment, CompensationState
from compensation.forms import NewPaymentForm, NewStateModalForm, NewDeadlineModalForm, NewActionModalForm
from compensation.models import Compensation, EcoAccount, Payment, CompensationState, CompensationAction
from compensation.tables import CompensationTable, EcoAccountTable
from intervention.models import Intervention
from konova.contexts import BaseContext
@ -300,6 +300,25 @@ def state_new_view(request: HttpRequest, id: str):
)
@login_required
def action_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new actions for a compensation
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id to which the new state will be related
Returns:
"""
comp = get_object_or_404(Compensation, id=id)
form = NewActionModalForm(request.POST or None, instance=comp, user=request.user)
return form.process_request(
request,
msg_success=_("Action added")
)
@login_required
def deadline_new_view(request: HttpRequest, id: str):
""" Renders a form for adding new states for a compensation
@ -321,9 +340,37 @@ def deadline_new_view(request: HttpRequest, id: str):
@login_required
def state_remove_view(request: HttpRequest, id: str):
""" Renders a form for removing a compensation state
Args:
request (HttpRequest): The incoming request
id (str): The state's id
Returns:
"""
state = get_object_or_404(CompensationState, id=id)
form = RemoveModalForm(request.POST or None, instance=state, user=request.user)
return form.process_request(
request,
msg_success=_("State removed")
)
@login_required
def action_remove_view(request: HttpRequest, id: str):
""" Renders a form for removing a compensation action
Args:
request (HttpRequest): The incoming request
id (str): The action's id
Returns:
"""
action = get_object_or_404(CompensationAction, id=id)
form = RemoveModalForm(request.POST or None, instance=action, user=request.user)
return form.process_request(
request,
msg_success=_("Action removed")
)

View File

@ -18,23 +18,3 @@ class BaseEnum(Enum):
empty_choice = [] if drop_empty_choice else [(None, "---")]
choices = empty_choice + [(enum.value, enum.name) for enum in cls]
return choices
class UnitEnum(BaseEnum):
"""
Predefines units for selection
"""
mm = "mm"
dm = "dm"
cm = "cm"
m = "m"
km = "km"
qmm = "qmm"
qdm = "qdm"
qcm = "qcm"
qm = "qm"
qkm = "qkm"
ha = "ha"
st = "St." # pieces

Binary file not shown.

View File

@ -4,17 +4,17 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#: compensation/forms.py:34 compensation/forms.py:39 compensation/forms.py:52
#: compensation/forms.py:177 intervention/filters.py:26
#: intervention/filters.py:40 intervention/filters.py:47
#: intervention/filters.py:48 konova/forms.py:84 konova/forms.py:213
#: konova/forms.py:244 konova/forms.py:249 konova/forms.py:261
#: konova/forms.py:272 konova/forms.py:285 user/forms.py:38
#: compensation/forms.py:182 compensation/forms.py:241
#: intervention/filters.py:26 intervention/filters.py:40
#: intervention/filters.py:47 intervention/filters.py:48 konova/forms.py:91
#: konova/forms.py:220 konova/forms.py:251 konova/forms.py:256
#: konova/forms.py:268 konova/forms.py:279 konova/forms.py:292 user/forms.py:38
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-03 17:21+0200\n"
"POT-Creation-Date: 2021-08-04 10:37+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -24,7 +24,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: compensation/forms.py:33
#: compensation/forms.py:33 compensation/forms.py:233
#: intervention/templates/intervention/detail/includes/eco-account-withdraws.html:33
msgid "Amount"
msgstr "Menge"
@ -84,7 +84,7 @@ msgstr "Neuer Zustand"
msgid "Insert data for the new state"
msgstr "Geben Sie die Daten des neuen Zustandes ein"
#: compensation/forms.py:113 konova/forms.py:134
#: compensation/forms.py:113 konova/forms.py:141
msgid "Object removed"
msgstr "Objekt entfernt"
@ -92,39 +92,88 @@ msgstr "Objekt entfernt"
msgid "Deadline Type"
msgstr "Fristart"
#: compensation/forms.py:158
#: compensation/forms.py:158 compensation/forms.py:218
msgid "Select the deadline type"
msgstr "Fristart wählen"
#: compensation/forms.py:162
#: compensation/forms.py:167
#: compensation/templates/compensation/detail/includes/deadlines.html:31
msgid "Date"
msgstr "Datum"
#: compensation/forms.py:165
#: compensation/forms.py:170
msgid "Select date"
msgstr "Datum wählen"
#: compensation/forms.py:176
#: compensation/forms.py:181 compensation/forms.py:240
#: compensation/templates/compensation/detail/includes/deadlines.html:34
#: compensation/templates/compensation/detail/includes/documents.html:31
#: intervention/templates/intervention/detail/includes/documents.html:31
#: konova/forms.py:271
#: konova/forms.py:278
msgid "Comment"
msgstr "Kommentar"
#: compensation/forms.py:178
#: compensation/forms.py:183 compensation/forms.py:242
msgid "Additional comment"
msgstr "Zusätzlicher Kommentar"
#: compensation/forms.py:189
#: compensation/forms.py:194
msgid "New deadline"
msgstr "Neue Frist"
#: compensation/forms.py:190
#: compensation/forms.py:195
msgid "Insert data for the new deadline"
msgstr "Geben Sie die Daten der neuen Frist ein"
#: compensation/forms.py:215
msgid "Action Type"
msgstr "Maßnahmentyp"
#: compensation/forms.py:221
#: compensation/templates/compensation/detail/includes/actions.html:34
msgid "Unit"
msgstr "Einheit"
#: compensation/forms.py:224
msgid "Select the unit"
msgstr "Einheit wählen"
#: compensation/forms.py:236
msgid "Insert the amount"
msgstr "Menge eingeben"
#: compensation/forms.py:253
msgid "New action"
msgstr "Neue Maßnahme"
#: compensation/forms.py:254
msgid "Insert data for the new action"
msgstr "Geben Sie die Daten der neuen Maßnahme ein"
#: compensation/models.py:71
msgid "cm"
msgstr ""
#: compensation/models.py:72
msgid "m"
msgstr ""
#: compensation/models.py:73
msgid "km"
msgstr ""
#: compensation/models.py:74
msgid "m²"
msgstr ""
#: compensation/models.py:75
msgid "ha"
msgstr ""
#: compensation/models.py:76
msgid "Pieces"
msgstr "Stück"
#: compensation/tables.py:24 compensation/tables.py:164
#: intervention/forms.py:28 intervention/tables.py:23
#: intervention/templates/intervention/detail/includes/compensations.html:30
@ -137,7 +186,7 @@ msgstr "Kennung"
#: intervention/forms.py:35 intervention/tables.py:28
#: intervention/templates/intervention/detail/includes/compensations.html:33
#: intervention/templates/intervention/detail/includes/documents.html:28
#: intervention/templates/intervention/detail/view.html:64 konova/forms.py:243
#: intervention/templates/intervention/detail/view.html:64 konova/forms.py:250
msgid "Title"
msgstr "Bezeichnung"
@ -206,7 +255,7 @@ msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
msgid "Access not granted"
msgstr "Nicht freigegeben - Datensatz nur lesbar"
#: compensation/tables.py:174 konova/forms.py:248
#: compensation/tables.py:174 konova/forms.py:255
msgid "Created on"
msgstr "Erstellt"
@ -226,6 +275,40 @@ msgstr "Bearbeite {}"
msgid "Delete {}"
msgstr "Lösche {}"
#: compensation/templates/compensation/detail/includes/actions.html:8
msgctxt "Compensation"
msgid "Actions"
msgstr "Maßnahmen"
#: compensation/templates/compensation/detail/includes/actions.html:14
msgid "Add new action"
msgstr "Neue Maßnahme hinzufügen"
#: compensation/templates/compensation/detail/includes/actions.html:28
msgid "Action type"
msgstr "Maßnahmentyp"
#: compensation/templates/compensation/detail/includes/actions.html:31
msgctxt "Compensation"
msgid "Amount"
msgstr "Menge"
#: compensation/templates/compensation/detail/includes/actions.html:37
#: compensation/templates/compensation/detail/includes/deadlines.html:37
#: compensation/templates/compensation/detail/includes/documents.html:34
#: compensation/templates/compensation/detail/includes/states-after.html:39
#: compensation/templates/compensation/detail/includes/states-before.html:39
#: intervention/templates/intervention/detail/includes/compensations.html:36
#: intervention/templates/intervention/detail/includes/documents.html:34
#: intervention/templates/intervention/detail/includes/eco-account-withdraws.html:36
#: intervention/templates/intervention/detail/includes/payments.html:37
msgid "Action"
msgstr "Aktionen"
#: compensation/templates/compensation/detail/includes/actions.html:51
msgid "Remove action"
msgstr "Maßnahme entfernen"
#: compensation/templates/compensation/detail/includes/deadlines.html:8
msgid "Deadlines"
msgstr "Termine und Fristen"
@ -239,17 +322,6 @@ msgstr "Neue Frist hinzufügen"
msgid "Type"
msgstr "Typ"
#: compensation/templates/compensation/detail/includes/deadlines.html:37
#: compensation/templates/compensation/detail/includes/documents.html:34
#: compensation/templates/compensation/detail/includes/states-after.html:39
#: compensation/templates/compensation/detail/includes/states-before.html:39
#: intervention/templates/intervention/detail/includes/compensations.html:36
#: intervention/templates/intervention/detail/includes/documents.html:34
#: intervention/templates/intervention/detail/includes/eco-account-withdraws.html:36
#: intervention/templates/intervention/detail/includes/payments.html:37
msgid "Action"
msgstr "Aktionen"
#: compensation/templates/compensation/detail/includes/deadlines.html:51
msgid "Remove deadline"
msgstr "Frist löschen"
@ -261,7 +333,7 @@ msgstr "Dokumente"
#: compensation/templates/compensation/detail/includes/documents.html:14
#: intervention/templates/intervention/detail/includes/documents.html:14
#: konova/forms.py:284
#: konova/forms.py:291
msgid "Add new document"
msgstr "Neues Dokument hinzufügen"
@ -384,13 +456,21 @@ msgid "State added"
msgstr "Zustand hinzugefügt"
#: compensation/views.py:318
msgid "Action added"
msgstr "Maßnahme hinzugefügt"
#: compensation/views.py:337
msgid "Deadline added"
msgstr "Frist hinzugefügt"
#: compensation/views.py:328
#: compensation/views.py:356
msgid "State removed"
msgstr "Zustand gelöscht"
#: compensation/views.py:375
msgid "Action removed"
msgstr "Maßnahme entfernt"
#: intervention/filters.py:25
msgid "Show unshared"
msgstr "Nicht freigegebene anzeigen"
@ -648,40 +728,40 @@ msgstr ""
msgid "You need to be part of another user group."
msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
#: konova/forms.py:57
#: konova/forms.py:64
msgid "Not editable"
msgstr "Nicht editierbar"
#: konova/forms.py:83 konova/forms.py:212
#: konova/forms.py:90 konova/forms.py:219
msgid "Confirm"
msgstr "Bestätige"
#: konova/forms.py:95 konova/forms.py:221
#: konova/forms.py:102 konova/forms.py:228
msgid "Remove"
msgstr "Löschen"
#: konova/forms.py:97
#: konova/forms.py:104
msgid "You are about to remove {} {}"
msgstr "Sie sind dabei {} {} zu löschen"
#: konova/forms.py:222
#: konova/forms.py:229
msgid "Are you sure?"
msgstr "Sind Sie sicher?"
#: konova/forms.py:250
#: konova/forms.py:257
msgid "When has this file been created? Important for photos."
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
#: konova/forms.py:260
#: konova/forms.py:267
#: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231
msgid "File"
msgstr "Datei"
#: konova/forms.py:262
#: konova/forms.py:269
msgid "Must be smaller than 15 Mb"
msgstr "Muss kleiner als 15 Mb sein"
#: konova/forms.py:273
#: konova/forms.py:280
msgid "Additional comment on this file"
msgstr "Zusätzlicher Kommentar"
@ -897,7 +977,7 @@ msgstr "Abbrechen"
msgid "Save"
msgstr "Speichern"
#: templates/table/generic_table_form_body.html:20
#: templates/table/generic_table_form_body.html:21
msgid "Fields with * are required."
msgstr "* sind Pflichtfelder."
@ -2247,9 +2327,6 @@ msgstr ""
#~ msgid "Withdraw from eco-account"
#~ msgstr "Von Konto abbuchen"
#~ msgid "Show actions"
#~ msgstr "Zeige Maßnahmen"
#~ msgid "You are currently working as "
#~ msgstr "Sie arbeiten gerade als "