339 lines
12 KiB
Python
339 lines
12 KiB
Python
import datetime
|
|
import calendar
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
from django.utils import timezone
|
|
from django.shortcuts import redirect, reverse
|
|
from django.views import generic
|
|
from django.core.mail import send_mail
|
|
from django.forms import modelformset_factory
|
|
from django.contrib import messages
|
|
|
|
from utilisateurs.mixins import MaraudeurMixin
|
|
|
|
from .models import ( Maraude, Maraudeur,
|
|
CompteRendu,
|
|
Rencontre, Lieu,
|
|
Planning, )
|
|
# Forms
|
|
from .forms import ( RencontreForm,
|
|
ObservationInlineFormSet,
|
|
MaraudeHiddenDateForm, MonthSelectForm,
|
|
AppelForm, SignalementForm,
|
|
SendMailForm )
|
|
from notes.mixins import NoteFormMixin
|
|
|
|
|
|
def derniers_sujets_rencontres():
|
|
""" Renvoie le 'set' des sujets rencontrés dans les deux dernières maraudes """
|
|
sujets = set()
|
|
for cr in list(CompteRendu.objects.filter(heure_fin__isnull=False))[-2:]:
|
|
for obs in cr.get_observations():
|
|
sujets.add(obs.sujet)
|
|
return list(sujets)
|
|
|
|
|
|
|
|
class IndexView(NoteFormMixin, MaraudeurMixin, generic.TemplateView):
|
|
|
|
template_name = "maraudes/index.html"
|
|
|
|
#NoteFormMixin
|
|
forms = {
|
|
'appel': AppelForm,
|
|
'signalement': SignalementForm,
|
|
}
|
|
|
|
def get_initial(self):
|
|
now = timezone.localtime(timezone.now())
|
|
return {'created_date': now.date(),
|
|
'created_time': now.time()}
|
|
|
|
def get_success_url(self):
|
|
return reverse('maraudes:index')
|
|
|
|
def get_context_data(self, *args, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['prochaine_maraude'] = Maraude.objects.get_next_of(self.request.user)
|
|
context['derniers_sujets_rencontres'] = derniers_sujets_rencontres()
|
|
|
|
if self.request.user.is_superuser:
|
|
context['missing_cr'] = CompteRendu.objects.get_queryset().filter(
|
|
heure_fin__isnull=True,
|
|
date__lt = timezone.localtime(timezone.now()).date()
|
|
)
|
|
return context
|
|
|
|
|
|
## COMPTE-RENDU DE MARAUDE
|
|
|
|
|
|
def redirect_to_current_compterendu(request):
|
|
prochaine_maraude = Maraude.objects.get_next_of(request.user)
|
|
current_date = timezone.localtime(timezone.now()).date()
|
|
if (not prochaine_maraude or
|
|
not prochaine_maraude.date == current_date):
|
|
return redirect("maraudes:index")
|
|
|
|
kwargs = {'pk': prochaine_maraude.pk}
|
|
if not prochaine_maraude.est_terminee():
|
|
return redirect("maraudes:create", **kwargs)
|
|
else:
|
|
return redirect("notes:details-maraude", **kwargs)
|
|
|
|
|
|
class CompteRenduCreateView(MaraudeurMixin, generic.DetailView):
|
|
""" Vue pour la création d'un compte-rendu de maraude """
|
|
|
|
model = CompteRendu
|
|
template_name = "maraudes/compterendu.html"
|
|
context_object_name = "maraude"
|
|
|
|
form = None
|
|
inline_formset = None
|
|
|
|
def get_forms(self, *args, initial=None):
|
|
self.form = RencontreForm(*args,
|
|
initial=initial)
|
|
self.inline_formset = ObservationInlineFormSet(
|
|
*args,
|
|
instance=self.form.instance
|
|
)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.get_forms(request.POST, request.FILES)
|
|
if self.form.has_changed():
|
|
if not self.form.is_valid() or not self.inline_formset.is_valid():
|
|
return self.get(request, new_form=False)
|
|
rencontre = self.form.save(commit=False)
|
|
rencontre.maraude = self.get_object()
|
|
rencontre.save()
|
|
self.inline_formset.save()
|
|
|
|
return redirect('maraudes:create', pk=self.get_object().pk)
|
|
|
|
def get(self, request, new_form=True, *args, **kwargs):
|
|
|
|
def calculate_end_time(debut, duree):
|
|
end_minute = debut.minute + duree
|
|
hour = debut.hour + end_minute // 60
|
|
if hour >= 24: hour -= 24
|
|
elif hour < 0: hour += 24
|
|
minute = end_minute % 60
|
|
return datetime.time(
|
|
hour,
|
|
minute,
|
|
0
|
|
)
|
|
if new_form:
|
|
last_rencontre = self.get_object().rencontres.last()
|
|
if last_rencontre:
|
|
initial = {
|
|
'lieu': last_rencontre.lieu,
|
|
'heure_debut': calculate_end_time(
|
|
last_rencontre.heure_debut,
|
|
last_rencontre.duree),
|
|
}
|
|
else:
|
|
initial = {
|
|
'heure_debut': self.get_object().heure_debut
|
|
}
|
|
self.get_forms(initial=initial)
|
|
return super().get(request, *args, **kwargs)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['form'] = self.form
|
|
context['inline_formset'] = self.inline_formset
|
|
context['rencontres'] = self.get_object().rencontres.order_by("-heure_debut")
|
|
# Link there so that "Compte-rendu" menu item is not disabled
|
|
context['prochaine_maraude'] = self.object
|
|
return context
|
|
|
|
|
|
|
|
class FinalizeView( MaraudeurMixin,
|
|
generic.detail.SingleObjectMixin,
|
|
generic.edit.FormView):
|
|
|
|
template_name = "maraudes/finalize.html"
|
|
model = Maraude
|
|
form_class = SendMailForm
|
|
success_url = "/maraudes/"
|
|
|
|
def get(self, *args, **kwargs):
|
|
print(self.request.GET)
|
|
if bool(self.request.GET.get("no_mail", False)) == True:
|
|
messages.warning(self.request, "Aucun compte-rendu n'a été envoyé !")
|
|
return self.finalize()
|
|
return super().get(*args, **kwargs)
|
|
|
|
def get_initial(self):
|
|
maraude = self.get_object()
|
|
objet = "%s - Compte-rendu de maraude" % maraude.date
|
|
sujets_rencontres = set()
|
|
for r in maraude.rencontres.all():
|
|
for s in r.get_sujets():
|
|
sujets_rencontres.add(s)
|
|
message = "Nous avons rencontré : " + ", ".join(map(str, sujets_rencontres)) + ".\n\n"
|
|
return {
|
|
"subject": objet,
|
|
"message": message
|
|
}
|
|
|
|
def finalize(self):
|
|
maraude = self.get_object()
|
|
maraude.heure_fin = timezone.localtime(timezone.now()).time()
|
|
maraude.save()
|
|
return redirect(self.get_success_url())
|
|
|
|
def form_valid(self, form):
|
|
# Send mail
|
|
maraude = self.get_object()
|
|
recipients = Maraudeur.objects.filter(
|
|
is_active=True
|
|
).exclude(
|
|
pk__in=(maraude.referent.pk,
|
|
maraude.binome.pk)
|
|
)
|
|
result = send_mail(
|
|
form.cleaned_data['subject'],
|
|
form.cleaned_data['message'],
|
|
maraude.referent.email,
|
|
[m.email for m in recipients],
|
|
)
|
|
|
|
if result == 1:
|
|
messages.success(self.request, "Le compte-rendu a été transmis à %s" % ", ".join(map(str, recipients)))
|
|
else:
|
|
messages.error(self.request, "Erreur lors de l'envoi du message !")
|
|
return self.finalize()
|
|
|
|
def get_context_data(self, **kwargs):
|
|
self.object = self.get_object()
|
|
context = super().get_context_data(**kwargs)
|
|
if self.object.est_terminee is True:
|
|
context['form'] = None#Useless form
|
|
return context
|
|
# Link there so that "Compte-rendu" menu item is not disabled
|
|
context['prochaine_maraude'] = self.object
|
|
return context
|
|
|
|
|
|
|
|
class PlanningView(MaraudeurMixin, generic.TemplateView):
|
|
""" Vue d'édition du planning des maraudes """
|
|
|
|
template_name = "maraudes/planning.html"
|
|
|
|
def _parse_request(self):
|
|
self.current_date = datetime.date.today()
|
|
try: self.month = int(self.request.GET['month'])
|
|
except: self.month = self.current_date.month
|
|
try: self.year = int(self.request.GET['year'])
|
|
except: self.year = self.current_date.year
|
|
|
|
def _calculate_initials(self):
|
|
self._parse_request()
|
|
self.initials = []
|
|
for day, time in Planning.get_maraudes_days_for_month(self.year, self.month):
|
|
date = datetime.date(self.year, self.month, day)
|
|
try:
|
|
maraude = Maraude.objects.get(date=date)
|
|
except Maraude.DoesNotExist:
|
|
self.initials.append({
|
|
'date': date,
|
|
'heure_debut': time,
|
|
})
|
|
|
|
def get_queryset(self):
|
|
return Maraude.objects.filter(
|
|
date__month=self.month,
|
|
date__year=self.year,
|
|
)
|
|
|
|
def get_formset(self, *args):
|
|
self._calculate_initials()
|
|
return modelformset_factory(
|
|
Maraude,
|
|
form = MaraudeHiddenDateForm,
|
|
extra = len(self.initials),
|
|
)(
|
|
*args,
|
|
queryset = self.get_queryset(),
|
|
initial = self.initials
|
|
)
|
|
|
|
def post(self, request):
|
|
self.formset = self.get_formset(request.POST, request.FILES)
|
|
for form in self.formset.forms:
|
|
if form.is_valid():
|
|
form.save()
|
|
else:
|
|
logger.info("Form was ignored ! (%s)" % (form.errors.as_data()))
|
|
return redirect('maraudes:planning')
|
|
|
|
def get(self, request):
|
|
self.formset = self.get_formset()
|
|
return super().get(request)
|
|
|
|
def get_weeks(self):
|
|
""" List of (day, form) tuples, split by weeks """
|
|
|
|
def form_generator(forms):
|
|
""" Yields None until the generator receives the day of
|
|
next form.
|
|
"""
|
|
forms = iter(sorted(forms, key=lambda f: f.initial['date']))
|
|
day = yield
|
|
for form in forms:
|
|
while day != form.initial['date'].day:
|
|
day = yield None
|
|
day = yield form
|
|
|
|
while True: # Avoid StopIteration
|
|
day = yield None
|
|
|
|
form_or_none = form_generator(self.formset)
|
|
form_or_none.send(None)
|
|
|
|
return [
|
|
[(day, form_or_none.send(day)) for day in week]
|
|
for week in calendar.monthcalendar(self.year, self.month)
|
|
]
|
|
|
|
def get_context_data(self, *args, **kwargs):
|
|
context = super().get_context_data(*args, **kwargs)
|
|
context['weekdays'] = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"]
|
|
context['weeks'] = self.get_weeks()
|
|
|
|
context['formset'] = self.formset
|
|
context['select_form'] = MonthSelectForm(month=self.month, year=self.year)
|
|
context['month'], context['year'] = self.month, self.year
|
|
return context
|
|
|
|
|
|
|
|
class LieuCreateView(generic.edit.CreateView):
|
|
""" Vue de création d'un lieu """
|
|
|
|
model = Lieu
|
|
template_name = "maraudes/lieu_create.html"
|
|
fields = "__all__"
|
|
success_url = "/maraudes/"
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
if 'next' in self.request.POST:
|
|
self.success_url = self.request.POST["next"]
|
|
return super().post(self, request, *args, **kwargs)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
try:
|
|
context['next'] = self.request.GET['next']
|
|
except:
|
|
context['next'] = None
|
|
return context
|