141 lines
6.3 KiB
Python
141 lines
6.3 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
|
|
from datetime import datetime, timedelta
|
|
from typing import Annotated
|
|
|
|
from msgraph import GraphServiceClient
|
|
from msgraph.generated.models.booking_appointment import BookingAppointment
|
|
from msgraph.generated.models.booking_customer_information import BookingCustomerInformation
|
|
from msgraph.generated.models.date_time_time_zone import DateTimeTimeZone
|
|
from msgraph.generated.models.location import Location
|
|
|
|
from semantic_kernel.functions.kernel_function_decorator import kernel_function
|
|
|
|
|
|
class BookingsPlugin:
|
|
"""A plugin for booking tables at a restaurant."""
|
|
|
|
def __init__(
|
|
self,
|
|
graph_client: GraphServiceClient,
|
|
booking_business_id: str,
|
|
booking_service_id: str,
|
|
customer_timezone: str = "America/Chicago",
|
|
):
|
|
"""Initializes a new instance of the BookingsPlugin class.
|
|
|
|
Args:
|
|
graph_client (GraphServiceClient): The GraphServiceClient instance.
|
|
booking_business_id (str): The ID of the booking business.
|
|
service_id (str): The ID of the service.
|
|
customer_timezone (str, optional): The timezone of the customer. Defaults to "America/Chicago".
|
|
"""
|
|
self.graph_client = graph_client
|
|
self.booking_business_id = booking_business_id
|
|
self.booking_service_id = booking_service_id
|
|
self.customer_timezone = customer_timezone
|
|
|
|
@kernel_function(name="book_table", description="Book a table at a restaurant")
|
|
async def book_table(
|
|
self,
|
|
restaurant: Annotated[str, "The name of the restaurant"],
|
|
date_time: Annotated[str, "The time in UTC, formatted as an ISO datetime string, like 2024-09-15T19:00:00"],
|
|
party_size: Annotated[int, "The number of people in the party"],
|
|
customer_name: Annotated[str, "The name of the customer"],
|
|
customer_email: Annotated[str, "The email of the customer"],
|
|
customer_phone: Annotated[str, "The phone number of the customer"],
|
|
) -> Annotated[str, "The booking appointment ID"]:
|
|
"""Book a table at a restaurant.
|
|
|
|
Args:
|
|
restaurant (str): The name of the restaurant.
|
|
date_time (datetime): The time in UTC.
|
|
party_size (int): The number of people in the party.
|
|
customer_name (str): The name of the customer.
|
|
customer_email (str): The email of the customer.
|
|
customer_phone (str): The phone number of the customer.
|
|
|
|
Returns:
|
|
str: The status of the booking.
|
|
"""
|
|
print(f"System > Do you want to book a table at {restaurant} on {date_time} for {party_size} people?")
|
|
print("System > Please confirm by typing 'yes' or 'no'.")
|
|
confirmation = input("User:> ")
|
|
if confirmation.lower() != "yes":
|
|
return "Booking aborted by the user."
|
|
request_body = BookingAppointment(
|
|
odata_type="#microsoft.graph.bookingAppointment",
|
|
customer_time_zone=self.customer_timezone,
|
|
sms_notifications_enabled=False,
|
|
start_date_time=DateTimeTimeZone(
|
|
odata_type="#microsoft.graph.dateTimeTimeZone",
|
|
date_time=date_time,
|
|
time_zone="UTC",
|
|
),
|
|
end_date_time=DateTimeTimeZone(
|
|
odata_type="#microsoft.graph.dateTimeTimeZone",
|
|
date_time=(datetime.fromisoformat(date_time) + timedelta(hours=2)).isoformat(),
|
|
time_zone="UTC",
|
|
),
|
|
is_location_online=False,
|
|
opt_out_of_customer_email=False,
|
|
anonymous_join_web_url=None,
|
|
service_id=self.booking_service_id,
|
|
service_location=Location(
|
|
odata_type="#microsoft.graph.location",
|
|
display_name=restaurant,
|
|
),
|
|
maximum_attendees_count=party_size,
|
|
filled_attendees_count=party_size,
|
|
customers=[
|
|
BookingCustomerInformation(
|
|
odata_type="#microsoft.graph.bookingCustomerInformation",
|
|
name=customer_name,
|
|
email_address=customer_email,
|
|
phone=customer_phone,
|
|
time_zone=self.customer_timezone,
|
|
),
|
|
],
|
|
additional_data={
|
|
"price_type@odata_type": "#microsoft.graph.bookingPriceType",
|
|
"reminders@odata_type": "#Collection(microsoft.graph.bookingReminder)",
|
|
"customers@odata_type": "#Collection(microsoft.graph.bookingCustomerInformation)",
|
|
},
|
|
)
|
|
|
|
response = await self.graph_client.solutions.booking_businesses.by_booking_business_id(
|
|
self.booking_business_id
|
|
).appointments.post(request_body)
|
|
|
|
return f"Booking successful! Your reservation ID is {response.id}."
|
|
|
|
@kernel_function(name="list_revervations", description="List all reservations")
|
|
async def list_reservations(self) -> Annotated[str, "The list of reservations"]:
|
|
"""List the reservations for the booking business."""
|
|
appointments = await self.graph_client.solutions.booking_businesses.by_booking_business_id(
|
|
self.booking_business_id
|
|
).appointments.get()
|
|
return "\n".join([
|
|
f"{appointment.service_location.display_name} on {appointment.start_date_time.date_time} with id: {appointment.id}" # noqa: E501
|
|
for appointment in appointments.value
|
|
])
|
|
|
|
@kernel_function(name="cancel_reservation", description="Cancel a reservation")
|
|
async def cancel_reservation(
|
|
self,
|
|
reservation_id: Annotated[str, "The ID of the reservation"],
|
|
restaurant: Annotated[str, "The name of the restaurant"],
|
|
date: Annotated[str, "The date of the reservation"],
|
|
time: Annotated[str, "The time of the reservation"],
|
|
party_size: Annotated[int, "The number of people in the party"],
|
|
) -> Annotated[str, "The cancellation status of the reservation"]:
|
|
"""Cancel a reservation."""
|
|
print(f"System > [Cancelling a reservation for {party_size} at {restaurant} on {date} at {time}]")
|
|
|
|
_ = (
|
|
await self.graph_client.solutions.booking_businesses.by_booking_business_id(self.booking_business_id)
|
|
.appointments.by_booking_appointment_id(reservation_id)
|
|
.delete()
|
|
)
|
|
return "Cancellation successful!"
|