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", "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): def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {} extra_context = extra_context or {}
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." 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") only_digital = cleaned_data.get("only_digital")
file_field = cleaned_data.get("file_field") 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. # check that amount is valid because invalid amount is a NoneType.
if amount: if amount:
if amount > 30 and resolution == "": if amount > 30 and resolution == "":
@@ -212,6 +220,29 @@ class BillUpdateForm(forms.ModelForm):
self.fields["comment"].disabled = True 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 BillInlineForm(forms.ModelForm):
class Meta: class Meta:
fields = [ fields = [
@@ -273,6 +304,7 @@ class BillAdminForm(forms.ModelForm):
class ResolutionAdminForm(forms.ModelForm): class ResolutionAdminForm(forms.ModelForm):
total = forms.CharField() total = forms.CharField()
budget_remaining = forms.CharField()
class Meta: class Meta:
model = Resolution model = Resolution
@@ -280,14 +312,16 @@ class ResolutionAdminForm(forms.ModelForm):
fields = [ fields = [
"name", "name",
"id", "id",
"date",
"option",
"is_visible", "is_visible",
"budget",
"total", "total",
"budget_remaining",
"voting",
"voting_text",
] ]
labels = {
"id": "ID",
}
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set 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"].label = "Gesamtsumme (EUR)"
self.fields["total"].required = False 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): class WirefAdminForm(forms.ModelForm):
total = forms.CharField() total = forms.CharField()

View File

@@ -27,11 +27,31 @@ class BankData(models.Model):
class Resolution(models.Model): class Resolution(models.Model):
id = models.CharField(primary_key=True, max_length=128) id = models.CharField(
name = models.CharField(max_length=128) 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") 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: class Meta:
verbose_name = "Beschluss" verbose_name = "Beschluss"
verbose_name_plural = "Beschlüsse" verbose_name_plural = "Beschlüsse"
@@ -39,6 +59,26 @@ class Resolution(models.Model):
def __str__(self): def __str__(self):
return f"{self.name}" 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): class Wiref(models.Model):
wiref_id = models.CharField(max_length=10, blank=True, null=True) wiref_id = models.CharField(max_length=10, blank=True, null=True)

View File

@@ -1,7 +1,14 @@
from django.urls import path from django.urls import path
from . import apps, views 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 app_name = apps.FinanceConfig.name
@@ -14,4 +21,8 @@ urlpatterns = [
BillCreateDoneView.as_view(), BillCreateDoneView.as_view(),
name="bill_create_done", 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 fet2020.utils import add_log_action
from members.models import Member from members.models import Member
from .forms import BankDataForm, BillCreateForm, BillUpdateForm from .forms import BankDataForm, BillCreateForm, BillUpdateForm, ResolutionCreateForm
from .models import BankData, Bill, Resolution from .models import BankData, Bill, Resolution
@@ -84,3 +84,19 @@ class BillUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
def handle_no_permission(self): def handle_no_permission(self):
return redirect("finance:bill_list") 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> <span class="text-sm font-medium">Neue Rechnung einreichen</span>
</a> </a>
</li> </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> <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"> <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> <i class="fa-solid fa-list mr-2"></i>
<span class="text-sm font-medium">Deine eingereichten Rechnungen</span> <span class="text-sm font-medium">Deine eingereichten Rechnungen</span>
</a> </a>
</li> </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> </ul>
</div> </div>