generated from coulomb/repo-seed
Implementiert UC-MB-01 bis UC-MB-03: Marktbegleiter-Katalog (Liste, Detail, Anlegen/Bearbeiten), Ausschreibungspassagen mit Verlässlichkeitsscore (1–10, Validator), Musterauswertung mit Aggregationen (Ausschreiber-Häufigkeit, Ø-Score, Passagen-Anzahl). 4 Tests grün. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
4.7 KiB
Python
111 lines
4.7 KiB
Python
from django import forms
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
|
|
from vergabe_teilnahme.apps.ausschreibungen.models import Ausschreibung
|
|
from vergabe_teilnahme.apps.dokumente.models import Dokument
|
|
|
|
from .models import Ausschreibungspassage, Marktbegleiter
|
|
|
|
|
|
KATEGORIE_CHOICES = [
|
|
('formulierung', 'Formulierung'),
|
|
('leistungsmerkmal', 'Leistungsmerkmal'),
|
|
('zertifizierung', 'Zertifizierung'),
|
|
('referenz', 'Referenz'),
|
|
('sonstiges', 'Sonstiges'),
|
|
]
|
|
|
|
|
|
class AusschreibungspassageForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Ausschreibungspassage
|
|
fields = [
|
|
'passage', 'marktbegleiter', 'dokument', 'fundstelle',
|
|
'kategorie', 'verlaesslichkeitsscore',
|
|
'begruendung_zuordnung', 'auswirkung_entscheidung',
|
|
'auswirkung_preisstrategie', 'auswirkung_loesungskonzept',
|
|
]
|
|
widgets = {
|
|
'passage': forms.Textarea(attrs={'class': 'form-input', 'rows': 6}),
|
|
'marktbegleiter': forms.Select(attrs={'class': 'form-select'}),
|
|
'dokument': forms.Select(attrs={'class': 'form-select'}),
|
|
'fundstelle': forms.TextInput(attrs={'class': 'form-input'}),
|
|
'kategorie': forms.Select(attrs={'class': 'form-select'}, choices=[('', '---------')] + KATEGORIE_CHOICES),
|
|
'verlaesslichkeitsscore': forms.NumberInput(attrs={
|
|
'class': 'form-input', 'type': 'range', 'min': 1, 'max': 10,
|
|
'x-model': 'score',
|
|
}),
|
|
'begruendung_zuordnung': forms.Textarea(attrs={'class': 'form-input', 'rows': 2}),
|
|
'auswirkung_entscheidung': forms.Textarea(attrs={'class': 'form-input', 'rows': 2}),
|
|
'auswirkung_preisstrategie': forms.Textarea(attrs={'class': 'form-input', 'rows': 2}),
|
|
'auswirkung_loesungskonzept': forms.Textarea(attrs={'class': 'form-input', 'rows': 2}),
|
|
}
|
|
|
|
def __init__(self, *args, ausschreibung=None, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.fields['marktbegleiter'].queryset = Marktbegleiter.objects.all()
|
|
if ausschreibung:
|
|
self.fields['dokument'].queryset = Dokument.objects.filter(ausschreibung=ausschreibung)
|
|
else:
|
|
self.fields['dokument'].queryset = Dokument.objects.none()
|
|
self.fields['dokument'].required = False
|
|
self.fields['fundstelle'].required = False
|
|
self.fields['kategorie'].required = False
|
|
self.fields['begruendung_zuordnung'].required = False
|
|
self.fields['auswirkung_entscheidung'].required = False
|
|
self.fields['auswirkung_preisstrategie'].required = False
|
|
self.fields['auswirkung_loesungskonzept'].required = False
|
|
|
|
|
|
def passagen_liste(request, ausschreibung_id):
|
|
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
|
passagen = Ausschreibungspassage.objects.filter(
|
|
ausschreibung=ausschreibung
|
|
).select_related('marktbegleiter', 'dokument').order_by('-verlaesslichkeitsscore')
|
|
return render(request, 'marktbegleiter/passagen_liste.html', {
|
|
'ausschreibung': ausschreibung,
|
|
'passagen': passagen,
|
|
})
|
|
|
|
|
|
def passage_neu(request, ausschreibung_id):
|
|
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
|
form = AusschreibungspassageForm(
|
|
request.POST or None, ausschreibung=ausschreibung
|
|
)
|
|
if form.is_valid():
|
|
passage = form.save(commit=False)
|
|
passage.ausschreibung = ausschreibung
|
|
passage.save()
|
|
return redirect('marktbegleiter:passagen:liste', ausschreibung_id=ausschreibung_id)
|
|
return render(request, 'marktbegleiter/passage_form.html', {
|
|
'form': form,
|
|
'ausschreibung': ausschreibung,
|
|
'neu': True,
|
|
})
|
|
|
|
|
|
def passage_detail(request, ausschreibung_id, pk):
|
|
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
|
passage = get_object_or_404(Ausschreibungspassage, pk=pk, ausschreibung=ausschreibung)
|
|
return render(request, 'marktbegleiter/passage_detail.html', {
|
|
'ausschreibung': ausschreibung,
|
|
'passage': passage,
|
|
})
|
|
|
|
|
|
def passage_bearbeiten(request, ausschreibung_id, pk):
|
|
ausschreibung = get_object_or_404(Ausschreibung, pk=ausschreibung_id)
|
|
passage = get_object_or_404(Ausschreibungspassage, pk=pk, ausschreibung=ausschreibung)
|
|
form = AusschreibungspassageForm(
|
|
request.POST or None, instance=passage, ausschreibung=ausschreibung
|
|
)
|
|
if form.is_valid():
|
|
form.save()
|
|
return redirect('marktbegleiter:passagen:detail', ausschreibung_id=ausschreibung_id, pk=pk)
|
|
return render(request, 'marktbegleiter/passage_form.html', {
|
|
'form': form,
|
|
'ausschreibung': ausschreibung,
|
|
'passage': passage,
|
|
})
|