from datetime import date, timedelta 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'), ] RECHTSGRUNDLAGE_CHOICES = [ ('vgv', 'VgV'), ('uvgo', 'UVgO'), ('vob_a', 'VOB/A'), ('sektvo', 'SektVO'), ('gwb', 'GWB'), ('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) rechtsgrundlage = models.CharField(max_length=20, choices=RECHTSGRUNDLAGE_CHOICES, blank=True) rechtsgrundlage_details = models.TextField(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) bindefrist_tage = models.PositiveSmallIntegerField(null=True, blank=True, help_text='Bindefrist in Tagen ab Abgabe') # 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) referenzen = models.ManyToManyField( 'bibliothek.Referenz', blank=True, related_name='ausschreibungen' ) # 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) archiviert = models.BooleanField(default=False, db_index=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 bindefrist_berechnet(self): """Enddatum aus abgabe_bis + bindefrist_tage, falls kein festes bindefrist-Datum.""" if self.bindefrist: return self.bindefrist if self.abgabe_bis and self.bindefrist_tage: return (self.abgabe_bis + timedelta(days=self.bindefrist_tage)).date() return None @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))