From 1da1ccf9897183e1c8d6be09a6a70a4f7fd68f25 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Sat, 28 Dec 2019 13:58:35 +0100
Subject: [PATCH] Refactor and redesign

---
 schoolapps/fibu/forms.py                      | 19 +---
 .../migrations/0002_auto_20191228_1357.py     | 90 +++++++++++++++++++
 schoolapps/fibu/models.py                     | 30 ++++---
 .../fibu/templates/fibu/account/edit.html     | 14 ++-
 .../fibu/templates/fibu/account/index.html    | 52 +++++------
 .../fibu/templates/fibu/booking/check.html    | 24 ++---
 schoolapps/fibu/views.py                      | 56 ++++++------
 7 files changed, 182 insertions(+), 103 deletions(-)
 create mode 100644 schoolapps/fibu/migrations/0002_auto_20191228_1357.py

diff --git a/schoolapps/fibu/forms.py b/schoolapps/fibu/forms.py
index a808ea334..6ee071405 100644
--- a/schoolapps/fibu/forms.py
+++ b/schoolapps/fibu/forms.py
@@ -2,7 +2,7 @@ from django import forms
 from django.contrib.auth.models import User
 from material import Layout, Row, Fieldset
 
-from .models import YEARLIST, Booking, Costcenter, Account, status_choices
+from .models import YEARS, Booking, Costcenter, Account, status_choices
 
 
 class BookingForm(forms.ModelForm):
@@ -19,11 +19,8 @@ class BookingForm(forms.ModelForm):
 
 
 class CheckBookingForm(forms.ModelForm):
-    accounts = Account.objects.filter().order_by('costcenter', 'name')
-    account = forms.ModelChoiceField(required=False, queryset=accounts, label='Buchungskonto')
-
     class Meta:
-        model = Account
+        model = Booking
         fields = ('account',)
 
 
@@ -66,7 +63,7 @@ class BookBookingForm(forms.ModelForm):
 
 class CostCenterForm(forms.ModelForm):
     name = forms.CharField(max_length=30, label='Kostenstelle')
-    year = forms.ChoiceField(choices=YEARLIST, label='Jahr')
+    year = forms.ChoiceField(choices=YEARS, label='Jahr')
 
     layout = Layout(Row('name', 'year'))
 
@@ -75,15 +72,7 @@ class CostCenterForm(forms.ModelForm):
         fields = ('id', 'name', 'year')
 
 
-class EditAccountForm(forms.ModelForm):
-    name = forms.CharField(max_length=30, label='Buchungskonto')
-    costcenterlist = Costcenter.objects.filter()
-    costcenter = forms.ModelChoiceField(queryset=costcenterlist, label='Kostenstelle')
-    income = forms.BooleanField(label='Budget-/Einnanhmekonto', required=False)
-    budget = forms.IntegerField(label='Budget')
-
-    layout = Layout(Row('name', 'costcenter', 'income', 'budget'))
-
+class AccountForm(forms.ModelForm):
     class Meta:
         model = Account
         fields = ('id', 'name', 'costcenter', 'income', 'budget')
