Commit 0e4672b6 authored by Hamza Dely's avatar Hamza Dely Committed by Daniel STAN

[validation] Ajout de la gestion des déménagements

parent eb6a2856
# -*- coding: utf-8 -*-
from django import forms
class DemenagementForm(forms.Form):
"""
Formulaire à remplir par l'utilisateur pour les changements de chambre.
"""
keep_connection = forms.BooleanField(required=False,
initial=True,
label=u'Je souhaite conserver ma connexion Cr@ns')
status = forms.ChoiceField(required=True,
initial='is_ext',
choices=(
('is_ext', u"J'habite à l'extérieur du campus de Cachan"),
('is_crous_cachan', u"J'habite sur le campus de Cachan"),
),
label=u'Nouveau statut',
)
new_chbre = forms.CharField(
max_length=255,
initial='',
label=u'Nouvelle chambre (Si tu es sur le campus de Cachan)',
required=False)
adresse_rue = forms.CharField(max_length=510, label=u'Rue', required=False)
adresse_code = forms.CharField(max_length=10, label=u'Code Postal', required=False)
adresse_ville = forms.CharField(max_length=255, label=u'Ville', required=False)
def clean(self):
"""
Effectue la vérification des informations fournies par l'adhérent, à savoir:
- Chambre manquante alors que l'adh déclare habiter sur le campus.
"""
# On effectue un premier nettoyage des informations
cleaned_data = super(forms.Form,self).clean()
keep_connection = cleaned_data.get('keep_connection')
status = cleaned_data.get('status')
new_chbre = cleaned_data.get('new_chbre').upper()
adresse_rue = cleaned_data.get('adresse_rue')
adresse_code = cleaned_data.get('adresse_code')
adresse_ville = cleaned_data.get('adresse_ville')
if not keep_connection:
# L'adhérent ne veut plus sa connexion
cleaned_data['new_chbre'] = u'EXT'
if status == 'is_crous_cachan':
# L'information new_room est-elle manquante ?
if new_chbre == '' or new_chbre == None:
raise forms.ValidationError(u"Tu n'as pas indiqué ta nouvelle chambre.")
cleaned_data['new_chbre'] = unicode(new_chbre)
else:
# L'adhérent est hors campus et veut garder sa connextion
cleaned_data['new_chbre'] = u'EXT'
if not adresse_rue:
raise forms.ValidationError(u"Tu n'as pas spécifié de rue pour ta nouvelle adresse.")
if not adresse_code:
raise forms.ValidationError(u"Tu n'as pas spécifié de code postal pour ta nouvelle adresse.")
if not adresse_ville:
raise forms.ValidationError(u"Tu n'as pas spécifié de ville pour ta nouvelle adresse.")
return cleaned_data
......@@ -12,6 +12,7 @@ urlpatterns = patterns('',
# Fonctions de callback (le name doit correspondre à celui fourni
# dans ConfirmAction.view_name
url('^upload/(\d+)/(.*)/$', views.upload, name='upload'),
url('^demenagement/(\d+)/(.*)/$',views.demenagement, name='demenagement'),
# TODO
# faire de même pour:
# * chbre invalide
......
# -*- coding: utf-8 -*-
# Create your views here.
import datetime
import json
from django.shortcuts import render
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, HttpResponseForbidden
from django.template.loader import render_to_string
from django.core.exceptions import PermissionDenied
from settings import BASE_LDAP_TEST
from models import ConfirmAction
from forms import DemenagementForm
import lc_ldap.shortcuts
from lc_ldap.attributs import UniquenessError
from gestion import secrets_new as secrets
import gestion.mail as mail_module
# On regarde si on doit utiliser la base LDAP de test, parce que c'est toujours
# marrant de tester des trucs en dev, et de se faire expulser de sa chambre sur
# la base de prod.
if BASE_LDAP_TEST:
use_ldap_admin = lc_ldap.shortcuts.with_ldap_conn(retries=2, delay=5,
constructor=lc_ldap.shortcuts.lc_ldap_test)
else:
use_ldap_admin = lc_ldap.shortcuts.with_ldap_conn(retries=2, delay=5,
constructor=lc_ldap.shortcuts.lc_ldap_admin)
use_ldap_admin = lc_ldap.shortcuts.with_ldap_conn(retries=2, delay=5,
constructor=lc_ldap.shortcuts.lc_ldap_admin)
RESPBATS = 'respbats@crans.org'
@use_ldap_admin
def upload(request, pk, secret, ldap):
......@@ -24,7 +40,7 @@ def upload(request, pk, secret, ldap):
task = get_object_or_404(ConfirmAction, pk=pk, view_name='upload',
secret=secret)
data = json.loads(task.data)
with ldap.search(data['dn'], mode='rw')[0] as adh:
bl = adh['blacklist'][data['blid']].value
if bl['fin'] == '-' and 'confirm' in request.POST:
......@@ -35,11 +51,153 @@ def upload(request, pk, secret, ldap):
task.save()
if bl['fin'] != '-':
fin = datetime.datetime.fromtimestamp(bl['fin'])
return render(request, 'validation/upload_done.html',
return render(request, 'validation/upload_done.html',
{'fin': fin})
else:
return render(request, 'validation/upload.html')
@use_ldap_admin
@csrf_exempt
def demenagement(request, pk, secret, ldap):
"""
Validation d'un déménagement. Propose les alternatives suivantes:
- Conservation de l'accès Internet (avec nouvelle chambre ou EXT)
- Suppression de l'accès Internet
"""
task = get_object_or_404(ConfirmAction, pk=pk, view_name='demenagement',
secret=secret)
data = json.loads(task.data)
f = DemenagementForm(label_suffix="")
chbre = data['chbre']
if isinstance(task.triggered, datetime.datetime) \
and task.triggered < datetime.datetime.now():
# L'url a déjà été triggered, on empêche un nouvel accès
raise PermissionDenied
if request.method == 'POST':
# On traite un formulaire de déménagement
f = DemenagementForm(request.POST, label_suffix="")
if f.is_valid():
keep_connection = f.cleaned_data['keep_connection']
status = f.cleaned_data['status']
new_chbre = f.cleaned_data['new_chbre']
adresse_rue = f.cleaned_data['adresse_rue']
adresse_code = f.cleaned_data['adresse_code']
adresse_ville = f.cleaned_data['adresse_ville']
adresse_complete = [adresse_rue, adresse_code, adresse_ville, ]
with ldap.search(data['dn'], mode='rw')[0] as adh:
if not keep_connection:
# L'adhérent ne souhaite plus garder sa connexion
# On supprime ses machines
for machine in adh.machines():
machine.delete()
# Si l'adhérent a renoncé à sa connexion tout en restant
# sur le campus, on rajoute l'adresse du CROUS
if status == 'is_crous_cachan':
adh["postalAddress"] = ["62-78 rue Camille Desmoulins",
"94230",
"Cachan"]
if status == u'is_ext':
# L'adhérent est domicilié à l'extérieur
# On enregistre sa nouvelle adresse
adh['postalAddress'] = adresse_complete
try:
# On modifie la chambre de l'adhérent
adh['chbre'] = new_chbre
except UniquenessError as e:
# 1er cas : La chambre est occupée
with mail_module.ServerConnection() as smtp:
smtp.send_template('demenagement_erreur', {
'from': RESPBATS,
'to': RESPBATS,
'adh': adh,
'aid': adh['aid'][0].value,
'chbre': chbre,
'new_chbre': new_chbre,
'type_erreur' : 'UniquenessError',
'erreur' : e,
})
return render(request, 'validation/demenagement_succes.html', {
'keep' : keep_connection,
'new_chbre' : new_chbre,
'ask_respbats' : True,
'adresse' : adresse_complete,
'why' : 'occupee',
})
except ValueError as e:
# 2ème cas : La chambre est invalide
# On ajoute une erreur au formulaire et on le renvoie
f.add_error('new_chbre', "La chambre %s est invalide." % new_chbre)
return render(request, 'validation/demenagement.html', {
'chbre' : chbre,
'form' : f,
})
except Exception as e:
# 3ème cas : Erreur inconnue
with mail_module.ServerConnection() as smtp:
smtp.send_template('demenagement_erreur', {
'from': RESPBATS,
'to': RESPBATS,
'adh': adh,
'aid': adh['aid'][0].value,
'chbre': chbre,
'new_chbre': new_chbre,
'type_erreur': 'Exception',
'erreur': e,
})
return render(request, 'validation/demenagement_succes.html', {
'keep' : keep_connection,
'new_chbre' : new_chbre,
'ask_respbats' : True,
'adresse' : adresse_complete,
'why' : 'inconnu',
})
# On oublie pas de sauvegarder les modifications
adh.history_gen(login=u'validate')
adh.save()
task.triggered = datetime.datetime.now()
task.save()
return render(request,'validation/demenagement_succes.html', {
'keep' : keep_connection,
'ask_respbats' : False,
'new_chbre' : new_chbre,
'adresse' : adresse_complete,
})
else:
return render(request, 'validation/demenagement.html', {
'form' : f,
'chbre' : chbre,
})
else:
# On envoie un formulaire de déménagement
return render(request, 'validation/demenagement.html', {
'form' : f,
'chbre' : chbre,
})
@csrf_exempt
def register(request, view_name):
"""Enregistre une action à effectuer. Les données d'exécution sont dans
......
div.compte
{
margin: auto;
display: block;
width: 70%;
max-width: 1280px;
}
#id_demenagement_table
{
display: table;
margin : auto;
border-collapse: collapse;
text-align: center;
width: 100%;
}
#id_demenagement_table tr
{
border-bottom: 2px solid #FAD163;
}
#id_demenagement_table th
{
padding: 25px 0;
}
#id_demenagement_table tr:last-child
{
border-bottom: none;
}
.recap
{
display: block;
text-align: center;
}
.recap li
{
display: inline-block;
border: 4px solid #FAD167;
border-radius: 25px/20px;
padding: 10px 0px;
margin: 10px auto;
width: 60%;
max-width: 1280px;
background-color: #FFF7D7;
}
#id_etat_chambre
{
color: red;
}
{% extends "template.html" %}
{% block head %}
<style type="text/css">
* #id_keep_connection:checked ~ * .test {
display: none;
}
</style>
{% load staticfiles %}
<link rel="stylesheet" href="{% static "css/validation.css" %}" />
{% endblock %}
{% block content %}
<h3>Notification de déménagement</h3>
<p>Un adhérent du Crans a déclaré résider dans la chambre {{ chbre }}, que tu occupais précédemment. Cela signifie que nous ne disposons plus d'informations de résidence valides à ton sujet.</p>
<p>Tu peux choisir de renoncer à ton accès internet (tes machines, Wi-Fi comme filaire, seront alors supprimées de notre base de données) ou de le conserver pour continuer à profiter de l'accès Internet du Crans sur le campus de Cachan</p>
<ul>
<li>Si tu ne souhaite pas garder ton accès Internet Crans, il te suffit de décocher la case ci-dessous</li>
<li>Si tu souhaites conserver ton accès Internet via le Crans, nous avons besoin que tu nous indiques si tu résides toujours sur le campus de Cachan, et également ta nouvelle chambre le cas échéant.</li>
</ul>
<div class="compte">
<form method="post" action="">
<table id="id_demenagement_table">
{{ form.as_table }}
<tr>
<td colspan=2><input type="submit" name="confirm" value="Envoyer" /></td>
</tr>
</table>
</form>
</div>
<p>En cas de problème concernant tes informations de résidence, tu peux toujours nous contacter à cette adresse : <a href='mailto:respbats@crans.org'>respbats@crans.org</a></p>
{% endblock %}
{% block javascript %}
<script>
// Récupération des options et des lignes du tableau
var choix = document.getElementById('id_status');
var chbre = document.getElementById('id_new_chbre').parentNode.parentNode;
var rue = document.getElementById('id_adresse_rue').parentNode.parentNode;
var code = document.getElementById('id_adresse_code').parentNode.parentNode;
var ville = document.getElementById('id_adresse_ville').parentNode.parentNode;
var adresse = [ rue, code, ville ];
// On crée les fonctions qui seront exécutées en cas de clic sur une option
function cache(e){ e.style.visibility = "collapse"; };
function revele(e){ e.style.visibility = ""; };
function choix_ext(){ cache(chbre); adresse.forEach(revele); };
function choix_crous(){ revele(chbre); adresse.forEach(cache); };
function change_choix(e)
{
if(e.target.value == 'is_ext')
{
choix_ext();
}
else if(e.target.value == 'is_crous_cachan')
{
choix_crous();
}
else
{
alert('Statut invalide');
}
};
// On place les écouteurs d'évènements sur le choix
// FIXME : Normalement, on devrait utiliser la méthode addEventListener, mais ça ne fonctionne pas ...
choix.onchange = change_choix;
// On commence avec les bons champs à l'affichage initial de la page
if(choix.value == 'is_ext')
{
cache(chbre);
}
else if(choix.value == 'is_crous_cachan')
{
adresse.forEach(cache);
}
</script>
{% endblock %}
Une notification de déménagement a été reçue, mais une erreur est survenue
pendant le traitement de la demande suivante:
aid ............................... {{ aid }}
Conservation du compte Crans ...... Non gérée
Conservation des machines ......... {% if keep %}Oui{% else %}Non{% endif %}
Ancienne chambre .................. {{ chbre }}
Nouvelle chambre annoncée ......... {{ new_chbre }}
{% if type_erreur == 'UniquenessError'%}
La chambre {{ new_chbre }} est déjà occupée par quelqu'un d'autre.
La validation du déménagement nécéssite une intervention manuelle.
{% else %}
Une erreur s'est produite :
{{ e }}
{% endif %}
----------------
Le service de notification des déménagements
{% extends 'template.html' %}
{% block head %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static "css/validation.css" %}"/>
{% endblock %}
{% block content %}
<h3>Déménagement</h3>
<p><b>Ta notification de déménagement a bien été prise en compte.</b></p>
<p>Tu as déclaré :</p>
<div class="recap">
<ul>
{% if keep %}
<li>Vouloir garder ta connexion Internet Crans (<b>tes machines ont été conservées</b>).</li>
{% else %}
<li><b>Ne pas</b> vouloir garder ta connexion Internet Crans (<b>tes machines ont été supprimées de notre base de données</b>)</li>
{% endif %}
{% if new_chbre == 'EXT' %}
<li>Habiter <b>à l'extérieur du campus</b>, à l'adresse suivante :<br /><span id="demenagement_adresse">{% for elem in adresse %}<br/><b>{{ elem }}</b>{% endfor%}</span></li>
{% else %}
<li>
<p>Habiter sur le campus dans la chambre <b>{{ new_chbre }}</b>.</p>
{% if ask_respbats %}
{% if why == 'occupee' %}<p id="id_etat_chambre">Cette chambre étant déjà occupée, un mail a été envoyé à respbats pour confirmation</p>
{% elif why == 'invalide' %}<p id="id_etat_chambre">Cependant cette chambre est invalide, elle n'a pas pu t'être attribuée, un mail a été envoyé à respbats pour confirmation</p>
{% else %}<p id="id_etat_chambre">Une erreur inconnue s'est produite pendant la procédure, un mail a été envoyé à respbats pour confirmation</p>
{% endif %}
{% endif %}
</li>
{% endif %}
</ul>
</div>
<p>Si une erreur s'est glissée dans le récapitulatif ci-dessus, tu peux nous contacter à l'adresse : <a href='mailto:respbats@crans.org'>respbats@crans.org</a></p>
<p>Merci d'avoir pris le temps de répondre à cette notification !</p>
{% endblock %}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment