From d215421776c7a6e9d80c190e117acebbc979fa25 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Tue, 5 Nov 2024 12:55:44 +0100 Subject: [PATCH 01/12] Add Scheduler model and configurtions resources --- src/main/kotlin/com/nylas/NylasClient.kt | 6 + src/main/kotlin/com/nylas/models/Scheduler.kt | 596 ++++++++++++++++++ .../com/nylas/resources/Configurations.kt | 210 ++++++ .../kotlin/com/nylas/resources/Scheduler.kt | 23 + 4 files changed, 835 insertions(+) create mode 100644 src/main/kotlin/com/nylas/models/Scheduler.kt create mode 100644 src/main/kotlin/com/nylas/resources/Configurations.kt create mode 100644 src/main/kotlin/com/nylas/resources/Scheduler.kt diff --git a/src/main/kotlin/com/nylas/NylasClient.kt b/src/main/kotlin/com/nylas/NylasClient.kt index b85f7021..e3e9085c 100644 --- a/src/main/kotlin/com/nylas/NylasClient.kt +++ b/src/main/kotlin/com/nylas/NylasClient.kt @@ -151,6 +151,12 @@ class NylasClient( */ fun contacts(): Contacts = Contacts(this) + /** + * Access the Scheduler API + * @return The Scheduler API + */ + fun scheduler(): Scheduler = Scheduler(this) + /** * Get a URL builder instance for the Nylas API. */ diff --git a/src/main/kotlin/com/nylas/models/Scheduler.kt b/src/main/kotlin/com/nylas/models/Scheduler.kt new file mode 100644 index 00000000..9fa62c5c --- /dev/null +++ b/src/main/kotlin/com/nylas/models/Scheduler.kt @@ -0,0 +1,596 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a Nylas scheduler configuration. + */ +data class Configuration( + /** + * Globally unique object identifier. + */ + @Json(name = "id") + val id: String, + /** + * List of participants included in the scheduled event. + */ + @Json(name = "participants") + val participants: List, + /** + * Rules that determine available time slots for the event. + */ + @Json(name = "availability") + val availability: Availability, + /** + * Booking data for the event. + */ + @Json(name = "event_booking") + val eventBooking: EventBooking, + /** + * Unique identifier for the Configuration object. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * If true, scheduling Availability and Bookings endpoints require a valid session ID. + */ + @Json(name = "requires_session_auth") + val requiresSessionAuth: Boolean? = null, + /** + * Settings for the Scheduler UI. + */ + @Json(name = "scheduler") + val scheduler: SchedulerSettings? = null, + /** + * Appearance settings for the Scheduler UI. + */ + @Json(name = "appearance") + val appearance: Map? = null, +) + +/** + * Class representation of a booking participant. + */ +data class ConfigParticipant( + /** + * Participant's email address. + */ + @Json(name = "email") + val email: String, + /** + * Availability data for the participant. + */ + @Json(name = "availability") + val availability: ParticipantAvailability, + /** + * Booking data for the participant. + */ + @Json(name = "booking") + val booking: ParticipantBooking, + /** + * Participant's name. + */ + @Json(name = "name") + val name: String? = null, + /** + * Whether the participant is the organizer of the event. + */ + @Json(name = "is_organizer") + val isOrganizer: Boolean? = null, + /** + * The participant's timezone. + */ + @Json(name = "timezone") + val timezone: String? = null, +) + +/** + * Class representation of availability settings. + */ +data class Availability( + /** + * The total number of minutes the event should last. + */ + @Json(name = "duration_minutes") + val durationMinutes: Int, + /** + * The interval between meetings in minutes. + */ + @Json(name = "interval_minutes") + val intervalMinutes: Int? = null, + /** + * Nylas rounds each time slot to the nearest multiple of this number of minutes. + */ + @Json(name = "round_to") + val roundTo: Int? = null, + /** + * Availability rules for scheduling configuration. + */ + @Json(name = "availability_rules") + val availabilityRules: AvailabilityRules? = null, +) + +/** + * Class representation of participant availability. + */ +data class ParticipantAvailability( + /** + * List of calendar IDs associated with the participant's email address. + */ + @Json(name = "calendar_ids") + val calendarIds: List, + /** + * Open hours for this participant. The endpoint searches for free time slots during these open hours. + */ + @Json(name = "open_hours") + val openHours: List? = null, +) + +/** + * Class representation of a participant booking. + */ +data class ParticipantBooking( + /** + * The calendar ID that the event is created in. + */ + @Json(name = "calendar_id") + val calendarId: String, +) + +/** + * Class representation of an event booking. + */ +data class EventBooking( + /** + * The title of the event. + */ + @Json(name = "title") + val title: String, + /** + * The description of the event. + */ + @Json(name = "description") + val description: String? = null, + /** + * The location of the event. + */ + @Json(name = "location") + val location: String? = null, + /** + * The timezone for displaying times in confirmation email messages and reminders. + */ + @Json(name = "timezone") + val timezone: String? = null, + /** + * The type of booking. + */ + @Json(name = "booking_type") + val bookingType: BookingType? = null, + /** + * Conference details for the event. + */ + @Json(name = "conferencing") + val conferencing: Conferencing? = null, + /** + * Whether Nylas sends email messages when an event is booked, cancelled, or rescheduled. + */ + @Json(name = "disable_emails") + val disableEmails: Boolean? = null, + /** + * The list of reminders to send to participants before the event starts. + */ + @Json(name = "reminders") + val reminders: List? = null, +) + +/** + * Class representation of scheduler settings. + */ +data class SchedulerSettings( + /** + * Definitions for additional fields to be displayed in the Scheduler UI. + */ + @Json(name = "additional_fields") + val additionalFields: Map? = null, + /** + * Number of days in the future that Scheduler is available for scheduling events. + */ + @Json(name = "available_days_in_future") + val availableDaysInFuture: Int? = null, + /** + * Minimum number of minutes in the future that a user can make a new booking. + */ + @Json(name = "min_booking_notice") + val minBookingNotice: Int? = null, + /** + * Minimum number of minutes before a booking can be cancelled. + */ + @Json(name = "min_cancellation_notice") + val minCancellationNotice: Int? = null, + /** + * A message about the cancellation policy to display when booking an event. + */ + @Json(name = "cancellation_policy") + val cancellationPolicy: String? = null, + /** + * The URL used to reschedule bookings. + */ + @Json(name = "rescheduling_url") + val reschedulingUrl: String? = null, + /** + * The URL used to cancel bookings. + */ + @Json(name = "cancellation_url") + val cancellationUrl: String? = null, + /** + * The URL used to confirm or cancel pending bookings. + */ + @Json(name = "organizer_confirmation_url") + val organizerConfirmationUrl: String? = null, + /** + * The custom URL to redirect to once the booking is confirmed. + */ + @Json(name = "confirmation_redirect_url") + val confirmationRedirectUrl: String? = null, + /** + * Whether the option to reschedule an event is hidden in booking confirmations and notifications. + */ + @Json(name = "hide_rescheduling_options") + val hideReschedulingOptions: Boolean? = null, + /** + * Whether the option to cancel an event is hidden in booking confirmations and notifications. + */ + @Json(name = "hide_cancellation_options") + val hideCancellationOptions: Boolean? = null, + /** + * Whether to hide the additional guests field on the scheduling page. + */ + @Json(name = "hide_additional_guests") + val hideAdditionalGuests: Boolean? = null, + /** + * Configurable settings for booking emails. + */ + @Json(name = "email_template") + val emailTemplate: EmailTemplate? = null, +) + +/** + * Class representation of an additional field. + */ +data class AdditionalField( + /** + * The text label to be displayed in the Scheduler UI. + */ + @Json(name = "label") + val label: String, + /** + * The field type. + * Supported values are text, multi_line_text, email, phone_number, dropdown, date, checkbox, and radio_button. + */ + @Json(name = "type") + val type: AdditionalFieldType, + /** + * Whether the field is required to be filled out by the guest when booking an event. + */ + @Json(name = "required") + val required: Boolean, + /** + * A regular expression pattern that the value of the field must match. + */ + @Json(name = "pattern") + val pattern: String? = null, + /** + * The order in which the field will be displayed in the Scheduler UI. + * Fields with lower order values will be displayed first. + */ + @Json(name = "order") + val order: Int? = null, + /** + * A list of options for the dropdown or radio_button types. + * This field is required for the dropdown and radio_button types. + */ + @Json(name = "options") + val options: AdditonalFieldOptionsType? = null, +) + +/** + * Class representation of an email template. + */ +data class EmailTemplate( + /** + * Configurable settings specifically for booking confirmed emails. + */ + @Json(name = "booking_confirmed") + val bookingConfirmed: BookingConfirmedTemplate? = null, +) + +/** + * Class representation of booking confirmed template settings. + */ +data class BookingConfirmedTemplate( + /** + * The title to replace the default 'Booking Confirmed' title. + */ + @Json(name = "title") + val title: String? = null, + /** + * The additional body to be appended after the default body. + */ + @Json(name = "body") + val body: String? = null, +) + +/** + * Class representation of a booking reminder. + */ +data class BookingReminder( + /** + * The reminder type. + */ + @Json(name = "type") + val type: String, + /** + * The number of minutes before the event to send the reminder. + */ + @Json(name = "minutes_before_event") + val minutesBeforeEvent: Int, + /** + * The recipient of the reminder. + */ + @Json(name = "recipient") + val recipient: String? = null, + /** + * The subject of the email reminder. + */ + @Json(name = "email_subject") + val emailSubject: String? = null, +) + +/** + * Class representation of a session. + */ +data class Session( + /** + * The ID of the session. + */ + @Json(name = "session_id") + val sessionId: String, +) + +/** + * Class representation of a booking guest. + */ +data class BookingGuest( + /** + * The email address of the guest. + */ + @Json(name = "email") + val email: String, + /** + * The name of the guest. + */ + @Json(name = "name") + val name: String, +) + +/** + * Class representation of a booking participant. + */ +data class BookingParticipant( + /** + * The email address of the participant to include in the booking. + */ + @Json(name = "email") + val email: String, +) + +/** + * Class representation of a create booking request. + */ +data class CreateBookingRequest( + /** + * The event's start time, in Unix epoch format. + */ + @Json(name = "start_time") + val startTime: Long, + /** + * The event's end time, in Unix epoch format. + */ + @Json(name = "end_time") + val endTime: Long, + /** + * Details about the guest that is creating the booking. + */ + @Json(name = "guest") + val guest: BookingGuest, + /** + * List of participant email addresses from the Configuration object to include in the booking. + */ + @Json(name = "participants") + val participants: List? = null, + /** + * The guest's timezone that is used in email notifications. + */ + @Json(name = "timezone") + val timezone: String? = null, + /** + * The language of the guest email notifications. + */ + @Json(name = "email_language") + val emailLanguage: EmailLanguage? = null, + /** + * List of additional guest email addresses to include in the booking. + */ + @Json(name = "additional_guests") + val additionalGuests: List? = null, + /** + * Dictionary of additional field keys mapped to values populated by the guest in the booking form. + */ + @Json(name = "additional_fields") + val additionalFields: Map? = null, +) + +/** + * Class representation of a booking organizer. + */ +data class BookingOrganizer( + /** + * The email address of the participant designated as the organizer of the event. + */ + @Json(name = "email") + val email: String, + /** + * The name of the participant designated as the organizer of the event. + */ + @Json(name = "name") + val name: String? = null, +) + +/** + * Class representation of a booking. + */ +data class Booking( + /** + * The unique ID of the booking. + */ + @Json(name = "booking_id") + val bookingId: String, + /** + * The unique ID of the event associated with the booking. + */ + @Json(name = "event_id") + val eventId: String, + /** + * The title of the event. + */ + @Json(name = "title") + val title: String, + /** + * The participant designated as the organizer of the event. + */ + @Json(name = "organizer") + val organizer: BookingOrganizer, + /** + * The current status of the booking. + */ + @Json(name = "status") + val status: BookingStatus, + /** + * The description of the event. + */ + @Json(name = "description") + val description: String? = null, +) + +/** + * Class representation of a confirm booking request. + */ +data class ConfirmBookingRequest( + /** + * The salt extracted from the booking reference embedded in the organizer confirmation link. + */ + @Json(name = "salt") + val salt: String, + /** + * The action to take on the pending booking. + */ + @Json(name = "status") + val status: ConfirmBookingStatus, + /** + * The reason the booking is being cancelled. + */ + @Json(name = "cancellation_reason") + val cancellationReason: String? = null, +) + +/** + * Class representation of a delete booking request. + */ +data class DeleteBookingRequest( + /** + * The reason the booking is being cancelled. + */ + @Json(name = "cancellation_reason") + val cancellationReason: String? = null, +) + +/** + * Class representation of a reschedule booking request. + */ +data class RescheduleBookingRequest( + /** + * The event's start time, in Unix epoch format. + */ + @Json(name = "start_time") + val startTime: Long, + /** + * The event's end time, in Unix epoch format. + */ + @Json(name = "end_time") + val endTime: Long, +) + +/** + * Enum for additional field types. + */ +enum class AdditionalFieldType { + @Json(name = "text") TEXT, + @Json(name = "multi_line_text") MULTI_LINE_TEXT, + @Json(name = "email") EMAIL, + @Json(name = "phone_number") PHONE_NUMBER, + @Json(name = "dropdown") DROPDOWN, + @Json(name = "date") DATE, + @Json(name = "checkbox") CHECKBOX, + @Json(name = "radio_button") RADIO_BUTTON, +} + +/** + * Enum for additional field options types. + */ +enum class AdditonalFieldOptionsType { + @Json(name = "text") TEXT, + @Json(name = "email") EMAIL, + @Json(name = "phone_number") PHONE_NUMBER, + @Json(name = "date") DATE, + @Json(name = "checkbox") CHECKBOX, + @Json(name = "radio_button") RADIO_BUTTON, +} + +/** + * Enum for booking types. + */ +enum class BookingType { + @Json(name = "booking") BOOKING, + @Json(name = "organizer-confirmation") ORGANIZER_CONFIRMATION, +} + +/** + * Enum for email language options. + */ +enum class EmailLanguage { + @Json(name = "en") EN, + @Json(name = "es") ES, + @Json(name = "fr") FR, + @Json(name = "de") DE, + @Json(name = "nl") NL, + @Json(name = "sv") SV, + @Json(name = "ja") JA, + @Json(name = "zh") ZH, +} + +/** + * Enum for booking statuses. + */ +enum class BookingStatus { + @Json(name = "pending") PENDING, + @Json(name = "confirmed") CONFIRMED, + @Json(name = "cancelled") CANCELLED, +} + +/** + * Enum for confirm booking statuses. + */ +enum class ConfirmBookingStatus { + @Json(name = "confirm") CONFIRM, + @Json(name = "cancel") CANCEL, +} diff --git a/src/main/kotlin/com/nylas/resources/Configurations.kt b/src/main/kotlin/com/nylas/resources/Configurations.kt new file mode 100644 index 00000000..0369c190 --- /dev/null +++ b/src/main/kotlin/com/nylas/resources/Configurations.kt @@ -0,0 +1,210 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.models.* +import com.nylas.util.JsonHelper +import com.squareup.moshi.Types + +/** + * Nylas Configurations API + * + * The Nylas configurations API allows you to create new configurations or manage existing ones, as well as getting + * configurations details for a user. + * + * Nylas Scheduler stores Configuration objects in the Scheduler database and loads + * them as Scheduling Pages in the Scheduler UI. + * + * @param client The configured Nylas API client + */ +class Configurations(client: NylasClient) : Resource(client, Configuration::class.java) { + + /** + * Return all Configurations + * @param identifier The identifier of the Grant to act upon. + * @param queryParams The query parameters to include in the request + * @param overrides Optional request overrides to apply + * @return The list of Configurations + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun list( + identifier: String, + queryParams: ListConfigurationsParams? = null, + overrides: RequestOverrides? = null + ): ListResponse { + val path = String.format("v3/grants/%s/scheduling/configurations", identifier) + return listResource(path, queryParams, overrides) + } + + /** + * Return a Configuration + * @param identifier The identifier of the Grant to act upon. + * @param configId The identifier of the Configuration to get. + * @param overrides Optional request overrides to apply + * @return The Configuration object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun find( + identifier: String, + configId: String, + overrides: RequestOverrides? = null + ): Response { + val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) + return findResource(path, overrides = overrides) + } + + /** + * Create a new Configuration + * @param identifier The identifier of the Grant to act upon. + * @param requestBody The data to create the Configuration with. + * @param overrides Optional request overrides to apply + * @return The Configuration object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun create( + identifier: String, + requestBody: CreateConfigurationRequest, + overrides: RequestOverrides? = null + ): Response { + val path = String.format("v3/grants/%s/scheduling/configurations", identifier) + val adapter = JsonHelper.moshi().adapter(CreateConfigurationRequest::class.java) + val serializedRequestBody = adapter.toJson(requestBody) + return createResource(path, serializedRequestBody, overrides = overrides) + } + + /** + * Update a Configuration + * @param identifier The identifier of the Grant to act upon. + * @param configId The identifier of the Configuration to update. + * @param requestBody The data to update the Configuration with. + * @param overrides Optional request overrides to apply + * @return The Configuration object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun update( + identifier: String, + configId: String, + requestBody: UpdateConfigurationRequest, + overrides: RequestOverrides? = null + ): Response { + val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) + val adapter = JsonHelper.moshi().adapter(UpdateConfigurationRequest::class.java) + val serializedRequestBody = adapter.toJson(requestBody) + return updateResource(path, serializedRequestBody, overrides = overrides) + } + + /** + * Delete a Configuration + * @param identifier The identifier of the Grant to act upon. + * @param configId The identifier of the Configuration to delete. + * @param overrides Optional request overrides to apply + * @return The deletion response + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + fun destroy( + identifier: String, + configId: String, + overrides: RequestOverrides? = null + ): DeleteResponse { + val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) + return destroyResource(path, overrides = overrides) + } +} + +/** + * Class representation of the query parameters for listing configurations. + * + * @property limit The maximum number of objects to return. Defaults to 50. The maximum allowed value is 200. + * @property pageToken An identifier that specifies which page of data to return. This value should be taken from a ListResponse object's next_cursor parameter. + */ +class ListConfigurationsParams : ListQueryParams() { + /** + * The identifier of the Grant to act upon. + */ + var identifier: String? = null +} + +/** + * Class representation of a request to create a configuration. + */ +data class CreateConfigurationRequest( + /** + * List of participants included in the scheduled event. + */ + @Json(name = "participants") + val participants: List, + /** + * Rules that determine available time slots for the event. + */ + @Json(name = "availability") + val availability: Availability, + /** + * Booking data for the event. + */ + @Json(name = "event_booking") + val eventBooking: EventBooking, + /** + * Unique identifier for the Configuration object. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * If true, scheduling Availability and Bookings endpoints require a valid session ID. + */ + @Json(name = "requires_session_auth") + val requiresSessionAuth: Boolean? = null, + /** + * Settings for the Scheduler UI. + */ + @Json(name = "scheduler") + val scheduler: SchedulerSettings? = null, + /** + * Appearance settings for the Scheduler UI. + */ + @Json(name = "appearance") + val appearance: Map? = null +) + +/** + * Class representation of a request to update a configuration. + */ +data class UpdateConfigurationRequest( + /** + * List of participants included in the scheduled event. + */ + @Json(name = "participants") + val participants: List? = null, + /** + * Rules that determine available time slots for the event. + */ + @Json(name = "availability") + val availability: Availability? = null, + /** + * Booking data for the event. + */ + @Json(name = "event_booking") + val eventBooking: EventBooking? = null, + /** + * Unique identifier for the Configuration object. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * If true, scheduling Availability and Bookings endpoints require a valid session ID. + */ + @Json(name = "requires_session_auth") + val requiresSessionAuth: Boolean? = null, + /** + * Settings for the Scheduler UI. + */ + @Json(name = "scheduler") + val scheduler: SchedulerSettings? = null, + /** + * Appearance settings for the Scheduler UI. + */ + @Json(name = "appearance") + val appearance: Map? = null +) diff --git a/src/main/kotlin/com/nylas/resources/Scheduler.kt b/src/main/kotlin/com/nylas/resources/Scheduler.kt new file mode 100644 index 00000000..c002dffc --- /dev/null +++ b/src/main/kotlin/com/nylas/resources/Scheduler.kt @@ -0,0 +1,23 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.resources.configurations.Configurations + +/** + * Nylas Scheduler API + * + * The Nylas Scheduler API allows you to manage scheduling configurations, bookings, and sessions. + * + * @param client The configured Nylas API client + */ +class Scheduler(private val client: NylasClient) { + + /** + * Access the Configurations API. + * + * @return The Configurations API. + */ + fun configurations(): Configurations { + return Configurations(client) + } +} From efda701bd09b7a2e0a169e2efdee4b6f47f81d8d Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Tue, 5 Nov 2024 14:53:34 +0100 Subject: [PATCH 02/12] Fix lint --- .../models/ListConfigurationsQueryParams.kt | 50 ++++++++ src/main/kotlin/com/nylas/models/Scheduler.kt | 110 +++++++++++++----- .../com/nylas/resources/Configurations.kt | 29 ++--- .../kotlin/com/nylas/resources/Scheduler.kt | 5 +- 4 files changed, 140 insertions(+), 54 deletions(-) create mode 100644 src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt diff --git a/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt b/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt new file mode 100644 index 00000000..719f687d --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt @@ -0,0 +1,50 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +data class ListConfigurationsParams( + /** + * The maximum number of objects to return. + * Defaults to 50. The maximum allowed value is 200. + */ + @Json(name = "limit") + val limit: Int? = null, + /** + * An identifier that specifies which page of data to return. + * This value should be taken from the [ListResponse.nextCursor] response field. + */ + @Json(name = "page_token") + val pageToken: String? = null, +) : IQueryParams + +/** + * Builder for [ListConfigurationsParams]. + */ +class Builder { + private var limit: Int? = null + private var pageToken: String? = null + + /** + * Sets the maximum number of objects to return. + * This field defaults to 50. The maximum allowed value is 200. + * @param limit The maximum number of objects to return. + * @return The builder. + */ + + fun limit(limit: Int?) = apply { this.limit = limit } + + /** + * Sets the identifier that specifies which page of data to return. + * This value should be taken from the next_cursor response field. + * @param pageToken The identifier that specifies which page of data to return. + * @return The builder. + */ + + fun pageToken(pageToken: String?) = apply { this.pageToken = pageToken } + + /** + * Builds a [ListConfigurationsParams] instance. + * @return The [ListConfigurationsParams] instance. + */ + fun build() = ListConfigurationsParams(limit, pageToken) +} diff --git a/src/main/kotlin/com/nylas/models/Scheduler.kt b/src/main/kotlin/com/nylas/models/Scheduler.kt index 9fa62c5c..d9e6cb15 100644 --- a/src/main/kotlin/com/nylas/models/Scheduler.kt +++ b/src/main/kotlin/com/nylas/models/Scheduler.kt @@ -534,63 +534,115 @@ data class RescheduleBookingRequest( * Enum for additional field types. */ enum class AdditionalFieldType { - @Json(name = "text") TEXT, - @Json(name = "multi_line_text") MULTI_LINE_TEXT, - @Json(name = "email") EMAIL, - @Json(name = "phone_number") PHONE_NUMBER, - @Json(name = "dropdown") DROPDOWN, - @Json(name = "date") DATE, - @Json(name = "checkbox") CHECKBOX, - @Json(name = "radio_button") RADIO_BUTTON, + @Json(name = "text") + TEXT, + + @Json(name = "multi_line_text") + MULTI_LINE_TEXT, + + @Json(name = "email") + EMAIL, + + @Json(name = "phone_number") + PHONE_NUMBER, + + @Json(name = "dropdown") + DROPDOWN, + + @Json(name = "date") + DATE, + + @Json(name = "checkbox") + CHECKBOX, + + @Json(name = "radio_button") + RADIO_BUTTON, } /** * Enum for additional field options types. */ enum class AdditonalFieldOptionsType { - @Json(name = "text") TEXT, - @Json(name = "email") EMAIL, - @Json(name = "phone_number") PHONE_NUMBER, - @Json(name = "date") DATE, - @Json(name = "checkbox") CHECKBOX, - @Json(name = "radio_button") RADIO_BUTTON, + @Json(name = "text") + TEXT, + + @Json(name = "email") + EMAIL, + + @Json(name = "phone_number") + PHONE_NUMBER, + + @Json(name = "date") + DATE, + + @Json(name = "checkbox") + CHECKBOX, + + @Json(name = "radio_button") + RADIO_BUTTON, } /** * Enum for booking types. */ enum class BookingType { - @Json(name = "booking") BOOKING, - @Json(name = "organizer-confirmation") ORGANIZER_CONFIRMATION, + @Json(name = "booking") + BOOKING, + + @Json(name = "organizer-confirmation") + ORGANIZER_CONFIRMATION, } /** * Enum for email language options. */ enum class EmailLanguage { - @Json(name = "en") EN, - @Json(name = "es") ES, - @Json(name = "fr") FR, - @Json(name = "de") DE, - @Json(name = "nl") NL, - @Json(name = "sv") SV, - @Json(name = "ja") JA, - @Json(name = "zh") ZH, + @Json(name = "en") + EN, + + @Json(name = "es") + ES, + + @Json(name = "fr") + FR, + + @Json(name = "de") + DE, + + @Json(name = "nl") + NL, + + @Json(name = "sv") + SV, + + @Json(name = "ja") + JA, + + @Json(name = "zh") + ZH, } /** * Enum for booking statuses. */ enum class BookingStatus { - @Json(name = "pending") PENDING, - @Json(name = "confirmed") CONFIRMED, - @Json(name = "cancelled") CANCELLED, + @Json(name = "pending") + PENDING, + + @Json(name = "confirmed") + CONFIRMED, + + @Json(name = "cancelled") + CANCELLED, } /** * Enum for confirm booking statuses. */ enum class ConfirmBookingStatus { - @Json(name = "confirm") CONFIRM, - @Json(name = "cancel") CANCEL, + @Json(name = "confirm") + CONFIRM, + + @Json(name = "cancel") + CANCEL, } diff --git a/src/main/kotlin/com/nylas/resources/Configurations.kt b/src/main/kotlin/com/nylas/resources/Configurations.kt index 0369c190..13491d09 100644 --- a/src/main/kotlin/com/nylas/resources/Configurations.kt +++ b/src/main/kotlin/com/nylas/resources/Configurations.kt @@ -3,7 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper -import com.squareup.moshi.Types +import com.squareup.moshi.Json /** * Nylas Configurations API @@ -30,7 +30,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf fun list( identifier: String, queryParams: ListConfigurationsParams? = null, - overrides: RequestOverrides? = null + overrides: RequestOverrides? = null, ): ListResponse { val path = String.format("v3/grants/%s/scheduling/configurations", identifier) return listResource(path, queryParams, overrides) @@ -48,7 +48,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf fun find( identifier: String, configId: String, - overrides: RequestOverrides? = null + overrides: RequestOverrides? = null, ): Response { val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) return findResource(path, overrides = overrides) @@ -66,7 +66,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf fun create( identifier: String, requestBody: CreateConfigurationRequest, - overrides: RequestOverrides? = null + overrides: RequestOverrides? = null, ): Response { val path = String.format("v3/grants/%s/scheduling/configurations", identifier) val adapter = JsonHelper.moshi().adapter(CreateConfigurationRequest::class.java) @@ -88,7 +88,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf identifier: String, configId: String, requestBody: UpdateConfigurationRequest, - overrides: RequestOverrides? = null + overrides: RequestOverrides? = null, ): Response { val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) val adapter = JsonHelper.moshi().adapter(UpdateConfigurationRequest::class.java) @@ -107,26 +107,13 @@ class Configurations(client: NylasClient) : Resource(client, Conf fun destroy( identifier: String, configId: String, - overrides: RequestOverrides? = null + overrides: RequestOverrides? = null, ): DeleteResponse { val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) return destroyResource(path, overrides = overrides) } } -/** - * Class representation of the query parameters for listing configurations. - * - * @property limit The maximum number of objects to return. Defaults to 50. The maximum allowed value is 200. - * @property pageToken An identifier that specifies which page of data to return. This value should be taken from a ListResponse object's next_cursor parameter. - */ -class ListConfigurationsParams : ListQueryParams() { - /** - * The identifier of the Grant to act upon. - */ - var identifier: String? = null -} - /** * Class representation of a request to create a configuration. */ @@ -165,7 +152,7 @@ data class CreateConfigurationRequest( * Appearance settings for the Scheduler UI. */ @Json(name = "appearance") - val appearance: Map? = null + val appearance: Map? = null, ) /** @@ -206,5 +193,5 @@ data class UpdateConfigurationRequest( * Appearance settings for the Scheduler UI. */ @Json(name = "appearance") - val appearance: Map? = null + val appearance: Map? = null, ) diff --git a/src/main/kotlin/com/nylas/resources/Scheduler.kt b/src/main/kotlin/com/nylas/resources/Scheduler.kt index c002dffc..cf135045 100644 --- a/src/main/kotlin/com/nylas/resources/Scheduler.kt +++ b/src/main/kotlin/com/nylas/resources/Scheduler.kt @@ -1,7 +1,6 @@ package com.nylas.resources import com.nylas.NylasClient -import com.nylas.resources.configurations.Configurations /** * Nylas Scheduler API @@ -17,7 +16,5 @@ class Scheduler(private val client: NylasClient) { * * @return The Configurations API. */ - fun configurations(): Configurations { - return Configurations(client) - } + fun configurations(): Configurations = Configurations(client) } From 46abe9802256d4320e063f8c229d215b0ff63445 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Tue, 5 Nov 2024 15:05:38 +0100 Subject: [PATCH 03/12] Add collective to availability_method --- src/main/kotlin/com/nylas/models/AvailabilityMethod.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/kotlin/com/nylas/models/AvailabilityMethod.kt b/src/main/kotlin/com/nylas/models/AvailabilityMethod.kt index f0283a0c..82b17e51 100644 --- a/src/main/kotlin/com/nylas/models/AvailabilityMethod.kt +++ b/src/main/kotlin/com/nylas/models/AvailabilityMethod.kt @@ -11,4 +11,7 @@ enum class AvailabilityMethod { @Json(name = "max-availability") MAX_AVAILABILITY, + + @Json(name = "collective") + COLLECTIVE, } From e3ea733768e345561d6b5164f313528df4bcdf63 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Wed, 6 Nov 2024 17:48:42 +0100 Subject: [PATCH 04/12] Add CreateConfigurations Model --- .../nylas/models/ConfigurationAvailability.kt | 69 ++++++ .../ConfigurationAvailabilityParticipant.kt | 46 ++++ .../models/ConfigurationBookingParticipant.kt | 28 +++ .../nylas/models/ConfigurationEventBooking.kt | 129 ++++++++++ .../nylas/models/ConfigurationParticipant.kt | 100 ++++++++ .../models/ConfigurationSchedulerSettings.kt | 215 +++++++++++++++++ .../models/CreateConfigurationRequest.kt | 108 +++++++++ src/main/kotlin/com/nylas/models/Scheduler.kt | 227 +----------------- .../com/nylas/resources/Configurations.kt | 49 +--- 9 files changed, 704 insertions(+), 267 deletions(-) create mode 100644 src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfigurationParticipant.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt create mode 100644 src/main/kotlin/com/nylas/models/CreateConfigurationRequest.kt diff --git a/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt b/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt new file mode 100644 index 00000000..b697bc13 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt @@ -0,0 +1,69 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of availability settings. + */ +data class ConfigurationAvailability( + /** + * The total number of minutes the event should last. + */ + @Json(name = "duration_minutes") + val durationMinutes: Int, + /** + * The interval between meetings in minutes. + */ + @Json(name = "interval_minutes") + val intervalMinutes: Int? = null, + /** + * Nylas rounds each time slot to the nearest multiple of this number of minutes. + */ + @Json(name = "round_to") + val roundTo: Int? = null, + /** + * Availability rules for scheduling configuration. + */ + @Json(name = "availability_rules") + val availabilityRules: AvailabilityRules? = null, +) { + data class Builder( + private val durationMinutes: Int, + ) { + private var intervalMinutes: Int? = null + private var roundTo: Int? = null + private var availabilityRules: AvailabilityRules? = null + + /** + * Set the interval between meetings in minutes. + * @param intervalMinutes The interval between meetings in minutes. + * @return The builder. + */ + fun intervalMinutes(intervalMinutes: Int) = apply { this.intervalMinutes = intervalMinutes } + + /** + * Set Nylas rounds each time slot to the nearest multiple of this number of minutes. + * @param roundTo Nylas rounds each time slot to the nearest multiple of this number of minutes. + * @return The builder. + */ + fun roundTo(roundTo: Int) = apply { this.roundTo = roundTo } + + /** + * Set availability rules for scheduling configuration. + * @param availabilityRules Availability rules for scheduling configuration. + * @return The builder. + */ + fun availabilityRules(availabilityRules: AvailabilityRules) = apply { this.availabilityRules = availabilityRules } + + /** + * Build the [ConfigurationAvailability]. + * @return The [ConfigurationAvailability]. + */ + fun build() = ConfigurationAvailability( + durationMinutes, + intervalMinutes, + roundTo, + availabilityRules, + ) + } +} diff --git a/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt b/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt new file mode 100644 index 00000000..615be10f --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt @@ -0,0 +1,46 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a participant in a booking. + */ + +data class ConfigurationAvailabilityParticipant( + /** + * @param calendarIds The calendar IDs that the event is created in. + */ + @Json(name = "calendar_ids") + val calendarIds: List, + /** + * Open hours for this participant. The endpoint searches for free time slots during these open hours. + */ + @Json(name = "open_hours") + val openHours: List? = null, +) { + /** + * Builder for [ConfigurationAvailabilityParticipant]. + */ + data class Builder( + private val calendarIds: List, + ) { + private var openHours: List? = null + + /** + * Set the open hours for this participant. + * @param openHours Open hours for this participant. + * @return The builder. + */ + fun openHours(openHours: List) = apply { this.openHours = openHours } + + /** + * Set the open hours for this participant. + * @param openHours Open hours for this participant. + * @return The builder. + */ + fun build() = ConfigurationAvailabilityParticipant( + calendarIds, + openHours, + ) + } +} diff --git a/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt b/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt new file mode 100644 index 00000000..c154e300 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt @@ -0,0 +1,28 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a participant in a booking. + */ +data class ConfigurationBookingParticipant( + /** + * The calendar ID that the event is created in. + */ + @Json(name = "calendar_id") + val calendarId: String, +) { + /** + * Builder for [ConfigurationBookingParticipant]. + * @param calendarId The calendar ID that the event is created in. + */ + data class Builder( + private val calendarId: String, + ) { + /** + * Builds a [ConfigurationBookingParticipant] instance. + * @return The [ConfigurationBookingParticipant] instance. + */ + fun build() = ConfigurationBookingParticipant(calendarId) + } +} diff --git a/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt b/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt new file mode 100644 index 00000000..5aeb7f49 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt @@ -0,0 +1,129 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of an event booking. + */ +data class ConfigurationEventBooking( + /** + * The title of the event. + */ + @Json(name = "title") + val title: String, + /** + * The description of the event. + */ + @Json(name = "description") + val description: String? = null, + /** + * The location of the event. + */ + @Json(name = "location") + val location: String? = null, + /** + * The timezone for displaying times in confirmation email messages and reminders. + */ + @Json(name = "timezone") + val timezone: String? = null, + /** + * The type of booking. + */ + @Json(name = "booking_type") + val bookingType: BookingType? = null, + /** + * Conference details for the event. + */ + @Json(name = "conferencing") + val conferencing: Conferencing? = null, + /** + * Whether Nylas sends email messages when an event is booked, cancelled, or rescheduled. + */ + @Json(name = "disable_emails") + val disableEmails: Boolean? = null, + /** + * The list of reminders to send to participants before the event starts. + */ + @Json(name = "reminders") + val reminders: List? = null, +) { + /** + * Builder for [ConfigurationEventBooking]. + * @property title The title of the event. + */ + data class Builder( + private val title: String, + ) { + private var description: String? = null + private var location: String? = null + private var timezone: String? = null + private var bookingType: BookingType? = null + private var conferencing: Conferencing? = null + private var disableEmails: Boolean? = null + private var reminders: List? = null + + /** + * Sets the description of the event. + * @param description The description of the event. + * @return The builder. + */ + fun description(description: String?) = apply { this.description = description } + + /** + * Sets the location of the event. + * @param location The location of the event. + * @return The builder. + */ + fun location(location: String?) = apply { this.location = location } + + /** + * Sets the timezone for displaying times in confirmation email messages and reminders. + * @param timezone The timezone for displaying times in confirmation email messages and reminders. + * @return The builder. + */ + fun timezone(timezone: String?) = apply { this.timezone = timezone } + + /** + * Sets the type of booking. + * @param bookingType The type of booking. + * @return The builder. + */ + fun bookingType(bookingType: BookingType?) = apply { this.bookingType = bookingType } + + /** + * Sets the conference details for the event. + * @param conferencing Conference details for the event. + * @return The builder. + */ + fun conferencing(conferencing: Conferencing?) = apply { this.conferencing = conferencing } + + /** + * Sets whether Nylas sends email messages when an event is booked, cancelled, or rescheduled. + * @param disableEmails Whether Nylas sends email messages when an event is booked, cancelled, or rescheduled. + * @return The builder. + */ + fun disableEmails(disableEmails: Boolean?) = apply { this.disableEmails = disableEmails } + + /** + * Sets the list of reminders to send to participants before the event starts. + * @param reminders The list of reminders to send to participants before the event starts. + * @return + */ + fun reminders(reminders: List?) = apply { this.reminders = reminders } + + /** + * Builds an [ConfigurationEventBooking] instance. + * @return The [ConfigurationEventBooking] instance. + */ + fun build() = ConfigurationEventBooking( + title, + description, + location, + timezone, + bookingType, + conferencing, + disableEmails, + reminders, + ) + } +} diff --git a/src/main/kotlin/com/nylas/models/ConfigurationParticipant.kt b/src/main/kotlin/com/nylas/models/ConfigurationParticipant.kt new file mode 100644 index 00000000..36afd68b --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfigurationParticipant.kt @@ -0,0 +1,100 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a participant in a scheduled event. + * @property email Email address of the participant. + * @property name Name of the participant. + * @property role Role of the participant. + * @property availability Availability data for the participant. + * @property booking Booking data for the participant. + * @property timezone Timezone of the participant. + */ +data class ConfigurationParticipant( + /** + * Email address of the participant. + */ + @Json(name = "email") + val email: String, + /** + * Name of the participant. + */ + @Json(name = "name") + val name: String? = null, + /** + * If true, the participant is the organizer of the event. + */ + @Json(name = "is_organizer") + val isOrganizer: Boolean? = null, + /** + * Availability data for the participant. + */ + @Json(name = "availability") + val availability: ConfigurationAvailabilityParticipant? = null, + /** + * Booking data for the participant. + */ + @Json(name = "booking") + val booking: ConfigurationBookingParticipant? = null, + /** + * Timezone of the participant. + */ + @Json(name = "timezone") + val timezone: String? = null, +) { + /** + * A builder for creating a [ConfigurationParticipant]. + * @param email Email address of the participant. + */ + data class Builder( + private val email: String, + ) { + private var name: String? = null + private var isOrganizer: Boolean? = null + private var availability: ConfigurationAvailabilityParticipant? = null + private var booking: ConfigurationBookingParticipant? = null + private var timezone: String? = null + + /** + * Set the name of the participant. + * @param name Name of the participant. + * @return The builder. + */ + fun name(name: String) = apply { this.name = name } + + /** + * Set if the participant is the organizer of the event. + * @param isOrganizer If true, the participant is the organizer of the event. + * @return The builder. + */ + fun isOrganizer(isOrganizer: Boolean) = apply { this.isOrganizer = isOrganizer } + + /** + * Set the availability data for the participant. + * @param availability Availability data for the participant. + * @return The builder. + */ + fun availability(availability: ConfigurationAvailabilityParticipant) = apply { this.availability = availability } + + /** + * Set the booking data for the participant. + * @param booking Booking data for the participant. + * @return The builder. + */ + fun booking(booking: ConfigurationBookingParticipant) = apply { this.booking = booking } + + /** + * Set the timezone of the participant. + * @param timezone Timezone of the participant. + * @return The builder. + */ + fun timezone(timezone: String) = apply { this.timezone = timezone } + + /** + * Build the [ConfigurationParticipant]. + * @return The [ConfigurationParticipant] + */ + fun build() = ConfigurationParticipant(email, name, isOrganizer, availability, booking, timezone) + } +} diff --git a/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt b/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt new file mode 100644 index 00000000..592f5434 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt @@ -0,0 +1,215 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of scheduler settings. + */ +data class ConfigurationSchedulerSettings( + /** + * Definitions for additional fields to be displayed in the Scheduler UI. + */ + @Json(name = "additional_fields") + val additionalFields: Map? = null, + /** + * Number of days in the future that Scheduler is available for scheduling events. + */ + @Json(name = "available_days_in_future") + val availableDaysInFuture: Int? = null, + /** + * Minimum number of minutes in the future that a user can make a new booking. + */ + @Json(name = "min_booking_notice") + val minBookingNotice: Int? = null, + /** + * Minimum number of minutes before a booking can be cancelled. + */ + @Json(name = "min_cancellation_notice") + val minCancellationNotice: Int? = null, + /** + * A message about the cancellation policy to display when booking an event. + */ + @Json(name = "cancellation_policy") + val cancellationPolicy: String? = null, + /** + * The URL used to reschedule bookings. + */ + @Json(name = "rescheduling_url") + val reschedulingUrl: String? = null, + /** + * The URL used to cancel bookings. + */ + @Json(name = "cancellation_url") + val cancellationUrl: String? = null, + /** + * The URL used to confirm or cancel pending bookings. + */ + @Json(name = "organizer_confirmation_url") + val organizerConfirmationUrl: String? = null, + /** + * The custom URL to redirect to once the booking is confirmed. + */ + @Json(name = "confirmation_redirect_url") + val confirmationRedirectUrl: String? = null, + /** + * Whether the option to reschedule an event is hidden in booking confirmations and notifications. + */ + @Json(name = "hide_rescheduling_options") + val hideReschedulingOptions: Boolean? = null, + /** + * Whether the option to cancel an event is hidden in booking confirmations and notifications. + */ + @Json(name = "hide_cancellation_options") + val hideCancellationOptions: Boolean? = null, + /** + * Whether to hide the additional guests field on the scheduling page. + */ + @Json(name = "hide_additional_guests") + val hideAdditionalGuests: Boolean? = null, + /** + * Configurable settings for booking emails. + */ + @Json(name = "email_template") + val emailTemplate: EmailTemplate? = null, +) { + class Builder { + private var additionalFields: Map? = null + private var availableDaysInFuture: Int? = null + private var minBookingNotice: Int? = null + private var minCancellationNotice: Int? = null + private var cancellationPolicy: String? = null + private var reschedulingUrl: String? = null + private var cancellationUrl: String? = null + private var organizerConfirmationUrl: String? = null + private var confirmationRedirectUrl: String? = null + private var hideReschedulingOptions: Boolean? = null + private var hideCancellationOptions: Boolean? = null + private var hideAdditionalGuests: Boolean? = null + private var emailTemplate: EmailTemplate? = null + + /** + * Set the definitions for additional fields to be displayed in the Scheduler UI. + * + * @param additionalFields Definitions for additional fields to be displayed in the Scheduler UI. + * @return The builder. + */ + fun additionalFields(additionalFields: Map) = apply { this.additionalFields = additionalFields } + + /** + * Set the number of days in the future that Scheduler is available for scheduling events. + * + * @param availableDaysInFuture Number of days in the future that Scheduler is available for scheduling events. + * @return The builder. + */ + fun availableDaysInFuture(availableDaysInFuture: Int) = apply { this.availableDaysInFuture = availableDaysInFuture } + + /** + * Set the minimum number of minutes in the future that a user can make a new booking. + * + * @param minBookingNotice Minimum number of minutes in the future that a user can make a new booking. + * @return The builder. + */ + fun minBookingNotice(minBookingNotice: Int) = apply { this.minBookingNotice = minBookingNotice } + + /** + * Set the minimum number of minutes before a booking can be cancelled. + * + * @param minCancellationNotice Minimum number of minutes before a booking can be cancelled. + * @return The builder. + */ + fun minCancellationNotice(minCancellationNotice: Int) = apply { this.minCancellationNotice = minCancellationNotice } + + /** + * Set a message about the cancellation policy to display when booking an event. + * + * @param cancellationPolicy A message about the cancellation policy to display when booking an event. + * @return The builder. + */ + fun cancellationPolicy(cancellationPolicy: String) = apply { this.cancellationPolicy = cancellationPolicy } + + /** + * Set the URL used to reschedule bookings. + * + * @param reschedulingUrl The URL used to reschedule bookings. + * @return The builder. + */ + fun reschedulingUrl(reschedulingUrl: String) = apply { this.reschedulingUrl = reschedulingUrl } + + /** + * Set the URL used to cancel bookings. + * + * @param cancellationUrl The URL used to cancel bookings. + * @return The builder. + */ + fun cancellationUrl(cancellationUrl: String) = apply { this.cancellationUrl = cancellationUrl } + + /** + * Set the URL used to confirm or cancel pending bookings. + * + * @param organizerConfirmationUrl The URL used to confirm or cancel pending bookings. + * @return The builder. + */ + fun organizerConfirmationUrl(organizerConfirmationUrl: String) = apply { this.organizerConfirmationUrl = organizerConfirmationUrl } + + /** + * Set the custom URL to redirect to once the booking is confirmed. + * + * @param confirmationRedirectUrl The custom URL to redirect to once the booking is confirmed. + * @return The builder. + */ + fun confirmationRedirectUrl(confirmationRedirectUrl: String) = apply { this.confirmationRedirectUrl = confirmationRedirectUrl } + + /** + * Set whether the option to reschedule an event is hidden in booking confirmations and notifications. + * + * @param hideReschedulingOptions Whether the option to reschedule an event is hidden in booking confirmations and notifications. + * @return The builder. + */ + fun hideReschedulingOptions(hideReschedulingOptions: Boolean) = apply { this.hideReschedulingOptions = hideReschedulingOptions } + + /** + * Set whether the option to cancel an event is hidden in booking confirmations and notifications. + * + * @param hideCancellationOptions Whether the option to cancel an event is hidden in booking confirmations and notifications. + * @return The builder. + */ + fun hideCancellationOptions(hideCancellationOptions: Boolean) = apply { this.hideCancellationOptions = hideCancellationOptions } + + /** + * Set whether to hide the additional guests field on the scheduling page. + * + * @param hideAdditionalGuests Whether to hide the additional guests field on the scheduling page. + * @return The builder. + */ + fun hideAdditionalGuests(hideAdditionalGuests: Boolean) = apply { this.hideAdditionalGuests = hideAdditionalGuests } + + /** + * Set the configurable settings for booking emails. + * + * @param emailTemplate Configurable settings for booking emails. + * @return The builder. + */ + fun emailTemplate(emailTemplate: EmailTemplate) = apply { this.emailTemplate = emailTemplate } + + /** + * Build the [ConfigurationSchedulerSettings]. + * + * @return The [ConfigurationSchedulerSettings] + */ + fun build() = ConfigurationSchedulerSettings( + additionalFields, + availableDaysInFuture, + minBookingNotice, + minCancellationNotice, + cancellationPolicy, + reschedulingUrl, + cancellationUrl, + organizerConfirmationUrl, + confirmationRedirectUrl, + hideReschedulingOptions, + hideCancellationOptions, + hideAdditionalGuests, + emailTemplate, + ) + } +} diff --git a/src/main/kotlin/com/nylas/models/CreateConfigurationRequest.kt b/src/main/kotlin/com/nylas/models/CreateConfigurationRequest.kt new file mode 100644 index 00000000..763dabd8 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateConfigurationRequest.kt @@ -0,0 +1,108 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a request to create a configuration. + */ +data class CreateConfigurationRequest( + /** + * List of participants included in the scheduled event. + */ + @Json(name = "participants") + val participants: List, + /** + * Rules that determine available time slots for the event. + */ + @Json(name = "availability") + val availability: ConfigurationAvailability, + /** + * Booking data for the event. + */ + @Json(name = "event_booking") + val eventBooking: ConfigurationEventBooking, + /** + * Unique identifier for the Configuration object. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * If true, scheduling Availability and Bookings endpoints require a valid session ID. + */ + @Json(name = "requires_session_auth") + val requiresSessionAuth: Boolean? = null, + /** + * Settings for the Scheduler UI. + */ + @Json(name = "scheduler") + val scheduler: ConfigurationSchedulerSettings? = null, + /** + * Appearance settings for the Scheduler UI. + */ + @Json(name = "appearance") + val appearance: Map? = null, +) { + /** + * A builder for creating a [CreateConfigurationRequest]. + * @param participants List of participants included in the scheduled event. + * @param availability Rules that determine available time slots for the event. + * @param eventBooking Booking data for the event. + */ + data class Builder( + private val participants: List, + private val availability: ConfigurationAvailability, + private val eventBooking: ConfigurationEventBooking, + ) { + private var requiresSessionAuth: Boolean? = null + private var slug: String? = null + private var scheduler: ConfigurationSchedulerSettings? = null + private var appearance: Map? = null + + /** + * Set the unique identifier for the configuration. + * + * @param slug Unique identifier for the Configuration object. + * @return The builder + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Set if scheduling Availability and Bookings endpoints require a valid session ID. + * + * @param requiresSessionAuth If true, scheduling Availability and Bookings endpoints require a valid session ID. + * @return The builder + */ + fun requiresSessionAuth(requiresSessionAuth: Boolean) = apply { this.requiresSessionAuth = requiresSessionAuth } + + /** + * Set the settings for the Scheduler UI. + * + * @param scheduler Settings for the Scheduler UI. + * @return The builder + */ + fun scheduler(scheduler: ConfigurationSchedulerSettings) = apply { this.scheduler = scheduler } + + /** + * Set the appearance settings for the Scheduler UI. + * + * @param appearance Appearance settings for the Scheduler UI. + * @return The builder + */ + fun appearance(appearance: Map) = apply { this.appearance = appearance } + + /** + * Build the [CreateConfigurationRequest]. + * + * @return The [CreateConfigurationRequest] + */ + fun build() = CreateConfigurationRequest( + participants, + availability, + eventBooking, + slug, + requiresSessionAuth, + scheduler, + appearance, + ) + } +} diff --git a/src/main/kotlin/com/nylas/models/Scheduler.kt b/src/main/kotlin/com/nylas/models/Scheduler.kt index d9e6cb15..bd5be584 100644 --- a/src/main/kotlin/com/nylas/models/Scheduler.kt +++ b/src/main/kotlin/com/nylas/models/Scheduler.kt @@ -15,17 +15,17 @@ data class Configuration( * List of participants included in the scheduled event. */ @Json(name = "participants") - val participants: List, + val participants: List, /** * Rules that determine available time slots for the event. */ @Json(name = "availability") - val availability: Availability, + val availability: ConfigurationAvailability, /** * Booking data for the event. */ @Json(name = "event_booking") - val eventBooking: EventBooking, + val eventBooking: ConfigurationEventBooking, /** * Unique identifier for the Configuration object. */ @@ -40,7 +40,7 @@ data class Configuration( * Settings for the Scheduler UI. */ @Json(name = "scheduler") - val scheduler: SchedulerSettings? = null, + val scheduler: ConfigurationSchedulerSettings? = null, /** * Appearance settings for the Scheduler UI. */ @@ -48,212 +48,6 @@ data class Configuration( val appearance: Map? = null, ) -/** - * Class representation of a booking participant. - */ -data class ConfigParticipant( - /** - * Participant's email address. - */ - @Json(name = "email") - val email: String, - /** - * Availability data for the participant. - */ - @Json(name = "availability") - val availability: ParticipantAvailability, - /** - * Booking data for the participant. - */ - @Json(name = "booking") - val booking: ParticipantBooking, - /** - * Participant's name. - */ - @Json(name = "name") - val name: String? = null, - /** - * Whether the participant is the organizer of the event. - */ - @Json(name = "is_organizer") - val isOrganizer: Boolean? = null, - /** - * The participant's timezone. - */ - @Json(name = "timezone") - val timezone: String? = null, -) - -/** - * Class representation of availability settings. - */ -data class Availability( - /** - * The total number of minutes the event should last. - */ - @Json(name = "duration_minutes") - val durationMinutes: Int, - /** - * The interval between meetings in minutes. - */ - @Json(name = "interval_minutes") - val intervalMinutes: Int? = null, - /** - * Nylas rounds each time slot to the nearest multiple of this number of minutes. - */ - @Json(name = "round_to") - val roundTo: Int? = null, - /** - * Availability rules for scheduling configuration. - */ - @Json(name = "availability_rules") - val availabilityRules: AvailabilityRules? = null, -) - -/** - * Class representation of participant availability. - */ -data class ParticipantAvailability( - /** - * List of calendar IDs associated with the participant's email address. - */ - @Json(name = "calendar_ids") - val calendarIds: List, - /** - * Open hours for this participant. The endpoint searches for free time slots during these open hours. - */ - @Json(name = "open_hours") - val openHours: List? = null, -) - -/** - * Class representation of a participant booking. - */ -data class ParticipantBooking( - /** - * The calendar ID that the event is created in. - */ - @Json(name = "calendar_id") - val calendarId: String, -) - -/** - * Class representation of an event booking. - */ -data class EventBooking( - /** - * The title of the event. - */ - @Json(name = "title") - val title: String, - /** - * The description of the event. - */ - @Json(name = "description") - val description: String? = null, - /** - * The location of the event. - */ - @Json(name = "location") - val location: String? = null, - /** - * The timezone for displaying times in confirmation email messages and reminders. - */ - @Json(name = "timezone") - val timezone: String? = null, - /** - * The type of booking. - */ - @Json(name = "booking_type") - val bookingType: BookingType? = null, - /** - * Conference details for the event. - */ - @Json(name = "conferencing") - val conferencing: Conferencing? = null, - /** - * Whether Nylas sends email messages when an event is booked, cancelled, or rescheduled. - */ - @Json(name = "disable_emails") - val disableEmails: Boolean? = null, - /** - * The list of reminders to send to participants before the event starts. - */ - @Json(name = "reminders") - val reminders: List? = null, -) - -/** - * Class representation of scheduler settings. - */ -data class SchedulerSettings( - /** - * Definitions for additional fields to be displayed in the Scheduler UI. - */ - @Json(name = "additional_fields") - val additionalFields: Map? = null, - /** - * Number of days in the future that Scheduler is available for scheduling events. - */ - @Json(name = "available_days_in_future") - val availableDaysInFuture: Int? = null, - /** - * Minimum number of minutes in the future that a user can make a new booking. - */ - @Json(name = "min_booking_notice") - val minBookingNotice: Int? = null, - /** - * Minimum number of minutes before a booking can be cancelled. - */ - @Json(name = "min_cancellation_notice") - val minCancellationNotice: Int? = null, - /** - * A message about the cancellation policy to display when booking an event. - */ - @Json(name = "cancellation_policy") - val cancellationPolicy: String? = null, - /** - * The URL used to reschedule bookings. - */ - @Json(name = "rescheduling_url") - val reschedulingUrl: String? = null, - /** - * The URL used to cancel bookings. - */ - @Json(name = "cancellation_url") - val cancellationUrl: String? = null, - /** - * The URL used to confirm or cancel pending bookings. - */ - @Json(name = "organizer_confirmation_url") - val organizerConfirmationUrl: String? = null, - /** - * The custom URL to redirect to once the booking is confirmed. - */ - @Json(name = "confirmation_redirect_url") - val confirmationRedirectUrl: String? = null, - /** - * Whether the option to reschedule an event is hidden in booking confirmations and notifications. - */ - @Json(name = "hide_rescheduling_options") - val hideReschedulingOptions: Boolean? = null, - /** - * Whether the option to cancel an event is hidden in booking confirmations and notifications. - */ - @Json(name = "hide_cancellation_options") - val hideCancellationOptions: Boolean? = null, - /** - * Whether to hide the additional guests field on the scheduling page. - */ - @Json(name = "hide_additional_guests") - val hideAdditionalGuests: Boolean? = null, - /** - * Configurable settings for booking emails. - */ - @Json(name = "email_template") - val emailTemplate: EmailTemplate? = null, -) - /** * Class representation of an additional field. */ @@ -373,17 +167,6 @@ data class BookingGuest( val name: String, ) -/** - * Class representation of a booking participant. - */ -data class BookingParticipant( - /** - * The email address of the participant to include in the booking. - */ - @Json(name = "email") - val email: String, -) - /** * Class representation of a create booking request. */ @@ -407,7 +190,7 @@ data class CreateBookingRequest( * List of participant email addresses from the Configuration object to include in the booking. */ @Json(name = "participants") - val participants: List? = null, + val participants: List? = null, /** * The guest's timezone that is used in email notifications. */ diff --git a/src/main/kotlin/com/nylas/resources/Configurations.kt b/src/main/kotlin/com/nylas/resources/Configurations.kt index 13491d09..3fd3fcfe 100644 --- a/src/main/kotlin/com/nylas/resources/Configurations.kt +++ b/src/main/kotlin/com/nylas/resources/Configurations.kt @@ -114,47 +114,6 @@ class Configurations(client: NylasClient) : Resource(client, Conf } } -/** - * Class representation of a request to create a configuration. - */ -data class CreateConfigurationRequest( - /** - * List of participants included in the scheduled event. - */ - @Json(name = "participants") - val participants: List, - /** - * Rules that determine available time slots for the event. - */ - @Json(name = "availability") - val availability: Availability, - /** - * Booking data for the event. - */ - @Json(name = "event_booking") - val eventBooking: EventBooking, - /** - * Unique identifier for the Configuration object. - */ - @Json(name = "slug") - val slug: String? = null, - /** - * If true, scheduling Availability and Bookings endpoints require a valid session ID. - */ - @Json(name = "requires_session_auth") - val requiresSessionAuth: Boolean? = null, - /** - * Settings for the Scheduler UI. - */ - @Json(name = "scheduler") - val scheduler: SchedulerSettings? = null, - /** - * Appearance settings for the Scheduler UI. - */ - @Json(name = "appearance") - val appearance: Map? = null, -) - /** * Class representation of a request to update a configuration. */ @@ -163,17 +122,17 @@ data class UpdateConfigurationRequest( * List of participants included in the scheduled event. */ @Json(name = "participants") - val participants: List? = null, + val participants: List? = null, /** * Rules that determine available time slots for the event. */ @Json(name = "availability") - val availability: Availability? = null, + val availability: ConfigurationAvailability? = null, /** * Booking data for the event. */ @Json(name = "event_booking") - val eventBooking: EventBooking? = null, + val eventBooking: ConfigurationEventBooking? = null, /** * Unique identifier for the Configuration object. */ @@ -188,7 +147,7 @@ data class UpdateConfigurationRequest( * Settings for the Scheduler UI. */ @Json(name = "scheduler") - val scheduler: SchedulerSettings? = null, + val scheduler: ConfigurationSchedulerSettings? = null, /** * Appearance settings for the Scheduler UI. */ From c47fd3b45a50df8e91d3051c0b2bac9780f2e18b Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Thu, 7 Nov 2024 11:31:48 +0100 Subject: [PATCH 05/12] Finishing configuration create, list, update & delete --- .../nylas/models/ConfigurationAvailability.kt | 18 ++- .../ConfigurationAvailabilityParticipant.kt | 14 +- .../models/ConfigurationBookingParticipant.kt | 14 +- .../nylas/models/ConfigurationEventBooking.kt | 15 ++- .../models/UpdateConfigurationRequest.kt | 125 ++++++++++++++++++ .../com/nylas/resources/Configurations.kt | 42 ------ 6 files changed, 167 insertions(+), 61 deletions(-) create mode 100644 src/main/kotlin/com/nylas/models/UpdateConfigurationRequest.kt diff --git a/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt b/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt index b697bc13..8a56b536 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt @@ -27,33 +27,39 @@ data class ConfigurationAvailability( @Json(name = "availability_rules") val availabilityRules: AvailabilityRules? = null, ) { - data class Builder( - private val durationMinutes: Int, - ) { + class Builder { + private var durationMinutes: Int? = null private var intervalMinutes: Int? = null private var roundTo: Int? = null private var availabilityRules: AvailabilityRules? = null + /** + * Set the duration of the event in minutes. + * @param durationMinutes The duration of the event in minutes. + * @return The builder. + */ + fun durationMinutes(durationMinutes: Int?) = apply { this.durationMinutes = durationMinutes } + /** * Set the interval between meetings in minutes. * @param intervalMinutes The interval between meetings in minutes. * @return The builder. */ - fun intervalMinutes(intervalMinutes: Int) = apply { this.intervalMinutes = intervalMinutes } + fun intervalMinutes(intervalMinutes: Int?) = apply { this.intervalMinutes = intervalMinutes } /** * Set Nylas rounds each time slot to the nearest multiple of this number of minutes. * @param roundTo Nylas rounds each time slot to the nearest multiple of this number of minutes. * @return The builder. */ - fun roundTo(roundTo: Int) = apply { this.roundTo = roundTo } + fun roundTo(roundTo: Int?) = apply { this.roundTo = roundTo } /** * Set availability rules for scheduling configuration. * @param availabilityRules Availability rules for scheduling configuration. * @return The builder. */ - fun availabilityRules(availabilityRules: AvailabilityRules) = apply { this.availabilityRules = availabilityRules } + fun availabilityRules(availabilityRules: AvailabilityRules?) = apply { this.availabilityRules = availabilityRules } /** * Build the [ConfigurationAvailability]. diff --git a/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt b/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt index 615be10f..b2297da6 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationAvailabilityParticipant.kt @@ -11,7 +11,7 @@ data class ConfigurationAvailabilityParticipant( * @param calendarIds The calendar IDs that the event is created in. */ @Json(name = "calendar_ids") - val calendarIds: List, + val calendarIds: List? = emptyList(), /** * Open hours for this participant. The endpoint searches for free time slots during these open hours. */ @@ -21,11 +21,17 @@ data class ConfigurationAvailabilityParticipant( /** * Builder for [ConfigurationAvailabilityParticipant]. */ - data class Builder( - private val calendarIds: List, - ) { + class Builder { + private var calendarIds: List? = null private var openHours: List? = null + /** + * Set the calendar IDs for this participant. + * @param calendarIds Calendar IDs for this participant. + * @return The builder. + */ + fun calendarIds(calendarIds: List) = apply { this.calendarIds = calendarIds } + /** * Set the open hours for this participant. * @param openHours Open hours for this participant. diff --git a/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt b/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt index c154e300..6330a49f 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt @@ -14,11 +14,17 @@ data class ConfigurationBookingParticipant( ) { /** * Builder for [ConfigurationBookingParticipant]. - * @param calendarId The calendar ID that the event is created in. */ - data class Builder( - private val calendarId: String, - ) { + class Builder { + private var calendarId: String? = null + + /** + * Set the calendar ID for this participant. + * @param calendarId The calendar ID for this participant. + * @return The builder. + */ + fun calendarId(calendarId: String?) = apply { this.calendarId = calendarId } + /** * Builds a [ConfigurationBookingParticipant] instance. * @return The [ConfigurationBookingParticipant] instance. diff --git a/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt b/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt index 5aeb7f49..0eeeffed 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt @@ -10,7 +10,7 @@ data class ConfigurationEventBooking( * The title of the event. */ @Json(name = "title") - val title: String, + val title: String? = null, /** * The description of the event. */ @@ -49,11 +49,9 @@ data class ConfigurationEventBooking( ) { /** * Builder for [ConfigurationEventBooking]. - * @property title The title of the event. */ - data class Builder( - private val title: String, - ) { + class Builder { + private var title: String? = null private var description: String? = null private var location: String? = null private var timezone: String? = null @@ -62,6 +60,13 @@ data class ConfigurationEventBooking( private var disableEmails: Boolean? = null private var reminders: List? = null + /** + * Set the title of the event. + * @param title The title of the event. + * @return The builder. + */ + fun title(title: String?) = apply { this.title = title } + /** * Sets the description of the event. * @param description The description of the event. diff --git a/src/main/kotlin/com/nylas/models/UpdateConfigurationRequest.kt b/src/main/kotlin/com/nylas/models/UpdateConfigurationRequest.kt new file mode 100644 index 00000000..3386ee0f --- /dev/null +++ b/src/main/kotlin/com/nylas/models/UpdateConfigurationRequest.kt @@ -0,0 +1,125 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a request to update a configuration. + */ +data class UpdateConfigurationRequest( + /** + * List of participants included in the scheduled event. + */ + @Json(name = "participants") + val participants: List? = null, + /** + * Rules that determine available time slots for the event. + */ + @Json(name = "availability") + val availability: ConfigurationAvailability? = null, + /** + * Booking data for the event. + */ + @Json(name = "event_booking") + val eventBooking: ConfigurationEventBooking? = null, + /** + * Unique identifier for the Configuration object. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * If true, scheduling Availability and Bookings endpoints require a valid session ID. + */ + @Json(name = "requires_session_auth") + val requiresSessionAuth: Boolean? = null, + /** + * Settings for the Scheduler UI. + */ + @Json(name = "scheduler") + val scheduler: ConfigurationSchedulerSettings? = null, + /** + * Appearance settings for the Scheduler UI. + */ + @Json(name = "appearance") + val appearance: Map? = null, +) { + /** + * A builder for creating a [UpdateConfigurationRequest]. + */ + class Builder { + private var participants: List? = null + private var availability: ConfigurationAvailability? = null + private var eventBooking: ConfigurationEventBooking? = null + private var requiresSessionAuth: Boolean? = null + private var slug: String? = null + private var scheduler: ConfigurationSchedulerSettings? = null + private var appearance: Map? = null + + /** + * Set the list of participants included in the scheduled event. + * @param participants List of participants included in the scheduled event. + * @return The builder + */ + fun participants(participants: List) = apply { this.participants = participants } + + /** + * Set the rules that determine available time slots for the event. + * @param availability Rules that determine available time slots for the event. + * @return The builder + */ + fun availability(availability: ConfigurationAvailability) = apply { this.availability = availability } + + /** + * Set the booking data for the event. + * @param eventBooking Booking data for the event. + * @return The builder + */ + fun eventBooking(eventBooking: ConfigurationEventBooking) = apply { this.eventBooking = eventBooking } + + /** + * Set the unique identifier for the configuration. + * + * @param slug Unique identifier for the Configuration object. + * @return The builder + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Set if scheduling Availability and Bookings endpoints require a valid session ID. + * + * @param requiresSessionAuth If true, scheduling Availability and Bookings endpoints require a valid session ID. + * @return The builder + */ + fun requiresSessionAuth(requiresSessionAuth: Boolean) = apply { this.requiresSessionAuth = requiresSessionAuth } + + /** + * Set the settings for the Scheduler UI. + * + * @param scheduler Settings for the Scheduler UI. + * @return The builder + */ + fun scheduler(scheduler: ConfigurationSchedulerSettings) = apply { this.scheduler = scheduler } + + /** + * Set the appearance settings for the Scheduler UI. + * + * @param appearance Appearance settings for the Scheduler UI. + * @return The builder + */ + fun appearance(appearance: Map) = apply { this.appearance = appearance } + + /** + * Build the [UpdateConfigurationRequest]. + * + * @return The [UpdateConfigurationRequest] + */ + fun build() = UpdateConfigurationRequest( + participants, + availability, + eventBooking, + slug, + requiresSessionAuth, + scheduler, + appearance, + ) + } +} diff --git a/src/main/kotlin/com/nylas/resources/Configurations.kt b/src/main/kotlin/com/nylas/resources/Configurations.kt index 3fd3fcfe..e0b8c01f 100644 --- a/src/main/kotlin/com/nylas/resources/Configurations.kt +++ b/src/main/kotlin/com/nylas/resources/Configurations.kt @@ -3,7 +3,6 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper -import com.squareup.moshi.Json /** * Nylas Configurations API @@ -113,44 +112,3 @@ class Configurations(client: NylasClient) : Resource(client, Conf return destroyResource(path, overrides = overrides) } } - -/** - * Class representation of a request to update a configuration. - */ -data class UpdateConfigurationRequest( - /** - * List of participants included in the scheduled event. - */ - @Json(name = "participants") - val participants: List? = null, - /** - * Rules that determine available time slots for the event. - */ - @Json(name = "availability") - val availability: ConfigurationAvailability? = null, - /** - * Booking data for the event. - */ - @Json(name = "event_booking") - val eventBooking: ConfigurationEventBooking? = null, - /** - * Unique identifier for the Configuration object. - */ - @Json(name = "slug") - val slug: String? = null, - /** - * If true, scheduling Availability and Bookings endpoints require a valid session ID. - */ - @Json(name = "requires_session_auth") - val requiresSessionAuth: Boolean? = null, - /** - * Settings for the Scheduler UI. - */ - @Json(name = "scheduler") - val scheduler: ConfigurationSchedulerSettings? = null, - /** - * Appearance settings for the Scheduler UI. - */ - @Json(name = "appearance") - val appearance: Map? = null, -) From 37c72d7800d8aa809a2c1854dc42e133148ebee3 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Thu, 7 Nov 2024 15:29:09 +0100 Subject: [PATCH 06/12] Add test for configurations --- .../com/nylas/models/AvailabilityRules.kt | 12 +- .../nylas/models/ConfigurationAvailability.kt | 2 +- .../models/ConfigurationBookingParticipant.kt | 2 +- .../models/ListConfigurationsQueryParams.kt | 10 +- .../com/nylas/resources/Configurations.kt | 2 +- .../com/nylas/resources/ConfigurationsTest.kt | 305 ++++++++++++++++++ 6 files changed, 319 insertions(+), 14 deletions(-) create mode 100644 src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt diff --git a/src/main/kotlin/com/nylas/models/AvailabilityRules.kt b/src/main/kotlin/com/nylas/models/AvailabilityRules.kt index 4b3919d1..26fa8fcd 100644 --- a/src/main/kotlin/com/nylas/models/AvailabilityRules.kt +++ b/src/main/kotlin/com/nylas/models/AvailabilityRules.kt @@ -27,8 +27,8 @@ data class AvailabilityRules( * The ID on events that Nylas considers when calculating the order of round-robin participants. * This is used for both max-fairness and max-availability methods. */ - @Json(name = "round_robin_event_id") - val roundRobinEventId: String? = null, + @Json(name = "round_robin_group_id") + val roundRobinGroupId: String? = null, ) { /** * A builder for creating a [AvailabilityRules]. @@ -37,7 +37,7 @@ data class AvailabilityRules( private var availabilityMethod: AvailabilityMethod? = null private var buffer: MeetingBuffer? = null private var defaultOpenHours: List? = null - private var roundRobinEventId: String? = null + private var roundRobinGroupId: String? = null /** * Set the method used to determine availability for a meeting. @@ -65,10 +65,10 @@ data class AvailabilityRules( /** * Set the ID on events that Nylas considers when calculating the order of round-robin participants. * This is used for both max-fairness and max-availability methods. - * @param roundRobinEventId The ID on events that Nylas considers when calculating the order of round-robin participants. + * @param roundRobinGroupId The ID on events that Nylas considers when calculating the order of round-robin participants. * @return The builder. */ - fun roundRobinEventId(roundRobinEventId: String) = apply { this.roundRobinEventId = roundRobinEventId } + fun roundRobinGroupId(roundRobinGroupId: String) = apply { this.roundRobinGroupId = roundRobinGroupId } /** * Build the [AvailabilityRules] object. @@ -78,7 +78,7 @@ data class AvailabilityRules( availabilityMethod = availabilityMethod, buffer = buffer, defaultOpenHours = defaultOpenHours, - roundRobinEventId = roundRobinEventId, + roundRobinGroupId = roundRobinGroupId, ) } } diff --git a/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt b/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt index 8a56b536..9c4d202e 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationAvailability.kt @@ -10,7 +10,7 @@ data class ConfigurationAvailability( * The total number of minutes the event should last. */ @Json(name = "duration_minutes") - val durationMinutes: Int, + val durationMinutes: Int? = null, /** * The interval between meetings in minutes. */ diff --git a/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt b/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt index 6330a49f..5946a2cc 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationBookingParticipant.kt @@ -10,7 +10,7 @@ data class ConfigurationBookingParticipant( * The calendar ID that the event is created in. */ @Json(name = "calendar_id") - val calendarId: String, + val calendarId: String? = null, ) { /** * Builder for [ConfigurationBookingParticipant]. diff --git a/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt b/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt index 719f687d..29656c5c 100644 --- a/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt +++ b/src/main/kotlin/com/nylas/models/ListConfigurationsQueryParams.kt @@ -2,7 +2,7 @@ package com.nylas.models import com.squareup.moshi.Json -data class ListConfigurationsParams( +data class ListConfigurationsQueryParams( /** * The maximum number of objects to return. * Defaults to 50. The maximum allowed value is 200. @@ -18,7 +18,7 @@ data class ListConfigurationsParams( ) : IQueryParams /** - * Builder for [ListConfigurationsParams]. + * Builder for [ListConfigurationsQueryParams]. */ class Builder { private var limit: Int? = null @@ -43,8 +43,8 @@ class Builder { fun pageToken(pageToken: String?) = apply { this.pageToken = pageToken } /** - * Builds a [ListConfigurationsParams] instance. - * @return The [ListConfigurationsParams] instance. + * Builds a [ListConfigurationsQueryParams] instance. + * @return The [ListConfigurationsQueryParams] instance. */ - fun build() = ListConfigurationsParams(limit, pageToken) + fun build() = ListConfigurationsQueryParams(limit, pageToken) } diff --git a/src/main/kotlin/com/nylas/resources/Configurations.kt b/src/main/kotlin/com/nylas/resources/Configurations.kt index e0b8c01f..cffc1ee4 100644 --- a/src/main/kotlin/com/nylas/resources/Configurations.kt +++ b/src/main/kotlin/com/nylas/resources/Configurations.kt @@ -28,7 +28,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf @JvmOverloads fun list( identifier: String, - queryParams: ListConfigurationsParams? = null, + queryParams: ListConfigurationsQueryParams? = null, overrides: RequestOverrides? = null, ): ListResponse { val path = String.format("v3/grants/%s/scheduling/configurations", identifier) diff --git a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt new file mode 100644 index 00000000..c557a91d --- /dev/null +++ b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt @@ -0,0 +1,305 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.models.* +import com.nylas.models.ListConfigurationsQueryParams +import com.nylas.models.Response +import com.nylas.util.JsonHelper +import com.squareup.moshi.Types +import okhttp3.* +import okio.Buffer +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.* +import java.lang.reflect.Type +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertIs + +class ConfigurationsTest { + private val mockHttpClient: OkHttpClient = Mockito.mock(OkHttpClient::class.java) + private val mockCall: Call = Mockito.mock(Call::class.java) + private val mockResponse: okhttp3.Response = Mockito.mock(okhttp3.Response::class.java) + private val mockResponseBody: ResponseBody = Mockito.mock(ResponseBody::class.java) + private val mockOkHttpClientBuilder: OkHttpClient.Builder = Mockito.mock() + + @BeforeEach + fun setup() { + MockitoAnnotations.openMocks(this) + whenever(mockOkHttpClientBuilder.addInterceptor(any())).thenReturn(mockOkHttpClientBuilder) + whenever(mockOkHttpClientBuilder.build()).thenReturn(mockHttpClient) + whenever(mockHttpClient.newCall(any())).thenReturn(mockCall) + whenever(mockCall.execute()).thenReturn(mockResponse) + whenever(mockResponse.isSuccessful).thenReturn(true) + whenever(mockResponse.body()).thenReturn(mockResponseBody) + } + + @Nested + inner class SerializationTests { + @Test + fun `Configuration serializes properly`() { + val adapter = JsonHelper.moshi().adapter(Configuration::class.java) + val jsonBuffer = Buffer().writeUtf8( + """ + { + "id": "abc-123-configuration-id", + "slug": None, + "participants": [ + { + "email": "test@nylas.com", + "isOrganizer": true, + "name": "Test", + "availability": { + "calendarIds": [ + "primary" + ], + "openHours": [ + { + "days": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "exdates": None, + "timezone": "", + "start": "09:00", + "end": "17:00" + } + ] + }, + "booking": { + "calendarId": "primary" + }, + "timezone": "" + } + ], + "requiresSessionAuth": false, + "availability": { + "durationMinutes": 30, + "intervalMinutes": 15, + "roundTo": 15, + "availabilityRules": { + "availabilityMethod": "collective", + "buffer": { + "before": 60, + "after": 0 + }, + "defaultOpenHours": [ + { + "days": [ + 0, + 1, + 2, + 5, + 6 + ], + "exdates": None, + "timezone": "", + "start": "09:00", + "end": "18:00" + } + ], + "roundRobinGroupId": "" + } + }, + "eventBooking": { + "title": "Updated Title", + "timezone": "utc", + "description": "", + "location": "none", + "bookingType": "booking", + "conferencing": { + "provider": "Microsoft Teams", + "autocreate": { + "conf_grant_id": "", + "conf_settings": None + } + }, + "hideParticipants": null, + "disableEmails": null + }, + "scheduler": { + "availableDaysInFuture": 7, + "minCancellationNotice": 60, + "minBookingNotice": 120, + "confirmationRedirectUrl": "", + "hideReschedulingOptions": false, + "hideCancellationOptions": false, + "hideAdditionalGuests": true, + "cancellationPolicy": "", + "emailTemplate": { + "bookingConfirmed": {} + } + }, + "appearance": { + "submitButtonLabel": "submit", + "thankYouMessage": "thank you for your business. your booking was successful." + } + } + """.trimIndent(), + ) + + val config = adapter.fromJson(jsonBuffer)!! + assertIs(config) + assertEquals("abc-123-configuration-id", config.id) + assertEquals(false, config.requiresSessionAuth) + assertEquals(7, config.scheduler?.availableDaysInFuture) + assertEquals(60, config.scheduler?.minCancellationNotice) + assertEquals(120, config.scheduler?.minBookingNotice) + assertEquals("", config.scheduler?.confirmationRedirectUrl) + assertEquals(false, config.scheduler?.hideReschedulingOptions) + assertEquals(false, config.scheduler?.hideCancellationOptions) + assertEquals(true, config.scheduler?.hideAdditionalGuests) + assertEquals("", config.scheduler?.cancellationPolicy) + assertEquals("submit", config.appearance?.get("submitButtonLabel")) + assertEquals("thank you for your business. your booking was successful.", config.appearance?.get("thankYouMessage")) + assertEquals(15, config.availability.durationMinutes) + assertEquals(15, config.availability.intervalMinutes) + assertEquals(15, config.availability.roundTo) + assertEquals(AvailabilityMethod.COLLECTIVE, config.availability.availabilityRules?.availabilityMethod) + assertEquals(60, config.availability.availabilityRules?.buffer?.before) + assertEquals(0, config.availability.availabilityRules?.buffer?.after) + assertEquals("", config.availability.availabilityRules?.roundRobinGroupId) + assertEquals(0, config.availability.availabilityRules?.defaultOpenHours?.first()?.days?.size) + assertEquals("09:00", config.availability.availabilityRules?.defaultOpenHours?.first()?.start) + assertEquals("18:00", config.availability.availabilityRules?.defaultOpenHours?.first()?.end) + } + } + + @Nested + inner class CrudTests { + private lateinit var grantId: String + private lateinit var mockNylasClient: NylasClient + private lateinit var configurations: Configurations + + @BeforeEach + fun setup() { + grantId = "abc-123-grant-id" + mockNylasClient = Mockito.mock(NylasClient::class.java) + configurations = Configurations(mockNylasClient) + } + + @Test + fun `listing configurations calls requests with the correct params`() { + configurations.list(grantId) + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/configurations", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(ListResponse::class.java, Configuration::class.java), typeCaptor.firstValue) + } + + @Test + fun `creating a configuration calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(CreateConfigurationRequest::class.java) + val participantCalendarIds = ArrayList() + participantCalendarIds.add("primary") + + val configurationAvailabilityParticipant = ConfigurationAvailabilityParticipant.Builder().calendarIds(participantCalendarIds).build() + + val configurationBookingParticipant = ConfigurationBookingParticipant.Builder().calendarId("primary").build() + + val configurationParticipant = ConfigurationParticipant.Builder("test@nylas.com") + .availability(configurationAvailabilityParticipant) + .booking(configurationBookingParticipant) + .name("Test Participant") + .isOrganizer(true) + .build() + + val configurationAvailability = ConfigurationAvailability.Builder().intervalMinutes(30).build() + + val configurationEventBooking = ConfigurationEventBooking.Builder().title("Test Event Booking").build() + + val participants = ArrayList() + participants.add(configurationParticipant) + + val createConfigurationRequest = CreateConfigurationRequest.Builder( + participants, + configurationAvailability, + configurationEventBooking, + ).build() + + configurations.create(grantId, createConfigurationRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + verify(mockNylasClient).executePost>( + pathCaptor.capture(), + typeCaptor.capture(), + requestBodyCaptor.capture(), + ) + assertEquals("v3/grants/$grantId/configurations", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) + assertEquals(adapter.toJson(createConfigurationRequest), requestBodyCaptor.firstValue) + } + + @Test + fun `updating a configuration calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(UpdateConfigurationRequest::class.java) + val configId = "abc-123-configuration-id" + val config = ConfigurationSchedulerSettings.Builder().minBookingNotice(120).build() + val updateConfigurationRequest = UpdateConfigurationRequest().Builder().scheduler(config).build() + + configurations.update(grantId, configId, updateConfigurationRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + verify(mockNylasClient).executePut>( + pathCaptor.capture(), + typeCaptor.capture(), + requestBodyCaptor.capture(), + ) + assertEquals("v3/grants/$grantId/configurations/$configId", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) + assertEquals(adapter.toJson(updateConfigurationRequest), requestBodyCaptor.firstValue) + } + + @Test + fun `finding a configuration calls requests with the correct params`() { + val configId = "configuration-id" + configurations.find(grantId, configId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + ) + assertEquals("v3/grants/$grantId/configurations/$configId", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) + + } + + @Test + fun `destroying a configuration calls requests with the correct params`() { + val configId = "configuration-id" + configurations.destroy(grantId, configId) + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete( + pathCaptor.capture(), + typeCaptor.capture(), + overrideParamCaptor.capture(), + ) + assertEquals("v3/grants/$grantId/configurations/$configId", pathCaptor.firstValue) + assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) + } + } +} From 8fd1eb1834dc25964e88ffe9d1a29fca60a603b0 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Fri, 8 Nov 2024 12:18:25 +0100 Subject: [PATCH 07/12] Test completion for configuration resources --- .../com/nylas/models/AvailabilityRules.kt | 2 +- .../nylas/models/ConfigurationEventBooking.kt | 14 +++ .../com/nylas/resources/CalendarsTest.kt | 2 +- .../com/nylas/resources/ConfigurationsTest.kt | 115 +++++++++++------- 4 files changed, 85 insertions(+), 48 deletions(-) diff --git a/src/main/kotlin/com/nylas/models/AvailabilityRules.kt b/src/main/kotlin/com/nylas/models/AvailabilityRules.kt index 26fa8fcd..1f4b2c66 100644 --- a/src/main/kotlin/com/nylas/models/AvailabilityRules.kt +++ b/src/main/kotlin/com/nylas/models/AvailabilityRules.kt @@ -14,7 +14,7 @@ data class AvailabilityRules( /** * The buffer to add to the start and end of a meeting. */ - @Json(name = "meeting_buffer") + @Json(name = "buffer") val buffer: MeetingBuffer? = null, /** * A default set of open hours to apply to all participants. diff --git a/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt b/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt index 0eeeffed..4acec054 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationEventBooking.kt @@ -46,6 +46,11 @@ data class ConfigurationEventBooking( */ @Json(name = "reminders") val reminders: List? = null, + /** + * Whether to hide participants from the event booking. + */ + @Json(name = "hide_participants") + val hideParticipants: Boolean? = null, ) { /** * Builder for [ConfigurationEventBooking]. @@ -59,6 +64,7 @@ data class ConfigurationEventBooking( private var conferencing: Conferencing? = null private var disableEmails: Boolean? = null private var reminders: List? = null + private var hideParticipants: Boolean? = null /** * Set the title of the event. @@ -116,6 +122,13 @@ data class ConfigurationEventBooking( */ fun reminders(reminders: List?) = apply { this.reminders = reminders } + /** + * Sets whether to hide participants from the event booking. + * @param hideParticipants Whether to hide participants from the event booking. + * @return The builder. + */ + fun hideParticipants(hideParticipants: Boolean?) = apply { this.hideParticipants = hideParticipants } + /** * Builds an [ConfigurationEventBooking] instance. * @return The [ConfigurationEventBooking] instance. @@ -129,6 +142,7 @@ data class ConfigurationEventBooking( conferencing, disableEmails, reminders, + hideParticipants, ) } } diff --git a/src/test/kotlin/com/nylas/resources/CalendarsTest.kt b/src/test/kotlin/com/nylas/resources/CalendarsTest.kt index 05d2d731..f9b88ea6 100644 --- a/src/test/kotlin/com/nylas/resources/CalendarsTest.kt +++ b/src/test/kotlin/com/nylas/resources/CalendarsTest.kt @@ -264,7 +264,7 @@ class CalendarsTest { exdates = listOf("2021-05-03", "2021-05-04"), ), ), - roundRobinEventId = "event-123", + roundRobinGroupId = "event-123", ), ) diff --git a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt index c557a91d..7fb5f34c 100644 --- a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt +++ b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt @@ -45,17 +45,17 @@ class ConfigurationsTest { """ { "id": "abc-123-configuration-id", - "slug": None, + "slug": null, "participants": [ { "email": "test@nylas.com", - "isOrganizer": true, + "is_organizer": true, "name": "Test", "availability": { - "calendarIds": [ + "calendar_ids": [ "primary" ], - "openHours": [ + "open_hours": [ { "days": [ 0, @@ -66,7 +66,7 @@ class ConfigurationsTest { 5, 6 ], - "exdates": None, + "exdates": null, "timezone": "", "start": "09:00", "end": "17:00" @@ -74,23 +74,23 @@ class ConfigurationsTest { ] }, "booking": { - "calendarId": "primary" + "calendar_id": "primary" }, "timezone": "" } ], - "requiresSessionAuth": false, + "requires_session_auth": false, "availability": { - "durationMinutes": 30, - "intervalMinutes": 15, - "roundTo": 15, - "availabilityRules": { - "availabilityMethod": "collective", + "duration_minutes": 30, + "interval_minutes": 15, + "round_to": 15, + "availability_rules": { + "availability_method": "collective", "buffer": { "before": 60, "after": 0 }, - "defaultOpenHours": [ + "default_open_hours": [ { "days": [ 0, @@ -99,47 +99,47 @@ class ConfigurationsTest { 5, 6 ], - "exdates": None, + "exdates": null, "timezone": "", "start": "09:00", "end": "18:00" } ], - "roundRobinGroupId": "" + "round_robin_group_id": "" } }, - "eventBooking": { + "event_booking": { "title": "Updated Title", "timezone": "utc", "description": "", - "location": "none", - "bookingType": "booking", + "location": null, + "booking_type": "booking", "conferencing": { "provider": "Microsoft Teams", "autocreate": { "conf_grant_id": "", - "conf_settings": None + "conf_settings": null } }, - "hideParticipants": null, - "disableEmails": null + "hide_participants": null, + "disable_emails": null }, "scheduler": { - "availableDaysInFuture": 7, - "minCancellationNotice": 60, - "minBookingNotice": 120, - "confirmationRedirectUrl": "", - "hideReschedulingOptions": false, - "hideCancellationOptions": false, - "hideAdditionalGuests": true, - "cancellationPolicy": "", - "emailTemplate": { - "bookingConfirmed": {} + "available_days_in_future": 7, + "min_cancellation_notice": 60, + "min_booking_notice": 120, + "confirmation_redirect_url": "", + "hide_rescheduling_options": false, + "hide_cancellation_options": false, + "hide_additional_guests": true, + "cancellation_policy": "", + "email_template": { + "booking_confirmed": {} } }, "appearance": { - "submitButtonLabel": "submit", - "thankYouMessage": "thank you for your business. your booking was successful." + "submit_button_label": "submit", + "thank_you_message": "thank you for your business. your booking was successful." } } """.trimIndent(), @@ -157,18 +157,28 @@ class ConfigurationsTest { assertEquals(false, config.scheduler?.hideCancellationOptions) assertEquals(true, config.scheduler?.hideAdditionalGuests) assertEquals("", config.scheduler?.cancellationPolicy) - assertEquals("submit", config.appearance?.get("submitButtonLabel")) - assertEquals("thank you for your business. your booking was successful.", config.appearance?.get("thankYouMessage")) - assertEquals(15, config.availability.durationMinutes) + assertEquals("submit", config.appearance?.get("submit_button_label")) + assertEquals(30, config.availability.durationMinutes) assertEquals(15, config.availability.intervalMinutes) assertEquals(15, config.availability.roundTo) assertEquals(AvailabilityMethod.COLLECTIVE, config.availability.availabilityRules?.availabilityMethod) assertEquals(60, config.availability.availabilityRules?.buffer?.before) assertEquals(0, config.availability.availabilityRules?.buffer?.after) assertEquals("", config.availability.availabilityRules?.roundRobinGroupId) - assertEquals(0, config.availability.availabilityRules?.defaultOpenHours?.first()?.days?.size) + assertEquals(5, config.availability.availabilityRules?.defaultOpenHours?.first()?.days?.size) assertEquals("09:00", config.availability.availabilityRules?.defaultOpenHours?.first()?.start) assertEquals("18:00", config.availability.availabilityRules?.defaultOpenHours?.first()?.end) + assertEquals("Updated Title", config.eventBooking.title) + assertEquals("utc", config.eventBooking.timezone) + assertEquals("", config.eventBooking.description) + assertEquals(null, config.eventBooking.location) + assertEquals(BookingType.BOOKING, config.eventBooking.bookingType) + assertEquals(null, config.eventBooking.hideParticipants) + assertEquals(null, config.eventBooking.disableEmails) + assertEquals(true, config.participants.first().isOrganizer) + assertEquals("test@nylas.com", config.participants.first().email) + assertEquals("Test", config.participants.first().name) + assertEquals("", config.participants.first().timezone) } } @@ -199,7 +209,7 @@ class ConfigurationsTest { overrideParamCaptor.capture(), ) - assertEquals("v3/grants/$grantId/configurations", pathCaptor.firstValue) + assertEquals("v3/grants/$grantId/scheduling/configurations", pathCaptor.firstValue) assertEquals(Types.newParameterizedType(ListResponse::class.java, Configuration::class.java), typeCaptor.firstValue) } @@ -238,12 +248,16 @@ class ConfigurationsTest { val pathCaptor = argumentCaptor() val typeCaptor = argumentCaptor() val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() verify(mockNylasClient).executePost>( pathCaptor.capture(), typeCaptor.capture(), requestBodyCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), ) - assertEquals("v3/grants/$grantId/configurations", pathCaptor.firstValue) + assertEquals("v3/grants/$grantId/scheduling/configurations", pathCaptor.firstValue) assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) assertEquals(adapter.toJson(createConfigurationRequest), requestBodyCaptor.firstValue) } @@ -253,19 +267,23 @@ class ConfigurationsTest { val adapter = JsonHelper.moshi().adapter(UpdateConfigurationRequest::class.java) val configId = "abc-123-configuration-id" val config = ConfigurationSchedulerSettings.Builder().minBookingNotice(120).build() - val updateConfigurationRequest = UpdateConfigurationRequest().Builder().scheduler(config).build() - + val updateConfigurationRequest = UpdateConfigurationRequest.Builder().scheduler(config).build() + configurations.update(grantId, configId, updateConfigurationRequest) val pathCaptor = argumentCaptor() val typeCaptor = argumentCaptor() val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() verify(mockNylasClient).executePut>( pathCaptor.capture(), typeCaptor.capture(), requestBodyCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), ) - assertEquals("v3/grants/$grantId/configurations/$configId", pathCaptor.firstValue) + assertEquals("v3/grants/$grantId/scheduling/configurations/$configId", pathCaptor.firstValue) assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) assertEquals(adapter.toJson(updateConfigurationRequest), requestBodyCaptor.firstValue) } @@ -277,13 +295,16 @@ class ConfigurationsTest { val pathCaptor = argumentCaptor() val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() verify(mockNylasClient).executeGet>( pathCaptor.capture(), typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), ) - assertEquals("v3/grants/$grantId/configurations/$configId", pathCaptor.firstValue) + assertEquals("v3/grants/$grantId/scheduling/configurations/$configId", pathCaptor.firstValue) assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) - } @Test @@ -292,13 +313,15 @@ class ConfigurationsTest { configurations.destroy(grantId, configId) val pathCaptor = argumentCaptor() val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() val overrideParamCaptor = argumentCaptor() verify(mockNylasClient).executeDelete( pathCaptor.capture(), typeCaptor.capture(), - overrideParamCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), ) - assertEquals("v3/grants/$grantId/configurations/$configId", pathCaptor.firstValue) + assertEquals("v3/grants/$grantId/scheduling/configurations/$configId", pathCaptor.firstValue) assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) } } From a3580f208ee954b6dc17cb608536e68305f7f186 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Fri, 8 Nov 2024 12:57:15 +0100 Subject: [PATCH 08/12] Add sessions resource --- .../com/nylas/models/CreateSessionRequest.kt | 64 +++++++++++++++++++ .../kotlin/com/nylas/resources/Scheduler.kt | 7 ++ .../kotlin/com/nylas/resources/Sessions.kt | 41 ++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 src/main/kotlin/com/nylas/models/CreateSessionRequest.kt create mode 100644 src/main/kotlin/com/nylas/resources/Sessions.kt diff --git a/src/main/kotlin/com/nylas/models/CreateSessionRequest.kt b/src/main/kotlin/com/nylas/models/CreateSessionRequest.kt new file mode 100644 index 00000000..b47a8b39 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateSessionRequest.kt @@ -0,0 +1,64 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a request to create a session. + */ +data class CreateSessionRequest( + /** + * The identifier of the Configuration to act upon. If you're using slug, configuration_id is not required. + */ + @Json(name = "configuration_id") + val configurationId: String? = null, + /** + * The time to live for the session. + */ + @Json(name = "time_to_live") + val timeToLive: Int? = null, + + /** + * The slug of the Scheduler Configuration object for the session. You can use slug instead of configuration_id + */ + @Json(name = "slug") + val slug: String? = null, +) { + /** + * A builder for creating a [CreateSessionRequest]. + * @param configurationId The identifier of the Configuration to act upon. + * @param timeToLive The time to live for the session. + * @param slug The slug of the Scheduler Configuration object for the session. + */ + class Builder { + private var configurationId: String? = null + private var timeToLive: Int? = null + private var slug: String? = null + + /** + * Set the configuration ID. + * @param configurationId The identifier of the Configuration to act upon. + * @return The builder. + */ + fun configurationId(configurationId: String) = apply { this.configurationId = configurationId } + + /** + * Set the time to live for the session. + * @param timeToLive The time to live for the session. + * @return The builder. + */ + fun timeToLive(timeToLive: Int) = apply { this.timeToLive = timeToLive } + + /** + * Set the slug of the Scheduler Configuration object for the session. + * @param slug The slug of the Scheduler Configuration object for the session. + * @return The builder. + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Build the [CreateSessionRequest]. + * @return The [CreateSessionRequest]. + */ + fun build() = CreateSessionRequest(configurationId, timeToLive, slug) + } +} diff --git a/src/main/kotlin/com/nylas/resources/Scheduler.kt b/src/main/kotlin/com/nylas/resources/Scheduler.kt index cf135045..83a03c12 100644 --- a/src/main/kotlin/com/nylas/resources/Scheduler.kt +++ b/src/main/kotlin/com/nylas/resources/Scheduler.kt @@ -17,4 +17,11 @@ class Scheduler(private val client: NylasClient) { * @return The Configurations API. */ fun configurations(): Configurations = Configurations(client) + + /** + * Access the Sessions API. + * + * @return The Sessions API. + */ + fun sessions(): Sessions = Sessions(client) } diff --git a/src/main/kotlin/com/nylas/resources/Sessions.kt b/src/main/kotlin/com/nylas/resources/Sessions.kt new file mode 100644 index 00000000..60b770af --- /dev/null +++ b/src/main/kotlin/com/nylas/resources/Sessions.kt @@ -0,0 +1,41 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.models.* +import com.nylas.util.JsonHelper +/** + * Nylas Sessions API + * + * The Nylas Sessions API allows you to create and delete sessions on user Schedulerconfigurations. + * + * @param client The configured Nylas API client + */ +class Sessions(client: NylasClient) : Resource(client, Session::class.java) { + /** + * Create a Session + * @param requestBody The values to create the session with + * @param overrides Optional request overrides to apply + * @return The created session + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun create(requestBody: CreateSessionRequest, overrides: RequestOverrides? = null): Response { + val path = "v3/scheduling/sessions" + val adapter = JsonHelper.moshi().adapter(CreateSessionRequest::class.java) + val serializedRequestBody = adapter.toJson(requestBody) + return createResource(path, serializedRequestBody, overrides = overrides) + } + + /** + * Delete a Session + * @param sessionId The ID of the session to delete + * @param overrides Optional request overrides to apply + * @return The deleted response + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun destroy(sessionId: String, overrides: RequestOverrides? = null): DeleteResponse { + val path = "v3/scheduling/sessions/$sessionId" + return destroyResource(path, overrides = overrides) + } +} From 48079f22ee988c66fccb0bc31ea305b09f8adc27 Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Fri, 8 Nov 2024 14:29:05 +0100 Subject: [PATCH 09/12] Add tests for sessions --- .../kotlin/com/nylas/resources/Sessions.kt | 2 +- .../com/nylas/resources/SessionsTest.kt | 103 ++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/test/kotlin/com/nylas/resources/SessionsTest.kt diff --git a/src/main/kotlin/com/nylas/resources/Sessions.kt b/src/main/kotlin/com/nylas/resources/Sessions.kt index 60b770af..2deea690 100644 --- a/src/main/kotlin/com/nylas/resources/Sessions.kt +++ b/src/main/kotlin/com/nylas/resources/Sessions.kt @@ -35,7 +35,7 @@ class Sessions(client: NylasClient) : Resource(client, Session::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(sessionId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = "v3/scheduling/sessions/$sessionId" + val path = String.format("v3/scheduling/sessions/%s", sessionId) return destroyResource(path, overrides = overrides) } } diff --git a/src/test/kotlin/com/nylas/resources/SessionsTest.kt b/src/test/kotlin/com/nylas/resources/SessionsTest.kt new file mode 100644 index 00000000..f4e7795c --- /dev/null +++ b/src/test/kotlin/com/nylas/resources/SessionsTest.kt @@ -0,0 +1,103 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.models.* +import com.nylas.models.Response +import com.nylas.util.JsonHelper +import com.squareup.moshi.Types +import okhttp3.* +import okio.Buffer +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.* +import java.lang.reflect.Type +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertIs + +class SessionsTest { + private val mockHttpClient: OkHttpClient = Mockito.mock(OkHttpClient::class.java) + private val mockCall: Call = Mockito.mock(Call::class.java) + private val mockResponse: okhttp3.Response = Mockito.mock(okhttp3.Response::class.java) + private val mockResponseBody: ResponseBody = Mockito.mock(ResponseBody::class.java) + private val mockOkHttpClientBuilder: OkHttpClient.Builder = Mockito.mock() + + @BeforeEach + fun setup() { + MockitoAnnotations.openMocks(this) + whenever(mockOkHttpClientBuilder.addInterceptor(any())).thenReturn(mockOkHttpClientBuilder) + whenever(mockOkHttpClientBuilder.build()).thenReturn(mockHttpClient) + whenever(mockHttpClient.newCall(any())).thenReturn(mockCall) + whenever(mockCall.execute()).thenReturn(mockResponse) + whenever(mockResponse.isSuccessful).thenReturn(true) + whenever(mockResponse.body()).thenReturn(mockResponseBody) + } + + @Nested + inner class SerializationTests { + @Test + fun `Session serializes properly`() { + val adapter = JsonHelper.moshi().adapter(Session::class.java) + val jsonBuffer = Buffer().writeUtf8( + """ + { + "session_id": "session-id" + } + """.trimIndent(), + ) + val session = adapter.fromJson(jsonBuffer)!! + assertIs(session) + assertEquals("session-id", session.sessionId) + } + } + + @Nested + inner class CrudTests { + private lateinit var mockNylasClient: NylasClient + private lateinit var sessions: Sessions + + @BeforeEach + fun setup() { + mockNylasClient = Mockito.mock(NylasClient::class.java) + sessions = Sessions(mockNylasClient) + } + + @Test + fun `creating a session calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(CreateSessionRequest::class.java) + val createSessionRequest = CreateSessionRequest.Builder() + .configurationId("config-id") + .timeToLive(30) + .build() + + sessions.create(createSessionRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executePost(pathCaptor.capture(), typeCaptor.capture(), requestBodyCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + + assertEquals("v3/scheduling/sessions", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Session::class.java), typeCaptor.firstValue) + assertEquals(adapter.toJson(createSessionRequest), requestBodyCaptor.firstValue) + } + + @Test + fun `deleting a session calls requests with the correct params`() { + val sessionId = "session-id" + sessions.destroy(sessionId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete(pathCaptor.capture(), typeCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + assertEquals("v3/scheduling/sessions/$sessionId", pathCaptor.firstValue) + assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) + } + } +} From b3a2780aec173735760cea71029514658e1af59e Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Fri, 8 Nov 2024 16:44:16 +0100 Subject: [PATCH 10/12] Add Booking resources and models --- .../com/nylas/models/BookingOrganizer.kt | 19 +++ .../com/nylas/models/BookingReminder.kt | 29 ++++ .../nylas/models/ConfirmBookingQueryParams.kt | 60 +++++++ .../com/nylas/models/ConfirmBookingRequest.kt | 57 +++++++ .../com/nylas/models/CreateBookingGuest.kt | 41 +++++ .../nylas/models/CreateBookingOrganizer.kt | 41 +++++ .../nylas/models/CreateBookingQueryParams.kt | 60 +++++++ .../com/nylas/models/CreateBookingReminder.kt | 60 +++++++ .../com/nylas/models/CreateBookingRequest.kt | 54 +++++++ .../nylas/models/DestroyBookingQueryParams.kt | 60 +++++++ .../com/nylas/models/DestroyBookingRequest.kt | 27 ++++ .../nylas/models/FindBookingQueryParams.kt | 63 ++++++++ .../models/RescheduleBookingQueryParams.kt | 55 +++++++ .../nylas/models/RescheduleBookingRequest.kt | 44 +++++ src/main/kotlin/com/nylas/models/Scheduler.kt | 152 ------------------ .../kotlin/com/nylas/resources/Bookings.kt | 107 ++++++++++++ .../kotlin/com/nylas/resources/Scheduler.kt | 7 + 17 files changed, 784 insertions(+), 152 deletions(-) create mode 100644 src/main/kotlin/com/nylas/models/BookingOrganizer.kt create mode 100644 src/main/kotlin/com/nylas/models/BookingReminder.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfirmBookingQueryParams.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt create mode 100644 src/main/kotlin/com/nylas/models/CreateBookingGuest.kt create mode 100644 src/main/kotlin/com/nylas/models/CreateBookingOrganizer.kt create mode 100644 src/main/kotlin/com/nylas/models/CreateBookingQueryParams.kt create mode 100644 src/main/kotlin/com/nylas/models/CreateBookingReminder.kt create mode 100644 src/main/kotlin/com/nylas/models/CreateBookingRequest.kt create mode 100644 src/main/kotlin/com/nylas/models/DestroyBookingQueryParams.kt create mode 100644 src/main/kotlin/com/nylas/models/DestroyBookingRequest.kt create mode 100644 src/main/kotlin/com/nylas/models/FindBookingQueryParams.kt create mode 100644 src/main/kotlin/com/nylas/models/RescheduleBookingQueryParams.kt create mode 100644 src/main/kotlin/com/nylas/models/RescheduleBookingRequest.kt create mode 100644 src/main/kotlin/com/nylas/resources/Bookings.kt diff --git a/src/main/kotlin/com/nylas/models/BookingOrganizer.kt b/src/main/kotlin/com/nylas/models/BookingOrganizer.kt new file mode 100644 index 00000000..4568aff5 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/BookingOrganizer.kt @@ -0,0 +1,19 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a booking organizer. + */ +data class BookingOrganizer( + /** + * The email address of the participant designated as the organizer of the event. + */ + @Json(name = "email") + val email: String, + /** + * The name of the participant designated as the organizer of the event. + */ + @Json(name = "name") + val name: String? = null, +) diff --git a/src/main/kotlin/com/nylas/models/BookingReminder.kt b/src/main/kotlin/com/nylas/models/BookingReminder.kt new file mode 100644 index 00000000..842a16d4 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/BookingReminder.kt @@ -0,0 +1,29 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a booking reminder. + */ +data class BookingReminder( + /** + * The reminder type. + */ + @Json(name = "type") + val type: String, + /** + * The number of minutes before the event to send the reminder. + */ + @Json(name = "minutes_before_event") + val minutesBeforeEvent: Int, + /** + * The recipient of the reminder. + */ + @Json(name = "recipient") + val recipient: String? = null, + /** + * The subject of the email reminder. + */ + @Json(name = "email_subject") + val emailSubject: String? = null, +) diff --git a/src/main/kotlin/com/nylas/models/ConfirmBookingQueryParams.kt b/src/main/kotlin/com/nylas/models/ConfirmBookingQueryParams.kt new file mode 100644 index 00000000..9f7f754d --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfirmBookingQueryParams.kt @@ -0,0 +1,60 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of the query parameters for confirming a booking. + */ +data class ConfirmBookingQueryParams( + /** + * The ID of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "configuration_id") + val configurationId: String? = null, + /** + * The slug of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * The client ID that was used to create the Configuration object. + */ + @Json(name = "client_id") + val clientId: String? = null, +) : IQueryParams { + /** + * Builder for [ConfirmBookingQueryParams]. + */ + class Builder { + private var configurationId: String? = null + private var slug: String? = null + private var clientId: String? = null + + /** + * Set the configuration ID of the booking. + * @param configurationId The configuration ID of the booking. + * @return The builder. + */ + fun configurationId(configurationId: String) = apply { this.configurationId = configurationId } + + /** + * Set the slug of the booking. + * @param slug The slug of the booking. + * @return The builder. + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Set the client ID of the booking. + * @param clientId The client ID of the booking. + * @return The builder. + */ + fun clientId(clientId: String) = apply { this.clientId = clientId } + + /** + * Builds a [ConfirmBookingQueryParams] instance. + * @return The [ConfirmBookingQueryParams] instance. + */ + fun build() = ConfirmBookingQueryParams(configurationId, slug, clientId) + } +} diff --git a/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt b/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt new file mode 100644 index 00000000..32ded24e --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt @@ -0,0 +1,57 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of the request body for confirming a booking. + */ +data class ConfirmBookingRequest( + @Json(name = "status") + val status: String? = null, + /** + * The salt extracted from the booking reference embedded in the organizer confirmation link. + */ + @Json(name = "salt") + val salt: String? = null, + /** + * The reason the booking is being cancelled. + */ + @Json(name = "cancellation_reason") + val cancellationReason: String? = null, +) { + /** + * Builder for [ConfirmBookingRequest]. + */ + class Builder { + private var status: String? = null + private var salt: String? = null + private var cancellationReason: String? = null + + /** + * Set the status of the booking. + * @param status The status of the booking. + * @return The builder. + */ + fun status(status: String) = apply { this.status = status } + + /** + * Set the salt of the booking. + * @param salt The salt of the booking. + * @return The builder. + */ + fun salt(salt: String) = apply { this.salt = salt } + + /** + * Set the cancellation reason of the booking. + * @param cancellationReason The cancellation reason of the booking. + * @return The builder. + */ + fun cancellationReason(cancellationReason: String) = apply { this.cancellationReason = cancellationReason } + + /** + * Builds a [ConfirmBookingRequest] instance. + * @return The [ConfirmBookingRequest] instance. + */ + fun build() = ConfirmBookingRequest(status, salt, cancellationReason) + } +} diff --git a/src/main/kotlin/com/nylas/models/CreateBookingGuest.kt b/src/main/kotlin/com/nylas/models/CreateBookingGuest.kt new file mode 100644 index 00000000..69deedc5 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateBookingGuest.kt @@ -0,0 +1,41 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a request to create a booking guest. + */ +data class CreateBookingGuest( + /** + * The email address of the guest. + */ + @Json(name = "email") + val email: String, + /** + * The name of the guest. + */ + @Json(name = "name") + val name: String? = null, +) { + /** + * Builder for [CreateBookingGuest]. + */ + data class Builder( + private val email: String, + ) { + private var name: String? = null + + /** + * Set the name of the guest. + * @param name The name of the guest. + * @return The builder. + */ + fun name(name: String) = apply { this.name = name } + + /** + * Builds a [CreateBookingGuest] instance. + * @return The [CreateBookingGuest] instance. + */ + fun build() = CreateBookingGuest(email, name) + } +} diff --git a/src/main/kotlin/com/nylas/models/CreateBookingOrganizer.kt b/src/main/kotlin/com/nylas/models/CreateBookingOrganizer.kt new file mode 100644 index 00000000..ddf441e6 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateBookingOrganizer.kt @@ -0,0 +1,41 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representing a request to create a booking organizer. + */ +data class CreateBookingOrganizer( + /** + * The email address of the participant designated as the organizer of the event. + */ + @Json(name = "email") + val email: String, + /** + * The name of the participant designated as the organizer of the event. + */ + @Json(name = "name") + val name: String? = null, +) { + /** + * Builder for [CreateBookingOrganizer]. + */ + data class Builder( + private val email: String, + ) { + private var name: String? = null + + /** + * Set the name of the participant designated as the organizer of the event. + * @param name The name of the participant designated as the organizer of the event. + * @return The builder. + */ + fun name(name: String) = apply { this.name = name } + + /** + * Builds a [CreateBookingOrganizer] instance. + * @return The [CreateBookingOrganizer] instance. + */ + fun build() = CreateBookingOrganizer(email, name) + } +} diff --git a/src/main/kotlin/com/nylas/models/CreateBookingQueryParams.kt b/src/main/kotlin/com/nylas/models/CreateBookingQueryParams.kt new file mode 100644 index 00000000..59a9eb06 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateBookingQueryParams.kt @@ -0,0 +1,60 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of the query parameters for creating a booking. + */ +data class CreateBookingQueryParams( + /** + * The ID of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "configuration_id") + val configurationId: String? = null, + /** + * The slug of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * The client ID that was used to create the Configuration object. + */ + @Json(name = "client_id") + val clientId: String? = null, +) : IQueryParams { + /** + * Builder for [CreateBookingQueryParams]. + */ + class Builder { + private var configurationId: String? = null + private var slug: String? = null + private var clientId: String? = null + + /** + * Sets the ID of the Configuration object whose settings are used for calculating availability. + * @param configurationId The ID of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun configurationId(configurationId: String) = apply { this.configurationId = configurationId } + + /** + * Sets the slug of the Configuration object whose settings are used for calculating availability. + * @param slug The slug of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Sets the client ID that was used to create the Configuration object. + * @param clientId The client ID that was used to create the Configuration object. + * @return The builder. + */ + fun clientId(clientId: String) = apply { this.clientId = clientId } + + /** + * Builds a [CreateBookingQueryParams] instance. + * @return The [CreateBookingQueryParams] instance. + */ + fun build() = CreateBookingQueryParams(configurationId, slug, clientId) + } +} diff --git a/src/main/kotlin/com/nylas/models/CreateBookingReminder.kt b/src/main/kotlin/com/nylas/models/CreateBookingReminder.kt new file mode 100644 index 00000000..40f2d3a9 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateBookingReminder.kt @@ -0,0 +1,60 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a request to create a booking reminder. + */ +data class CreateBookingReminder( + /** + * The reminder type. + */ + @Json(name = "type") + val type: String, + /** + * The number of minutes before the event to send the reminder. + */ + @Json(name = "minutes_before_event") + val minutesBeforeEvent: Int, + /** + * The recipient of the reminder. + */ + @Json(name = "recipient") + val recipient: String? = null, + /** + * The subject of the email reminder. + */ + @Json(name = "email_subject") + val emailSubject: String? = null, +) { + /** + * Builder for [CreateBookingReminder]. + */ + data class Builder( + private val type: String, + private val minutesBeforeEvent: Int, + ) { + private var recipient: String? = null + private var emailSubject: String? = null + + /** + * Set the recipient of the reminder. + * @param recipient The recipient of the reminder. + * @return The builder. + */ + fun recipient(recipient: String) = apply { this.recipient = recipient } + + /** + * Set the subject of the email reminder. + * @param emailSubject The subject of the email reminder. + * @return The builder. + */ + fun emailSubject(emailSubject: String) = apply { this.emailSubject = emailSubject } + + /** + * Builds a [CreateBookingReminder] instance. + * @return The [CreateBookingReminder] instance. + */ + fun build() = CreateBookingReminder(type, minutesBeforeEvent, recipient, emailSubject) + } +} diff --git a/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt b/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt new file mode 100644 index 00000000..9524f437 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt @@ -0,0 +1,54 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a confirm booking request. + */ +data class CreateBookingRequest( + /** + * The salt extracted from the booking reference embedded in the organizer confirmation link. + */ + @Json(name = "salt") + val salt: String, + /** + * The action to take on the pending booking. + */ + @Json(name = "status") + val status: ConfirmBookingStatus? = null, + /** + * The reason the booking is being cancelled. + */ + @Json(name = "cancellation_reason") + val cancellationReason: String? = null, +) { + /** + * Builder for [CreateBookingRequest]. + */ + data class Builder( + private val salt: String, + ) { + private var status: ConfirmBookingStatus? = null + private var cancellationReason: String? = null + + /** + * Sets the status of the booking. + * @param status The status of the booking. + * @return The builder. + */ + fun status(status: ConfirmBookingStatus) = apply { this.status = status } + + /** + * Sets the cancellation reason of the booking. + * @param cancellationReason The cancellation reason of the booking. + * @return The builder. + */ + fun cancellationReason(cancellationReason: String) = apply { this.cancellationReason = cancellationReason } + + /** + * Builds a [CreateBookingRequest] instance. + * @return The [CreateBookingRequest] instance. + */ + fun build() = CreateBookingRequest(salt, status, cancellationReason) + } +} diff --git a/src/main/kotlin/com/nylas/models/DestroyBookingQueryParams.kt b/src/main/kotlin/com/nylas/models/DestroyBookingQueryParams.kt new file mode 100644 index 00000000..34b31e71 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/DestroyBookingQueryParams.kt @@ -0,0 +1,60 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of the query parameters for destroying a booking. + */ +data class DestroyBookingQueryParams( + /** + * The ID of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "configuration_id") + val configurationId: String? = null, + /** + * The slug of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "slug") + val slug: String? = null, + /** + * The client ID that was used to create the Configuration object. + */ + @Json(name = "client_id") + val clientId: String? = null, +) : IQueryParams { + /** + * Builder for [DestroyBookingQueryParams]. + */ + class Builder { + private var configurationId: String? = null + private var slug: String? = null + private var clientId: String? = null + + /** + * Sets the ID of the Configuration object whose settings are used for calculating availability. + * @param configurationId The ID of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun configurationId(configurationId: String) = apply { this.configurationId = configurationId } + + /** + * Sets the slug of the Configuration object whose settings are used for calculating availability. + * @param slug The slug of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Sets the client ID that was used to create the Configuration object. + * @param clientId The client ID that was used to create the Configuration object. + * @return The builder. + */ + fun clientId(clientId: String) = apply { this.clientId = clientId } + + /** + * Builds a [DestroyBookingQueryParams] instance. + * @return The [DestroyBookingQueryParams] instance. + */ + fun build() = DestroyBookingQueryParams(configurationId, slug, clientId) + } +} diff --git a/src/main/kotlin/com/nylas/models/DestroyBookingRequest.kt b/src/main/kotlin/com/nylas/models/DestroyBookingRequest.kt new file mode 100644 index 00000000..51d86cac --- /dev/null +++ b/src/main/kotlin/com/nylas/models/DestroyBookingRequest.kt @@ -0,0 +1,27 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a request to destroy a booking. + */ +data class DestroyBookingRequest( + /** + * The reason for the cancellation of the booking. + */ + @Json(name = "cancellation_reason") + val cancellationReason: String, +) { + /** + * Builder for [DestroyBookingRequest]. + */ + data class Builder( + private val cancellationReason: String, + ) { + /** + * Builds a [DestroyBookingRequest] instance. + * @return The [DestroyBookingRequest] instance. + */ + fun build() = DestroyBookingRequest(cancellationReason) + } +} diff --git a/src/main/kotlin/com/nylas/models/FindBookingQueryParams.kt b/src/main/kotlin/com/nylas/models/FindBookingQueryParams.kt new file mode 100644 index 00000000..cf728812 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/FindBookingQueryParams.kt @@ -0,0 +1,63 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of the query parameters for finding a booking. + */ +data class FindBookingQueryParams( + /** + * The ID of the Configuration object whose settings are used for calculating availability. + * If you're using session authentication (requires_session_auth is set to true), configuration_id is not required + */ + @Json(name = "configuration_id") + val configurationId: String? = null, + /** + * The slug of the Configuration object whose settings are used for calculating availability. + * If you're using session authentication (requires_session_auth is set to true), or using configuration_id, slug is not required + */ + @Json(name = "slug") + val slug: String? = null, + /** + * The client ID that was used to create the Configuration object. + * client_id is required only if using slug. + */ + @Json(name = "client_id") + val clientId: String? = null, +) : IQueryParams { + /** + * Builder for [FindBookingQueryParams]. + */ + class Builder { + private var configurationId: String? = null + private var slug: String? = null + private var clientId: String? = null + + /** + * Sets the ID of the Configuration object whose settings are used for calculating availability. + * @param configurationId The ID of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun configurationId(configurationId: String) = apply { this.configurationId = configurationId } + + /** + * Sets the slug of the Configuration object whose settings are used for calculating availability. + * @param slug The slug of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Sets the client ID that was used to create the Configuration object. + * @param clientId The client ID that was used to create the Configuration object. + * @return The builder. + */ + fun clientId(clientId: String) = apply { this.clientId = clientId } + + /** + * Builds a [FindBookingQueryParams] instance. + * @return The [FindBookingQueryParams] instance. + */ + fun build() = FindBookingQueryParams(configurationId, slug, clientId) + } +} diff --git a/src/main/kotlin/com/nylas/models/RescheduleBookingQueryParams.kt b/src/main/kotlin/com/nylas/models/RescheduleBookingQueryParams.kt new file mode 100644 index 00000000..74228046 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/RescheduleBookingQueryParams.kt @@ -0,0 +1,55 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of the query parameters for rescheduling a booking. + */ +data class RescheduleBookingQueryParams( + /** + * The ID of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "configuration_id") + val configurationId: String, + /** + * The slug of the Configuration object whose settings are used for calculating availability. + */ + @Json(name = "slug") + val slug: String, + /** + * The client ID that was used to create the Configuration object. + */ + @Json(name = "client_id") + val clientId: String, +) : IQueryParams { + /** + * Builder for [RescheduleBookingQueryParams]. + */ + class Builder { + private var configurationId: String? = null + private var slug: String? = null + private var clientId: String? = null + + /** + * Sets the ID of the Configuration object whose settings are used for calculating availability. + * @param configurationId The ID of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun configurationId(configurationId: String) = apply { this.configurationId = configurationId } + + /** + * Sets the slug of the Configuration object whose settings are used for calculating availability. + * @param slug The slug of the Configuration object whose settings are used for calculating availability. + * @return The builder. + */ + fun slug(slug: String) = apply { this.slug = slug } + + /** + * Sets the client ID that was used to create the Configuration object. + * @param clientId The client ID that was used to create the Configuration object. + * @return The builder. + */ + fun clientId(clientId: String) = apply { this.clientId = clientId } + } + fun build() = RescheduleBookingQueryParams(configurationId, slug, clientId) +} diff --git a/src/main/kotlin/com/nylas/models/RescheduleBookingRequest.kt b/src/main/kotlin/com/nylas/models/RescheduleBookingRequest.kt new file mode 100644 index 00000000..d0bfdd62 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/RescheduleBookingRequest.kt @@ -0,0 +1,44 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +data class RescheduleBookingRequest( + /** + * The event's start time, in Unix epoch format. + */ + @Json(name = "start_time") + val startTime: Int? = null, + /** + * The event's end time, in Unix epoch format. + */ + @Json(name = "end_time") + val endTime: Int? = null, +) { + /** + * Builder for [RescheduleBookingRequest]. + */ + class Builder { + private var startTime: Int? = null + private var endTime: Int? = null + + /** + * Set the start time of the booking. + * @param startTime The start time of the booking. + * @return The builder. + */ + fun startTime(startTime: Int) = apply { this.startTime = startTime } + + /** + * Set the end time of the booking. + * @param endTime The end time of the booking. + * @return The builder. + */ + fun endTime(endTime: Int) = apply { this.endTime = endTime } + + /** + * Builds a [RescheduleBookingRequest] instance. + * @return The [RescheduleBookingRequest] instance. + */ + fun build() = RescheduleBookingRequest(startTime, endTime) + } +} diff --git a/src/main/kotlin/com/nylas/models/Scheduler.kt b/src/main/kotlin/com/nylas/models/Scheduler.kt index bd5be584..6b9a291c 100644 --- a/src/main/kotlin/com/nylas/models/Scheduler.kt +++ b/src/main/kotlin/com/nylas/models/Scheduler.kt @@ -114,32 +114,6 @@ data class BookingConfirmedTemplate( val body: String? = null, ) -/** - * Class representation of a booking reminder. - */ -data class BookingReminder( - /** - * The reminder type. - */ - @Json(name = "type") - val type: String, - /** - * The number of minutes before the event to send the reminder. - */ - @Json(name = "minutes_before_event") - val minutesBeforeEvent: Int, - /** - * The recipient of the reminder. - */ - @Json(name = "recipient") - val recipient: String? = null, - /** - * The subject of the email reminder. - */ - @Json(name = "email_subject") - val emailSubject: String? = null, -) - /** * Class representation of a session. */ @@ -151,84 +125,6 @@ data class Session( val sessionId: String, ) -/** - * Class representation of a booking guest. - */ -data class BookingGuest( - /** - * The email address of the guest. - */ - @Json(name = "email") - val email: String, - /** - * The name of the guest. - */ - @Json(name = "name") - val name: String, -) - -/** - * Class representation of a create booking request. - */ -data class CreateBookingRequest( - /** - * The event's start time, in Unix epoch format. - */ - @Json(name = "start_time") - val startTime: Long, - /** - * The event's end time, in Unix epoch format. - */ - @Json(name = "end_time") - val endTime: Long, - /** - * Details about the guest that is creating the booking. - */ - @Json(name = "guest") - val guest: BookingGuest, - /** - * List of participant email addresses from the Configuration object to include in the booking. - */ - @Json(name = "participants") - val participants: List? = null, - /** - * The guest's timezone that is used in email notifications. - */ - @Json(name = "timezone") - val timezone: String? = null, - /** - * The language of the guest email notifications. - */ - @Json(name = "email_language") - val emailLanguage: EmailLanguage? = null, - /** - * List of additional guest email addresses to include in the booking. - */ - @Json(name = "additional_guests") - val additionalGuests: List? = null, - /** - * Dictionary of additional field keys mapped to values populated by the guest in the booking form. - */ - @Json(name = "additional_fields") - val additionalFields: Map? = null, -) - -/** - * Class representation of a booking organizer. - */ -data class BookingOrganizer( - /** - * The email address of the participant designated as the organizer of the event. - */ - @Json(name = "email") - val email: String, - /** - * The name of the participant designated as the organizer of the event. - */ - @Json(name = "name") - val name: String? = null, -) - /** * Class representation of a booking. */ @@ -265,54 +161,6 @@ data class Booking( val description: String? = null, ) -/** - * Class representation of a confirm booking request. - */ -data class ConfirmBookingRequest( - /** - * The salt extracted from the booking reference embedded in the organizer confirmation link. - */ - @Json(name = "salt") - val salt: String, - /** - * The action to take on the pending booking. - */ - @Json(name = "status") - val status: ConfirmBookingStatus, - /** - * The reason the booking is being cancelled. - */ - @Json(name = "cancellation_reason") - val cancellationReason: String? = null, -) - -/** - * Class representation of a delete booking request. - */ -data class DeleteBookingRequest( - /** - * The reason the booking is being cancelled. - */ - @Json(name = "cancellation_reason") - val cancellationReason: String? = null, -) - -/** - * Class representation of a reschedule booking request. - */ -data class RescheduleBookingRequest( - /** - * The event's start time, in Unix epoch format. - */ - @Json(name = "start_time") - val startTime: Long, - /** - * The event's end time, in Unix epoch format. - */ - @Json(name = "end_time") - val endTime: Long, -) - /** * Enum for additional field types. */ diff --git a/src/main/kotlin/com/nylas/resources/Bookings.kt b/src/main/kotlin/com/nylas/resources/Bookings.kt new file mode 100644 index 00000000..bdebdd7f --- /dev/null +++ b/src/main/kotlin/com/nylas/resources/Bookings.kt @@ -0,0 +1,107 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.models.* +import com.nylas.util.JsonHelper + +/** + * Nylas Bookings API + * + * The Nylas Bookings API allows you to create new bookings or manage existing ones, as well as getting + * bookings details for a user. + */ +class Bookings(client: NylasClient) : Resource(client, Booking::class.java) { + /** + * Find a booking + * @param bookingId The ID of the booking to find. + * @param queryParams Optional query parameters to apply + * @param overrides Optional request overrides to apply + * @return The Booking object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun find( + bookingId: String, + queryParams: FindBookingQueryParams? = null, + overrides: RequestOverrides? = null, + ): Response { + val path = String.format("v3/scheduling/bookings/%s", bookingId) + return findResource(path, queryParams, overrides = overrides) + } + + /** + * Create a booking + * @param requestBody The data to create the booking with. + * @param queryParams Optional query parameters to apply + * @param overrides Optional request overrides to apply + * @return The Booking object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun create( + requestBody: CreateBookingRequest, + queryParams: CreateBookingQueryParams? = null, + overrides: RequestOverrides? = null, + ): Response { + val path = "v3/scheduling/bookings" + val adapter = JsonHelper.moshi().adapter(CreateBookingRequest::class.java) + val serializedRequestBody = adapter.toJson(requestBody) + return createResource(path, serializedRequestBody, queryParams, overrides = overrides) + } + + /** + * Confirm a booking + * @param bookingId The ID of the booking to update. + * @param requestBody The data to update the booking with. + * @param queryParams Optional query parameters to apply + * @param overrides Optional request overrides to apply + * @return The Booking object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun confirm( + bookingId: String, + requestBody: ConfirmBookingRequest, + queryParams: ConfirmBookingQueryParams? = null, + overrides: RequestOverrides? = null, + ): Response { + val path = String.format("v3/scheduling/bookings/%s", bookingId) + val adapter = JsonHelper.moshi().adapter(ConfirmBookingRequest::class.java) + val serializedRequestBody = adapter.toJson(requestBody) + return updateResource(path, serializedRequestBody, queryParams, overrides = overrides) + } + + /** + * Reschedule a booking + * @param bookingId The ID of the booking to update. + * @param requestBody The data to update the booking with. + * @param queryParams Optional query parameters to apply + * @param overrides Optional request overrides to apply + * @return The Booking object + */ + @Throws(NylasApiError::class, NylasSdkTimeoutError::class) + @JvmOverloads + fun reschedule( + bookingId: String, + requestBody: RescheduleBookingRequest, + queryParams: RescheduleBookingQueryParams? = null, + overrides: RequestOverrides? = null, + ): Response { + val path = String.format("v3/scheduling/bookings/%s", bookingId) + val adapter = JsonHelper.moshi().adapter(RescheduleBookingRequest::class.java) + val serializedRequestBody = adapter.toJson(requestBody) + return patchResource(path, serializedRequestBody, queryParams, overrides = overrides) + } + + /** + * Destroy a booking + * @param bookingId The ID of the booking to destroy. + * @param queryParams Optional query parameters to apply + * @param overrides Optional request overrides to apply + * @return The DeleteResponse object + */ + fun destroy(bookingId: String, queryParams: DestroyBookingQueryParams? = null, overrides: RequestOverrides? = null): DeleteResponse { + val path = String.format("v3/scheduling/bookings/%s", bookingId) + return destroyResource(path, queryParams, overrides = overrides) + } +} diff --git a/src/main/kotlin/com/nylas/resources/Scheduler.kt b/src/main/kotlin/com/nylas/resources/Scheduler.kt index 83a03c12..4388878f 100644 --- a/src/main/kotlin/com/nylas/resources/Scheduler.kt +++ b/src/main/kotlin/com/nylas/resources/Scheduler.kt @@ -24,4 +24,11 @@ class Scheduler(private val client: NylasClient) { * @return The Sessions API. */ fun sessions(): Sessions = Sessions(client) + + /** + * Access the Bookings API. + * + * @return The Bookings API. + */ + fun bookings(): Bookings = Bookings(client) } From 339fd313657f6ab05874d426a93ac4c543cc90ff Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Tue, 12 Nov 2024 10:20:11 +0100 Subject: [PATCH 11/12] Refactor Scheduler model --- .../kotlin/com/nylas/models/BookingGuest.kt | 19 ++ .../kotlin/com/nylas/models/BookingStatus.kt | 17 ++ .../kotlin/com/nylas/models/BookingType.kt | 14 ++ .../models/ConfigurationSchedulerSettings.kt | 118 +++++++++++ .../com/nylas/models/ConfirmBookingStatus.kt | 14 ++ .../com/nylas/models/CreateBookingRequest.kt | 115 +++++++++-- .../kotlin/com/nylas/models/EmailLanguage.kt | 32 +++ src/main/kotlin/com/nylas/models/Scheduler.kt | 183 +----------------- 8 files changed, 312 insertions(+), 200 deletions(-) create mode 100644 src/main/kotlin/com/nylas/models/BookingGuest.kt create mode 100644 src/main/kotlin/com/nylas/models/BookingStatus.kt create mode 100644 src/main/kotlin/com/nylas/models/BookingType.kt create mode 100644 src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt create mode 100644 src/main/kotlin/com/nylas/models/EmailLanguage.kt diff --git a/src/main/kotlin/com/nylas/models/BookingGuest.kt b/src/main/kotlin/com/nylas/models/BookingGuest.kt new file mode 100644 index 00000000..5502a298 --- /dev/null +++ b/src/main/kotlin/com/nylas/models/BookingGuest.kt @@ -0,0 +1,19 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Class representation of a booking guest. + */ +data class BookingGuest( + /** + * The email address of the guest. + */ + @Json(name = "email") + val email: String, + /** + * The name of the guest. + */ + @Json(name = "name") + val name: String? = null, +) diff --git a/src/main/kotlin/com/nylas/models/BookingStatus.kt b/src/main/kotlin/com/nylas/models/BookingStatus.kt new file mode 100644 index 00000000..ad271ebf --- /dev/null +++ b/src/main/kotlin/com/nylas/models/BookingStatus.kt @@ -0,0 +1,17 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Enum for booking statuses. + */ +enum class BookingStatus { + @Json(name = "pending") + PENDING, + + @Json(name = "confirmed") + CONFIRMED, + + @Json(name = "cancelled") + CANCELLED, +} diff --git a/src/main/kotlin/com/nylas/models/BookingType.kt b/src/main/kotlin/com/nylas/models/BookingType.kt new file mode 100644 index 00000000..4a40ef4f --- /dev/null +++ b/src/main/kotlin/com/nylas/models/BookingType.kt @@ -0,0 +1,14 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Enum for booking types. + */ +enum class BookingType { + @Json(name = "booking") + BOOKING, + + @Json(name = "organizer-confirmation") + ORGANIZER_CONFIRMATION, +} diff --git a/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt b/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt index 592f5434..c67bb771 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt @@ -213,3 +213,121 @@ data class ConfigurationSchedulerSettings( ) } } + +/** + * Class representation of an additional field. + */ +data class AdditionalField( + /** + * The text label to be displayed in the Scheduler UI. + */ + @Json(name = "label") + val label: String, + /** + * The field type. + * Supported values are text, multi_line_text, email, phone_number, dropdown, date, checkbox, and radio_button. + */ + @Json(name = "type") + val type: AdditionalFieldType, + /** + * Whether the field is required to be filled out by the guest when booking an event. + */ + @Json(name = "required") + val required: Boolean, + /** + * A regular expression pattern that the value of the field must match. + */ + @Json(name = "pattern") + val pattern: String? = null, + /** + * The order in which the field will be displayed in the Scheduler UI. + * Fields with lower order values will be displayed first. + */ + @Json(name = "order") + val order: Int? = null, + /** + * A list of options for the dropdown or radio_button types. + * This field is required for the dropdown and radio_button types. + */ + @Json(name = "options") + val options: AdditonalFieldOptionsType? = null, +) + +/** + * Class representation of an email template. + */ +data class EmailTemplate( + /** + * Configurable settings specifically for booking confirmed emails. + */ + @Json(name = "booking_confirmed") + val bookingConfirmed: BookingConfirmedTemplate? = null, +) + +/** + * Class representation of booking confirmed template settings. + */ +data class BookingConfirmedTemplate( + /** + * The title to replace the default 'Booking Confirmed' title. + */ + @Json(name = "title") + val title: String? = null, + /** + * The additional body to be appended after the default body. + */ + @Json(name = "body") + val body: String? = null, +) + +/** + * Enum for additional field types. + */ +enum class AdditionalFieldType { + @Json(name = "text") + TEXT, + + @Json(name = "multi_line_text") + MULTI_LINE_TEXT, + + @Json(name = "email") + EMAIL, + + @Json(name = "phone_number") + PHONE_NUMBER, + + @Json(name = "dropdown") + DROPDOWN, + + @Json(name = "date") + DATE, + + @Json(name = "checkbox") + CHECKBOX, + + @Json(name = "radio_button") + RADIO_BUTTON, +} + +/** + * Enum for additional field options types. + */ +enum class AdditonalFieldOptionsType { + @Json(name = "text") + TEXT, + + @Json(name = "email") + EMAIL, + + @Json(name = "phone_number") + PHONE_NUMBER, + + @Json(name = "date") + DATE, + + @Json(name = "checkbox") + CHECKBOX, + + @Json(name = "radio_button") + RADIO_BUTTON, +} diff --git a/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt b/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt new file mode 100644 index 00000000..825519ab --- /dev/null +++ b/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt @@ -0,0 +1,14 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Enum for confirm booking statuses. + */ +enum class ConfirmBookingStatus { + @Json(name = "confirm") + CONFIRM, + + @Json(name = "cancel") + CANCEL, +} diff --git a/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt b/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt index 9524f437..a3879f4a 100644 --- a/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt +++ b/src/main/kotlin/com/nylas/models/CreateBookingRequest.kt @@ -7,48 +7,121 @@ import com.squareup.moshi.Json */ data class CreateBookingRequest( /** - * The salt extracted from the booking reference embedded in the organizer confirmation link. + * The event's start time, in Unix epoch format. */ - @Json(name = "salt") - val salt: String, + @Json(name = "start_time") + val startTime: String? = null, /** - * The action to take on the pending booking. + * The event's end time, in Unix epoch format. */ - @Json(name = "status") - val status: ConfirmBookingStatus? = null, + @Json(name = "end_time") + val endTime: String? = null, /** - * The reason the booking is being cancelled. + * An array of objects that include a list of participant + * email addresses from the Configuration object to include in the booking. + * If not provided, Nylas includes all participants from the Configuration object. */ - @Json(name = "cancellation_reason") - val cancellationReason: String? = null, + @Json(name = "participants") + val participants: List? = null, + /** + * Details about the guest that is creating the booking. The guest name and email are required. + */ + @Json(name = "guest") + val guest: BookingGuest? = null, + /** + * The guest's timezone that is used in email notifications. + */ + @Json(name = "timezone") + val timezone: String? = null, + /** + * The language of the guest's email notifications. + */ + @Json(name = "email_language") + val emailLanguage: EmailLanguage? = null, + /** + * An array of objects that include a list of additional guest email addresses to include in the booking. + */ + @Json(name = "additional_guests") + val additionalGuests: List? = null, + /** + * A dictionary of additional field keys mapped to the values populated by the guest in the booking form. + */ + @Json(name = "additional_fields") + val additionalFields: Map? = null, ) { /** * Builder for [CreateBookingRequest]. */ - data class Builder( - private val salt: String, - ) { - private var status: ConfirmBookingStatus? = null - private var cancellationReason: String? = null + class Builder { + private var startTime: String? = null + private var endTime: String? = null + private var participants: List? = null + private var guest: BookingGuest? = null + private var timezone: String? = null + private var emailLanguage: EmailLanguage? = null + private var additionalGuests: List? = null + private var additionalFields: Map? = null + + /** + * Set the start time of the booking. + * @param startTime The start time of the booking. + * @return The builder. + */ + fun startTime(startTime: String) = apply { this.startTime = startTime } + + /** + * Set the end time of the booking. + * @param endTime The end time of the booking. + * @return The builder. + */ + fun endTime(endTime: String) = apply { this.endTime = endTime } + + /** + * Set the participants of the booking. + * @param participants The participants of the booking. + * @return The builder. + */ + fun participants(participants: List) = apply { this.participants = participants } + + /** + * Set the guests of the booking. + * @param guests The guests of the booking. + * @return The builder. + */ + fun guest(guest: BookingGuest) = apply { this.guest = guest } + + /** + * Set the timezone of the booking. + * @param timezone The timezone of the booking. + * @return The builder. + */ + fun timezone(timezone: String) = apply { this.timezone = timezone } + + /** + * Set the email language of the booking. + * @param emailLanguage The email language of the booking. + * @return The builder. + */ + fun emailLanguage(emailLanguage: EmailLanguage) = apply { this.emailLanguage = emailLanguage } /** - * Sets the status of the booking. - * @param status The status of the booking. + * Set the additional guests of the booking. + * @param additionalGuests The additional guests of the booking. * @return The builder. */ - fun status(status: ConfirmBookingStatus) = apply { this.status = status } + fun additionalGuests(additionalGuests: List) = apply { this.additionalGuests = additionalGuests } /** - * Sets the cancellation reason of the booking. - * @param cancellationReason The cancellation reason of the booking. + * Set the additional fields of the booking. + * @param additionalFields The additional fields of the booking. * @return The builder. */ - fun cancellationReason(cancellationReason: String) = apply { this.cancellationReason = cancellationReason } + fun additionalFields(additionalFields: Map) = apply { this.additionalFields = additionalFields } /** * Builds a [CreateBookingRequest] instance. * @return The [CreateBookingRequest] instance. */ - fun build() = CreateBookingRequest(salt, status, cancellationReason) + fun build() = CreateBookingRequest(startTime, endTime, participants, guest, timezone, emailLanguage, additionalGuests, additionalFields) } } diff --git a/src/main/kotlin/com/nylas/models/EmailLanguage.kt b/src/main/kotlin/com/nylas/models/EmailLanguage.kt new file mode 100644 index 00000000..ff97cfff --- /dev/null +++ b/src/main/kotlin/com/nylas/models/EmailLanguage.kt @@ -0,0 +1,32 @@ +package com.nylas.models + +import com.squareup.moshi.Json + +/** + * Enum for email language options. + */ +enum class EmailLanguage { + @Json(name = "en") + EN, + + @Json(name = "es") + ES, + + @Json(name = "fr") + FR, + + @Json(name = "de") + DE, + + @Json(name = "nl") + NL, + + @Json(name = "sv") + SV, + + @Json(name = "ja") + JA, + + @Json(name = "zh") + ZH, +} diff --git a/src/main/kotlin/com/nylas/models/Scheduler.kt b/src/main/kotlin/com/nylas/models/Scheduler.kt index 6b9a291c..026491c9 100644 --- a/src/main/kotlin/com/nylas/models/Scheduler.kt +++ b/src/main/kotlin/com/nylas/models/Scheduler.kt @@ -48,72 +48,6 @@ data class Configuration( val appearance: Map? = null, ) -/** - * Class representation of an additional field. - */ -data class AdditionalField( - /** - * The text label to be displayed in the Scheduler UI. - */ - @Json(name = "label") - val label: String, - /** - * The field type. - * Supported values are text, multi_line_text, email, phone_number, dropdown, date, checkbox, and radio_button. - */ - @Json(name = "type") - val type: AdditionalFieldType, - /** - * Whether the field is required to be filled out by the guest when booking an event. - */ - @Json(name = "required") - val required: Boolean, - /** - * A regular expression pattern that the value of the field must match. - */ - @Json(name = "pattern") - val pattern: String? = null, - /** - * The order in which the field will be displayed in the Scheduler UI. - * Fields with lower order values will be displayed first. - */ - @Json(name = "order") - val order: Int? = null, - /** - * A list of options for the dropdown or radio_button types. - * This field is required for the dropdown and radio_button types. - */ - @Json(name = "options") - val options: AdditonalFieldOptionsType? = null, -) - -/** - * Class representation of an email template. - */ -data class EmailTemplate( - /** - * Configurable settings specifically for booking confirmed emails. - */ - @Json(name = "booking_confirmed") - val bookingConfirmed: BookingConfirmedTemplate? = null, -) - -/** - * Class representation of booking confirmed template settings. - */ -data class BookingConfirmedTemplate( - /** - * The title to replace the default 'Booking Confirmed' title. - */ - @Json(name = "title") - val title: String? = null, - /** - * The additional body to be appended after the default body. - */ - @Json(name = "body") - val body: String? = null, -) - /** * Class representation of a session. */ @@ -162,118 +96,9 @@ data class Booking( ) /** - * Enum for additional field types. + * Class representation of a booking participant. */ -enum class AdditionalFieldType { - @Json(name = "text") - TEXT, - - @Json(name = "multi_line_text") - MULTI_LINE_TEXT, - +data class BookingParticipant( @Json(name = "email") - EMAIL, - - @Json(name = "phone_number") - PHONE_NUMBER, - - @Json(name = "dropdown") - DROPDOWN, - - @Json(name = "date") - DATE, - - @Json(name = "checkbox") - CHECKBOX, - - @Json(name = "radio_button") - RADIO_BUTTON, -} - -/** - * Enum for additional field options types. - */ -enum class AdditonalFieldOptionsType { - @Json(name = "text") - TEXT, - - @Json(name = "email") - EMAIL, - - @Json(name = "phone_number") - PHONE_NUMBER, - - @Json(name = "date") - DATE, - - @Json(name = "checkbox") - CHECKBOX, - - @Json(name = "radio_button") - RADIO_BUTTON, -} - -/** - * Enum for booking types. - */ -enum class BookingType { - @Json(name = "booking") - BOOKING, - - @Json(name = "organizer-confirmation") - ORGANIZER_CONFIRMATION, -} - -/** - * Enum for email language options. - */ -enum class EmailLanguage { - @Json(name = "en") - EN, - - @Json(name = "es") - ES, - - @Json(name = "fr") - FR, - - @Json(name = "de") - DE, - - @Json(name = "nl") - NL, - - @Json(name = "sv") - SV, - - @Json(name = "ja") - JA, - - @Json(name = "zh") - ZH, -} - -/** - * Enum for booking statuses. - */ -enum class BookingStatus { - @Json(name = "pending") - PENDING, - - @Json(name = "confirmed") - CONFIRMED, - - @Json(name = "cancelled") - CANCELLED, -} - -/** - * Enum for confirm booking statuses. - */ -enum class ConfirmBookingStatus { - @Json(name = "confirm") - CONFIRM, - - @Json(name = "cancel") - CANCEL, -} + val email: String, +) From 6e9b7765442e0ee6f8bd945aa3eba51157e6718f Mon Sep 17 00:00:00 2001 From: Subash Pradhan Date: Tue, 12 Nov 2024 11:50:16 +0100 Subject: [PATCH 12/12] Add tests for bookings reference --- .../kotlin/com/nylas/models/BookingStatus.kt | 4 +- .../com/nylas/models/ConfirmBookingRequest.kt | 6 +- .../com/nylas/models/ConfirmBookingStatus.kt | 8 +- .../com/nylas/resources/BookingsTest.kt | 189 ++++++++++++++++++ 4 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 src/test/kotlin/com/nylas/resources/BookingsTest.kt diff --git a/src/main/kotlin/com/nylas/models/BookingStatus.kt b/src/main/kotlin/com/nylas/models/BookingStatus.kt index ad271ebf..c140c163 100644 --- a/src/main/kotlin/com/nylas/models/BookingStatus.kt +++ b/src/main/kotlin/com/nylas/models/BookingStatus.kt @@ -9,8 +9,8 @@ enum class BookingStatus { @Json(name = "pending") PENDING, - @Json(name = "confirmed") - CONFIRMED, + @Json(name = "booked") + BOOKED, @Json(name = "cancelled") CANCELLED, diff --git a/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt b/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt index 32ded24e..aa278d7f 100644 --- a/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt +++ b/src/main/kotlin/com/nylas/models/ConfirmBookingRequest.kt @@ -7,7 +7,7 @@ import com.squareup.moshi.Json */ data class ConfirmBookingRequest( @Json(name = "status") - val status: String? = null, + val status: ConfirmBookingStatus? = null, /** * The salt extracted from the booking reference embedded in the organizer confirmation link. */ @@ -23,7 +23,7 @@ data class ConfirmBookingRequest( * Builder for [ConfirmBookingRequest]. */ class Builder { - private var status: String? = null + private var status: ConfirmBookingStatus? = null private var salt: String? = null private var cancellationReason: String? = null @@ -32,7 +32,7 @@ data class ConfirmBookingRequest( * @param status The status of the booking. * @return The builder. */ - fun status(status: String) = apply { this.status = status } + fun status(status: ConfirmBookingStatus) = apply { this.status = status } /** * Set the salt of the booking. diff --git a/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt b/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt index 825519ab..b8d5c937 100644 --- a/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt +++ b/src/main/kotlin/com/nylas/models/ConfirmBookingStatus.kt @@ -6,9 +6,9 @@ import com.squareup.moshi.Json * Enum for confirm booking statuses. */ enum class ConfirmBookingStatus { - @Json(name = "confirm") - CONFIRM, + @Json(name = "confirmed") + CONFIRMED, - @Json(name = "cancel") - CANCEL, + @Json(name = "cancelled") + CANCELLED, } diff --git a/src/test/kotlin/com/nylas/resources/BookingsTest.kt b/src/test/kotlin/com/nylas/resources/BookingsTest.kt new file mode 100644 index 00000000..137950e3 --- /dev/null +++ b/src/test/kotlin/com/nylas/resources/BookingsTest.kt @@ -0,0 +1,189 @@ +package com.nylas.resources + +import com.nylas.NylasClient +import com.nylas.models.* +import com.nylas.models.Response +import com.nylas.util.JsonHelper +import com.squareup.moshi.Types +import okhttp3.* +import okio.Buffer +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.* +import java.lang.reflect.Type +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertIs + +class BookingsTest { + private val mockHttpClient: OkHttpClient = Mockito.mock(OkHttpClient::class.java) + private val mockCall: Call = Mockito.mock(Call::class.java) + private val mockResponse: okhttp3.Response = Mockito.mock(okhttp3.Response::class.java) + private val mockResponseBody: ResponseBody = Mockito.mock(ResponseBody::class.java) + private val mockOkHttpClientBuilder: OkHttpClient.Builder = Mockito.mock() + + @BeforeEach + fun setUp() { + MockitoAnnotations.openMocks(this) + whenever(mockOkHttpClientBuilder.addInterceptor(any())).thenReturn(mockOkHttpClientBuilder) + whenever(mockOkHttpClientBuilder.build()).thenReturn(mockHttpClient) + whenever(mockHttpClient.newCall(any())).thenReturn(mockCall) + whenever(mockCall.execute()).thenReturn(mockResponse) + whenever(mockResponse.isSuccessful).thenReturn(true) + whenever(mockResponse.body()).thenReturn(mockResponseBody) + } + + @Nested + inner class SerializationTests { + @Test + fun `Booking serializes properly`() { + val adapter = JsonHelper.moshi().adapter(Booking::class.java) + val jsonBuffer = Buffer().writeUtf8( + """ + { + "booking_id": "booking-123", + "event_id": "event-123", + "title": "My test event", + "organizer": { + "name": "John Doe", + "email": "user@example.com" + }, + "status": "booked", + "description": "This is an example of a description." + } + """.trimIndent(), + ) + + val booking = adapter.fromJson(jsonBuffer) + assertIs(booking) + assertEquals("booking-123", booking.bookingId) + assertEquals("event-123", booking.eventId) + assertEquals("My test event", booking.title) + assertEquals("John Doe", booking.organizer.name) + assertEquals("user@example.com", booking.organizer.email) + assertEquals(BookingStatus.BOOKED, booking.status) + assertEquals("This is an example of a description.", booking.description) + } + } + + @Nested + inner class CrudTests { + private lateinit var mockNylasClient: NylasClient + private lateinit var bookings: Bookings + + @BeforeEach + fun setup() { + mockNylasClient = Mockito.mock(NylasClient::class.java) + bookings = Bookings(mockNylasClient) + } + + @Test + fun `creating a booking calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(CreateBookingRequest::class.java) + val participants = ArrayList() + val bookingParticipant = BookingParticipant("test@nylas.com") + participants.add(bookingParticipant) + + val bookingGuest = BookingGuest("guest@nylas.com", "Guest") + val startTime = "1630000000" + val endTime = "1630003600" + + val createBookingRequest = CreateBookingRequest( + startTime = startTime, + endTime = endTime, + participants = participants, + guest = bookingGuest, + ) + + bookings.create(createBookingRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executePost(pathCaptor.capture(), typeCaptor.capture(), requestBodyCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + + assertEquals("v3/scheduling/bookings", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Booking::class.java), typeCaptor.firstValue) + assertEquals(adapter.toJson(createBookingRequest), requestBodyCaptor.firstValue) + } + + @Test + fun `finding a booking calls requests with the correct params`() { + val bookingId = "booking-id" + bookings.find(bookingId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet(pathCaptor.capture(), typeCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + + assertEquals("v3/scheduling/bookings/$bookingId", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Booking::class.java), typeCaptor.firstValue) + } + + @Test + fun `rescheduling a booking calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(RescheduleBookingRequest::class.java) + val bookingId = "booking-id" + val rescheduleBookingRequest = RescheduleBookingRequest( + startTime = 1630000000, + endTime = 1630003600, + ) + bookings.reschedule(bookingId, rescheduleBookingRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executePatch(pathCaptor.capture(), typeCaptor.capture(), requestBodyCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + + assertEquals("v3/scheduling/bookings/$bookingId", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Booking::class.java), typeCaptor.firstValue) + assertEquals(adapter.toJson(rescheduleBookingRequest), requestBodyCaptor.firstValue) + } + + @Test + fun `confirming a booking calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(ConfirmBookingRequest::class.java) + val bookingId = "booking-id" + val confirmBookingRequest = ConfirmBookingRequest( + salt = "salt123", + status = ConfirmBookingStatus.CANCELLED, + ) + + bookings.confirm(bookingId, confirmBookingRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executePut(pathCaptor.capture(), typeCaptor.capture(), requestBodyCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + + assertEquals("v3/scheduling/bookings/$bookingId", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Booking::class.java), typeCaptor.firstValue) + assertEquals(adapter.toJson(confirmBookingRequest), requestBodyCaptor.firstValue) + } + + @Test + fun `destryoing a booking calls request with the correct params`() { + val bookingId = "booking-id" + bookings.destroy(bookingId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete(pathCaptor.capture(), typeCaptor.capture(), queryParamCaptor.capture(), overrideParamCaptor.capture()) + + assertEquals("v3/scheduling/bookings/$bookingId", pathCaptor.firstValue) + assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) + } + } +}