Quotation returned after succesful booking

This commit is contained in:
Ruidy Nemausat 2019-12-03 13:39:43 +01:00
parent cf9fb67232
commit be7bdec84f
6 changed files with 139 additions and 114 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ rental/__pycache__
rental/migrations
villafleurie/__pycache__
.DS_Store
.vscode/

102
README.md
View file

@ -7,76 +7,88 @@
## Projet
Créer un site vitrine présentant l'activité de Villafleurie :
* location de logements : T2 et T3
* navette entre l'aéroport, la gare maritime et la résidence
* découverte de l'archipel
- location de logements : T2 et T3
- navette entre l'aéroport, la gare maritime et la résidence
- découverte de l'archipel
Le visiteur doit pouvoir :
* connaitre les disponibilité de chaque logement,
* leur tarif,
* pouvoir contacter les propriétaires,
* et pouvoir réserver
- connaitre les disponibilité de chaque logement,
- leur tarif,
- pouvoir contacter les propriétaires,
- et pouvoir réserver
## Structure
### Pages
1. Page d'accueil
* Landing page
* CTA = "Réserver maintenant"
- Landing page
- CTA = "Réserver maintenant"
2. Page logement
* photos,
* disponibilités,
* tarif pour la période sélectionnée,
- photos,
- disponibilités,
- tarif pour la période sélectionnée,
3. Page réservation
* Entrer ses coordonnées
* Prépayer la réservation ou la caution,
- Entrer ses coordonnées
- Prépayer la réservation ou la caution,
4. Page remerciements
* Expliquer les prochaines étapes
- Expliquer les prochaines étapes
5. Page contact
6. Page légale
### Données
1. Logement :
* nom,
* photos,
* description,
* calendrier,
* tarif
- nom,
- photos,
- description,
- calendrier,
- tarif
2. Client :
* nom,
* mail,
* téléphone,
* _réservation_
- nom,
- mail,
- téléphone,
- _réservation_
3. Réservation :
* _client_,
* _logement_,
* dates de calendrier,
- _client_,
- _logement_,
- dates de calendrier,
4. Témoignages :
* _client_,
* _reservation_,
* témoignage
- _client_,
- _reservation_,
- témoignage
## TO DO
* Page service : navette + location
* Gestion du calendrier
..* Google calendar pour afficher les disponibilités
.. * Check si les dates choisies sont libres
* Module calcul prix réservation, afficher le résultat sur la page remerciement
ou envoyer devis par mail …
* Ajout page/module de paiement
* ajouter les témoignages depuis Booking, AirBnb, ajouter le lien
* changer la couleur des liens hypertextes
* changer l'adresse de l'admin
* ajouter un diaporama en bas de page de location ?
* deploy on Heroku or somewhere else … don't care
* change placeholders for dates
* factoriser le code de réservation
- Page service : navette + location
- Gestion du calendrier
.._ Google calendar pour afficher les disponibilités
.._ Check si les dates choisies sont libres
- Envoyer devis réservation par mail et notification aux hôtes
- Ajout page/module de paiement
- ajouter les témoignages depuis Booking, AirBnb, ajouter le lien
- changer la couleur des liens hypertextes
- changer l'adresse de l'admin
- ajouter un diaporama en bas de page de location ?
- deploy on Heroku or somewhere else … don't care
- change placeholders for dates
- factoriser le code de réservation
## BUGS

View file

