diff --git a/apps/booking/__init__.py b/apps/booking/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/booking/admin.py b/apps/booking/admin.py new file mode 100644 index 00000000..3eb9d180 --- /dev/null +++ b/apps/booking/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +from booking.models import models + + +@admin.register(models.Booking) +class BookingModelAdmin(admin.ModelAdmin): + """Model admin for model Comment""" \ No newline at end of file diff --git a/apps/booking/apps.py b/apps/booking/apps.py new file mode 100644 index 00000000..5319bb5b --- /dev/null +++ b/apps/booking/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ + + +class BookingConfig(AppConfig): + name = 'booking' + verbose_name = _('Booking') diff --git a/apps/booking/migrations/0001_initial_squashed_0010_auto_20190920_1206.py b/apps/booking/migrations/0001_initial_squashed_0010_auto_20190920_1206.py new file mode 100644 index 00000000..33131471 --- /dev/null +++ b/apps/booking/migrations/0001_initial_squashed_0010_auto_20190920_1206.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.4 on 2019-10-03 10:38 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + replaces = [('booking', '0001_initial'), ('booking', '0002_booking_user'), ('booking', '0003_auto_20190916_1533'), ('booking', '0004_auto_20190916_1646'), ('booking', '0005_auto_20190918_1308'), ('booking', '0006_booking_country_code'), ('booking', '0007_booking_booking_id'), ('booking', '0008_auto_20190919_2008'), ('booking', '0009_booking_user'), ('booking', '0010_auto_20190920_1206')] + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Booking', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('type', models.CharField(choices=[('L', 'Lastable'), ('G', 'GuestOnline')], max_length=2, verbose_name='Guestonline or Lastable')), + ('booking_user_locale', models.CharField(default='en', max_length=10, verbose_name='booking locale')), + ('restaurant_id', models.PositiveIntegerField(default=None, verbose_name='booking service establishment id')), + ('pending_booking_id', models.TextField(default=None, verbose_name='external service pending booking')), + ('booking_id', models.TextField(db_index=True, default=None, null=True, verbose_name='external service booking id')), + ('user', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bookings', to=settings.AUTH_USER_MODEL, verbose_name='booking owner')), + ], + options={ + 'abstract': False, + 'verbose_name': 'Booking', + 'verbose_name_plural': 'Booking', + }, + ), + ] diff --git a/apps/booking/migrations/0002_auto_20191003_1601.py b/apps/booking/migrations/0002_auto_20191003_1601.py new file mode 100644 index 00000000..7f3814cd --- /dev/null +++ b/apps/booking/migrations/0002_auto_20191003_1601.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.4 on 2019-10-03 16:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('booking', '0001_initial_squashed_0010_auto_20190920_1206'), + ] + + operations = [ + migrations.RemoveField( + model_name='booking', + name='restaurant_id', + ), + migrations.AddField( + model_name='booking', + name='restaurant_id', + field=models.TextField(default=None, verbose_name='booking service establishment id'), + ), + ] diff --git a/apps/booking/migrations/__init__.py b/apps/booking/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/booking/models/__init__.py b/apps/booking/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/booking/models/models.py b/apps/booking/models/models.py new file mode 100644 index 00000000..41cfc6d7 --- /dev/null +++ b/apps/booking/models/models.py @@ -0,0 +1,67 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers +from utils.models import ProjectBaseMixin +from booking.models.services import LastableService, GuestonlineService +from account.models import User + + +class BookingManager(models.QuerySet): + def by_user(self, user: User): + return self.filter(user=user) + + +class Booking(ProjectBaseMixin): + LASTABLE = 'L' + GUESTONLINE = 'G' + AVAILABLE_SERVICES = ( + (LASTABLE, 'Lastable'), + (GUESTONLINE, 'GuestOnline') + ) + type = models.CharField(max_length=2, choices=AVAILABLE_SERVICES, verbose_name=_('Guestonline or Lastable')) + restaurant_id = models.TextField(verbose_name=_('booking service establishment id'), default=None) + booking_user_locale = models.CharField(verbose_name=_('booking locale'), default='en', max_length=10) + pending_booking_id = models.TextField(verbose_name=_('external service pending booking'), default=None) + booking_id = models.TextField(verbose_name=_('external service booking id'), default=None, null=True, + db_index=True, ) + user = models.ForeignKey( + 'account.User', verbose_name=_('booking owner'), null=True, + related_name='bookings', + blank=True, default=None, on_delete=models.CASCADE) + objects = BookingManager.as_manager() + + @property + def accept_email_spam(self): + return False + + @property + def accept_sms_spam(self): + return False + + @classmethod + def get_service_by_type(cls, type): + if type == cls.GUESTONLINE: + return GuestonlineService() + elif type == cls.LASTABLE: + return LastableService() + else: + return None + + @classmethod + def get_booking_id_by_type(cls, establishment, type): + if type == cls.GUESTONLINE: + return establishment.guestonline_id + elif type == cls.LASTABLE: + return establishment.lastable_id + else: + return None + + def delete(self, using=None, keep_parents=False): + service = self.get_service_by_type(self.type) + if not service.cancel_booking(self.booking_id): + raise serializers.ValidationError(detail='Something went wrong! Unable to cancel.') + super().delete(using, keep_parents) + + class Meta: + verbose_name = _('Booking') + verbose_name_plural = _('Booking') diff --git a/apps/booking/models/services.py b/apps/booking/models/services.py new file mode 100644 index 00000000..fd685548 --- /dev/null +++ b/apps/booking/models/services.py @@ -0,0 +1,166 @@ +from abc import ABC, abstractmethod +import json +import requests +from django.conf import settings +from rest_framework import status +import booking.models.models as models +from rest_framework import serializers + + +class AbstractBookingService(ABC): + """ Abstract class for Guestonline && Lastable booking services""" + + def __init__(self, service): + self.service = None + self.response = None + if service not in [models.Booking.LASTABLE, models.Booking.GUESTONLINE]: + raise Exception('Service %s is not implemented yet' % service) + self.service = service + if service == models.Booking.GUESTONLINE: + self.token = settings.GUESTONLINE_TOKEN + self.url = settings.GUESTONLINE_SERVICE + elif service == models.Booking.LASTABLE: + self.token = settings.LASTABLE_TOKEN + self.url = settings.LASTABLE_SERVICE + + @staticmethod + def get_certain_keys(d: dict, keys_to_preserve: set) -> dict: + """ Helper """ + return {key: d[key] for key in d.keys() & keys_to_preserve} + + @abstractmethod + def check_whether_booking_available(self, restaurant_id, date): + """ checks whether booking is available """ + if date is None: + raise serializers.ValidationError(detail='date query param is required') + + @abstractmethod + def cancel_booking(self, payload): + """ cancels booking and returns the result """ + pass + + @abstractmethod + def create_booking(self, payload): + """ returns pending booking id if created. otherwise False """ + pass + + @abstractmethod + def update_booking(self, payload): + """ updates pending booking with contacts """ + pass + + @abstractmethod + def get_common_headers(self): + pass + + @abstractmethod + def get_booking_details(self, payload): + """ fetches booking details from external service """ + pass + + +class GuestonlineService(AbstractBookingService): + def __init__(self): + super().__init__(models.Booking.GUESTONLINE) + + def get_common_headers(self): + return {'X-Token': self.token, 'Content-type': 'application/json', 'Accept': 'application/json'} + + def check_whether_booking_available(self, restaurant_id, date: str): + super().check_whether_booking_available(restaurant_id, date) + url = f'{self.url}v1/runtime_services' + params = {'restaurant_id': restaurant_id, 'date': date, 'expands[]': 'table_availabilities'} + r = requests.get(url, headers=self.get_common_headers(), params=params) + if not status.is_success(r.status_code): + return False + response = json.loads(r.content)['runtime_services'] + keys_to_preserve = {'left_seats', 'table_availabilities', 'closed', 'start_time', 'end_time', 'last_booking'} + response = map(lambda x: self.get_certain_keys(x, keys_to_preserve), response) + self.response = response + return True + + def commit_booking(self, payload): + url = f'{self.url}v1/pending_bookings/{payload}/commit' + r = requests.put(url, headers=self.get_common_headers()) + self.response = json.loads(r.content) + if status.is_success(r.status_code) and self.response is None: + raise serializers.ValidationError(detail='Booking already committed.') + return status.is_success(r.status_code) + + def update_booking(self, payload): + booking_id = payload.pop('pending_booking_id') + url = f'{self.url}v1/pending_bookings/{booking_id}' + payload['lastname'] = payload.pop('last_name') + payload['firstname'] = payload.pop('first_name') + payload['mobile_phone'] = payload.pop('phone') + headers = self.get_common_headers() + r = requests.put(url, headers=headers, data=json.dumps({'contact_info': payload})) + return status.is_success(r.status_code) + + def create_booking(self, payload): + url = f'{self.url}v1/pending_bookings' + payload['hour'] = payload.pop('booking_time') + payload['persons'] = payload.pop('booked_persons_number') + payload['date'] = payload.pop('booking_date') + r = requests.post(url, headers=self.get_common_headers(), data=json.dumps(payload)) + return json.loads(r.content)['id'] if status.is_success(r.status_code) else False + + def cancel_booking(self, payload): + url = f'{self.url}v1/pending_bookings/{payload}' + r = requests.delete(url, headers=self.get_common_headers()) + return status.is_success(r.status_code) + + def get_booking_details(self, payload): + url = f'{self.url}v1/bookings/{payload}' + r = requests.get(url, headers=self.get_common_headers()) + return json.loads(r.content) + + +class LastableService(AbstractBookingService): + def __init__(self): + super().__init__(models.Booking.LASTABLE) + self.proxies = { + 'http': settings.LASTABLE_PROXY, + 'https': settings.LASTABLE_PROXY, + } + + def create_booking(self, payload): + url = f'{self.url}v1/partner/orders' + payload['places'] = payload.pop('booked_persons_number') + payload['hour'] = payload.pop('booking_time') + payload['firstName'] = payload.pop('first_name') + payload['lastName'] = payload.pop('last_name') + r = requests.post(url, headers=self.get_common_headers(), proxies=self.proxies, data=json.dumps(payload)) + return json.loads(r.content)['data']['_id'] if status.is_success(r.status_code) else False + + def get_common_headers(self): + return {'Authorization': f'Bearer {self.token}', 'Content-type': 'application/json', + 'Accept': 'application/json'} + + def check_whether_booking_available(self, restaurant_id, date): + super().check_whether_booking_available(restaurant_id, date) + url = f'{self.url}v1/restaurant/{restaurant_id}/offers' + r = requests.get(url, headers=self.get_common_headers(), proxies=self.proxies) + response = json.loads(r.content)['data'] + if not status.is_success(r.status_code) or not response: + return False + self.response = response + return True + + def commit_booking(self, payload): + """ Lastable service has no pending booking to commit """ + return False + + def update_booking(self, payload): + """ Lastable service has no pending booking to update """ + return False + + def cancel_booking(self, payload): + url = f'{self.url}v1/partner/orders/{payload}' + r = requests.delete(url, headers=self.get_common_headers(), proxies=self.proxies) + return status.is_success(r.status_code) + + def get_booking_details(self, payload): + url = f'{self.url}v1/partner/orders/{payload}' + r = requests.get(url, headers=self.get_common_headers(), proxies=self.proxies) + return json.loads(r.content) diff --git a/apps/booking/serializers/__init__.py b/apps/booking/serializers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/booking/serializers/web.py b/apps/booking/serializers/web.py new file mode 100644 index 00000000..1094aef8 --- /dev/null +++ b/apps/booking/serializers/web.py @@ -0,0 +1,64 @@ +from rest_framework import serializers +from booking.models import models + + +class BookingSerializer(serializers.ModelSerializer): + class Meta: + model = models.Booking + fields = ( + 'id', + 'type', + ) + + +class CheckBookingSerializer(serializers.ModelSerializer): + available = serializers.BooleanField() + type = serializers.ChoiceField(choices=models.Booking.AVAILABLE_SERVICES, allow_null=True) + details = serializers.DictField() + + class Meta: + model = models.Booking + fields = ( + 'available', + 'type', + 'details', + ) + + +class PendingBookingSerializer(serializers.ModelSerializer): + restaurant_id = serializers.CharField() + booking_id = serializers.CharField(allow_null=True, allow_blank=True) + id = serializers.ReadOnlyField() + user = serializers.ReadOnlyField() + + class Meta: + model = models.Booking + fields = ( + 'id', + 'type', + 'restaurant_id', + 'booking_id', + 'pending_booking_id', + 'user', + ) + + +class UpdateBookingSerializer(serializers.ModelSerializer): + id = serializers.ReadOnlyField() + + class Meta: + model = models.Booking + fields = ('booking_id', 'id') + + +class GetBookingSerializer(serializers.ModelSerializer): + details = serializers.SerializerMethodField() + + def get_details(self, obj): + booking = self.instance + service = booking.get_service_by_type(booking.type) + return service.get_booking_details(booking.booking_id) + + class Meta: + model = models.Booking + fields = '__all__' diff --git a/apps/booking/tests.py b/apps/booking/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/apps/booking/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/booking/urls.py b/apps/booking/urls.py new file mode 100644 index 00000000..900ec8cb --- /dev/null +++ b/apps/booking/urls.py @@ -0,0 +1,14 @@ +"""Booking app urls.""" +from django.urls import path +from booking import views + +app = 'booking' + +urlpatterns = [ + path('/check/', views.CheckWhetherBookingAvailable.as_view(), name='booking-check'), + path('/create/', views.CreatePendingBooking.as_view(), name='create-pending-booking'), + path('/', views.UpdatePendingBooking.as_view(), name='update-pending-booking'), + path('/cancel/', views.CancelBooking.as_view(), name='cancel-existing-booking'), + path('last/', views.LastBooking.as_view(), name='last_booking-for-authorizer-user'), + path('retrieve//', views.GetBookingById.as_view(), name='retrieves-booking-by-id'), +] diff --git a/apps/booking/views.py b/apps/booking/views.py new file mode 100644 index 00000000..245dbf05 --- /dev/null +++ b/apps/booking/views.py @@ -0,0 +1,118 @@ +from rest_framework import generics, permissions, status, serializers + +from django.shortcuts import get_object_or_404 +from establishment.models import Establishment +from booking.models.models import Booking, GuestonlineService, LastableService +from rest_framework.response import Response +from booking.serializers.web import (PendingBookingSerializer, + UpdateBookingSerializer, GetBookingSerializer, CheckBookingSerializer) + + +class CheckWhetherBookingAvailable(generics.GenericAPIView): + """ Checks which service to use if establishmend is managed by any """ + + permission_classes = (permissions.AllowAny,) + serializer_class = CheckBookingSerializer + pagination_class = None + + def get(self, request, *args, **kwargs): + is_booking_available = False + establishment = get_object_or_404(Establishment, pk=kwargs['establishment_id']) + service = None + date = request.query_params.get('date') + g_service = GuestonlineService() + l_service = LastableService() + if (not establishment.lastable_id is None) and l_service \ + .check_whether_booking_available(establishment.lastable_id, date): + is_booking_available = True + service = l_service + service.service_id = establishment.lastable_id + elif (not establishment.guestonline_id is None) and g_service \ + .check_whether_booking_available(establishment.guestonline_id, date): + is_booking_available = True + service = g_service + service.service_id = establishment.guestonline_id + + response = { + 'available': is_booking_available, + 'type': service.service, + } + response.update({'details': service.response} if service.response else {}) + return Response(data=response, status=200) + + +class CreatePendingBooking(generics.CreateAPIView): + """ Creates pending booking """ + permission_classes = (permissions.AllowAny,) + serializer_class = PendingBookingSerializer + + def post(self, request, *args, **kwargs): + data = request.data.copy() + if data.get('type') == Booking.LASTABLE and data.get("offer_id") is None: + raise serializers.ValidationError(detail='Offer_id is required field for Lastable service') + establishment = get_object_or_404(Establishment, pk=kwargs['establishment_id']) + data['restaurant_id'] = Booking.get_booking_id_by_type(establishment, data.get('type')) + service = Booking.get_service_by_type(request.data.get('type')) + data['user'] = request.user.pk if request.user else None + service_to_keys = { + Booking.GUESTONLINE: {'restaurant_id', 'booking_time', 'booking_date', 'booked_persons_number', }, + Booking.LASTABLE: {'booking_time', 'booked_persons_number', 'offer_id', 'email', 'phone', + 'first_name', 'last_name', }, + } + data['pending_booking_id'] = service.create_booking( + service.get_certain_keys(data.copy(), service_to_keys[data.get('type')])) + if not data['pending_booking_id']: + return Response(status=status.HTTP_403_FORBIDDEN, data='Unable to create booking') + data['booking_id'] = data['pending_booking_id'] if data.get('type') == Booking.LASTABLE else None + serializer = self.get_serializer(data=data) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(status=status.HTTP_201_CREATED, data=serializer.data) + + +class UpdatePendingBooking(generics.UpdateAPIView): + """ Update pending booking with contacts """ + queryset = Booking.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = UpdateBookingSerializer + + def patch(self, request, *args, **kwargs): + instance = self.get_object() + data = request.data.copy() + service = Booking.get_service_by_type(instance.type) + data['pending_booking_id'] = instance.pending_booking_id + service.update_booking(service.get_certain_keys(data, { + 'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id', + })) + service.commit_booking(data['pending_booking_id']) + data = { + 'booking_id': service.response.get('id'), + 'id': instance.pk, + } + serializer = self.get_serializer(data=data) + serializer.is_valid(raise_exception=True) + serializer.update(instance, data) + return Response(status=status.HTTP_200_OK, data=serializer.data) + + +class CancelBooking(generics.DestroyAPIView): + """ Cancel existing booking """ + queryset = Booking.objects.all() + permission_classes = (permissions.AllowAny,) + + +class LastBooking(generics.RetrieveAPIView): + """ Get last booking by user credentials """ + permission_classes = (permissions.IsAuthenticated,) + serializer_class = GetBookingSerializer + lookup_field = None + + def get_object(self): + return Booking.objects.by_user(self.request.user).latest('modified') + + +class GetBookingById(generics.RetrieveAPIView): + """ Returns booking by its id""" + permission_classes = (permissions.AllowAny,) + serializer_class = GetBookingSerializer + queryset = Booking.objects.all() diff --git a/apps/establishment/migrations/0020_auto_20190916_1532.py b/apps/establishment/migrations/0020_auto_20190916_1532.py new file mode 100644 index 00000000..d22fad07 --- /dev/null +++ b/apps/establishment/migrations/0020_auto_20190916_1532.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.4 on 2019-09-16 15:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0019_establishment_is_publish'), + ] + + operations = [ + migrations.AddField( + model_name='establishment', + name='guestonline_id', + field=models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='guestonline id'), + ), + migrations.AddField( + model_name='establishment', + name='lastable_id', + field=models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='lastable id'), + ), + ] diff --git a/apps/establishment/migrations/0032_merge_20191001_1530.py b/apps/establishment/migrations/0032_merge_20191001_1530.py new file mode 100644 index 00000000..d0448141 --- /dev/null +++ b/apps/establishment/migrations/0032_merge_20191001_1530.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.4 on 2019-10-01 15:30 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0020_auto_20190916_1532'), + ('establishment', '0031_establishment_slug'), + ] + + operations = [ + ] diff --git a/apps/establishment/migrations/0033_auto_20191003_0943_squashed_0034_auto_20191003_1036.py b/apps/establishment/migrations/0033_auto_20191003_0943_squashed_0034_auto_20191003_1036.py new file mode 100644 index 00000000..48a0fa8d --- /dev/null +++ b/apps/establishment/migrations/0033_auto_20191003_0943_squashed_0034_auto_20191003_1036.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.4 on 2019-10-03 10:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('establishment', '0033_auto_20191003_0943'), ('establishment', '0034_auto_20191003_1036')] + + dependencies = [ + ('establishment', '0032_merge_20191001_1530'), + ] + + operations = [ + migrations.RemoveField( + model_name='establishment', + name='lastable_id', + ), + migrations.AddField( + model_name='establishment', + name='lastable_id', + field=models.TextField(blank=True, default=None, null=True, unique=True, verbose_name='lastable id'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 5c2a0ff0..43bc2f94 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -271,6 +271,10 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): verbose_name=_('Twitter URL')) lafourchette = models.URLField(blank=True, null=True, default=None, verbose_name=_('Lafourchette URL')) + guestonline_id = models.PositiveIntegerField(blank=True, verbose_name=_('guestonline id'), + null=True, default=None,) + lastable_id = models.TextField(blank=True, verbose_name=_('lastable id'), unique=True, + null=True, default=None,) booking = models.URLField(blank=True, null=True, default=None, verbose_name=_('Booking URL')) is_publish = models.BooleanField(default=False, verbose_name=_('Publish status')) diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index d0c70b2f..8bd09e85 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -39,7 +39,9 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer): 'image_url', 'slug', # TODO: check in admin filters - 'is_publish' + 'is_publish', + 'guestonline_id', + 'lastable_id', ] diff --git a/apps/timetable/migrations/0003_auto_20191003_0943.py b/apps/timetable/migrations/0003_auto_20191003_0943.py new file mode 100644 index 00000000..4c5a22b4 --- /dev/null +++ b/apps/timetable/migrations/0003_auto_20191003_0943.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.4 on 2019-10-03 09:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('timetable', '0002_auto_20190919_1124'), + ] + + operations = [ + migrations.AlterModelOptions( + name='timetable', + options={'ordering': ['weekday'], 'verbose_name': 'Timetable', 'verbose_name_plural': 'Timetables'}, + ), + ] diff --git a/project/settings/base.py b/project/settings/base.py index cec6a4d1..06f83811 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -55,6 +55,7 @@ PROJECT_APPS = [ 'advertisement.apps.AdvertisementConfig', 'account.apps.AccountConfig', 'authorization.apps.AuthorizationConfig', + 'booking.apps.BookingConfig', 'collection.apps.CollectionConfig', 'establishment.apps.EstablishmentConfig', 'gallery.apps.GalleryConfig', @@ -263,6 +264,13 @@ SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { 'fields': 'id, name, email', } +# Booking API configuration +GUESTONLINE_SERVICE = 'https://api-preprod.guestonline.fr/' +GUESTONLINE_TOKEN = 'iiReiYpyojshpPjpmczS' +LASTABLE_SERVICE = 'http://34.251.84.222/' +LASTABLE_TOKEN = '6dfc608ce5e494' +LASTABLE_PROXY = 'socks5://octopod:adgjmptw@94.177.171.154:2080' + # SMS Settings SMS_EXPIRATION = 5 SMS_SEND_DELAY = 30 diff --git a/project/settings/production.py b/project/settings/production.py index e491a1fb..5682a59d 100644 --- a/project/settings/production.py +++ b/project/settings/production.py @@ -1,2 +1,9 @@ """Production settings.""" from .base import * + +# Booking API configuration +GUESTONLINE_SERVICE = 'https://api.guestonline.fr/' +GUESTONLINE_TOKEN = '' +LASTABLE_SERVICE = '' +LASTABLE_TOKEN = '' +LASTABLE_PROXY = '' \ No newline at end of file diff --git a/project/urls/web.py b/project/urls/web.py index 5bf538f3..59c08a6f 100644 --- a/project/urls/web.py +++ b/project/urls/web.py @@ -19,6 +19,7 @@ app_name = 'web' urlpatterns = [ path('account/', include('account.urls.web')), + path('booking/', include('booking.urls')), path('re_blocks/', include('advertisement.urls.web')), path('collections/', include('collection.urls.web')), path('establishments/', include('establishment.urls.web')), diff --git a/requirements/base.txt b/requirements/base.txt index 25749c4b..716d21c6 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -9,6 +9,7 @@ fcm-django django-easy-select2 bootstrap-admin drf-yasg==1.16.0 +PySocks!=1.5.7,>=1.5.6; djangorestframework==3.9.4 markdown