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

+
+
+ {% 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 %} + +
+ +
+
+
+
+{% endblock %} diff --git a/fet2020/templates/finance/resolution_list.html b/fet2020/templates/finance/resolution_list.html new file mode 100644 index 00000000..09128353 --- /dev/null +++ b/fet2020/templates/finance/resolution_list.html @@ -0,0 +1,48 @@ +{% extends "base.html" %} + +{% block title %}Beschlusssammlung{% endblock %} + +{% block content %} + +
+

Beschlusssammlung

+ +
+
+ + {% for result in object_list %} +
+

{{ result.id }}: {{ result.name }}

+
    +
  • {{ result.get_option_display }}
  • +
  • {{ result.date }}
  • +
  • Abstimmungsverhalten: {{ result.voting }}
  • +
+
+ {% endfor %} + +
+
+ + {% if not object_list %} +
+
+

Keinen Beschluss in dieser Liste.

+
+
+ {% endif %} + +
+
+ +
+
+
+{% endblock %} diff --git a/fet2020/templates/home.html b/fet2020/templates/home.html index eea2510f..57d1224e 100644 --- a/fet2020/templates/home.html +++ b/fet2020/templates/home.html @@ -49,12 +49,24 @@ Neue Rechnung einreichen +
  • + + + Neuen Beschluss eingeben + +
  • Deine eingereichten Rechnungen
  • +
  • + + + Beschlusssammlung + +