Files
vergabe-teilnahme/vergabe_teilnahme/apps/ausschreibungen/views.py

196 lines
6.6 KiB
Python

from datetime import date, timedelta
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from vergabe_teilnahme.apps.accounts.models import Mitarbeiter
from .models import Ausschreibung
def _is_htmx(request):
return request.headers.get('HX-Request') == 'true'
def dashboard(request):
from vergabe_teilnahme.apps.aufgaben.models import Aufgabe
heute = date.today()
in_14_tagen = heute + timedelta(days=14)
ctx = {
'kritische_fristen': Ausschreibung.objects.filter(
abgabe_bis__date__lte=in_14_tagen,
abgabe_bis__date__gte=heute,
status__lt=10,
).order_by('abgabe_bis')[:10],
'ohne_entscheidung': Ausschreibung.objects.filter(
teilnahmeentscheidung='offen',
erstellt_am__lte=timezone.now() - timedelta(days=3),
status__lt=10,
).order_by('erstellt_am')[:10],
'ueberfaellige_aufgaben': Aufgabe.objects.filter(
frist__lt=heute,
status__in=['offen', 'in_bearbeitung', 'wartend_intern', 'wartend_sub', 'wartend_ausschreiber'],
).select_related('ausschreibung').order_by('frist')[:15],
'laufende_ausschreibungen': Ausschreibung.objects.filter(
status__range=(1, 9),
).order_by('-geaendert_am')[:10],
'breadcrumbs': [{'label': 'Übersicht', 'url': None}],
}
return render(request, 'ausschreibungen/dashboard.html', ctx)
def ausschreibung_liste(request):
qs = Ausschreibung.objects.all()
status_filter = request.GET.get('status')
if status_filter:
qs = qs.filter(status=status_filter)
archiviert = request.GET.get('archiviert', '0') == '1'
qs = qs.filter(archiviert=archiviert)
bid_manager_filter = request.GET.get('bid_manager')
if bid_manager_filter:
qs = qs.filter(bid_manager=bid_manager_filter)
qs = qs.select_related('bid_manager').order_by('-geaendert_am')
ctx = {
'ausschreibungen': qs,
'status_choices': Ausschreibung.STATUS_CHOICES,
'mitarbeiter': Mitarbeiter.objects.all(),
'archiviert': archiviert,
'current_status': status_filter or '',
'current_bid_manager': bid_manager_filter or '',
'breadcrumbs': [{'label': 'Ausschreibungen', 'url': None}],
}
if _is_htmx(request):
return render(request, 'ausschreibungen/liste_partial.html', ctx)
return render(request, 'ausschreibungen/liste.html', ctx)
def ausschreibung_neu(request):
from .forms import AusschreibungForm
historisch = request.GET.get('historisch') == '1'
if request.method == 'POST':
form = AusschreibungForm(request.POST)
if form.is_valid():
a = form.save()
return redirect('ausschreibungen:detail', pk=a.pk)
else:
form = AusschreibungForm()
return render(request, 'ausschreibungen/form.html', {
'form': form,
'historisch': historisch,
'titel': 'Neue Ausschreibung',
'breadcrumbs': [
{'label': 'Ausschreibungen', 'url': '/ausschreibungen/'},
{'label': 'Neu', 'url': None},
],
})
def ausschreibung_detail(request, pk):
from vergabe_teilnahme.apps.core.services import build_phase_nav, get_deadline_warnings
a = get_object_or_404(Ausschreibung, pk=pk)
ctx = {
'ausschreibung': a,
'ausschreibung_id': pk,
'phases': build_phase_nav(a),
'warnungen': get_deadline_warnings(a),
'breadcrumbs': [
{'label': 'Ausschreibungen', 'url': '/ausschreibungen/'},
{'label': a.titel, 'url': None},
],
}
return render(request, 'ausschreibungen/detail.html', ctx)
def ausschreibung_bearbeiten(request, pk):
from .forms import AusschreibungForm
a = get_object_or_404(Ausschreibung, pk=pk)
form = AusschreibungForm(request.POST or None, instance=a)
if request.method == 'POST' and form.is_valid():
form.save()
return redirect('ausschreibungen:detail', pk=pk)
return render(request, 'ausschreibungen/form.html', {
'form': form,
'titel': 'Ausschreibung bearbeiten',
'ausschreibung': a,
'breadcrumbs': [
{'label': 'Ausschreibungen', 'url': '/ausschreibungen/'},
{'label': a.titel, 'url': f'/ausschreibungen/{pk}/'},
{'label': 'Bearbeiten', 'url': None},
],
})
def ausschreibung_status(request, pk):
a = get_object_or_404(Ausschreibung, pk=pk)
if request.method == 'POST':
neuer_status = request.POST.get('status')
if neuer_status and neuer_status.isdigit():
a.status = int(neuer_status)
a.save(update_fields=['status', 'geaendert_am'])
return render(request, 'ausschreibungen/partials/status_widget.html', {'ausschreibung': a})
def ausschreibung_entscheidung(request, pk):
from .services import entscheidungsregel_auswertung
a = get_object_or_404(Ausschreibung, pk=pk)
if request.method == 'POST':
a.teilnahmeentscheidung = request.POST.get('teilnahmeentscheidung', 'offen')
a.entscheidungsbegruendung = request.POST.get('begruendung', a.entscheidungsbegruendung)
if a.teilnahmeentscheidung in ['teilnahme', 'ablehnung']:
a.status = max(a.status, 3)
a.save()
return redirect('ausschreibungen:detail', pk=pk)
from vergabe_teilnahme.apps.lose.models import Anforderung
ausschlusskriterien = Anforderung.objects.filter(
ausschreibung=a,
ausschlusskriterium=True,
erfuellungsstatus='nicht_erfuellbar',
).select_related('los')
ctx = {
'ausschreibung': a,
'regelergebnis': entscheidungsregel_auswertung(a),
'ausschlusskriterien_nicht_erfuellbar': ausschlusskriterien,
'breadcrumbs': [
{'label': 'Ausschreibungen', 'url': '/ausschreibungen/'},
{'label': a.titel, 'url': f'/ausschreibungen/{pk}/'},
{'label': 'Teilnahmeentscheidung', 'url': None},
],
}
return render(request, 'ausschreibungen/entscheidung.html', ctx)
def ausschreibung_archivieren(request, pk):
a = get_object_or_404(Ausschreibung, pk=pk)
if request.method == 'POST':
a.archiviert = True
a.status = 13
a.save(update_fields=['archiviert', 'status', 'geaendert_am'])
return redirect('ausschreibungen:liste')
return render(request, 'ausschreibungen/archivieren_confirm.html', {
'ausschreibung': a,
'breadcrumbs': [
{'label': 'Ausschreibungen', 'url': '/ausschreibungen/'},
{'label': a.titel, 'url': f'/ausschreibungen/{pk}/'},
{'label': 'Archivieren', 'url': None},
],
})