404 lines
17 KiB
Python
404 lines
17 KiB
Python
# vim:spell:spelllang=fr
|
|
# -*- encoding: utf-8 -*-
|
|
|
|
import random
|
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
import django.forms as forms
|
|
from django.core.exceptions import ValidationError
|
|
from django.utils.safestring import mark_safe
|
|
from django.core.urlresolvers import reverse
|
|
from django.core.cache import cache
|
|
from django.template import Template, Context
|
|
from django.core.mail import send_mail
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
from django.contrib.localflavor.fr.forms import FRZipCodeField
|
|
from crispy_forms.helper import FormHelper
|
|
from crispy_forms.layout import Layout, Submit, Fieldset, ButtonHolder, HTML, Field
|
|
|
|
from appli_project.appli_socle import models
|
|
from appli_project.appli_socle.settings import Parametres
|
|
from appli_project.appli_socle.forms import FormulaireAvecRelaie
|
|
from appli_project.appli_socle.utils import next_url, envoyer_jeton
|
|
from appli_project.appli_socle import views as socle_views
|
|
|
|
|
|
class InscriptionForm(FormulaireAvecRelaie):
|
|
email = forms.EmailField(label=_(u'Votre email'))
|
|
first_name = forms.CharField(label=_(u'Prénom'))
|
|
last_name = forms.CharField(label=_(u'Nom'))
|
|
address = forms.CharField(label=_(u'Adresse personnelle'),
|
|
widget=forms.Textarea)
|
|
phone = forms.CharField(max_length=20,
|
|
label=_(u'Téléphone fixe'))
|
|
mobile = forms.CharField(max_length=20,
|
|
label=_(u'Mobile'))
|
|
job = forms.CharField(max_length=128,
|
|
label=_(u'Profession'))
|
|
comment = forms.ChoiceField(label=_(u'Comment avez-vous connu le site ?'),
|
|
choices=models.ProfilOffre.COMMENT)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.static_next_url = reverse('mes-alertes-offre')
|
|
super(InscriptionForm, self).__init__(*args, **kwargs)
|
|
|
|
def clean_email(self):
|
|
'''Vérifie que l'email n'est pas déjà utilisé par un profil offre'''
|
|
email = self.cleaned_data['email']
|
|
|
|
if models.ProfilOffre.objects.filter(email=email).exists():
|
|
url = reverse('mot-de-passe-perdu', kwargs=dict(email=email))
|
|
raise ValidationError(mark_safe(_(u'''Cette adresse email est déjà '''
|
|
u'''utilisée. <a href="%s">Peut-être avez vous oublié'''
|
|
u''' votre mot de passe ?</a>''') % url))
|
|
return email
|
|
|
|
def save(self):
|
|
email = self.cleaned_data['email']
|
|
url = self.next_url()
|
|
self.jeton = jeton = ''.join([random.SystemRandom().choice('123456789ABCDEFGHJKMNPQRSTUVWXYZ')
|
|
for i in range(8)])
|
|
d = { 'next': url, 'creation': 1 }
|
|
d.update(self.cleaned_data)
|
|
cache.set('inscription_%s' % jeton, d, settings.INSCRIPTION_TIMEOUT)
|
|
jeton_url = self.request.build_absolute_uri(
|
|
reverse('confirmation-email', kwargs=dict(jeton=jeton)))
|
|
confirmation_url = self.request.build_absolute_uri(
|
|
reverse('confirmation-email', kwargs=dict(jeton='')))
|
|
modele, created = models.EmailModele.objects.get_or_create(
|
|
nom='Inscription')
|
|
host = self.request.get_host()
|
|
if created:
|
|
modele.sujet = u'''Confirmation de votre email pour inscription à {{host}}'''
|
|
modele.texte = u'''Vous venez d'inscrire votre email {{email}} sur {{host}}.
|
|
|
|
Il est nécessaire de confirmer cet email pour que votre compte soit créé.
|
|
Pour cela veuillez entrez le code {{ jeton }} sur la page Web suivante:
|
|
|
|
{{ confirmation_url }}
|
|
|
|
ou bien recopier le lien suivant dans la barre d'adresse de votre navigateur:
|
|
|
|
{{ jeton_url }}'''
|
|
modele.save()
|
|
|
|
variables = Context({ 'email' : email, 'jeton': jeton,
|
|
'jeton_url': jeton_url, 'host': host,
|
|
'confirmation_url': confirmation_url})
|
|
subject = Template(modele.sujet).render(variables)
|
|
body = Template(modele.texte).render(variables)
|
|
send_mail(subject, body, settings.INSCRIPTION_FROM_EMAIL, [email])
|
|
|
|
helper = FormHelper()
|
|
helper.form_class = 'form-horizontal'
|
|
helper.layout = Layout(
|
|
'email',
|
|
'first_name',
|
|
'last_name',
|
|
'address',
|
|
'phone',
|
|
'mobile',
|
|
'job',
|
|
'comment',
|
|
'next',
|
|
ButtonHolder(
|
|
Submit('submit', _(u"M'inscrire"), css_class="btn-primary btn"),
|
|
css_class="bouton-group"))
|
|
|
|
|
|
from django.contrib.gis.admin.widgets import OpenLayersWidget
|
|
from django.contrib.gis.admin import options
|
|
|
|
class MapWidget(OpenLayersWidget):
|
|
template = 'appli_offre/openlayers.html'
|
|
geom_type = 'POINT'
|
|
params = {
|
|
'default_lon': 261223.54412843,
|
|
'default_lat': 6251249.4833769,
|
|
'default_zoom': 11,
|
|
'display_wkt': False,
|
|
'geom_type': 'POINT',
|
|
'field_name': 'position_geographique',
|
|
'is_collection': False,
|
|
'scrollable': True,
|
|
'layerswitcher': False,
|
|
'collectiontype': 'None',
|
|
'is_linestring': False,
|
|
'is_polygon': False,
|
|
'is_point': True,
|
|
'num_zoom': 20,
|
|
'max_zoom': False,
|
|
'min_zoom': False,
|
|
'units': 'm',
|
|
'max_resolution': '156543.0339',
|
|
'max_extent': '-20037508,-20037508,20037508,20037508',
|
|
'modifiable': True,
|
|
'mouse_position': True,
|
|
'scale_text': True,
|
|
'map_width': '400',
|
|
'map_height': 400,
|
|
'point_zoom': 11,
|
|
'srid': options.spherical_mercator_srid,
|
|
'display_srid': False,
|
|
'wms_url': 'http://vmap0.tiles.osgeo.org/wms/vmap0',
|
|
'wms_layer': 'basic',
|
|
'wms_name': 'OpenLayers WMS'
|
|
}
|
|
|
|
class AnnonceForm(forms.ModelForm):
|
|
class Meta:
|
|
model = models.Annonce
|
|
widgets = {
|
|
'position_geographique': MapWidget,
|
|
}
|
|
fields = ('prix_par_mois', 'duree_location', 'surface_en_m2', 'type_de_logement',
|
|
'pays', 'ville', 'type_d_offre', 'position_geographique',
|
|
'photo', 'description')
|
|
|
|
class Media:
|
|
js = ('/static/openlayers/OpenLayers.js',)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.request = kwargs.pop('request')
|
|
self.helper = FormHelper()
|
|
self.helper.form_class = 'form-horizontal'
|
|
self.prestations = fields = []
|
|
type_de_prestations = models.TypeDePrestation.objects.order_by('ordre')
|
|
for type_de_prestation in type_de_prestations:
|
|
name = 'prestation-%s' % type_de_prestation.id
|
|
if type_de_prestation.type_de_valeur == 'B':
|
|
field = forms.BooleanField(label=type_de_prestation.nom,
|
|
required=False)
|
|
elif type_de_prestation.type_de_valeur == 'N':
|
|
field = forms.IntegerField(label=type_de_prestation.nom,
|
|
required=False)
|
|
fields.append((name, field))
|
|
field_names = [x[0] for x in fields]
|
|
super(AnnonceForm, self).__init__(*args, **kwargs)
|
|
self.fields.update(dict(fields))
|
|
self.fields['duree_location'].required = True
|
|
if self.instance.id:
|
|
# modification
|
|
for prestation in self.instance.prestations.all():
|
|
type_de_prestation = prestation.type_de_prestation
|
|
name = 'prestation-%s' % type_de_prestation.id
|
|
if type_de_prestation.type_de_valeur == 'B':
|
|
self.fields[name].initial = True
|
|
elif type_de_prestation.type_de_valeur == 'N':
|
|
self.fields[name].initial = prestation.valeur_numerique
|
|
submits = [Submit('modifier-et-publier', _(u'Modifier et publier'), css_class='btn btn-primary'),
|
|
Submit('modifier', _(u'Modifier')),
|
|
Submit('supprimer', _(u'Supprimer'))]
|
|
else:
|
|
# création
|
|
submits = [Submit('creer', _(u'Créer'))]
|
|
self.helper.layout = Layout(
|
|
'type_de_logement',
|
|
'prix_par_mois',
|
|
'duree_location',
|
|
'surface_en_m2',
|
|
'pays',
|
|
Field('ville', placeholder=_(u'en région parisienne'), help_text='coin'),
|
|
'type_d_offre',
|
|
Field('position_geographique', css_class='osm-input'),
|
|
'photo',
|
|
'description',
|
|
Fieldset(_(u'Prestations diverses'),
|
|
HTML(_("""<p class="alert alert-info">Tous ces champs sont facultatifs</p>""")),
|
|
*field_names),
|
|
ButtonHolder(*submits,
|
|
css_class='bouton-group'))
|
|
|
|
def clean_surface_en_m2(self):
|
|
'''Vérifie que la surface dépasse la surface minimum autorisée'''
|
|
surface_en_m2 = self.cleaned_data['surface_en_m2']
|
|
surface_minimum = Parametres().surface_minimum
|
|
if surface_en_m2 < surface_minimum:
|
|
raise ValidationError(
|
|
mark_safe(_(u'Pour respecter la <a href="/charte-qualite">charte'
|
|
u' qualité</a> la surface doit être supérieur à %s '
|
|
u'm²') % surface_minimum))
|
|
return surface_en_m2
|
|
|
|
def clean_photo(self):
|
|
photo = self.cleaned_data['photo']
|
|
if photo and photo.size > 1024*1024:
|
|
raise ValidationError(_(u'La taille des images est limitée à 1Mo'))
|
|
return photo
|
|
|
|
def clean(self):
|
|
'''Vérifie que l'annonce respecte le prix maximum au m²'''
|
|
cleaned_data = super(AnnonceForm, self).clean()
|
|
try:
|
|
surface_en_m2 = cleaned_data['surface_en_m2']
|
|
prix_par_mois = cleaned_data['prix_par_mois']
|
|
except KeyError:
|
|
return cleaned_data
|
|
parametres = Parametres()
|
|
prix_au_m2_maximum = parametres.prix_au_m2_maximum
|
|
prix_au_m2 = float(prix_par_mois) / float(surface_en_m2)
|
|
prix_maximum = surface_en_m2 * parametres.prix_au_m2_maximum
|
|
if prix_au_m2 > prix_au_m2_maximum:
|
|
raise ValidationError(
|
|
mark_safe(_(u'Pour respecter la <a href="/charte-qualite">charte'
|
|
u' qualité</a> le prix au m² ne doit pas dépasser {0}'
|
|
u' €/m². Ici il est de {1:.2f} €/m². Le prix par mois'
|
|
u' maximum au vu de la surface est de {2} €').format(prix_au_m2_maximum,
|
|
prix_au_m2,
|
|
prix_maximum)))
|
|
return cleaned_data
|
|
|
|
def save(self):
|
|
self.instance.monnaie = 'EUR'
|
|
self.instance.proprietaire = self.request.user
|
|
# Les profils offre sans validation ont leurs offres validés
|
|
# automatiquement
|
|
if self.request.user.sans_validation:
|
|
if self.instance.etat_validation != 'publiee':
|
|
self.instance.etat_validation = 'valide'
|
|
else:
|
|
if self.instance.etat_validation == 'valide':
|
|
pass
|
|
elif self.instance.etat_validation == 'invalide':
|
|
self.instance.etat_validation = 'attend_validation'
|
|
elif self.instance.etat_validation == 'publiee':
|
|
self.instance.etat_validation = 'attend_validation'
|
|
elif self.instance.etat_validation == 'attend_validation':
|
|
pass
|
|
instance = super(AnnonceForm, self).save()
|
|
new_prestations = []
|
|
for type_de_prestation in models.TypeDePrestation.objects.order_by('ordre'):
|
|
name = 'prestation-%s' % type_de_prestation.id
|
|
if type_de_prestation.type_de_valeur == 'B' \
|
|
and self.cleaned_data.get(name, False):
|
|
prestation, created = models.Prestation.objects.get_or_create(
|
|
type_de_prestation=type_de_prestation)
|
|
new_prestations.append(prestation)
|
|
elif type_de_prestation.type_de_valeur == 'N' \
|
|
and self.cleaned_data.get(name) is not None:
|
|
prestation, created = models.Prestation.objects.get_or_create(
|
|
type_de_prestation=type_de_prestation,
|
|
valeur_numerique=self.cleaned_data[name])
|
|
new_prestations.append(prestation)
|
|
instance.prestations = new_prestations
|
|
return instance
|
|
|
|
class MonEmailForm(FormulaireAvecRelaie):
|
|
email = forms.EmailField(label=_(u'Mon email'))
|
|
url_de_contact = forms.URLField(label=_(u'URL de contact'), required=False,
|
|
help_text=_(u'en option, remplace le mail pour le contact du propriétaire'))
|
|
success_url = '/offre'
|
|
|
|
def __init__(self, **kwargs):
|
|
request = kwargs.get('request')
|
|
user = self.user = request.user
|
|
initial = kwargs.setdefault('initial', {})
|
|
initial['email'] = user.email
|
|
if hasattr(user, 'url_de_contact'):
|
|
initial['url_de_contact'] = user.url_de_contact
|
|
self.helper = FormHelper()
|
|
self.helper.form_class = 'form-horizontal'
|
|
self.helper.layout = Layout('email', 'url_de_contact', 'next',
|
|
ButtonHolder(Submit('submit', _(u"Confirmer"))))
|
|
super(MonEmailForm, self).__init__(**kwargs)
|
|
|
|
def clean_email(self):
|
|
email = self.cleaned_data.get('email')
|
|
if email and models.ProfilOffre.objects \
|
|
.filter(email=email) \
|
|
.exclude(id=self.request.user.id).exists():
|
|
raise ValidationError(_(u'Cet email est déjà utilisé par un autre compte'))
|
|
return email
|
|
|
|
def save(self):
|
|
cleaned_data = self.cleaned_data
|
|
if hasattr(self.user, 'url_de_contact'):
|
|
if self.user.url_de_contact != cleaned_data['url_de_contact']:
|
|
self.user.url_de_contact = cleaned_data['url_de_contact']
|
|
self.user.save()
|
|
email = cleaned_data['email']
|
|
if email != self.user.email:
|
|
jeton = envoyer_jeton(self.request, "Changement d'email",
|
|
_(u'''Code de confirmation pour le changement d'email sur {{host}}'''),
|
|
_(u'''\
|
|
Vous avez demandé à changer d'email sur {{ host }}. Pour confirmer
|
|
ce changement veuillez entrer le code {{jeton}} sur la page:
|
|
|
|
{{ confirmation_url }}
|
|
|
|
ou bien recopier le lien suivant dans la barre de navigation de votre navigateur
|
|
|
|
{{ jeton_url }}'''),
|
|
{ },
|
|
settings.CHANGE_EMAIL_FROM,
|
|
cleaned_data['email'],
|
|
{ 'email': email, 'user_id': self.user.id,
|
|
'change_email': 1, 'next': next_url(self.request, '/')
|
|
})
|
|
|
|
messages.info(self.request, _(u"Vous avez demandé à changer d'email."
|
|
u" Un email a été envoyé a l'email"
|
|
u" %s pour validation. Après validation votre email sera"
|
|
u" changé.") % cleaned_data['email'])
|
|
self.request.logger.info(u"demande un changement d'email "
|
|
u"de %s à %s", self.request.user.email, cleaned_data['email'])
|
|
self.request.logger.info(u"le jeton %s lui a été envoyé", jeton)
|
|
|
|
class MesAlertesForm(FormulaireAvecRelaie):
|
|
refuse_notif_depublication = forms.BooleanField(
|
|
label=_(u'Je ne souhaite pas recevoir les messages de'
|
|
u' désactivation automatique des annonces'),
|
|
required=False)
|
|
refuse_notif_alertes = forms.BooleanField(
|
|
label=_(u'Je ne souhaite pas recevoir de notification'
|
|
u" des périodes d'affluence"),
|
|
required=False)
|
|
refuse_invitations = forms.BooleanField(
|
|
label=_(u"Je ne souhaite pas recevoir d'invitations"),
|
|
required=False)
|
|
success_url = '/offre'
|
|
|
|
|
|
def __init__(self, **kwargs):
|
|
request = kwargs.get('request')
|
|
user = self.user = request.user
|
|
initial = kwargs.setdefault('initial', {})
|
|
if not socle_views.is_webmaster(user):
|
|
initial['refuse_notif_depublication'] = not user.accepte_notif_depublication
|
|
initial['refuse_notif_alertes'] = not user.accepte_notif_alertes
|
|
initial['refuse_invitations'] = not user.accepte_invitations
|
|
self.helper = FormHelper()
|
|
self.helper.form_class = 'form-horizontal'
|
|
button_holder = ButtonHolder(Submit('submit', _(u"Confirmer")))
|
|
fields = [ 'refuse_notif_depublication',
|
|
'refuse_notif_alertes', 'refuse_invitations', 'next',
|
|
button_holder]
|
|
if socle_views.is_webmaster(user):
|
|
invitations = True
|
|
else:
|
|
invitations = models.Annonce.objects \
|
|
.filter(proprietaire=user) \
|
|
.exclude(type_d_offre=1) \
|
|
.filter(etat_validation__in=['valide', 'publiee']) \
|
|
.exists() or user.accepte_invitations
|
|
if not invitations:
|
|
fields.remove('refuse_invitations')
|
|
self.helper.layout = Layout(*fields)
|
|
super(MesAlertesForm, self).__init__(**kwargs)
|
|
if not invitations:
|
|
del self.fields['refuse_invitations']
|
|
|
|
def save(self):
|
|
cleaned_data = self.cleaned_data
|
|
for other in cleaned_data:
|
|
if other.startswith('refuse_'):
|
|
key = 'accepte_' + other[len('refuse_'):]
|
|
if getattr(self.user, key) == cleaned_data[other]:
|
|
setattr(self.user, key, not cleaned_data[other])
|
|
self.request.logger.info(
|
|
u"met son paramètre %s"
|
|
u" à la valeur %s",
|
|
key, getattr(self.user, key))
|
|
self.user.save()
|