From 7b5c113f821ba773bd18104dd8406d9e8210bbc0 Mon Sep 17 00:00:00 2001 From: Kumi Date: Fri, 5 Aug 2022 15:24:06 +0000 Subject: [PATCH] Basic reservation implementation Static file storage MySQL databases --- .gitignore | 3 +- config.dist.ini | 16 ++++++++++- core/models/reservation.py | 57 ++++++++++++++++++++++++++++++++++++++ requirements.txt | 12 +++++++- restoroo/settings.py | 32 +++++++++++++++++++-- 5 files changed, 114 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 540f05e..9cdacd3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ venv/ *.pyc __pycache__/ config.ini -db.sqlite3 \ No newline at end of file +db.sqlite3 +/static/ \ No newline at end of file diff --git a/config.dist.ini b/config.dist.ini index d9bf612..681edbb 100644 --- a/config.dist.ini +++ b/config.dist.ini @@ -1,2 +1,16 @@ [RESTOROO] -Debug = 1 # Do not run with debug turned on in production! \ No newline at end of file +Debug = 1 # Do not run with debug turned on in production! +# StaticRoot = /var/www/html/restoroo/static + +# [MySQL] +# Database = restoroo +# Username = restoroo +# Password = secret123! +# Host = localhost +# Port = 3306 + +# [S3] +# AccessKey = restoroo +# SecretKey = !!!verysecret!!! +# Bucket = restoroo +# Endpoint = https://minio.resto.roo \ No newline at end of file diff --git a/core/models/reservation.py b/core/models/reservation.py index e69de29..0581a87 100644 --- a/core/models/reservation.py +++ b/core/models/reservation.py @@ -0,0 +1,57 @@ +from django.db import models +from django.utils.translation import gettext as _ + +from .profiles import Profile + +from phonenumber_field.modelfields import PhoneNumberField + + +class Guest(models.Model): + """Class representing a guest for a reservation + + Could also be used to link other people to a reservation + (think keeping data on the guest's guests, for contact tracing...) + + All data in here is optional – both for (eventual) GDPR compliance + and because different restaurants might request different information + """ + user_profile = models.ForeignKey(Profile, models.SET_NULL, null=True) + first_name = models.CharField(max_length=128, null=True, blank=True) + last_name = models.CharField(max_length=128, null=True, blank=True) + email = models.EmailField(null=True, blank=True) + phone = PhoneNumberField(null=True, blank=True) + + +class Reservation(models.Model): + """Class representing a table reservation + + Includes just the basic information on the reservation (number of people, + date, time, stuff like that) – personal data is stored in the Guest model + """ + + class ReservationStatusChoices(models.IntegerChoices): + """Class defining options for the status of a reservation + """ + UNCONFIRMED = (0, _("Unconfirmed")) + CONFIRMED = (1, _("Confirmed")) + CANCELLED_BY_GUEST = (-1, _("Cancelled by guest")) + CANCELLED_BY_RESTAURANT = (-2, _("Cancelled by restaurant")) + + booker = models.ForeignKey(Guest, models.PROTECT) + datetime = models.DateTimeField() + persons = models.PositiveSmallIntegerField() + status = models.IntegerField(choices=ReservationStatusChoices.choices) + + created_at = models.DateTimeField(auto_now_add=True) + + @property + def cancelled(self) -> bool: + """Exposes the status of a Reservation as a boolean value + + A negative integer value of Reservation.status will be considered a + cancelled Reservation + + Returns: + bool: True if the Reservation is in a cancelled state, else False + """ + return status < 0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d78e5a1..536e1a7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,14 @@ dbsettings argon2-cffi geopy django-countries[pyuca] -pillow \ No newline at end of file +pillow +django-phonenumber-field[phonenumbers] + +# For S3 + +django-storages +boto3 + +# For MySQL + +mysqlclient \ No newline at end of file diff --git a/restoroo/settings.py b/restoroo/settings.py index bc7fa82..1cb674f 100644 --- a/restoroo/settings.py +++ b/restoroo/settings.py @@ -27,6 +27,8 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', + 'phonenumber_field', + 'core', ] @@ -67,8 +69,18 @@ WSGI_APPLICATION = 'restoroo.wsgi.application' # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases -if CONFIG_FILE.config.has_section("MariaDB"): - pass # TODO +if "MySQL" in CONFIG_FILE.config: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': CONFIG_FILE.config.get("MySQL", "Database"), + 'USER': CONFIG_FILE.config.get("MySQL", "Username"), + 'PASSWORD': CONFIG_FILE.config.get("MySQL", "Password"), + 'HOST': CONFIG_FILE.config.get("MySQL", "Host", fallback="localhost"), + 'PORT': CONFIG_FILE.config.getint("MySQL", "Port", fallback=3306) + } + } + else: DATABASES = { 'default': { @@ -120,7 +132,21 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ -STATIC_URL = 'static/' +STATIC_URL = '/static/' + +STATIC_ROOT = None if DEBUG else CONFIG_FILE.config.get("RESTOROO", "StaticRoot", fallback=BASE_DIR / "static") + +LOGIN_REDIRECT_URL = '/' +LOGOUT_REDIRECT_URL = "/" + +if "S3" in CONFIG_FILE.config: + DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' + STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' + AWS_ACCESS_KEY_ID = CONFIG_FILE.config.get("S3", "AccessKey") + AWS_SECRET_ACCESS_KEY = CONFIG_FILE.config.get("S3", "SecretKey") + AWS_STORAGE_BUCKET_NAME = CONFIG_FILE.config.get("S3", "Bucket") + AWS_S3_ENDPOINT_URL = CONFIG_FILE.config.get("S3", "Endpoint") + # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field