{{ result.id }}: {{ result.name }}
+-
+
- {{ result.get_option_display }} +
- {{ result.date }} +
- Abstimmungsverhalten: {{ result.voting }} +
diff --git a/fet2020/finance/admin.py b/fet2020/finance/admin.py
index 007b7e11..892e4d23 100644
--- a/fet2020/finance/admin.py
+++ b/fet2020/finance/admin.py
@@ -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."
diff --git a/fet2020/finance/forms.py b/fet2020/finance/forms.py
index aea2d6d2..26fd64f3 100644
--- a/fet2020/finance/forms.py
+++ b/fet2020/finance/forms.py
@@ -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()
diff --git a/fet2020/finance/models.py b/fet2020/finance/models.py
index 1f05f39c..5c7a937f 100644
--- a/fet2020/finance/models.py
+++ b/fet2020/finance/models.py
@@ -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)
diff --git a/fet2020/finance/urls.py b/fet2020/finance/urls.py
index e8ba6d19..8d7947b1 100644
--- a/fet2020/finance/urls.py
+++ b/fet2020/finance/urls.py
@@ -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"),
]
diff --git a/fet2020/finance/views.py b/fet2020/finance/views.py
index c474e640..6d4a0c80 100644
--- a/fet2020/finance/views.py
+++ b/fet2020/finance/views.py
@@ -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"
diff --git a/fet2020/templates/finance/resolution_create.html b/fet2020/templates/finance/resolution_create.html
new file mode 100644
index 00000000..17452de6
--- /dev/null
+++ b/fet2020/templates/finance/resolution_create.html
@@ -0,0 +1,26 @@
+{% extends 'base.html' %}
+
+{% block title %}Neuen Beschluss eingeben{% endblock %}
+
+{% block content %}
+
+Neuen Beschluss eingeben
+ Beschlusssammlung
+
+ {{ result.id }}: {{ result.name }}
+
+
+ Keinen Beschluss in dieser Liste.
+