mirror of
https://github.com/rjNemo/villafleurie
synced 2026-06-06 02:16:47 +00:00
Quotation returned after succesful booking
This commit is contained in:
parent
cf9fb67232
commit
be7bdec84f
6 changed files with 139 additions and 114 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,3 +4,4 @@ rental/__pycache__
|
|||
rental/migrations
|
||||
villafleurie/__pycache__
|
||||
.DS_Store
|
||||
.vscode/
|
||||
|
|
|
|||
102
README.md
102
README.md
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue