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:
@@ -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
|
||||
|
||||
|
||||
@@ -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 "{} | {} m²".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", _("m²")
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -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>
|
||||
@@ -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'),
|
||||
]
|
||||
@@ -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")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user