Files
vergabe-teilnahme/vergabe_teilnahme/apps/ausschreibungen/models.py
2026-05-08 14:26:48 +02:00

108 lines
3.7 KiB
Python

from datetime import date
from django.db import models
from vergabe_teilnahme.apps.core.models import FlexibleModel
class Ausschreibung(FlexibleModel):
STATUS_CHOICES = [
(1, 'Recherche & Unterlagen'),
(2, 'Teilnahmeentscheidung'),
(3, 'Detaillierte Durchsicht'),
(4, 'Klärungsphase'),
(5, 'Preismodell'),
(6, 'Unterlagen finalisieren'),
(7, 'Abgabe'),
(8, 'Zuschlag / Nachbetrachtung'),
(9, 'Abgegeben'),
(10, 'Gewonnen'),
(11, 'Verloren'),
(12, 'Aufgehoben'),
(13, 'Zurückgezogen'),
]
TEILNAHME_CHOICES = [
('offen', 'Offen'),
('teilnahme', 'Teilnahme'),
('ablehnung', 'Ablehnung'),
]
VERGABEART_CHOICES = [
('oeffentlich', 'Öffentliche Ausschreibung'),
('beschraenkt', 'Beschränkte Ausschreibung'),
('freihanding', 'Freihändige Vergabe'),
('wettbewerb', 'Wettbewerb'),
('rahmenvertrag', 'Rahmenvertrag'),
('sonstige', 'Sonstige'),
]
titel = models.CharField(max_length=400)
ausschreiber = models.CharField(max_length=300)
vergabeplattform = models.CharField(max_length=200, blank=True)
vergabenummer = models.CharField(max_length=100, blank=True)
vergabeart = models.CharField(max_length=30, choices=VERGABEART_CHOICES, blank=True)
status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, default=1)
teilnahmeentscheidung = models.CharField(
max_length=20, choices=TEILNAHME_CHOICES, default='offen'
)
entscheidungsbegruendung = models.TextField(blank=True)
# Fristen
veroeffentlichungsdatum = models.DateField(null=True, blank=True)
bieterfragen_bis = models.DateField(null=True, blank=True)
abgabe_bis = models.DateTimeField(null=True, blank=True)
bindefrist = models.DateField(null=True, blank=True)
# Verantwortlichkeiten
bid_manager = models.ForeignKey(
'accounts.Mitarbeiter', on_delete=models.SET_NULL,
null=True, blank=True, related_name='verwaltete_ausschreibungen'
)
team = models.ManyToManyField(
'accounts.Mitarbeiter', blank=True, related_name='team_ausschreibungen'
)
# Beschreibung & Klassifizierung
leistungsbeschreibung = models.TextField(blank=True)
branche = models.CharField(max_length=200, blank=True)
schlagwoerter = models.CharField(max_length=500, blank=True)
geschaetztes_volumen = models.DecimalField(max_digits=14, decimal_places=2, null=True, blank=True)
laufzeit = models.CharField(max_length=100, blank=True)
optionen = models.TextField(blank=True)
# Herkunft & Dokumente
fundstelle_url = models.URLField(max_length=1000, blank=True)
unterlagen_erhalten = models.BooleanField(default=False)
unterlagen_erhalten_am = models.DateField(null=True, blank=True)
# Timestamps
erstellt_am = models.DateTimeField(auto_now_add=True)
geaendert_am = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-erstellt_am']
verbose_name = 'Ausschreibung'
verbose_name_plural = 'Ausschreibungen'
def __str__(self):
return self.titel
@property
def ist_aktiv(self):
return 1 <= self.status <= 9
@property
def naechste_frist(self):
heute = date.today()
kandidaten = []
if self.bieterfragen_bis and self.bieterfragen_bis >= heute:
kandidaten.append(self.bieterfragen_bis)
if self.abgabe_bis:
abgabe = self.abgabe_bis.date() if hasattr(self.abgabe_bis, 'date') else self.abgabe_bis
if abgabe >= heute:
kandidaten.append(abgabe)
return min(kandidaten) if kandidaten else None
@property
def phase_nummer(self):
return min(8, max(1, self.status))