211 lines
6.0 KiB
Python
211 lines
6.0 KiB
Python
from django.core.validators import FileExtensionValidator, ValidationError
|
|
from django.db import models
|
|
from django.urls import reverse
|
|
|
|
from members.models import Member
|
|
|
|
|
|
class BankData(models.Model):
|
|
# members can be deleted but never their bank datas
|
|
bankdata_creator = models.ForeignKey(
|
|
Member,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
verbose_name="Verknüpfung zum Mitglied",
|
|
)
|
|
name = models.CharField(max_length=128, verbose_name="Kontoinhaber:in")
|
|
iban = models.CharField(max_length=34, verbose_name="IBAN")
|
|
bic = models.CharField(max_length=11, verbose_name="BIC")
|
|
|
|
is_disabled = models.BooleanField(default=False, verbose_name="deaktiviert")
|
|
|
|
class Meta:
|
|
verbose_name = "Bankdaten"
|
|
verbose_name_plural = "Bankdaten"
|
|
|
|
def __str__(self):
|
|
return f"{self.name} - {self.iban}"
|
|
|
|
def clean(self):
|
|
if self.iban:
|
|
self.iban = self.iban.replace(" ", "")
|
|
|
|
if self.bic:
|
|
self.bic = self.bic.replace(" ", "")
|
|
|
|
|
|
class Resolution(models.Model):
|
|
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"
|
|
|
|
def __str__(self):
|
|
return f"{self.id} / {self.name}"
|
|
|
|
def get_absolute_url(self):
|
|
return reverse("finance:resolution_detail", kwargs={"id": self.id})
|
|
|
|
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)
|
|
|
|
file_field = models.FileField(
|
|
upload_to="uploads/finance/wiref/",
|
|
validators=[FileExtensionValidator(["pdf"])],
|
|
blank=True,
|
|
null=True,
|
|
verbose_name="Wiref Formular",
|
|
)
|
|
|
|
class Status(models.TextChoices):
|
|
OPENED = "O", "Offen"
|
|
SUBMITTED = "S", "Eingereicht"
|
|
TRANSFERRED = "T", "Überwiesen"
|
|
|
|
status = models.CharField(
|
|
max_length=1,
|
|
choices=Status.choices,
|
|
default=Status.OPENED,
|
|
verbose_name="Status",
|
|
)
|
|
|
|
class Meta:
|
|
verbose_name = "Wiref Formular"
|
|
verbose_name_plural = "Wiref Formulare"
|
|
|
|
def __str__(self):
|
|
return f"{self.wiref_id}"
|
|
|
|
|
|
class Bill(models.Model):
|
|
# members can be deleted but never their bills
|
|
bill_creator = models.ForeignKey(
|
|
Member, on_delete=models.PROTECT, blank=True, null=True, verbose_name="Verantwortliche:r"
|
|
)
|
|
|
|
bankdata = models.ForeignKey(
|
|
BankData,
|
|
on_delete=models.SET_NULL,
|
|
blank=True,
|
|
null=True,
|
|
verbose_name="Kontodaten",
|
|
)
|
|
|
|
resolution = models.ForeignKey(
|
|
Resolution,
|
|
on_delete=models.SET_NULL,
|
|
blank=True,
|
|
null=True,
|
|
verbose_name="Beschlussnummer",
|
|
)
|
|
|
|
date = models.DateField()
|
|
invoice = models.TextField()
|
|
amount = models.DecimalField(max_digits=7, decimal_places=2, verbose_name="Betrag (EUR)")
|
|
purpose = models.CharField(max_length=140, verbose_name="Verwendungszweck")
|
|
|
|
class Affiliation(models.TextChoices):
|
|
VEREIN = "V", "Vereinsbudget"
|
|
OFFICIAL = "B", "Offizielles Budget"
|
|
REPRESENTATION = "R", "Bundesvertretung"
|
|
|
|
affiliation = models.CharField(
|
|
max_length=1, choices=Affiliation.choices, verbose_name="Abrechnungsbudget"
|
|
)
|
|
|
|
class Payer(models.TextChoices):
|
|
ME = "M", "Privat"
|
|
VEREIN = "V", "Verein (Safe/Kreditkarte)"
|
|
|
|
payer = models.CharField(
|
|
max_length=1,
|
|
choices=Payer.choices,
|
|
verbose_name="Wie wurde die Rechnung bezahlt?",
|
|
)
|
|
|
|
only_digital = models.BooleanField(default=False, verbose_name="Digitale Rechnung")
|
|
|
|
file_field = models.FileField(
|
|
upload_to="uploads/finance/bills/",
|
|
validators=[FileExtensionValidator(["pdf"])],
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
|
|
comment = models.TextField(blank=True, null=True)
|
|
|
|
class Status(models.TextChoices):
|
|
SUBMITTED = "S", "Eingereicht"
|
|
INCOMPLETED = "I", "Unvollständig"
|
|
CLEARED = "C", "Abgerechnet"
|
|
FINISHED = "F", "Abgeschlossen"
|
|
|
|
status = models.CharField(
|
|
max_length=1,
|
|
choices=Status.choices,
|
|
default=Status.SUBMITTED,
|
|
verbose_name="Status",
|
|
)
|
|
|
|
wiref = models.ForeignKey(
|
|
Wiref,
|
|
on_delete=models.SET_NULL,
|
|
blank=True,
|
|
null=True,
|
|
verbose_name="Wiref",
|
|
)
|
|
|
|
date_created = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
verbose_name = "Rechnung"
|
|
verbose_name_plural = "Rechnungen"
|
|
|
|
def __str__(self):
|
|
return f"{self.purpose}"
|
|
|
|
def clean(self):
|
|
if self.status is None:
|
|
self.status = Bill.Status.SUBMITTED
|