add creating resolution and view of them

This commit is contained in:
2023-10-10 11:01:45 +00:00
parent afa05afcc0
commit 5a1222187a
8 changed files with 239 additions and 8 deletions

View File

@@ -226,6 +226,41 @@ class ResolutionAdmin(admin.ModelAdmin):
"total",
]
fieldsets = (
(
None,
{
"fields": (
"name",
"id",
"date",
"option",
"is_visible",
)
},
),
(
"Budget",
{
"fields": (
"budget",
"total",
"budget_remaining",
)
},
),
(
"Abstimmung",
{
"classes": ["collapse"],
"fields": (
"voting",
"voting_text",
),
},
),
)
def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."

View File

@@ -102,6 +102,14 @@ class BillCreateForm(forms.ModelForm):
only_digital = cleaned_data.get("only_digital")
file_field = cleaned_data.get("file_field")
# check if resolution exists
try:
Resolution.objects.get(id=resolution)
except:
raise ValidationError(
f"Es gibt keinen Beschluss mit dieser ID. (Eingegebene ID: {resolution})"
)
# check that amount is valid because invalid amount is a NoneType.
if amount:
if amount > 30 and resolution == "":
@@ -212,6 +220,29 @@ class BillUpdateForm(forms.ModelForm):
self.fields["comment"].disabled = True
class ResolutionCreateForm(forms.ModelForm):
class Meta:
model = Resolution
fields = [
"option",
"date",
"voting",
"voting_text",
]
labels = {
"option": "Beschluss",
"date": "Datum",
"voting": "Abstimmungsverhalten",
"voting_text": "Abstimmungstext",
}
widgets = {
"date": DateInput(format=("%Y-%m-%d")),
}
class BillInlineForm(forms.ModelForm):
class Meta:
fields = [
@@ -273,6 +304,7 @@ class BillAdminForm(forms.ModelForm):
class ResolutionAdminForm(forms.ModelForm):
total = forms.CharField()
budget_remaining = forms.CharField()
class Meta:
model = Resolution
@@ -280,14 +312,16 @@ class ResolutionAdminForm(forms.ModelForm):
fields = [
"name",
"id",
"date",
"option",
"is_visible",
"budget",
"total",
"budget_remaining",
"voting",
"voting_text",
]
labels = {
"id": "ID",
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set
@@ -302,6 +336,15 @@ class ResolutionAdminForm(forms.ModelForm):
self.fields["total"].label = "Gesamtsumme (EUR)"
self.fields["total"].required = False
budget = 0
if resolution:
budget = resolution.budget
self.fields["budget_remaining"].disabled = True
self.fields["budget_remaining"].initial = budget - total
self.fields["budget_remaining"].label = "Restbudget (EUR)"
self.fields["budget_remaining"].required = False
class WirefAdminForm(forms.ModelForm):
total = forms.CharField()

View File

@@ -27,11 +27,31 @@ class BankData(models.Model):
class Resolution(models.Model):
id = models.CharField(primary_key=True, max_length=128)
name = models.CharField(max_length=128)
id = models.CharField(
primary_key=True, max_length=128, verbose_name="Beschlussnummer"
)
name = models.CharField(max_length=128, verbose_name="Bezeichnung")
is_visible = models.BooleanField(default=False, verbose_name="sichtbar")
class Option(models.TextChoices):
NORMAL = "B", "normaler Beschluss"
PERMANENT = "D", "Dauerbeschluss"
FINANCE = "F", "Finanzbeschluss"
FSREF = "R", "FsRef-Beschluss"
option = models.CharField(
max_length=1, choices=Option.choices, verbose_name="Beschluss"
)
date = models.DateField(verbose_name="Datum")
voting = models.CharField(max_length=15, verbose_name="Abstimmungsverhalten")
voting_text = models.TextField(verbose_name="Abstimmungstext")
budget = models.DecimalField(
max_digits=7, decimal_places=2, default=0.00, verbose_name="Budget (EUR)"
)
class Meta:
verbose_name = "Beschluss"
verbose_name_plural = "Beschlüsse"
@@ -39,6 +59,26 @@ class Resolution(models.Model):
def __str__(self):
return f"{self.name}"
def clean(self):
if self.id == "":
year = self.date.strftime("%y")
week = self.date.strftime("%W")
_id = ""
for nmb in range(99):
_id = f"{year}{week}-{nmb + 1:02d}"
if not Resolution.objects.filter(id=_id).exists():
break
else:
raise ValidationError(
f"Es wurden zu viele Beschlüsse in dieser Woche angelegt. (ID: {_id})"
)
self.id = _id
if self.name == "":
self.name = self.id
class Wiref(models.Model):
wiref_id = models.CharField(max_length=10, blank=True, null=True)

View File

@@ -1,7 +1,14 @@
from django.urls import path
from . import apps, views
from .views import BillCreateView, BillCreateDoneView, BillListView, BillUpdateView
from .views import (
BillCreateDoneView,
BillCreateView,
BillListView,
BillUpdateView,
ResolutionCreateView,
ResolutionListView,
)
app_name = apps.FinanceConfig.name
@@ -14,4 +21,8 @@ urlpatterns = [
BillCreateDoneView.as_view(),
name="bill_create_done",
),
path(
"create-resolution/", ResolutionCreateView.as_view(), name="resolution_create"
),
path("resolutions/", ResolutionListView.as_view(), name="resolution_list"),
]

View File

@@ -9,7 +9,7 @@ from django.views.generic.edit import CreateView, UpdateView
from fet2020.utils import add_log_action
from members.models import Member
from .forms import BankDataForm, BillCreateForm, BillUpdateForm
from .forms import BankDataForm, BillCreateForm, BillUpdateForm, ResolutionCreateForm
from .models import BankData, Bill, Resolution
@@ -84,3 +84,19 @@ class BillUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
def handle_no_permission(self):
return redirect("finance:bill_list")
class ResolutionCreateView(LoginRequiredMixin, CreateView):
form_class = ResolutionCreateForm
model = Resolution
success_url = reverse_lazy("finance:resolution_list")
template_name = "finance/resolution_create.html"
def form_valid(self, form):
add_log_action(self.request, form, "finance", "resolution", True)
return super().form_valid(form)
class ResolutionListView(LoginRequiredMixin, ListView):
model = Resolution
template_name = "finance/resolution_list.html"

View File

@@ -0,0 +1,26 @@
{% extends 'base.html' %}
{% block title %}Neuen Beschluss eingeben{% endblock %}
{% block content %}
<!-- Main Content -->
<main class="container mx-auto w-full px-4 my-8 flex-1">
<h1 class="page-title">Neuen Beschluss eingeben</h1>
<div class="w-full h-full flex-1 flex justify-center items-center">
<form action="" enctype="multipart/form-data" method="POST" class="w-full max-w-xs sm:max-w-prose sm:px-28 sm:py-4 grid grid-cols-1 gap-y-3 sm:gap-y-6 text-gray-900">
{% csrf_token %}
{% include "baseform/non_field_errors.html" %}
{% include "baseform/select.html" with field=form.option %}
{% include "baseform/date.html" with field=form.date %}
{% include "baseform/text.html" with field=form.voting %}
{% include "baseform/textarea.html" with field=form.voting_text %}
<div class="flex flex-col-reverse sm:flex-row gap-3 justify-end pt-4 sm:pt-0">
<input type="submit" class="block btn btn-primary" value="Absenden">
</div>
</form>
</div>
</main>
{% endblock %}

View File

@@ -0,0 +1,48 @@
{% extends "base.html" %}
{% block title %}Beschlusssammlung{% endblock %}
{% block content %}
<!-- Main Content -->
<main class="container mx-auto w-full px-4 my-8 flex-1">
<h1 class="page-title">Beschlusssammlung</h1>
<section>
<div class="mx-auto max-w-prose flex flex-col gap-4">
{% for result in object_list %}
<article class="flex-grow-0">
<h2 class="line-clamp-1 hover:underline decoration-1 text-gray-800 dark:text-gray-200 font-medium">{{ result.id }}: {{ result.name }}</h2>
<ul class="text-gray-700 dark:text-gray-300 text-sm sm:text-base">
<li><i class="fa-fw text-gray-600 dark:text-gray-400 mr-1"></i>{{ result.get_option_display }}</li>
<li><i class="fa-fw text-gray-600 dark:text-gray-400 mr-1"></i>{{ result.date }}</li>
<li><i class="fa-fw text-gray-600 dark:text-gray-400 mr-1"></i>Abstimmungsverhalten: {{ result.voting }}</li>
</ul>
</article>
{% endfor %}
</div>
</section>
{% if not object_list %}
<section>
<div class="mx-auto max-w-prose flex flex-col gap-4">
<h2 class="mb-1 text-gray-700 dark:text-gray-200">Keinen Beschluss in dieser Liste.</h2>
</div>
</section>
{% endif %}
<div class="flex flex-col gap-y-4 max-w-prose mx-auto text-gray-700 dark:text-gray-300">
<section>
<div class="flex flex-col md:flex-row gap-y-2 md:gap-y-0 md:gap-x-2 lg:justify-end mt-4">
<a
href="{% url 'finance:resolution_create' %}"
class="btn btn-primary block md:flex-grow lg:flex-grow-0"
>
<i class="fa-solid fa-plus-square mr-2"></i>Beschluss eingeben
</a>
</div>
</section>
</div>
</main>
{% endblock %}

View File

@@ -49,12 +49,24 @@
<span class="text-sm font-medium">Neue Rechnung einreichen</span>
</a>
</li>
<li>
<a href="{% url 'finance:resolution_create' %}" class="flex items-center py-2 px-5 hover:bg-gray-100 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-white">
<i class="fa-solid fa-plus mr-2"></i>
<span class="text-sm font-medium">Neuen Beschluss eingeben</span>
</a>
</li>
<li>
<a href="{% url 'finance:bill_list' %}" class="flex items-center py-2 px-5 hover:bg-gray-100 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-white">
<i class="fa-solid fa-list mr-2"></i>
<span class="text-sm font-medium">Deine eingereichten Rechnungen</span>
</a>
</li>
<li>
<a href="{% url 'finance:resolution_list' %}" class="flex items-center py-2 px-5 hover:bg-gray-100 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-white">
<i class="fa-solid fa-list mr-2"></i>
<span class="text-sm font-medium">Beschlusssammlung</span>
</a>
</li>
</ul>
</div>