diff --git a/schoolapps/fibu/migrations/0002_auto_20191228_1357.py b/schoolapps/fibu/migrations/0002_auto_20191228_1357.py
new file mode 100644
index 000000000..5150e026d
--- /dev/null
+++ b/schoolapps/fibu/migrations/0002_auto_20191228_1357.py
@@ -0,0 +1,90 @@
+# Generated by Django 2.2.6 on 2019-12-28 12:57
+
+import datetime
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('fibu', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='account',
+            options={'permissions': [('manage_account', 'Can manage account')], 'verbose_name': 'Buchungskonto',
+                     'verbose_name_plural': 'Buchungskonten'},
+        ),
+        migrations.AlterModelOptions(
+            name='booking',
+            options={
+                'permissions': [('manage_booking', 'Can manage bookings'), ('request_booking', 'Can request a booking'),
+                                ('check_booking', 'Can check bookings')], 'verbose_name': 'Buchung',
+                'verbose_name_plural': 'Buchungen'},
+        ),
+        migrations.AlterModelOptions(
+            name='costcenter',
+            options={'permissions': [('manage_costcenter', 'Can manage costcenter')], 'verbose_name': 'Kostenstelle',
+                     'verbose_name_plural': 'Kostenstellen'},
+        ),
+        migrations.AlterField(
+            model_name='account',
+            name='budget',
+            field=models.DecimalField(decimal_places=2, default=0.0, max_digits=9, verbose_name='Budget'),
+        ),
+        migrations.AlterField(
+            model_name='account',
+            name='costcenter',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fibu.Costcenter',
+                                    verbose_name='Kostenstelle'),
+        ),
+        migrations.AlterField(
+            model_name='account',
+            name='income',
+            field=models.BooleanField(default=False, verbose_name='Einnahmekonto'),
+        ),
+        migrations.AlterField(
+            model_name='account',
+            name='name',
+            field=models.CharField(max_length=20, verbose_name='Buchungskonto'),
+        ),
+        migrations.AlterField(
+            model_name='booking',
+            name='booking_date',
+            field=models.DateField(default=datetime.date.today),
+        ),
+        migrations.AlterField(
+            model_name='booking',
+            name='invoice_date',
+            field=models.DateField(default=datetime.date.today),
+        ),
+        migrations.AlterField(
+            model_name='booking',
+            name='maturity',
+            field=models.DateField(default=datetime.date.today),
+        ),
+        migrations.AlterField(
+            model_name='booking',
+            name='status',
+            field=models.IntegerField(
+                choices=[(0, 'beantragt'), (1, 'abgelehnt'), (2, 'bewilligt'), (3, 'bestellt'), (4, 'eingereicht'),
+                         (5, 'bezahlt')], default=0, verbose_name='Status'),
+        ),
+        migrations.AlterField(
+            model_name='booking',
+            name='submission_date',
+            field=models.DateField(default=datetime.date.today),
+        ),
+        migrations.AlterField(
+            model_name='costcenter',
+            name='name',
+            field=models.CharField(max_length=30, verbose_name='Kostenstelle'),
+        ),
+        migrations.AlterField(
+            model_name='costcenter',
+            name='year',
+            field=models.IntegerField(choices=[(2019, '2019'), (2020, '2020'), (2021, '2021'), (2022, '2022')],
+                                      default=2019, verbose_name='Jahr'),
+        ),
+    ]
diff --git a/schoolapps/fibu/models.py b/schoolapps/fibu/models.py
index 04c0b5a34..be68eb87e 100644
--- a/schoolapps/fibu/models.py
+++ b/schoolapps/fibu/models.py
@@ -1,12 +1,10 @@
+from django.utils import timezone
 from django.db import models
 from django.contrib.auth.models import User
 from datetime import date
 
-# TODO: Make dynamic
-YEARLIST = [(2020, '2020'),
-            (2021, '2021'),
-            (2022, '2022'),
-            (2023, '2023')]
+current_year = timezone.now().year
+YEARS = [(x, str(x)) for x in range(current_year, current_year + 4)]
 
 
 class Status:
@@ -32,13 +30,15 @@ status_choices = [(x, val.name) for x, val in enumerate(status_list)]
 
 class Costcenter(models.Model):
     # Kostenstellen z.B. Schulträger-konsumtiv, Schulträger-investiv, Elternverein, ...
-    name = models.CharField(max_length=30)
-    year = models.IntegerField(default=2019, choices=YEARLIST, verbose_name="Jahr")
+    name = models.CharField(max_length=30, blank=False, verbose_name="Kostenstelle")
+    year = models.IntegerField(default=timezone.now().year, choices=YEARS, blank=False, verbose_name="Jahr")
 
     def __str__(self):
         return self.name
 
     class Meta:
+        verbose_name = "Kostenstelle"
+        verbose_name_plural = "Kostenstellen"
         permissions = [
             ('manage_costcenter', 'Can manage costcenter'),
         ]
@@ -46,10 +46,11 @@ class Costcenter(models.Model):
 
 class Account(models.Model):
     # Buchungskonten, z.B. Fachschaften, Sekretariat, Schulleiter, Kopieren, Tafelnutzung
