171 lines
6 KiB
Python
171 lines
6 KiB
Python
from datetime import datetime
|
||
from dateutil.relativedelta import relativedelta
|
||
|
||
from django import forms
|
||
from django.utils.translation import gettext_lazy as _
|
||
|
||
from .models import RoadAuthorization, RoadAuthorizationDocument, RoadAuthorizationDate
|
||
|
||
# Default initial datetime for occupation dates: next month
|
||
_DEFAULT_DATE = lambda: (datetime.today() + relativedelta(months=1)).strftime('%Y-%m-%d')
|
||
|
||
|
||
class AuthorizationForm(forms.ModelForm):
|
||
"""Main authorization request form – no crispy forms dependency."""
|
||
|
||
class Meta:
|
||
model = RoadAuthorization
|
||
fields = (
|
||
'language',
|
||
'type',
|
||
'description',
|
||
'location',
|
||
'applicant_name',
|
||
'applicant_email',
|
||
'applicant_address',
|
||
'applicant_enterprise',
|
||
)
|
||
widgets = {
|
||
'type': forms.RadioSelect(attrs={'class': 'btn-check', 'autocomplete': 'off'}),
|
||
'language': forms.RadioSelect(attrs={'class': 'btn-check', 'autocomplete': 'off'}),
|
||
}
|
||
|
||
# Hidden field that receives the GeoJSON polygon drawn on the MapLibre map.
|
||
# The view converts it to a MultiPolygonField before saving.
|
||
geom_geojson = forms.CharField(
|
||
widget=forms.HiddenInput(),
|
||
required=True,
|
||
label='',
|
||
)
|
||
|
||
def __init__(self, *args, **kwargs):
|
||
super().__init__(*args, **kwargs)
|
||
# Remove the blank "-------" choice Django injects when there is no default value
|
||
self.fields['type'].choices = [
|
||
(k, v) for k, v in self.fields['type'].choices if k != ''
|
||
]
|
||
self.fields['language'].choices = [
|
||
(k, v) for k, v in self.fields['language'].choices if k != ''
|
||
]
|
||
self.fields['description'].widget.attrs.update({'class': 'form-control', 'rows': 5})
|
||
self.fields['location'].widget.attrs.update({'class': 'form-control'})
|
||
self.fields['applicant_name'].widget.attrs.update({'class': 'form-control'})
|
||
self.fields['applicant_email'].widget.attrs.update({'class': 'form-control'})
|
||
self.fields['applicant_address'].widget.attrs.update({'class': 'form-control'})
|
||
self.fields['applicant_enterprise'].widget.attrs.update({'class': 'form-control'})
|
||
|
||
def clean_geom_geojson(self):
|
||
"""Validate that the submitted GeoJSON is a valid polygon."""
|
||
import json
|
||
value = self.cleaned_data.get('geom_geojson', '').strip()
|
||
if not value:
|
||
raise forms.ValidationError(_("Veuillez dessiner la zone concernée sur la carte."))
|
||
try:
|
||
geom = json.loads(value)
|
||
except (ValueError, TypeError):
|
||
raise forms.ValidationError(_("Géométrie invalide."))
|
||
if geom.get('type') not in ('Polygon', 'MultiPolygon'):
|
||
raise forms.ValidationError(_("Veuillez dessiner un polygone."))
|
||
return value
|
||
|
||
|
||
class AuthorizationDocumentForm(forms.ModelForm):
|
||
class Meta:
|
||
model = RoadAuthorizationDocument
|
||
fields = ('description', 'file')
|
||
widgets = {
|
||
'description': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Description du document')}),
|
||
'file': forms.ClearableFileInput(attrs={'class': 'form-control'}),
|
||
}
|
||
|
||
|
||
AuthorizationDocumentFormSet = forms.inlineformset_factory(
|
||
RoadAuthorization,
|
||
RoadAuthorizationDocument,
|
||
form=AuthorizationDocumentForm,
|
||
extra=1,
|
||
can_delete=False,
|
||
)
|
||
|
||
|
||
class AuthorizationDateForm(forms.ModelForm):
|
||
class Meta:
|
||
model = RoadAuthorizationDate
|
||
fields = ('begin_date', 'end_date')
|
||
widgets = {
|
||
'begin_date': forms.DateTimeInput(
|
||
attrs={
|
||
'type': 'datetime-local',
|
||
'class': 'form-control',
|
||
}
|
||
),
|
||
'end_date': forms.DateTimeInput(
|
||
attrs={
|
||
'type': 'datetime-local',
|
||
'class': 'form-control',
|
||
}
|
||
),
|
||
}
|
||
|
||
def __init__(self, *args, **kwargs):
|
||
super().__init__(*args, **kwargs)
|
||
self.fields['end_date'].required = False
|
||
|
||
|
||
AuthorizationDateFormSet = forms.inlineformset_factory(
|
||
RoadAuthorization,
|
||
RoadAuthorizationDate,
|
||
form=AuthorizationDateForm,
|
||
extra=1,
|
||
can_delete=False,
|
||
)
|
||
|
||
|
||
class AuthorizationFilterForm(forms.Form):
|
||
"""Filter form used on the staff list view."""
|
||
include_archives = forms.BooleanField(
|
||
label=_("Inclure les archives (> 2 ans)"),
|
||
required=False,
|
||
widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
||
)
|
||
authorization_type = forms.MultipleChoiceField(
|
||
label=_("Type d'autorisation"),
|
||
choices=RoadAuthorization.AUTH_TYPE,
|
||
widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
|
||
required=False,
|
||
)
|
||
agent = forms.MultipleChoiceField(
|
||
label=_("Agent traitant"),
|
||
widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
|
||
required=False,
|
||
)
|
||
search_text = forms.CharField(
|
||
max_length=250,
|
||
required=False,
|
||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Recherche…')}),
|
||
)
|
||
|
||
def __init__(self, *args, **kwargs):
|
||
super().__init__(*args, **kwargs)
|
||
from django.contrib.auth import get_user_model
|
||
from django.db.models import Q
|
||
from common.utils import get_short_name
|
||
User = get_user_model()
|
||
|
||
agent_ids = RoadAuthorization.objects.exclude(agent__isnull=True).values_list('agent_id', flat=True)
|
||
agent_qs = User.objects.filter(
|
||
Q(id__in=agent_ids) |
|
||
Q(config__accessible_views__code='authorizations') |
|
||
Q(is_superuser=True)
|
||
).distinct()
|
||
|
||
agent_choices = [
|
||
('unassigned', _("Non assigné")),
|
||
]
|
||
user_list = [
|
||
(str(u.pk), get_short_name(u)) for u in agent_qs
|
||
]
|
||
user_list.sort(key=lambda x: x[1].lower())
|
||
agent_choices.extend(user_list)
|
||
self.fields['agent'].choices = agent_choices
|
||
|