From 780188e7d61d41d2b01d1cc219524fad216a8b90 Mon Sep 17 00:00:00 2001 From: Ruidy Date: Fri, 31 Jul 2020 08:02:10 +0200 Subject: [PATCH] Refactor (#7) * crete setting module to split prod and dev configs * fix calendar midmatch * lint imports using isort * doc: add doctrings --- rental/admin.py | 3 +- rental/enums.py | 3 + rental/forms/booking.py | 6 +- rental/forms/contact.py | 6 +- rental/migrations/0001_initial.py | 2 +- rental/migrations/0006_auto_20191107_2114.py | 2 +- rental/migrations/0007_auto_20191107_2116.py | 2 +- rental/migrations/0012_auto_20191110_1814.py | 2 +- rental/migrations/0013_auto_20191110_1817.py | 2 +- rental/migrations/0017_auto_20191111_0855.py | 2 +- rental/migrations/0019_auto_20191111_1020.py | 2 +- rental/migrations/0021_auto_20191111_1112.py | 2 +- rental/migrations/0022_auto_20191111_1211.py | 2 +- rental/models/booking.py | 28 ++-- rental/models/contact.py | 9 +- rental/models/guest.py | 1 + rental/models/picture.py | 2 + rental/models/place.py | 9 +- rental/models/testimonial.py | 11 +- rental/services/calendar.py | 14 +- rental/static/rental/lib/calendar/main.js | 32 ---- rental/tasks/{apiMailer.py => api_mailer.py} | 28 ++-- rental/tasks/{gMailer.py => g_mailer.py} | 23 +-- rental/templates/rental/detail_place.html | 1 - rental/tests/booking.py | 2 +- rental/urls.py | 7 +- rental/views/booking.py | 24 +-- rental/views/contact.py | 2 + rental/views/errors.py | 4 +- rental/views/place.py | 6 +- villafleurie/__init__.py | 1 + villafleurie/celery.py | 12 +- villafleurie/settings.py | 153 ------------------- villafleurie/settings/__init__.py | 6 + villafleurie/settings/base.py | 69 +++++++++ villafleurie/settings/development.py | 46 ++++++ villafleurie/settings/production.py | 65 ++++++++ villafleurie/urls.py | 7 +- 38 files changed, 328 insertions(+), 270 deletions(-) delete mode 100644 rental/static/rental/lib/calendar/main.js rename rental/tasks/{apiMailer.py => api_mailer.py} (84%) rename rental/tasks/{gMailer.py => g_mailer.py} (89%) delete mode 100644 villafleurie/settings.py create mode 100644 villafleurie/settings/__init__.py create mode 100644 villafleurie/settings/base.py create mode 100644 villafleurie/settings/development.py create mode 100644 villafleurie/settings/production.py diff --git a/rental/admin.py b/rental/admin.py index 90e09d6..95fe245 100644 --- a/rental/admin.py +++ b/rental/admin.py @@ -1,3 +1,5 @@ +""" Register models and configure admin dashboard """ + from django.contrib import admin from rental.models.booking import Booking @@ -7,7 +9,6 @@ from rental.models.picture import Picture from rental.models.place import Place from rental.models.testimonial import Testimonial - admin.site.register(Booking) admin.site.register(Guest) admin.site.register(Place) diff --git a/rental/enums.py b/rental/enums.py index 32eb66a..68095f2 100644 --- a/rental/enums.py +++ b/rental/enums.py @@ -3,5 +3,8 @@ from django.utils.translation import gettext_lazy as _ class PlaceNames(models.TextChoices): + """ PlaceNames enums serve to list places and prepare + for internationalisation + """ T2 = "T2", _("T2") T3 = "T3", _("T3") diff --git a/rental/forms/booking.py b/rental/forms/booking.py index 6888892..91b4ed5 100644 --- a/rental/forms/booking.py +++ b/rental/forms/booking.py @@ -1,11 +1,13 @@ from django import forms -from rental.models.booking import Booking -from rental.models.place import Place from rental.enums import PlaceNames class BookingForm(forms.Form): + """ + BookingForm serve to validate input and create a new booking. + doc: https://docs.djangoproject.com/fr/2.2/topics/forms/modelforms/ + """ name = forms.CharField( label="", diff --git a/rental/forms/contact.py b/rental/forms/contact.py index 0f77957..bd74797 100644 --- a/rental/forms/contact.py +++ b/rental/forms/contact.py @@ -1,9 +1,11 @@ from django import forms -from rental.models.contact import Contact -from rental.models.place import Place class ContactForm(forms.Form): + """ + ContactForm serve to validate input and create a new contact. + doc: https://docs.djangoproject.com/fr/2.2/topics/forms/modelforms/ + """ name = forms.CharField( label='', diff --git a/rental/migrations/0001_initial.py b/rental/migrations/0001_initial.py index 22c35d5..0d0289d 100644 --- a/rental/migrations/0001_initial.py +++ b/rental/migrations/0001_initial.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-06 11:50 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0006_auto_20191107_2114.py b/rental/migrations/0006_auto_20191107_2114.py index 232fe5a..50bad0e 100644 --- a/rental/migrations/0006_auto_20191107_2114.py +++ b/rental/migrations/0006_auto_20191107_2114.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-07 21:14 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0007_auto_20191107_2116.py b/rental/migrations/0007_auto_20191107_2116.py index ba63ee8..48727f6 100644 --- a/rental/migrations/0007_auto_20191107_2116.py +++ b/rental/migrations/0007_auto_20191107_2116.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-07 21:16 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0012_auto_20191110_1814.py b/rental/migrations/0012_auto_20191110_1814.py index 76d1dd6..89002c2 100644 --- a/rental/migrations/0012_auto_20191110_1814.py +++ b/rental/migrations/0012_auto_20191110_1814.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-10 18:14 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0013_auto_20191110_1817.py b/rental/migrations/0013_auto_20191110_1817.py index dba67c7..801274b 100644 --- a/rental/migrations/0013_auto_20191110_1817.py +++ b/rental/migrations/0013_auto_20191110_1817.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-10 18:17 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0017_auto_20191111_0855.py b/rental/migrations/0017_auto_20191111_0855.py index 68dd637..b0b6513 100644 --- a/rental/migrations/0017_auto_20191111_0855.py +++ b/rental/migrations/0017_auto_20191111_0855.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-11 08:55 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0019_auto_20191111_1020.py b/rental/migrations/0019_auto_20191111_1020.py index e25e875..fbdaad2 100644 --- a/rental/migrations/0019_auto_20191111_1020.py +++ b/rental/migrations/0019_auto_20191111_1020.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-11 10:20 -from django.db import migrations, models import django.utils.timezone +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0021_auto_20191111_1112.py b/rental/migrations/0021_auto_20191111_1112.py index 1751701..6f41e1e 100644 --- a/rental/migrations/0021_auto_20191111_1112.py +++ b/rental/migrations/0021_auto_20191111_1112.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-11 11:12 -from django.db import migrations, models import django.utils.timezone +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/migrations/0022_auto_20191111_1211.py b/rental/migrations/0022_auto_20191111_1211.py index c799305..237d951 100644 --- a/rental/migrations/0022_auto_20191111_1211.py +++ b/rental/migrations/0022_auto_20191111_1211.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.6 on 2019-11-11 12:11 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/rental/models/booking.py b/rental/models/booking.py index 1c2c0c3..bbf9ab0 100644 --- a/rental/models/booking.py +++ b/rental/models/booking.py @@ -1,27 +1,35 @@ from datetime import datetime + from django.db import models +import rental.services.calendar as calendar +import rental.tasks.api_mailer as mailer # or g_mailer from rental.models.guest import Guest from rental.models.place import Place -import rental.services.calendar as calendar -import rental.tasks.apiMailer as mailer # or gMailer class BookingManager(models.Manager): - """ BookingManager is the interface through which database query operations - are provided to Django models. + """ + BookingManager is the interface through which database query operations + are provided to Django models. """ def create_booking(self, **kwargs): - """ create_booking creates a Booking instance, computes the price and - updates the remote calendar. """ + """ + Create_booking creates a Booking instance, computes the price and + updates the remote calendar. + """ + booking = self.create(**kwargs) booking.price = booking.get_price() calendar.update(booking) + return booking class Booking(models.Model): + """ Booking encapsulate booking instance information """ + class Meta: verbose_name = 'Réservation' @@ -38,15 +46,17 @@ class Booking(models.Model): price = models.DecimalField(max_digits=6, decimal_places=2, null=True) def get_price(self): - """ Compute booking price as a function of place and dates """ + """ Compute booking price as a function of place and dates. """ - if type(self.start) == str: + if isinstance(self.start, str): self.start = datetime.strptime(self.start, '%Y-%m-%d') - if type(self.end) == str: + if isinstance(self.end, str): self.end = datetime.strptime(self.end, '%Y-%m-%d') nights = (self.end - self.start).days return self.place.price * nights def send_quotation(self): + """ Notify user of booking details """ + mailer.send_quotation.delay(self.guest.name, self.guest.email) diff --git a/rental/models/contact.py b/rental/models/contact.py index 45fd95f..b5d7f89 100644 --- a/rental/models/contact.py +++ b/rental/models/contact.py @@ -1,9 +1,12 @@ from django.db import models -import rental.tasks.apiMailer as mailer # or gMailer +import rental.tasks.api_mailer as mailer # or g_mailer class Contact(models.Model): + """ + Contact encapsulates communication with a customer. + """ def __str__(self): return f"Message de {self.name}, le {self.date}" @@ -15,9 +18,13 @@ class Contact(models.Model): date = models.DateTimeField(auto_now_add=True) def send_confirmation(self): + """ Notify that the message has been succesfully sent. """ + mailer.send_confirmation.delay(self.name, self.email) def send_notification(self): + """ Notify admins that a message has been sent. """ + mailer.send_notification.delay( self.name, self.email, diff --git a/rental/models/guest.py b/rental/models/guest.py index bd63895..b4db62a 100644 --- a/rental/models/guest.py +++ b/rental/models/guest.py @@ -2,6 +2,7 @@ from django.db import models class Guest(models.Model): + """ Guest summarizes customer information. """ class Meta: verbose_name = "Voyageur" diff --git a/rental/models/picture.py b/rental/models/picture.py index 7a5dc36..ac58e0a 100644 --- a/rental/models/picture.py +++ b/rental/models/picture.py @@ -2,6 +2,8 @@ from django.db import models class Picture(models.Model): + """ Picture manages media and set alt tags. """ + def __str__(self): return self.alt diff --git a/rental/models/place.py b/rental/models/place.py index 75eb4c8..a15ef9c 100644 --- a/rental/models/place.py +++ b/rental/models/place.py @@ -1,10 +1,12 @@ from django.db import models -from rental.models.picture import Picture import rental.services.calendar as calendar +from rental.models.picture import Picture class Place(models.Model): + """Place encapsulates a loaction information.""" + class Meta: verbose_name = "Appartement" @@ -21,9 +23,12 @@ class Place(models.Model): beds = models.IntegerField(null=True, blank=True) max_occupation = models.IntegerField(null=True, blank=True) thumbnail = models.ForeignKey( - Picture, on_delete=models.CASCADE, blank=True, null=True) + Picture, on_delete=models.CASCADE, blank=True, null=True + ) images = models.ManyToManyField(Picture, related_name="places", blank=True) calendar = models.CharField(max_length=350, blank=True, null=True) def is_available(self, start, end): + """Check weither a location is available at a given time period.""" + return calendar.check_availability(self, start, end) diff --git a/rental/models/testimonial.py b/rental/models/testimonial.py index f282568..f4ab288 100644 --- a/rental/models/testimonial.py +++ b/rental/models/testimonial.py @@ -5,6 +5,8 @@ from rental.models.guest import Guest class Testimonial(models.Model): + """Testimonial represent a past customer testimony.""" + class Meta: verbose_name = "Témoignage" @@ -14,9 +16,12 @@ class Testimonial(models.Model): author = models.CharField(max_length=200) text = models.TextField(max_length=1000) picture = models.ImageField( - max_length=200, upload_to='img/', null=True, blank=True) + max_length=200, upload_to='img/', null=True, blank=True + ) link = models.URLField(max_length=200, null=True, blank=True) guest = models.OneToOneField( - Guest, on_delete=models.CASCADE, blank=True, null=True) + Guest, on_delete=models.CASCADE, blank=True, null=True + ) reservation = models.OneToOneField( - Booking, on_delete=models.CASCADE, blank=True, null=True) + Booking, on_delete=models.CASCADE, blank=True, null=True + ) diff --git a/rental/services/calendar.py b/rental/services/calendar.py index a6c56e9..f97633d 100644 --- a/rental/services/calendar.py +++ b/rental/services/calendar.py @@ -1,17 +1,17 @@ import datetime -import os import logging +import os import pickle -from google.auth.transport.requests import Request -from google_auth_oauthlib.flow import InstalledAppFlow, Flow -from googleapiclient.discovery import build from django.shortcuts import get_object_or_404 +from google.auth.transport.requests import Request +from google_auth_oauthlib.flow import Flow, InstalledAppFlow +from googleapiclient.discovery import build -from villafleurie.settings import BASE_DIR -from rental.models.guest import Guest -import rental.models.place as m_place import rental.models.booking as m_booking +import rental.models.place as m_place +from rental.models.guest import Guest +from villafleurie.settings import BASE_DIR def build_service(): diff --git a/rental/static/rental/lib/calendar/main.js b/rental/static/rental/lib/calendar/main.js deleted file mode 100644 index e98ac33..0000000 --- a/rental/static/rental/lib/calendar/main.js +++ /dev/null @@ -1,32 +0,0 @@ -document.addEventListener("DOMContentLoaded", () => { - const calendarEl = document.getElementById("calendar"); - const calendar = new FullCalendar.Calendar(calendarEl, { - headerToolbar: { - left: "prev,next", - right: "title", - }, - locale: "fr", - firstDay: 1, // week start on Monday - displayEventTime: false, // don't show the time column in list view - googleCalendarApiKey: "AIzaSyC2Wcg2Q2sq071w_L6k5JfHnPptlseU16g", - events: { - googleCalendarId: - "burik7aclvhc7vsboh06c179uo@group.calendar.google.com", - }, - // eventColor: "#378006", - contentHeight: "auto", - // don't navigate in main tab - eventClick: (arg) => { - arg.jsEvent.preventDefault(); - }, - themeSystem: "bootstrap", - - loading: (bool) => { - document.getElementById("loading").style.display = bool - ? "block" - : "none"; - }, - }); - - calendar.render(); - }); \ No newline at end of file diff --git a/rental/tasks/apiMailer.py b/rental/tasks/api_mailer.py similarity index 84% rename from rental/tasks/apiMailer.py rename to rental/tasks/api_mailer.py index 53be4e0..f1ac1c6 100644 --- a/rental/tasks/apiMailer.py +++ b/rental/tasks/api_mailer.py @@ -1,11 +1,3 @@ -from __future__ import absolute_import, unicode_literals -from datetime import datetime - -from celery import shared_task -import requests - -from villafleurie.settings import EMAIL_HOST_USER, DEFAULT_FROM_EMAIL - """ Mailer Service used to send messages using API WebHooks. All Mailers must implement the following methods: @@ -16,7 +8,18 @@ from villafleurie.settings import EMAIL_HOST_USER, DEFAULT_FROM_EMAIL def send_quotation(name, email)->void """ -URL = "https://hooks.zapier.com/hooks/catch/4071838/o93celz/" +from __future__ import absolute_import, unicode_literals + +from datetime import datetime +import os + +import requests +from celery import shared_task + +from villafleurie.settings import DEFAULT_FROM_EMAIL, EMAIL_HOST_USER + +# get mailing hook URL from env +URL = os.environ.get("MAIL_HOOK") @shared_task @@ -31,8 +34,7 @@ def send_confirmation(name, email): "body": f"Merci {name}, nous avons bien reçu votre message, nous revenons vers vous rapidement !\nCordialement,\nNilka (VillaFleurie)" } - resp = requests.post(URL, data=payload) - + requests.post(URL, data=payload) @shared_task @@ -47,12 +49,12 @@ def send_notification(name, email, subject, message, date): "body": f"Sujet : {subject}\nDe : {name}, {email}\nLe : {date}\nMessage : {message}\nCordialement,\nNilka (VillaFleurie)" } - resp = requests.post(URL, data=payload) + requests.post(URL, data=payload) @shared_task def send_quotation(name, email): - """ Send quotation to customer """ + """ Notify admins then send quotation to customer """ send_notification( name, diff --git a/rental/tasks/gMailer.py b/rental/tasks/g_mailer.py similarity index 89% rename from rental/tasks/gMailer.py rename to rental/tasks/g_mailer.py index 411f594..dd23b27 100644 --- a/rental/tasks/gMailer.py +++ b/rental/tasks/g_mailer.py @@ -1,11 +1,3 @@ -from __future__ import absolute_import, unicode_literals - -from celery import shared_task -from django.core.mail import send_mail, mail_admins - -from villafleurie.settings import EMAIL_HOST_USER - - """ Mailer Service used to send messages using Gmail. All Mailers must implement the following methods: @@ -14,12 +6,20 @@ from villafleurie.settings import EMAIL_HOST_USER def send_notification(name, email, subject, message)->void def send_quotation(name, email)->void - """ +""" + +from __future__ import absolute_import, unicode_literals + +from celery import shared_task +from django.core.mail import mail_admins, send_mail + +from villafleurie.settings import EMAIL_HOST_USER @shared_task def send_confirmation(name, email): """ Send confirmation message to customer """ + subject = "Nous avons reçu votre message" message = f" Merci {name}, Bien reçu nous revenons vers vous rapidement !" @@ -27,7 +27,7 @@ def send_confirmation(name, email): subject, message, EMAIL_HOST_USER, - [email] + [email] ) @@ -44,4 +44,5 @@ def send_notification(name, email, subject, message): @shared_task def send_quotation(name, email): """ Send quotation to customer """ - send_confirmation_mail(name, email) + + send_confirmation(name, email) diff --git a/rental/templates/rental/detail_place.html b/rental/templates/rental/detail_place.html index 6d2f5bd..dd74a72 100644 --- a/rental/templates/rental/detail_place.html +++ b/rental/templates/rental/detail_place.html @@ -3,7 +3,6 @@ -