-    name = models.CharField(max_length=20, default='')
-    costcenter = models.ForeignKey(to=Costcenter, on_delete=models.CASCADE, default='')
-    income = models.BooleanField(default=False)  # True, wenn es sich um ein Einnahmekonto handelt
-    budget = models.DecimalField(max_digits=9, decimal_places=2, default=0.00)
+    name = models.CharField(max_length=20, blank=False, verbose_name="Buchungskonto")
+    costcenter = models.ForeignKey(to=Costcenter, on_delete=models.CASCADE, blank=False, verbose_name="Kostenstelle")
+    income = models.BooleanField(default=False,
+                                 verbose_name="Einnahmekonto")  # True, wenn es sich um ein Einnahmekonto handelt
+    budget = models.DecimalField(max_digits=9, decimal_places=2, default=0.00, verbose_name="Budget")
     saldo = models.DecimalField(max_digits=9, decimal_places=2, default=0.00)
     rest = models.DecimalField(max_digits=9, decimal_places=2, default=0.00)
 
@@ -57,6 +58,8 @@ class Account(models.Model):
         return "{}: {}".format(self.costcenter, self.name)
 
     class Meta:
+        verbose_name = "Buchungskonto"
+        verbose_name_plural = "Buchungskonten"
         permissions = [
             ('manage_account', 'Can manage account'),
         ]
@@ -83,7 +86,12 @@ class Booking(models.Model):
     def get_status(self):
         return status_list[self.status]
 
+    def __str__(self):
+        return "{} ({})".format(self.description, self.account)
+
     class Meta:
