We are building, workplan now registered with statehub
This commit is contained in:
parent
14b0bc6d01
commit
f202b71c75
37 changed files with 2036 additions and 22 deletions
52
vergabe_teilnahme/apps/lose/forms.py
Normal file
52
vergabe_teilnahme/apps/lose/forms.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
from django import forms
|
||||
|
||||
from vergabe_teilnahme.apps.accounts.models import Mitarbeiter
|
||||
|
||||
from .models import Anforderung, Los
|
||||
|
||||
|
||||
class LosForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Los
|
||||
fields = ['losnummer', 'lostitel', 'beschreibung', 'abgrenzung', 'zustaendiger', 'teilnahme']
|
||||
widgets = {
|
||||
'losnummer': forms.TextInput(attrs={'class': 'form-input', 'autofocus': True}),
|
||||
'lostitel': forms.TextInput(attrs={'class': 'form-input'}),
|
||||
'beschreibung': forms.Textarea(attrs={'class': 'form-input', 'rows': 3}),
|
||||
'abgrenzung': forms.Textarea(attrs={'class': 'form-input', 'rows': 3}),
|
||||
'zustaendiger': forms.Select(attrs={'class': 'form-input'}),
|
||||
'teilnahme': forms.NullBooleanSelect(attrs={'class': 'form-input'}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
ausschreibung = kwargs.pop('ausschreibung', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['teilnahme'].required = False
|
||||
|
||||
|
||||
class AnforderungForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Anforderung
|
||||
fields = [
|
||||
'titel', 'beschreibung', 'quelle_im_dokument', 'kategorie', 'verbindlichkeit',
|
||||
'ausschlusskriterium', 'bewertungskriterium', 'zustaendiger',
|
||||
'erfuellungsstatus', 'nachweis_erforderlich', 'los',
|
||||
]
|
||||
widgets = {
|
||||
'titel': forms.TextInput(attrs={'class': 'form-input', 'autofocus': True}),
|
||||
'beschreibung': forms.Textarea(attrs={'class': 'form-input', 'rows': 3}),
|
||||
'quelle_im_dokument': forms.TextInput(attrs={'class': 'form-input'}),
|
||||
'kategorie': forms.Select(attrs={'class': 'form-input'}),
|
||||
'verbindlichkeit': forms.RadioSelect(),
|
||||
'zustaendiger': forms.Select(attrs={'class': 'form-input'}),
|
||||
'erfuellungsstatus': forms.Select(attrs={'class': 'form-input'}),
|
||||
'los': forms.Select(attrs={'class': 'form-input'}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, ausschreibung=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if ausschreibung is not None:
|
||||
self.fields['los'].queryset = Los.objects.filter(ausschreibung=ausschreibung)
|
||||
self.fields['los'].required = False
|
||||
self.fields['zustaendiger'].required = False
|
||||
self.fields['kategorie'].required = False
|
||||
|
|
@ -1,3 +1,114 @@
|
|||
from django.test import TestCase
|
||||
import factory
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
|
||||
# Create your tests here.
|
||||
from vergabe_teilnahme.apps.ausschreibungen.models import Ausschreibung
|
||||
from vergabe_teilnahme.apps.ausschreibungen.tests import AusschreibungFactory
|
||||
from vergabe_teilnahme.apps.bibliothek.models import Nachweis
|
||||
|
||||
from .models import Anforderung, Los
|
||||
|
||||
|
||||
class LosFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Los
|
||||
|
||||
ausschreibung = factory.SubFactory(AusschreibungFactory)
|
||||
losnummer = factory.Sequence(lambda n: f"L{n:02d}")
|
||||
lostitel = factory.Sequence(lambda n: f"Los {n}")
|
||||
|
||||
|
||||
class AnforderungFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Anforderung
|
||||
|
||||
ausschreibung = factory.SubFactory(AusschreibungFactory)
|
||||
titel = factory.Sequence(lambda n: f"Anforderung {n}")
|
||||
verbindlichkeit = 'muss'
|
||||
erfuellungsstatus = 'offen'
|
||||
|
||||
|
||||
class NachweisFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Nachweis
|
||||
|
||||
titel = factory.Sequence(lambda n: f"Nachweis {n}")
|
||||
|
||||
|
||||
# ─── Lose ──────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_lose_liste_get(client):
|
||||
a = AusschreibungFactory()
|
||||
url = reverse('ausschreibungen:lose:liste', kwargs={'ausschreibung_id': a.pk})
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_los_neu_post(client):
|
||||
a = AusschreibungFactory()
|
||||
url = reverse('ausschreibungen:lose:neu', kwargs={'ausschreibung_id': a.pk})
|
||||
response = client.post(url, {'losnummer': 'L01', 'lostitel': 'Testlos'})
|
||||
assert response.status_code == 302
|
||||
assert Los.objects.filter(ausschreibung=a, losnummer='L01').exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_los_detail_get(client):
|
||||
los = LosFactory()
|
||||
url = reverse('ausschreibungen:lose:detail',
|
||||
kwargs={'ausschreibung_id': los.ausschreibung_id, 'los_pk': los.pk})
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
# ─── Anforderungen ─────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_anforderung_neu_post_muss(client):
|
||||
a = AusschreibungFactory()
|
||||
url = reverse('ausschreibungen:lose:anforderung_neu', kwargs={'ausschreibung_id': a.pk})
|
||||
response = client.post(url, {'titel': 'Neue Anforderung', 'verbindlichkeit': 'muss',
|
||||
'erfuellungsstatus': 'offen'})
|
||||
assert response.status_code == 302
|
||||
assert Anforderung.objects.filter(ausschreibung=a, titel='Neue Anforderung').exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_anforderung_status_htmx(client):
|
||||
anf = AnforderungFactory()
|
||||
url = reverse('ausschreibungen:lose:anforderung_status',
|
||||
kwargs={'ausschreibung_id': anf.ausschreibung_id, 'pk': anf.pk})
|
||||
response = client.post(url, {'erfuellungsstatus': 'nicht_erfuellbar'},
|
||||
HTTP_HX_REQUEST='true')
|
||||
assert response.status_code == 200
|
||||
anf.refresh_from_db()
|
||||
assert anf.erfuellungsstatus == 'nicht_erfuellbar'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_ausschlusskriterium_banner_shown(client):
|
||||
a = AusschreibungFactory()
|
||||
AnforderungFactory(
|
||||
ausschreibung=a,
|
||||
ausschlusskriterium=True,
|
||||
erfuellungsstatus='nicht_erfuellbar',
|
||||
)
|
||||
url = reverse('ausschreibungen:entscheidung', kwargs={'pk': a.pk})
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
assert b'Nicht erf\xc3\xbcllbare Ausschlusskriterien' in response.content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_nachweis_zuordnen(client):
|
||||
anf = AnforderungFactory()
|
||||
n = NachweisFactory()
|
||||
url = reverse('ausschreibungen:lose:nachweis_zuordnen',
|
||||
kwargs={'ausschreibung_id': anf.ausschreibung_id, 'pk': anf.pk})
|
||||
response = client.post(url, {'nachweis_pk': n.pk})
|
||||
assert response.status_code == 200
|
||||
assert anf.nachweise.filter(pk=n.pk).exists()
|
||||
|
|
|
|||
|
|
@ -1,2 +1,22 @@
|
|||
from django.urls import path
|
||||
urlpatterns = []
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = 'lose'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.lose_liste, name='liste'),
|
||||
path('neu/', views.los_neu, name='neu'),
|
||||
path('<int:los_pk>/', views.los_detail, name='detail'),
|
||||
path('<int:los_pk>/bearbeiten/', views.los_bearbeiten, name='bearbeiten'),
|
||||
path('<int:los_pk>/loeschen/', views.los_loeschen, name='loeschen'),
|
||||
path('anforderungen/', views.anforderungen_liste, name='anforderungen_liste'),
|
||||
path('anforderungen/neu/', views.anforderung_neu, name='anforderung_neu'),
|
||||
path('anforderungen/<int:pk>/', views.anforderung_detail, name='anforderung_detail'),
|
||||
path('anforderungen/<int:pk>/bearbeiten/', views.anforderung_bearbeiten, name='anforderung_bearbeiten'),
|
||||
path('anforderungen/<int:pk>/status/', views.anforderung_status, name='anforderung_status'),
|
||||
path('anforderungen/<int:pk>/nachweis/', views.nachweis_suche_modal, name='nachweis_suche'),
|
||||
path('anforderungen/<int:pk>/nachweis/zuordnen/', views.nachweis_zuordnen, name='nachweis_zuordnen'),
|
||||
path('anforderungen/<int:pk>/nachweis/<int:nachweis_pk>/entfernen/', views.nachweis_entfernen, name='nachweis_entfernen'),
|
||||
path('anforderungen/<int:pk>/aufgabe/', views.anforderung_aufgabe_erstellen, name='anforderung_aufgabe'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,287 @@
|
|||
from django.shortcuts import render
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
# Create your views here.
|
||||
from vergabe_teilnahme.apps.ausschreibungen.models import Ausschreibung
|
||||
from vergabe_teilnahme.apps.bibliothek.models import Nachweis
|
||||
|
||||
from .forms import AnforderungForm, LosForm
|
||||
from .models import Anforderung, Los
|
||||
|
||||
|
||||
def _is_htmx(request):
|
||||
return request.headers.get('HX-Request') == 'true'
|
||||
|
||||
|
||||
def _ausschreibung_breadcrumbs(ausschreibung, *extra):
|
||||
crumbs = [
|
||||
{'label': 'Ausschreibungen', 'url': '/ausschreibungen/'},
|
||||
{'label': ausschreibung.titel, 'url': f'/ausschreibungen/{ausschreibung.pk}/'},
|
||||
]
|
||||
for label, url in extra:
|
||||
crumbs.append({'label': label, 'url': url})
|
||||
return crumbs
|
||||
|
||||
|
||||
# ─── Lose ────────────────────────────────────────────────────────────────────
|
||||
|
||||
def lose_liste(request, ausschreibung_id):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
lose = Los.objects.filter(ausschreibung=ausschreibung).order_by('losnummer')
|
||||
return render(request, 'lose/liste.html', {
|
||||
'ausschreibung': ausschreibung,
|
||||
'lose': lose,
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung, ('Lose', None)),
|
||||
})
|
||||
|
||||
|
||||
def los_neu(request, ausschreibung_id):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
if request.method == 'POST':
|
||||
form = LosForm(request.POST, ausschreibung=ausschreibung)
|
||||
if form.is_valid():
|
||||
los = form.save(commit=False)
|
||||
los.ausschreibung = ausschreibung
|
||||
los.save()
|
||||
if _is_htmx(request):
|
||||
return render(request, 'lose/partials/los_row.html', {'los': los, 'ausschreibung': ausschreibung})
|
||||
return redirect('ausschreibungen:lose:liste', ausschreibung_id=ausschreibung_id)
|
||||
else:
|
||||
form = LosForm(ausschreibung=ausschreibung)
|
||||
return render(request, 'lose/form.html', {
|
||||
'form': form,
|
||||
'ausschreibung': ausschreibung,
|
||||
'titel': 'Los hinzufügen',
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Lose', f'/ausschreibungen/{ausschreibung_id}/lose/'),
|
||||
('Neu', None)),
|
||||
})
|
||||
|
||||
|
||||
def los_detail(request, ausschreibung_id, los_pk):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
los = get_object_or_404(Los, pk=los_pk, ausschreibung=ausschreibung)
|
||||
anforderungen = los.anforderungen.all().order_by('verbindlichkeit', 'titel')
|
||||
return render(request, 'lose/detail.html', {
|
||||
'ausschreibung': ausschreibung,
|
||||
'los': los,
|
||||
'anforderungen': anforderungen,
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Lose', f'/ausschreibungen/{ausschreibung_id}/lose/'),
|
||||
(str(los), None)),
|
||||
})
|
||||
|
||||
|
||||
def los_bearbeiten(request, ausschreibung_id, los_pk):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
los = get_object_or_404(Los, pk=los_pk, ausschreibung=ausschreibung)
|
||||
form = LosForm(request.POST or None, instance=los, ausschreibung=ausschreibung)
|
||||
if request.method == 'POST' and form.is_valid():
|
||||
form.save()
|
||||
return redirect('ausschreibungen:lose:detail', ausschreibung_id=ausschreibung_id, los_pk=los_pk)
|
||||
return render(request, 'lose/form.html', {
|
||||
'form': form,
|
||||
'ausschreibung': ausschreibung,
|
||||
'los': los,
|
||||
'titel': 'Los bearbeiten',
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Lose', f'/ausschreibungen/{ausschreibung_id}/lose/'),
|
||||
(str(los), f'/ausschreibungen/{ausschreibung_id}/lose/{los_pk}/'),
|
||||
('Bearbeiten', None)),
|
||||
})
|
||||
|
||||
|
||||
def los_loeschen(request, ausschreibung_id, los_pk):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
los = get_object_or_404(Los, pk=los_pk, ausschreibung=ausschreibung)
|
||||
if request.method == 'POST':
|
||||
los.delete()
|
||||
return redirect('ausschreibungen:lose:liste', ausschreibung_id=ausschreibung_id)
|
||||
return render(request, 'lose/loeschen_confirm.html', {
|
||||
'ausschreibung': ausschreibung,
|
||||
'los': los,
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Lose', f'/ausschreibungen/{ausschreibung_id}/lose/'),
|
||||
(str(los), f'/ausschreibungen/{ausschreibung_id}/lose/{los_pk}/'),
|
||||
('Löschen', None)),
|
||||
})
|
||||
|
||||
|
||||
# ─── Anforderungen ───────────────────────────────────────────────────────────
|
||||
|
||||
def anforderungen_liste(request, ausschreibung_id):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
qs = Anforderung.objects.filter(ausschreibung=ausschreibung).select_related('los', 'zustaendiger')
|
||||
|
||||
verbindlichkeit = request.GET.get('verbindlichkeit', '')
|
||||
if verbindlichkeit:
|
||||
qs = qs.filter(verbindlichkeit=verbindlichkeit)
|
||||
|
||||
status_filter = request.GET.get('erfuellungsstatus', '')
|
||||
if status_filter:
|
||||
qs = qs.filter(erfuellungsstatus=status_filter)
|
||||
|
||||
los_filter = request.GET.get('los', '')
|
||||
if los_filter == 'allgemein':
|
||||
qs = qs.filter(los__isnull=True)
|
||||
elif los_filter:
|
||||
qs = qs.filter(los_id=los_filter)
|
||||
|
||||
lose = Los.objects.filter(ausschreibung=ausschreibung).order_by('losnummer')
|
||||
|
||||
grouped = {}
|
||||
for los in lose:
|
||||
grouped[los] = []
|
||||
grouped[None] = []
|
||||
|
||||
for a in qs.order_by('verbindlichkeit', 'titel'):
|
||||
grouped[a.los].append(a)
|
||||
|
||||
grouped = {k: v for k, v in grouped.items() if v}
|
||||
|
||||
ctx = {
|
||||
'ausschreibung': ausschreibung,
|
||||
'grouped': grouped,
|
||||
'lose': lose,
|
||||
'verbindlichkeit_choices': Anforderung.VERBINDLICHKEIT_CHOICES,
|
||||
'erfuellung_choices': Anforderung.ERFUELLUNG_CHOICES,
|
||||
'current_verbindlichkeit': verbindlichkeit,
|
||||
'current_status': status_filter,
|
||||
'current_los': los_filter,
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung, ('Anforderungen', None)),
|
||||
}
|
||||
|
||||
if _is_htmx(request):
|
||||
return render(request, 'lose/anforderungen_liste_partial.html', ctx)
|
||||
return render(request, 'lose/anforderungen_liste.html', ctx)
|
||||
|
||||
|
||||
def anforderung_neu(request, ausschreibung_id):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
if request.method == 'POST':
|
||||
form = AnforderungForm(request.POST, ausschreibung=ausschreibung)
|
||||
if form.is_valid():
|
||||
a = form.save(commit=False)
|
||||
a.ausschreibung = ausschreibung
|
||||
a.save()
|
||||
return redirect('ausschreibungen:lose:anforderung_detail',
|
||||
ausschreibung_id=ausschreibung_id, pk=a.pk)
|
||||
else:
|
||||
los_pk = request.GET.get('los')
|
||||
initial = {'los': los_pk} if los_pk else {}
|
||||
form = AnforderungForm(ausschreibung=ausschreibung, initial=initial)
|
||||
return render(request, 'lose/anforderung_form.html', {
|
||||
'form': form,
|
||||
'ausschreibung': ausschreibung,
|
||||
'titel': 'Anforderung anlegen',
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Anforderungen', f'/ausschreibungen/{ausschreibung_id}/lose/anforderungen/'),
|
||||
('Neu', None)),
|
||||
})
|
||||
|
||||
|
||||
def anforderung_detail(request, ausschreibung_id, pk):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung=ausschreibung)
|
||||
aufgaben = anforderung.aufgaben.all().order_by('prioritaet', 'frist')
|
||||
return render(request, 'lose/anforderung_detail.html', {
|
||||
'ausschreibung': ausschreibung,
|
||||
'anforderung': anforderung,
|
||||
'aufgaben': aufgaben,
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Anforderungen', f'/ausschreibungen/{ausschreibung_id}/lose/anforderungen/'),
|
||||
(anforderung.titel[:50], None)),
|
||||
})
|
||||
|
||||
|
||||
def anforderung_bearbeiten(request, ausschreibung_id, pk):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung=ausschreibung)
|
||||
form = AnforderungForm(request.POST or None, instance=anforderung, ausschreibung=ausschreibung)
|
||||
if request.method == 'POST' and form.is_valid():
|
||||
form.save()
|
||||
return redirect('ausschreibungen:lose:anforderung_detail',
|
||||
ausschreibung_id=ausschreibung_id, pk=pk)
|
||||
return render(request, 'lose/anforderung_form.html', {
|
||||
'form': form,
|
||||
'ausschreibung': ausschreibung,
|
||||
'anforderung': anforderung,
|
||||
'titel': 'Anforderung bearbeiten',
|
||||
'breadcrumbs': _ausschreibung_breadcrumbs(ausschreibung,
|
||||
('Anforderungen', f'/ausschreibungen/{ausschreibung_id}/lose/anforderungen/'),
|
||||
(anforderung.titel[:50], f'/ausschreibungen/{ausschreibung_id}/lose/anforderungen/{pk}/'),
|
||||
('Bearbeiten', None)),
|
||||
})
|
||||
|
||||
|
||||
def anforderung_status(request, ausschreibung_id, pk):
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung_id=ausschreibung_id)
|
||||
if request.method == 'POST':
|
||||
neuer_status = request.POST.get('erfuellungsstatus')
|
||||
if neuer_status:
|
||||
anforderung.erfuellungsstatus = neuer_status
|
||||
anforderung.save(update_fields=['erfuellungsstatus'])
|
||||
return render(request, 'lose/partials/erfuellungsstatus_widget.html', {'anforderung': anforderung})
|
||||
|
||||
|
||||
# ─── Nachweise ───────────────────────────────────────────────────────────────
|
||||
|
||||
def nachweis_suche_modal(request, ausschreibung_id, pk):
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung_id=ausschreibung_id)
|
||||
q = request.GET.get('q', '')
|
||||
nachweise = Nachweis.objects.all()
|
||||
if q:
|
||||
nachweise = nachweise.filter(titel__icontains=q)
|
||||
bereits_zugeordnet = anforderung.nachweise.values_list('pk', flat=True)
|
||||
return render(request, 'lose/partials/nachweis_modal.html', {
|
||||
'anforderung': anforderung,
|
||||
'nachweise': nachweise[:20],
|
||||
'bereits_zugeordnet': list(bereits_zugeordnet),
|
||||
'q': q,
|
||||
'ausschreibung_id': ausschreibung_id,
|
||||
})
|
||||
|
||||
|
||||
def nachweis_zuordnen(request, ausschreibung_id, pk):
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung_id=ausschreibung_id)
|
||||
if request.method == 'POST':
|
||||
nachweis_pk = request.POST.get('nachweis_pk')
|
||||
if nachweis_pk:
|
||||
nachweis = get_object_or_404(Nachweis, pk=nachweis_pk)
|
||||
anforderung.nachweise.add(nachweis)
|
||||
return render(request, 'lose/partials/nachweise_liste.html', {
|
||||
'anforderung': anforderung,
|
||||
'ausschreibung_id': ausschreibung_id,
|
||||
})
|
||||
|
||||
|
||||
def nachweis_entfernen(request, ausschreibung_id, pk, nachweis_pk):
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung_id=ausschreibung_id)
|
||||
if request.method == 'POST':
|
||||
nachweis = get_object_or_404(Nachweis, pk=nachweis_pk)
|
||||
anforderung.nachweise.remove(nachweis)
|
||||
return render(request, 'lose/partials/nachweise_liste.html', {
|
||||
'anforderung': anforderung,
|
||||
'ausschreibung_id': ausschreibung_id,
|
||||
})
|
||||
|
||||
|
||||
# ─── Aufgabe aus Anforderung ─────────────────────────────────────────────────
|
||||
|
||||
def anforderung_aufgabe_erstellen(request, ausschreibung_id, pk):
|
||||
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
||||
anforderung = get_object_or_404(Anforderung, pk=pk, ausschreibung=ausschreibung)
|
||||
if request.method == 'POST':
|
||||
from vergabe_teilnahme.apps.aufgaben.models import Aufgabe
|
||||
Aufgabe.objects.create(
|
||||
ausschreibung=ausschreibung,
|
||||
los=anforderung.los,
|
||||
anforderung=anforderung,
|
||||
titel=f'Klärung: {anforderung.titel[:200]}',
|
||||
typ='fachlich',
|
||||
verantwortlicher=anforderung.zustaendiger,
|
||||
)
|
||||
return redirect('ausschreibungen:lose:anforderung_detail',
|
||||
ausschreibung_id=ausschreibung_id, pk=pk)
|
||||
return render(request, 'lose/aufgabe_erstellen_confirm.html', {
|
||||
'ausschreibung': ausschreibung,
|
||||
'anforderung': anforderung,
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue