diff --git a/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java b/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java index a983dd3fc3..52878c4195 100644 --- a/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java +++ b/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java @@ -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 > "); } } diff --git a/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java b/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java index f445d1587a..60afec1573 100644 --- a/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java +++ b/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java @@ -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 listReservations( + @KernelFunctionParameter(name = "customerName", description = "The name of the customer") String customerName) { List appointments = graphServiceClient.solutions().bookingBusinesses() - .byBookingBusinessId(bookingBusinessId).appointments().get().getValue(); + .byBookingBusinessId(bookingBusinessId).appointments().get().getValue(); - StringBuilder appointmentsList = new StringBuilder(); + List 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 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"; } } diff --git a/java/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml b/java/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml index ef49e0ed73..267d175667 100644 --- a/java/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml +++ b/java/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml @@ -19,7 +19,7 @@ - +