Files
django-maraudes/maraudes/views.py
artus40 0d3798f087 changed redirect_to_current_compterendu view to use Maraude manager's
get_in_progress(), which is now a method instead of cache property.
+ better display of admin panel's buttons in sujets detail views
2017-08-28 17:35:56 +02:00

365 lines
12 KiB
Python

import datetime
import calendar
import logging
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,)
from .notes import Signalement
# Forms
from .forms import (RencontreForm,
ObservationInlineFormSet,
MaraudeHiddenDateForm, MonthSelectForm,
AppelForm, SignalementForm,
SendMailForm)
from notes.mixins import NoteFormMixin
logger = logging.getLogger(__name__)
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)
def derniers_sujets_signales():
def recent_filter(qs):
NUMBER_OF_MONTH_BACKWARDS = 1 # Must be lower than 12 !
current_date = timezone.localtime(timezone.now()).date()
recent_dates = [(current_date.month, current_date.year)]
for i in range(1, NUMBER_OF_MONTH_BACKWARDS + 1):
prev_month, prev_year = current_date.month - i, current_date.year
if prev_month <= 0:
prev_month += 12
prev_year -= 1
recent_dates.append(
(prev_month, prev_year)
)
# Select recent ones
filtered = []
for month, year in recent_dates:
filtered += list(qs.filter(created_date__year=year, created_date__month=month))
return filtered
return recent_filter(Signalement.objects.all())
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()
context['derniers_sujets_signales'] = derniers_sujets_signales()
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):
maraude_en_cours = Maraude.objects.get_in_progress()
if not maraude_en_cours:
return redirect("maraudes:index")
kwargs = {'pk': maraude_en_cours.pk}
if not maraude_en_cours.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