249 lines
7.9 KiB
Python
249 lines
7.9 KiB
Python
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
|
from django.db.models import CharField, Q, Value
|
|
from django.shortcuts import redirect
|
|
from django.urls import reverse, reverse_lazy
|
|
from django.views.generic import ListView, TemplateView
|
|
from django.views.generic.detail import DetailView
|
|
from django.views.generic.edit import CreateView, UpdateView
|
|
|
|
from fet2020.utils import add_log_action
|
|
from posts.models import FetMeeting
|
|
|
|
from .forms import (
|
|
BillCreateForm,
|
|
BillUpdateForm,
|
|
ResolutionCreateForm,
|
|
ResolutionUpdateForm,
|
|
)
|
|
from .models import BankData, Bill, Resolution
|
|
|
|
|
|
def set_bankdata(
|
|
creator, name: str, iban: str, bic: str, saving: bool, address: str = ""
|
|
) -> BankData:
|
|
if not name or not iban or not bic:
|
|
return None
|
|
|
|
# Replace whitespaces in iban and bic text.
|
|
iban = iban.replace(" ", "")
|
|
bic = bic.replace(" ", "")
|
|
|
|
obj, created = BankData.objects.get_or_create(
|
|
name=name,
|
|
iban=iban,
|
|
bic=bic,
|
|
defaults={"bankdata_creator": creator, "is_disabled": not saving, "address": address},
|
|
)
|
|
|
|
if not created and address:
|
|
BankData.objects.filter(id=obj.id).update(address=address)
|
|
|
|
if saving:
|
|
# Disable old bank data.
|
|
qs = BankData.objects.filter(
|
|
~Q(id=obj.id) & Q(bankdata_creator=obj.bankdata_creator) & Q(is_disabled=False)
|
|
)
|
|
qs.update(is_disabled=True)
|
|
|
|
return obj
|
|
|
|
|
|
class BillCreateView(LoginRequiredMixin, CreateView):
|
|
form_class = BillCreateForm
|
|
model = Bill
|
|
template_name = "finance/bill_create.html"
|
|
|
|
def form_valid(self, form):
|
|
# Get or create bankdata object.
|
|
creator = form.cleaned_data["bill_creator"]
|
|
name = form.cleaned_data["name_text"]
|
|
iban = form.cleaned_data["iban_text"]
|
|
bic = form.cleaned_data["bic_text"]
|
|
saving = form.cleaned_data["saving"]
|
|
form.instance.bankdata = set_bankdata(creator, name, iban, bic, saving)
|
|
|
|
add_log_action(self.request, form, "finance", "bill", True)
|
|
return super().form_valid(form)
|
|
|
|
def get_form_kwargs(self):
|
|
kwargs = super().get_form_kwargs()
|
|
|
|
# Request user for bill creator.
|
|
kwargs["user"] = self.request.user
|
|
return kwargs
|
|
|
|
def get_success_url(self):
|
|
return reverse("finance:bill_create_done", kwargs={"pk": self.object.pk})
|
|
|
|
|
|
class BillCreateDoneView(LoginRequiredMixin, TemplateView):
|
|
template_name = "finance/bill_create_done.html"
|
|
|
|
|
|
class BillListView(LoginRequiredMixin, ListView):
|
|
model = Bill
|
|
template_name = "finance/index.html"
|
|
|
|
paginate_by = 10
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["bill_status"] = Bill.Status
|
|
|
|
return context
|
|
|
|
def get_queryset(self):
|
|
qs = (
|
|
Bill.objects.filter(bill_creator__username=self.request.user)
|
|
.values("amount", "status", "id", "date", "purpose")
|
|
.annotate(model=Value("BILL", output_field=CharField()))
|
|
)
|
|
|
|
return qs.order_by("-date", "purpose")
|
|
|
|
|
|
class BillUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
|
|
form_class = BillUpdateForm
|
|
model = Bill
|
|
success_url = reverse_lazy("finance:bill_list")
|
|
template_name = "finance/bill_update.html"
|
|
|
|
def form_valid(self, form):
|
|
if self.object.status == Bill.Status.INCOMPLETED:
|
|
# Set status to submitted if changes are valid and bill is incompleted.
|
|
self.object.status = Bill.Status.SUBMITTED
|
|
|
|
# Override only_digital db value by value of new only_digital.
|
|
if "file_field" in form.changed_data:
|
|
self.object.only_digital = form.cleaned_data["only_digital_new"]
|
|
|
|
# Get or create bankdata object.
|
|
creator = form.cleaned_data["bill_creator"]
|
|
name = form.cleaned_data["name_text"]
|
|
iban = form.cleaned_data["iban_text"]
|
|
bic = form.cleaned_data["bic_text"]
|
|
saving = form.cleaned_data["saving"]
|
|
form.instance.bankdata = set_bankdata(creator, name, iban, bic, saving)
|
|
|
|
add_log_action(self.request, form, "finance", "bill", False)
|
|
return super().form_valid(form)
|
|
|
|
# Call bill if it's only yours.
|
|
def test_func(self):
|
|
return self.get_object().bill_creator.username == self.request.user.username
|
|
|
|
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 ResolutionDetailView(LoginRequiredMixin, DetailView):
|
|
model = Resolution
|
|
pk_url_kwarg = "id"
|
|
template_name = "finance/resolution_detail.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["fetmeeting"] = (
|
|
FetMeeting.objects.get_queryset().filter(date=self.object.date).first()
|
|
)
|
|
|
|
return context
|
|
|
|
|
|
class ResolutionListView(LoginRequiredMixin, ListView):
|
|
model = Resolution
|
|
template_name = "finance/resolution_list.html"
|
|
|
|
ordering = ["-id"]
|
|
paginate_by = 10
|
|
_per_page = 10
|
|
_per_page_lst = ["10", "20", "50", "Alle"]
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
self.q = request.GET.get("q", "")
|
|
|
|
self.options_filters = request.GET.getlist("options", [])
|
|
|
|
self._per_page = request.GET.get("paginate_by", "10")
|
|
if self._per_page == "Alle":
|
|
self.paginate_by = None
|
|
else:
|
|
self.paginate_by = self._per_page
|
|
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context["q"] = self.q
|
|
|
|
# Add selected and all options
|
|
context["options"] = Resolution.Option.choices
|
|
context["selected_options"] = self.options_filters
|
|
|
|
# Add current per page value and list
|
|
context["per_page"] = self._per_page
|
|
context["per_page_values"] = self._per_page_lst
|
|
|
|
# Add paginator links
|
|
if context["is_paginated"]:
|
|
_page_obj = context["page_obj"]
|
|
|
|
base_url = "?"
|
|
for option in self.options_filters:
|
|
base_url += f"options={option}&".replace(" ", "+")
|
|
if self.q:
|
|
base_url += f"q={self.q}&".replace(" ", "+")
|
|
end_url = f"paginate_by={self._per_page}"
|
|
|
|
if _page_obj.has_previous():
|
|
context["prev_page"] = (
|
|
f"{base_url}page={_page_obj.previous_page_number()}&{end_url}"
|
|
)
|
|
context["first_page"] = f"{base_url}page=1&{end_url}"
|
|
|
|
if _page_obj.has_next():
|
|
context["next_page"] = f"{base_url}page={_page_obj.next_page_number()}&{end_url}"
|
|
context["last_page"] = f"{base_url}page={_page_obj.paginator.num_pages}&{end_url}"
|
|
|
|
return context
|
|
|
|
def get_queryset(self):
|
|
qs = super().get_queryset()
|
|
|
|
if self.q:
|
|
qs = qs.filter(Q(name__icontains=self.q) | Q(voting_text__icontains=self.q))
|
|
|
|
if self.options_filters:
|
|
filter_lst = [
|
|
elem[0] for elem in Resolution.Option.choices if elem[1] in self.options_filters
|
|
]
|
|
qs = qs.filter(option__in=filter_lst)
|
|
|
|
return qs
|
|
|
|
|
|
class ResolutionUpdateView(LoginRequiredMixin, UpdateView):
|
|
form_class = ResolutionUpdateForm
|
|
model = Resolution
|
|
pk_url_kwarg = "id"
|
|
success_url = reverse_lazy("finance:resolution_list")
|
|
template_name = "finance/resolution_update.html"
|
|
|
|
def form_valid(self, form):
|
|
add_log_action(self.request, form, "finance", "resolution", False)
|
|
return super().form_valid(form)
|