예제 #1
0
    def test_get_a_table(self):
        """ Try get a table utils """
        now = datetime.datetime.now()

        with self.app.app_context():
            booking = (now.replace(hour=13) + datetime.timedelta(days=1))
            r = get_a_table(3, 1, booking)
            self.assertEqual(r, 6, msg=r) # expected table 6

            r = get_a_table(3, 4, booking)
            self.assertEqual(r, 5, msg=r) # expected table 5

            r = get_a_table(3, 5, booking)
            self.assertEqual(r, -1, msg=r) # expected table no table (no free tables with such capacity)
예제 #2
0
def new_booking():
    """ Add a new booking.

    POST /bookings
    
    Returns the booking if it can be made, otherwise returns an error message.

    Requires a json object with:
        - number_of_people: the number of people for the booking
        - booking_datetime: the datetime of the booking
        - user_id: the id of the user who made the booking
        - restaurant_id: the id of the restaurant

    Status Codes:
        201 - The booking has been created
        400 - Wrong datetime
        409 - Impossible to change the booking (it is full, it is closed ...)
        500 - Error in communicating with the restaurant service or problem with the database (try again)
    """

    req = request.json
    try:
        req["booking_datetime"] = dateutil.parser.parse(
            req["booking_datetime"])
    except:
        return Error400("booking_datetime is not a valid datetime").get()

    timezone = req["booking_datetime"].tzinfo
    now = datetime.datetime.now(timezone)  #timezone aware computation
    if req["booking_datetime"] <= now:
        return Error400("booking_datetime must be in the future").get()

    # try to get a table in the restaurant for the booking
    table = get_a_table(req["restaurant_id"], req["number_of_people"],
                        req["booking_datetime"])
    if table is None:  # an error occured (problem during the connection with the restaurant's microservice)
        return Error500().get()
    elif table == -1:  # The restaurant does not accept the booking because there are no free tables
        return Error(
            "about:blank", "Conflict", 409,
            "We are sorry! It is not possible to make the booking: there are no free tables!"
        ).get()
    elif table == -2:  # The restaurant does not accept the booking because it is closed
        return Error(
            "about:blank", "Conflict", 409,
            "We are sorry! It is not possible to make the booking: the restaurant is closed on that datetime!"
        ).get()

    booking = add_booking(req["user_id"], req["restaurant_id"],
                          req["number_of_people"], req["booking_datetime"],
                          table)
    if booking is None:  # DB error
        return Error500().get()

    booking, status_code = get_booking(booking)
    if status_code == 200:
        return booking, 201
    else:  # unexpected error
        return Error500().get()
예제 #3
0
    def test_get_a_table_failure(self):
        """ Try get a table utils without mocks """
        now = datetime.datetime.now()

        app = create_app("FAILURE_TEST") # Test without mocks (FAILURE_TEST is configuration in config.ini that disable mocks but maintains fake data)
        app = app.app 
        app.config['TESTING'] = True

        with app.app_context():
            booking = (now.replace(hour=13) + datetime.timedelta(days=1))
            r = get_a_table(3, 1, booking)
            self.assertEqual(r, None, msg=r) # expected None in case of connections problems

            r = get_a_table(3, 4, booking)
            self.assertEqual(r, None, msg=r) # expected None in case of connections problems

            r = get_a_table(3, 5, booking)
            self.assertEqual(r, None, msg=r) # expected None in case of connections problems
예제 #4
0
    def test_get_table_restaurant_closed(self):
        """ Try to get a free table in a closed restaurant with mocks """
        now = datetime.datetime.now()
        booking = now.replace( year=2020, month=11, day=17, hour=11, minute=30, second=0, microsecond=0)

        with self.app.app_context():
            r = get_a_table(1, 1, booking)
            self.assertEqual(r, -2) # -2 in case that the restaurant is closed

            booking = now.replace( year=2020, month=11, day=17, hour=23, minute=0, second=0, microsecond=0 )

            for i in [1,2]:
                r = get_a_table(i, 1, booking)
                self.assertEqual(r, -2, msg=i) # -2 in case that the restaurant is closed

            booking = now.replace( year=2020, month=11, day=16, hour=23, minute=0, second=0, microsecond=0 )
            
            for i in [1,2]:
                r = get_a_table(i, 1, booking)
                self.assertEqual(r, -2, msg=i) # -2 in case that the restaurant is closed
