Java: Add customer information to reservations (#6296)

### Motivation and Context

<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->

### Description

<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [ ] The code builds clean without any errors or warnings
- [ ] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [ ] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄
This commit is contained in:
Milder Hernandez
2024-05-16 16:08:50 +00:00
committed by GitHub
parent c5c85c462f
commit 9ffa87efc1
3 changed files with 88 additions and 89 deletions
@@ -101,7 +101,7 @@ public class BookingAgent {
.getChatMessageContentsAsync(chatHistory, kernel, invocationContext).block().get(0);
chatHistory.addAssistantMessage(result.getContent());
System.out.println("Assistant > " + result);
System.out.println("System > " + result);
System.out.println("User > ");
}
}
@@ -14,7 +14,9 @@ import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunction
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class BookingPlugin {
public static final int BOOKING_HOURS = 2;
@@ -37,123 +39,120 @@ public class BookingPlugin {
public String bookTable(
@KernelFunctionParameter(name = "restaurant", description = "The name of the restaurant") String restaurant,
@KernelFunctionParameter(name = "date", description = "The date of the reservation in UTC", type = OffsetDateTime.class) OffsetDateTime date,
@KernelFunctionParameter(name = "partySize", description = "The number of people in the party", type = int.class) int partySize) {
BookingAppointment bookingAppointment = new BookingAppointment();
bookingAppointment.setOdataType("#microsoft.graph.bookingAppointment");
bookingAppointment.setCustomerTimeZone(userTimeZone);
bookingAppointment.setSmsNotificationsEnabled(false);
DateTimeTimeZone endDateTime = new DateTimeTimeZone();
endDateTime.setOdataType("#microsoft.graph.dateTimeTimeZone");
endDateTime.setDateTime(date.plusHours(BOOKING_HOURS).toString());
endDateTime.setTimeZone("UTC");
bookingAppointment.setEndDateTime(endDateTime);
bookingAppointment.setIsLocationOnline(false);
bookingAppointment.setOptOutOfCustomerEmail(false);
bookingAppointment.setAnonymousJoinWebUrl(null);
PeriodAndDuration postBuffer = PeriodAndDuration.ofDuration(Duration.parse("PT10M"));
bookingAppointment.setPostBuffer(postBuffer);
PeriodAndDuration preBuffer = PeriodAndDuration.ofDuration(Duration.parse("PT5M"));
bookingAppointment.setPreBuffer(preBuffer);
bookingAppointment.setServiceId(serviceId);
Location serviceLocation = new Location();
serviceLocation.setOdataType("#microsoft.graph.location");
serviceLocation.setDisplayName(restaurant);
bookingAppointment.setServiceLocation(serviceLocation);
DateTimeTimeZone startDateTime = new DateTimeTimeZone();
startDateTime.setOdataType("#microsoft.graph.dateTimeTimeZone");
startDateTime.setDateTime(date.toString());
startDateTime.setTimeZone("UTC");
bookingAppointment.setStartDateTime(startDateTime);
bookingAppointment.setMaximumAttendeesCount(partySize);
bookingAppointment.setFilledAttendeesCount(partySize);
@KernelFunctionParameter(name = "partySize", description = "The number of people in the party", type = int.class) int partySize,
@KernelFunctionParameter(name = "customerName", description = "The name of the customer") String customerName,
@KernelFunctionParameter(name = "customerEmail", description = "The email of the customer") String customerEmail,
@KernelFunctionParameter(name = "customerPhone", description = "The phone of the customer") String customerPhone
) {
System.out.println("System > Do you want to book a table at " + restaurant + " on " + date + " for " + partySize + " people?");
System.out.println("System > Please confirm the booking by typing 'yes' or 'no'");
Scanner scanner = new Scanner(System.in);
String response = scanner.nextLine().toLowerCase();
graphServiceClient.solutions().bookingBusinesses().byBookingBusinessId(bookingBusinessId)
.appointments().post(bookingAppointment);
if (response.equals("yes")) {
BookingAppointment bookingAppointment = new BookingAppointment();
bookingAppointment.setOdataType("#microsoft.graph.bookingAppointment");
bookingAppointment.setCustomerTimeZone(userTimeZone);
bookingAppointment.setSmsNotificationsEnabled(false);
DateTimeTimeZone endDateTime = new DateTimeTimeZone();
endDateTime.setOdataType("#microsoft.graph.dateTimeTimeZone");
endDateTime.setDateTime(date.plusHours(BOOKING_HOURS).toString());
endDateTime.setTimeZone("UTC");
bookingAppointment.setEndDateTime(endDateTime);
bookingAppointment.setIsLocationOnline(false);
bookingAppointment.setOptOutOfCustomerEmail(false);
bookingAppointment.setAnonymousJoinWebUrl(null);
PeriodAndDuration postBuffer = PeriodAndDuration.ofDuration(Duration.parse("PT10M"));
bookingAppointment.setPostBuffer(postBuffer);
PeriodAndDuration preBuffer = PeriodAndDuration.ofDuration(Duration.parse("PT5M"));
bookingAppointment.setPreBuffer(preBuffer);
bookingAppointment.setServiceId(serviceId);
Location serviceLocation = new Location();
serviceLocation.setOdataType("#microsoft.graph.location");
serviceLocation.setDisplayName(restaurant);
bookingAppointment.setServiceLocation(serviceLocation);
DateTimeTimeZone startDateTime = new DateTimeTimeZone();
startDateTime.setOdataType("#microsoft.graph.dateTimeTimeZone");
startDateTime.setDateTime(date.toString());
startDateTime.setTimeZone("UTC");
bookingAppointment.setStartDateTime(startDateTime);
bookingAppointment.setMaximumAttendeesCount(partySize);
bookingAppointment.setFilledAttendeesCount(partySize);
bookingAppointment.setCustomers(List.of(new BookingCustomerInformation() {
{
setOdataType("#microsoft.graph.bookingCustomerInformation");
new BookingCustomerInformationBase() {
{
setOdataType("#microsoft.graph.bookingCustomerInformationBase");
setName(customerName);
setEmailAddress(customerEmail);
setPhone(customerPhone);
}
};
}
}));
return "Successful booking at " + restaurant;
graphServiceClient.solutions().bookingBusinesses().byBookingBusinessId(bookingBusinessId)
.appointments().post(bookingAppointment);
return "Booking successful!";
}
return "Booking aborted by the user";
}
@DefineKernelFunction(name = "listReservations", description = "List all reservations for a restaurant", returnType = "string")
public String listReservations(
@KernelFunctionParameter(name = "restaurant", description = "The name of the restaurant") String restaurant) {
@DefineKernelFunction(name = "listReservations", description = "List all reservations for a customer")
public List<String> listReservations(
@KernelFunctionParameter(name = "customerName", description = "The name of the customer") String customerName) {
List<BookingAppointment> appointments = graphServiceClient.solutions().bookingBusinesses()
.byBookingBusinessId(bookingBusinessId).appointments().get().getValue();
.byBookingBusinessId(bookingBusinessId).appointments().get().getValue();
StringBuilder appointmentsList = new StringBuilder();
List<String> reservations = new ArrayList<>();
for (BookingAppointment appointment : appointments) {
if (appointment.getServiceLocation().getDisplayName().equals(restaurant)) {
appointmentsList.append(appointment.getServiceLocation().getDisplayName())
.append(" at ")
.append(appointment.getStartDateTime().getDateTime())
.append(" for ")
.append(appointment.getMaximumAttendeesCount())
.append(" people\n");
if (appointment.getCustomers() != null && !appointment.getCustomers().isEmpty() &&
appointment.getCustomers().get(0).getBackingStore().get("name").equals(customerName)) {
String reservation = "Restaurant: " +
appointment.getServiceLocation().getDisplayName() +
"Date: " +
appointment.getStartDateTime().getDateTime() +
"Party size: " +
appointment.getMaximumAttendeesCount();
reservations.add(reservation);
}
}
if (appointmentsList.toString().isEmpty()) {
return "No reservations found for " + restaurant;
}
return appointmentsList.toString();
return reservations;
}
private BookingAppointment getAppointment(String restaurant, OffsetDateTime date) {
private BookingAppointment getAppointment(String restaurant, String customerName, OffsetDateTime date) {
List<BookingAppointment> appointments = graphServiceClient.solutions().bookingBusinesses()
.byBookingBusinessId(bookingBusinessId).appointments().get().getValue();
for (BookingAppointment appointment : appointments) {
if (appointment.getServiceLocation().getDisplayName().equals(restaurant)
&& OffsetDateTime.parse(appointment.getStartDateTime().getDateTime())
&& appointment.getCustomers() != null && !appointment.getCustomers().isEmpty()
&& appointment.getCustomers().get(0).getBackingStore().get("name").equals(customerName)
&& OffsetDateTime.parse(appointment.getStartDateTime().getDateTime())
.equals(date)) {
return appointment;
}
}
return null;
}
@DefineKernelFunction(name = "modifyReservation", description = "Modify an existing reservation at a restaurant", returnType = "string")
public String modifyReservation(
@KernelFunctionParameter(name = "restaurant", description = "The name of the restaurant") String restaurant,
@KernelFunctionParameter(name = "date", description = "The date of the reservation in UTC", type = OffsetDateTime.class) OffsetDateTime date,
@KernelFunctionParameter(name = "updatedDate", description = "The updated date of the reservation in UTC", type = OffsetDateTime.class) OffsetDateTime updatedDate) {
BookingAppointment appointment = getAppointment(restaurant, date);
if (appointment == null) {
return "No reservation found for " + restaurant + " on " + date;
}
appointment.setStartDateTime(new DateTimeTimeZone() {
{
setDateTime(updatedDate.toString());
setTimeZone("UTC");
}
});
appointment.setEndDateTime(new DateTimeTimeZone() {
{
setDateTime(updatedDate.plusHours(BOOKING_HOURS).toString());
setTimeZone("UTC");
}
});
graphServiceClient.solutions().bookingBusinesses().byBookingBusinessId(bookingBusinessId)
.appointments().byBookingAppointmentId(appointment.getId()).patch(appointment);
return "Reservation updated at " + restaurant + " from " + date + " to " + updatedDate;
}
@DefineKernelFunction(name = "cancelReservation", description = "Cancel a reservation at a restaurant", returnType = "string")
public String cancelReservation(
@KernelFunctionParameter(name = "restaurant", description = "The name of the restaurant") String restaurant,
@KernelFunctionParameter(name = "date", description = "The date of the reservation in UTC", type = OffsetDateTime.class) OffsetDateTime date) {
BookingAppointment appointment = getAppointment(restaurant, date);
if (appointment == null) {
return "No reservation found for " + restaurant + " on " + date;
}
@KernelFunctionParameter(name = "date", description = "The date of the reservation in UTC", type = OffsetDateTime.class) OffsetDateTime date,
@KernelFunctionParameter(name = "customerName", description = "The name of the customer") String customerName) {
System.out.println("System > [Cancelling a reservation for " + customerName + " at " + restaurant + " on " + date + "]");
BookingAppointment appointment = getAppointment(restaurant, customerName, date);
graphServiceClient.solutions().bookingBusinesses().byBookingBusinessId(bookingBusinessId)
.appointments().byBookingAppointmentId(appointment.getId()).delete();
return "Reservation cancelled at " + restaurant + " on " + date;
return "Reservation cancelled";
}
}
@@ -19,7 +19,7 @@
<Logger name="com.microsoft.semantickernel.orchestration.FunctionInvocation" level="info">
<AppenderRef ref="Console"/>
</Logger>
<Root level="warn">
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>