184 lines
7.3 KiB
Python
184 lines
7.3 KiB
Python
import json
|
|
from abc import ABC, abstractmethod
|
|
|
|
import requests
|
|
from django.conf import settings
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from rest_framework import serializers, status
|
|
from rest_framework.response import Response
|
|
|
|
import booking.models.models as models
|
|
|
|
|
|
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, required: set = {}, check: bool = True) -> dict:
|
|
""" Helper """
|
|
if len(required) == 0 and check:
|
|
required = keys_to_preserve.copy()
|
|
if required and check:
|
|
diff = required - d.keys()
|
|
if diff:
|
|
raise serializers.ValidationError({field: _(f'This field is required') for field in diff})
|
|
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, *args, **kwargs):
|
|
url = f'{self.url}v1/periods'
|
|
params = {'restaurant_id': restaurant_id, **kwargs}
|
|
r = requests.get(url, headers=self.get_common_headers(), params=params)
|
|
if not status.is_success(r.status_code):
|
|
return False
|
|
self.response = r.json()
|
|
return True
|
|
|
|
def commit_booking(self, payload, stripe_token = None):
|
|
url = f'{self.url}v1/pending_bookings/{payload}/commit'
|
|
if stripe_token:
|
|
r = requests.put(url, headers=self.get_common_headers(),
|
|
data=json.dumps({'stripe_token': stripe_token}))
|
|
else:
|
|
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')
|
|
payload['user_locale'] = payload.pop('country_code')
|
|
headers = self.get_common_headers()
|
|
r = requests.put(url, headers=headers, data=json.dumps({'contact_info': payload}))
|
|
response = r.json()
|
|
self.response = response.get('prepayment')
|
|
if not status.is_success(r.status_code):
|
|
return Response(status=r.status_code, data=response)
|
|
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))
|
|
if status.is_success(r.status_code):
|
|
return json.loads(r.content)['id']
|
|
else:
|
|
return Response(status=r.status_code, data=r.json())
|
|
|
|
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).get('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)
|