예제 #5
0
    def test_get_table_restaurant_closed_failure(self):
        """ Try get a table utils without mocks """
        app = create_app("FAILURE_TEST") # Test without mocks (FAILURE_TEST is configuration in config.ini that disable mocks but maintains fake data)
        app = app.app 
        app.config['TESTING'] = True

        now = datetime.datetime.now()
        booking = now.replace( year=2020, month=11, day=17, hour=11, minute=30, second=0, microsecond=0)

        with app.app_context():
            for i in [1,2,3,4]:
                r = get_a_table(i, 1, booking)
                self.assertEqual(r, None, msg=i) # expected None in case of connections problems
예제 #6
0
def put_booking(booking_id, entrance=False):
    """ Edit a booking.

    GET /bookings/{booking_id}?[entrance=true/false]

    Changes the number of people and/or the date of the booking. 
    Or marks the user's entry.

    The request to mark the entrance is made through the query parameter entrance (a boolean)

    Change requests are made through json objects with the following properties (both optional)
        - booking_datetime: the new requested datetime
        - number_of_people: the new requested number of people

    If one of the two fields is not set, the one already entered is recovered.
    If both are not entered the request is void (unless required to mark the entry()in this case the json is ignored).

    If entry is marked, other requests for changes are ignored (if the user has already entered the changes no longer make sense).
    Likewise, if the entry is marked, no more changes can be made.

    The booking must not have already passed, in the event of a change.

    Change of a booking may not always be possible (on the requested date there are no seats available, the restaurant is closed on that date ...)

    Status Codes:
        200 - OK
        400 - Wrong datetime or bad request (entry already marked)
        404 - Booking not found
        409 - Impossible to change the booking
        500 - Error in communicating with the restaurant service or problem with the database (try again)
    """
    q = db.session.query(Booking).filter_by(id=booking_id).first()
    if q is None:
        return Error404("Booking not found").get()
    q = q.dump()

    if entrance:
        if q["entrance_datetime"] is not None:
            return Error400(
                "Entrance has already been marked for this booking").get()
        now = datetime.datetime.now()
        booking = update_booking(q["id"], q["number_of_people"],
                                 q["booking_datetime"], q["table_id"], now)
        if booking is None:  # DB error
            return Error500().get()
        booking, status_code = get_booking(booking)
        if status_code == 200:
            return booking, 200
        else:  # unexpected error
            return Error500().get()

    if q["entrance_datetime"] is not None:
        return Error400(
            "The entry has already been marked, the reservation can no longer be changed"
        ).get()

    now = datetime.datetime.now()
    if q["booking_datetime"] < now:
        return Error400("You cannot change a past booking").get()

    req = request.json

    if "booking_datetime" in req and req["booking_datetime"] is not None:
        try:
            req["booking_datetime"] = dateutil.parser.parse(
                req["booking_datetime"])
        except:
            return Error400("booking_datetime is not a valid datetime").get()
    else:  # use the "old" datetime
        req["booking_datetime"] = q["booking_datetime"]

    timezone = req["booking_datetime"].tzinfo
    now = datetime.datetime.now(timezone)
    if req["booking_datetime"] <= now:
        return Error400("booking_datetime must be in the future").get()

    if "number_of_people" not in req or req["number_of_people"] is None:
        req["number_of_people"] = q["number_of_people"]

    if (q["booking_datetime"] != req["booking_datetime"]) or (
            q["number_of_people"] != req["number_of_people"]):

        table = get_a_table(q["restaurant_id"],
                            req["number_of_people"],
                            req["booking_datetime"],
                            excluded=booking_id)  # try to get a table

        if table is None:  # an error occured (problem during the connection with the restaurant's microservice)
            return Error500().get()
        elif table == -1:  # The restaurant does not accept the changes because there are no free tables
            return Error(
                "about:blank", "Conflict", 409,
                "We are sorry! It is not possible to change the booking: there are no free tables!"
            ).get()
        elif table == -2:  # The restaurant does not accept the changes because it is closed
            return Error(
                "about:blank", "Conflict", 409,
                "We are sorry! It is not possible to change the booking: the restaurant is closed on that datetime!"
            ).get()

        booking = update_booking(q["id"], req["number_of_people"],
                                 req["booking_datetime"], table)
        if booking is None:  # DB error
            return Error500().get()

        booking, status_code = get_booking(booking)
        if status_code == 200:
            return booking, 200
        else:  # unexpected error
            return Error500().get()

    return Error400("No changes were requested").get()