@ -6,8 +6,8 @@ class Image(models.Model):
def __str__(self):
return self.alt
img=models.ImageField(upload_to='img/', null=True,blank=True)
alt=models.CharField(max_length=100)
img = models.ImageField(upload_to='img/', null=True, blank=True)
alt = models.CharField(max_length=100)
class Place(models.Model):
@ -17,17 +17,18 @@ class Place(models.Model):
def __str__(self):
return self.name
name=models.CharField(max_length=10, unique=True)
description=models.TextField(blank=True)
info=models.TextField(blank=True)
subname=models.CharField(max_length=100, blank=True)
tagline=models.CharField(max_length=100, blank=True)
price=models.DecimalField(max_digits=6, decimal_places=2, null=True)
surface=models.IntegerField(null=True,blank=True)
beds=models.IntegerField(null=True,blank=True)
max_occupation=models.IntegerField(null=True,blank=True)
thumbnail=models.ForeignKey(Image, on_delete=models.CASCADE, blank=True, null=True)
images=models.ManyToManyField(Image, related_name = "places", blank=True)
name = models.CharField(max_length=10, unique=True)
description = models.TextField(blank=True)
info = models.TextField(blank=True)
subname = models.CharField(max_length=100, blank=True)
tagline = models.CharField(max_length=100, blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
surface = models.IntegerField(null=True, blank=True)
beds = models.IntegerField(null=True, blank=True)
max_occupation = models.IntegerField(null=True, blank=True)
thumbnail = models.ForeignKey(
Image, on_delete=models.CASCADE, blank=True, null=True)
images = models.ManyToManyField(Image, related_name="places", blank=True)
class Guest(models.Model):
@ -37,9 +38,9 @@ class Guest(models.Model):
def __str__(self):
return self.name
name=models.CharField(max_length=100)
email=models.EmailField(unique=True)
phone=PhoneNumberField(blank=True)
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
phone = PhoneNumberField(blank=True)
class Reservation(models.Model):
@ -49,23 +50,26 @@ class Reservation(models.Model):
def __str__(self):
return "Réservation du {} par {}".format(self.place, self.guest)
place=models.ForeignKey(Place,on_delete=models.CASCADE)
guest=models.ForeignKey(Guest,on_delete=models.CASCADE)
message=models.TextField(blank=True)
start=models.DateField()
end=models.DateField()
place = models.ForeignKey(Place, on_delete=models.CASCADE)
guest = models.ForeignKey(Guest, on_delete=models.CASCADE)
message = models.TextField(blank=True)
start = models.DateField()
end = models.DateField()
price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
class Testimonial(models.Model):
class Meta:
verbose_name="Témoignage"
verbose_name = "Témoignage"
def __str__(self):
return self.author
return f"Témoignage de {self.author}"
author=models.CharField(max_length=100)
text=models.TextField()
picture=models.ImageField(upload_to='img/',null=True,blank=True)
link=models.URLField(null=True,blank=True)
guest=models.OneToOneField(Guest,on_delete=models.CASCADE,blank=True,null=True)
reservation=models.OneToOneField(Reservation,on_delete=models.CASCADE,blank=True,null=True)
author = models.CharField(max_length=100)
text = models.TextField()
picture = models.ImageField(upload_to='img/', null=True, blank=True)
link = models.URLField(null=True, blank=True)
guest = models.OneToOneField(
Guest, on_delete=models.CASCADE, blank=True, null=True)
reservation = models.OneToOneField(
Reservation, on_delete=models.CASCADE, blank=True, null=True)

View file

@ -1,20 +1,18 @@
"""
Compute booking price as a function of place and dates
"""
from models import Place
from datetime import *
from django.shortcuts import get_object_or_404
def get_reservation_price(place, start, end):
"""
Compute booking price as a function of place and dates
"""
nights = (end - start).days
return place.price * nights
place_name = 'T2'
start = datetime(2019, 11, 14)
end = datetime(2019, 11, 20)
stay = end-start
nights = stay.days
def quotation(place_name, nights):
if __name__ == '__main__':
from rental.models import Place
from datetime import *
from django.shortcuts import get_object_or_404
place_name = 'T2'
place = get_object_or_404(Place, name=place_name)
return place.price_per_night * (end - start)
x = quotation(place_name, nights)
print(x)
start = datetime(2019, 11, 14)
end = datetime(2019, 11, 20)
x = get_reservation_price(place_name, start, end)
print(x)

View file

@ -1,19 +1,24 @@
{% extends 'rental/base.html' %}
{% load static %}
{% block content %}
{% extends 'rental/base.html' %} {% load static %} {% block content %}
<section class="intro-single">
<div class="container">
<div class="row">
<div class="col-md-12 col-lg-8">
<div class="title-single-box">
<h1 class="title-single">Merci pour votre réservation </h1>
<span class="color-text-a">Nous avons enregistré la réservation de {{ guest.name }} du {{ place.name }}.<br/> Nous nous recontactons rapidement ! </span>
<h1 class="title-single">Merci pour votre réservation</h1>
<span class="color-text-a"
>Nous avons enregistré la réservation du {{reservation.place.name}}
sous le nom de {{reservation.guest.name}} pour un montant de
{{reservation.price}}.<br />
Nous nous recontactons rapidement !
</span>
</div>
</div>
<div class="col-md-12 col-lg-4">
<nav aria-label="breadcrumb" class="breadcrumb-box d-flex justify-content-lg-end">
<nav
aria-label="breadcrumb"
class="breadcrumb-box d-flex justify-content-lg-end"
>
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'rental:index' %}">Accueil</a>
@ -31,14 +36,15 @@
<div class="property-summary">
<div class="row">
<div class="col-sm-12">
<div class="col-md-12 mb-1">
<a href="{% url 'rental:index' %}"><button class="btn btn-a">Retour à l'accueil</button></a>
</div>
<div class="col-md-12 mb-1">
<a href="{% url 'rental:index' %}"
><button class="btn btn-a">Retour à l'accueil</button></a
>
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}

View file

@ -5,14 +5,15 @@ from django.urls import reverse_lazy
from django.views.generic.base import TemplateView
from .forms import ReservationForm
from django.db import IntegrityError
from rental.pricing import get_reservation_price
def index(request):
places = Place.objects.all()
temoignages = Testimonial.objects.all()
context = {
'places' : places,
'temoignages' : temoignages
'places': places,
'temoignages': temoignages
}
return render(request, 'rental/index.html', context)
@ -24,8 +25,8 @@ def liste_location(request):
imgs = place.images.all()
images.append(imgs)
context = {
'places' : places,
'images' : images
'places': places,
'images': images
}
return render(request, 'rental/list_place.html', context)
@ -34,11 +35,12 @@ def location(request, place_name='T2'):
place = get_object_or_404(Place, name=place_name)
images = place.images.all()
context = {
'place' : place,
'images' : images
'place': place,
'images': images
}
if request.method == 'POST':
form = ReservationForm(request.POST)#, error_class=ParagraphErrorList)
# , error_class=ParagraphErrorList)
form = ReservationForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
@ -58,16 +60,17 @@ def location(request, place_name='T2'):
guest = guest.first()
place = get_object_or_404(Place, name=place_name)
price = get_reservation_price(place, start, end)
reservation = Reservation.objects.create(
guest=guest,
place=place,
message=message,
start=start,
end=end
end=end,
price=price
)
context = {
'guest': guest,
'place': place
'reservation': reservation
}
return render(request, 'rental/merci.html', context)
except IntegrityError:
@ -82,7 +85,8 @@ def location(request, place_name='T2'):
def reservation(request):
if request.method == 'POST':
form = ReservationForm(request.POST)#, error_class=ParagraphErrorList)
# , error_class=ParagraphErrorList)
form = ReservationForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
@ -117,7 +121,7 @@ def reservation(request):
form.errors['internal'] = "Une erreur interne est apparue. Merci de recommencer votre requête."
else:
form = ReservationForm()
context = {'form' : form}
context = {'form': form}
context['errors'] = form.errors.items()
return render(request, 'rental/reservation.html', context)