+        verbose_name = "Buchung"
+        verbose_name_plural = "Buchungen"
         permissions = [
             ('manage_booking', 'Can manage bookings'),
             ('request_booking', 'Can request a booking'),
diff --git a/schoolapps/fibu/templates/fibu/account/edit.html b/schoolapps/fibu/templates/fibu/account/edit.html
index 85616988e..c977c32d4 100644
--- a/schoolapps/fibu/templates/fibu/account/edit.html
+++ b/schoolapps/fibu/templates/fibu/account/edit.html
@@ -2,21 +2,19 @@
 {% load material_form %}
 
 <main>
+    <h4>Buchungskonto bearbeiten</h4>
 
-   <h4>Buchungskonto bearbeiten</h4>
-
-    <form method="POST" style="background: #eee">
+    <form method="POST" action="">
         {% csrf_token %}
         {% form form=form %}
         {% endform %}
+
         <span class="right">
             <button type="submit" class="waves-effect waves-light btn green">
-            <i class="material-icons left">send</i> Änderungen übernehmen
-            </button>
-            <a href="{% url 'account' %}">
-            <button type="button" class="waves-effect waves-light btn grey">
-            <i class="material-icons left">cancel</i> Abbrechen
+                <i class="material-icons left">save</i> Änderungen übernehmen
             </button>
+            <a href="{% url 'account' %}" class="waves-effect waves-light btn red">
+                <i class="material-icons left">cancel</i> Abbrechen
             </a>
         </span>
     </form>
diff --git a/schoolapps/fibu/templates/fibu/account/index.html b/schoolapps/fibu/templates/fibu/account/index.html
index 58a8ea4fc..1451f422c 100755
--- a/schoolapps/fibu/templates/fibu/account/index.html
+++ b/schoolapps/fibu/templates/fibu/account/index.html
@@ -2,8 +2,7 @@
 {% load material_form %}
 
 <main>
-
-   <a class="waves-effect waves-light btn green modal-trigger right" href="#new-modal">
+    <a class="waves-effect waves-light btn green modal-trigger right" href="#new-modal">
         <i class="material-icons left">add</i> Buchungskonto anlegen
     </a>
 
@@ -34,47 +33,44 @@
     </form>
 
     <table>
-    <thead>
-    <tr>
-        <th>Buchungskonto</th>
-        <th>Kostenstelle</th>
-        <th>erwartete Einnahmen</th>
-        <th>erwartete Ausgaben</th>
-        <th>Aktionen</th>
-    </tr>
-    </thead>
-    <tbody>
+        <thead>
+        <tr>
+            <th>Buchungskonto</th>
+            <th>Kostenstelle</th>
+            <th>erwartete Einnahmen</th>
+            <th>erwartete Ausgaben</th>
+            <th>Aktionen</th>
+        </tr>
+        </thead>
+        <tbody>
         {% for account in accounts %}
             <tr>
                 <td>{{ account.name }}</td>
                 <td>{{ account.costcenter }}</td>
-                {%  if account.income %}
-                    <td>{{ account.budget }}</td>
+                {% if account.income %}
+                    <td class="green-text">{{ account.budget }}</td>
                     <td></td>
                 {% else %}
                     <td></td>
-                    <td>{{ account.budget }}</td>
+                    <td class="red-text">{{ account.budget }}</td>
                 {% endif %}
                 <td class="right-align">
-                    <form action="{% url 'account_edit' account.id %}" class="left">
-                        {% csrf_token %}
-                        <input type="hidden" value="{{ account.id }}" name="account-id">
-                        <button type="submit" name="edit"
-                                class="waves-effect waves-light btn-flat btn-flat-medium" title="Bearbeiten">
-                            <i class="material-icons center green-text">create</i>
-                        </button>
-                    </form>
+                    <a href="{% url 'account_edit' account.id %}"
+                       class="waves-effect waves-light btn-flat btn-flat-medium left" title="Bearbeiten">
+                        <i class="material-icons center green-text">create</i>
+                    </a>
                     <form action="" method="POST" class="left">
                         {% csrf_token %}
-                            <input type="hidden" value="{{ account.id }}" name="account-id">
-                            <button type="submit" onclick="return confirm('Wollen Sie das Buchungskonto wirklich löschen?')" name="cancel" class="waves-effect waves-light btn-flat btn-flat-medium" title="Löschen">
-                                <i class="material-icons center red-text">cancel</i>
-                            </button>
+                        <input type="hidden" value="{{ account.id }}" name="id">
+                        <button type="submit" onclick="return confirm('Buchungskonto wirklich löschen?')"
+                                name="cancel" class="waves-effect waves-light btn-flat btn-flat-medium" title="Löschen">
+                            <i class="material-icons center red-text">cancel</i>
+                        </button>
                     </form>
                 </td>
             </tr>
         {% endfor %}
-    </tbody>
+        </tbody>
     </table>
 </main>
 {% include 'partials/footer.html' %}
diff --git a/schoolapps/fibu/templates/fibu/booking/check.html b/schoolapps/fibu/templates/fibu/booking/check.html
index 67e9ee228..9dad97f53 100755
--- a/schoolapps/fibu/templates/fibu/booking/check.html
+++ b/schoolapps/fibu/templates/fibu/booking/check.html
@@ -8,12 +8,12 @@
             Keine offenen Anträge vorhanden
         </span>
     {% else %}
-        <div class="collection-item row grey white-text">
-            <span class="col s2">Antragsteller</span>
-            <span class="col s3">Anschaffungswunsch</span>
-            <span class="col s2 right-align">Geplante Kosten</span>
-            <span class="col s3">Buchungskonto</span>
-            <span class="col s2">Aktionen</span>
+        <div class="collection-item row">
+            <div class="col s2"><strong>Antragsteller</strong></div>
+            <div class="col s3"><strong>Anschaffungswunsch</strong></div>
+            <div class="col s2 right-align"><strong>Geplante Kosten</strong></div>
+            <div class="col s3"><strong>Buchungskonto</strong></div>
+            <div class="col s2"><strong>Aktionen</strong></div>
         </div>
 
         {% for booking in filter.qs %}
@@ -21,11 +21,11 @@
                 <form method="POST">
                     {% csrf_token %}
                     <input type="hidden" value="{{ booking.id }}" name="booking-id">
-                    <span class="col s2">{{ booking.contact.get_full_name }}</span>
-                    <span class="col s3">{{ booking.description }}</span>
-                    <span class="col s2 right-align">{{ booking.planned_amount }} €</span>
-                    <span class="col s3">{{ form.account }}</span>
-                    <span  class="col s2">
+                    <div class="col s2">{{ booking.contact.get_full_name }}</div>
+                    <div class="col s3">{{ booking.description }}</div>
+                    <div class="col s2 right-align">{{ booking.planned_amount }} €</div>
+                    <div class="col s3">{{ form.account }}</div>
+                    <div class="col s2">
                         <button type="submit" name="allow"
                                 class="waves-effect waves-light btn-flat btn-flat-medium" title="Annehmen">
                             <i class="material-icons center green-text">check_circle</i>
@@ -34,7 +34,7 @@
                                 class="waves-effect waves-light btn-flat btn-flat-medium" title="Ablehnen">
                             <i class="material-icons center red-text">not_interested</i>
                         </button>
-                    </span>
+                    </div>
                 </form>
             </div>
         {% endfor %}
diff --git a/schoolapps/fibu/views.py b/schoolapps/fibu/views.py
index d95ab2bd1..33bcd20aa 100644
--- a/schoolapps/fibu/views.py
+++ b/schoolapps/fibu/views.py
@@ -5,7 +5,7 @@ from django.urls import reverse
 from django.shortcuts import render, redirect, get_object_or_404
 from .models import Booking, Costcenter, Account
 from .filters import BookingFilter
-from .forms import BookingForm, CheckBookingForm, BookBookingForm, CostCenterForm, EditAccountForm
+from .forms import BookingForm, CheckBookingForm, BookBookingForm, CostCenterForm, AccountForm
 
 
 @login_required
@@ -190,30 +190,25 @@ def cost_center_edit(request, id):
 @login_required
 @permission_required('fibu.manage_account')
 def account(request):
+    form = AccountForm()
+
     if request.method == 'POST':
-        if 'account-id' in request.POST:
-            account_id = request.POST['account-id']
+        if 'account-id' in request.POST and 'cancel' in request.POST:
+            account_id = request.POST['id']
             account = Account.objects.get(id=account_id)
-            if 'cancel' in request.POST:
-                account.delete()
+            account.delete()
 
-                print('Eintrag gelöscht')
-                return redirect('account')
-            print('Edit-Form erstellt ############# form.is_valid:', form.is_valid())
-            form = EditAccountForm(instance=account)
+            messages.success(request, "Das Buchungskonto wurde erfolgreich gelöscht")
+            return redirect('account')
         else:
-            form = EditAccountForm(request.POST or None)
-    else:
-        form = EditAccountForm()
+            form = AccountForm(request.POST)
+
     if form.is_valid():
-        name = form.cleaned_data['name']
-        costcenter = form.cleaned_data['costcenter']
-        income = form.cleaned_data['income']
-        budget = form.cleaned_data['budget']
-        account = Account(name=name, costcenter=costcenter, income=income, budget=budget)
-        account.save()
+        form.save()
 
+        messages.success(request, "Das Buchungskonto wurde erfolgreich angelegt.")
         return redirect('account')
+
     accounts = Account.objects.filter()
     context = {'accounts': accounts, 'form': form}
     return render(request, 'fibu/account/index.html', context)
@@ -223,17 +218,19 @@ def account(request):
 @permission_required('fibu.manage_account')
 def account_edit(request, id):
     account = get_object_or_404(Account, id=id)
-    form = EditAccountForm(instance=account)
-    template = 'fibu/account/edit.html'
+    form = AccountForm(instance=account)
+
     if request.method == 'POST':
-        form = EditAccountForm(request.POST, instance=account)
-        print('\n\n\nBLUBB', form)
+        form = AccountForm(request.POST, instance=account)
+
         if form.is_valid():
             form.save()
 
+            messages.success(request, "Die Änderungen am Buchungskonto wurden erfolgreich übernommen.")
             return redirect(reverse('account'))
+
     context = {'form': form}
-    return render(request, template, context)
+    return render(request, 'fibu/account/edit.html', context)
 
 
 @login_required
@@ -245,11 +242,11 @@ def reports(request):
 @login_required
 @permission_required('fibu.manage_booking')
 def expenses(request):
-    costcenterlist = Costcenter.objects.filter()
-    costcenter_accounts = {}
+    cost_centers = Costcenter.objects.filter()
+    cost_center_accounts = {}
     account_rests = {}
-    for costcenter in costcenterlist:
-        accounts = Account.objects.filter(costcenter=costcenter)
+    for cost_center in cost_centers:
+        accounts = Account.objects.filter(costcenter=cost_center)
         # update saldo
         for account in accounts:
             saldo = Booking.objects.filter(account=account).aggregate(Sum('amount'))
@@ -263,6 +260,7 @@ def expenses(request):
             except:
                 Account.objects.filter(id=account.id).update(saldo=0, rest=0)
 
-        costcenter_accounts[costcenter.name] = list(Account.objects.filter(costcenter=costcenter).order_by('-income'))
-    context = {'costcenter_accounts': costcenter_accounts, 'account_rests': account_rests}
+        cost_center_accounts[cost_center.name] = list(
+            Account.objects.filter(costcenter=cost_center).order_by('-income'))
+    context = {'costcenter_accounts': cost_center_accounts, 'account_rests': account_rests}
     return render(request, 'fibu/reports/expenses.html', context)
-- 
GitLab