diff --git a/README.md b/README.md index 479c3ecb..de460306 100644 --- a/README.md +++ b/README.md @@ -420,6 +420,9 @@ HotelOfferSearch offer = amadeus.shopping.hotelOfferSearch("QF3MNOBDQ8").get(); // The body can be a String version of your JSON or a JsonObject HotelBooking[] hotel = amadeus.booking.hotelBookings.post(body); +// Hotel Booking v2 +HotelOrder hotel = amadeus.booking.hotelOrders.post(body); + // Hotel Ratings / Sentiments HotelSentiment[] hotelSentiments = amadeus.ereputation.hotelSentiments.get(Params.with("hotelIds", "ELONMFS,ADNYCCTB")); diff --git a/src/main/java/com/amadeus/Booking.java b/src/main/java/com/amadeus/Booking.java index a6d5c40d..5ea24d66 100644 --- a/src/main/java/com/amadeus/Booking.java +++ b/src/main/java/com/amadeus/Booking.java @@ -3,6 +3,7 @@ import com.amadeus.booking.FlightOrder; import com.amadeus.booking.FlightOrders; import com.amadeus.booking.HotelBookings; +import com.amadeus.booking.HotelOrders; public class Booking { private Amadeus client; @@ -31,6 +32,14 @@ public class Booking { */ public HotelBookings hotelBookings; + /** + *
+ * A namespaced client for the
+ * /v2/booking/hotelOrders
endpoints.
+ *
+ * A namespaced client for the
+ * /v2/booking/hotel-orders
endpoints.
+ *
+ * Access via the Amadeus client object. + *
+ * + *+ * Amadeus amadeus = Amadeus.builder(API_KEY, API_SECRET).build(); + * amadeus.booking.HotelOrders;+ */ +public class HotelOrders { + private Amadeus client; + + /** + * Constructor. + * + * @hide + */ + public HotelOrders(Amadeus client) { + this.client = client; + } + + /** + *
+ * The Hotel Booking API allows you to perform hotel booking. + *
+ * + *+ * amadeus.booking.hotelOrders.post(body);+ * + * @param body the parameters to send to the API as a JSonObject + * @return an API resource + * @throws ResponseException when an exception occurs + */ + public HotelOrder post(JsonObject body) throws ResponseException { + Response response = client.post("/v2/booking/hotel-orders", body); + return (HotelOrder) Resource.fromObject(response, HotelOrder.class); + } + + /** + *
+ * The Hotel Booking API allows you to perform hotel booking. + *
+ * + *+ * amadeus.booking.hotelOrders.post(body);+ * + * @param body the parameters to send to the API as a String + * @return an API resource + * @throws ResponseException when an exception occurs + */ + public HotelOrder post(String body) throws ResponseException { + Response response = client.post("/v2/booking/hotel-orders", body); + return (HotelOrder) Resource.fromObject(response, HotelOrder.class); + } + + /** + * Convenience method for calling
post
without any parameters.
+ *
+ * @see HotelBookings#post()
+ */
+ public HotelOrder post() throws ResponseException {
+ return post((String) null);
+ }
+}
diff --git a/src/main/java/com/amadeus/resources/FlightOrder.java b/src/main/java/com/amadeus/resources/FlightOrder.java
index ffff30d6..1caa6507 100644
--- a/src/main/java/com/amadeus/resources/FlightOrder.java
+++ b/src/main/java/com/amadeus/resources/FlightOrder.java
@@ -48,6 +48,7 @@ public static class Traveler {
@AllArgsConstructor
@NoArgsConstructor
+
@ToString
public static class Name {
diff --git a/src/main/java/com/amadeus/resources/Hotel.java b/src/main/java/com/amadeus/resources/Hotel.java
index b46d2a99..b9e0fbe8 100644
--- a/src/main/java/com/amadeus/resources/Hotel.java
+++ b/src/main/java/com/amadeus/resources/Hotel.java
@@ -1,6 +1,5 @@
package com.amadeus.resources;
-import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.ToString;
diff --git a/src/main/java/com/amadeus/resources/HotelOrder.java b/src/main/java/com/amadeus/resources/HotelOrder.java
new file mode 100644
index 00000000..e5649e9f
--- /dev/null
+++ b/src/main/java/com/amadeus/resources/HotelOrder.java
@@ -0,0 +1,91 @@
+package com.amadeus.resources;
+
+import com.amadeus.resources.HotelOfferSearch.Offer;
+import lombok.Getter;
+import lombok.ToString;
+
+/**
+ * An HotelOrder object as returned by the Hotel Booking v2 API.
+ * @see com.amadeus.booking.HotelOrders#get()
+ */
+@ToString
+public class HotelOrder extends Resource {
+ private @Getter String self;
+ private @Getter String type;
+ private @Getter String id;
+ private @Getter HotelBooking[] hotelBookings;
+ private @Getter AssociatedRecord[] associatedRecords;
+ private @Getter Guest[] guests;
+
+ protected HotelOrder() {}
+
+ @ToString
+ public static class HotelBooking {
+ private @Getter String type;
+ private @Getter String id;
+ private @Getter String bookingStatus;
+ private @Getter RoomAssociation[] roomAssociations;
+ private @Getter Offer hotelOffer;
+ private @Getter Hotel hotel;
+
+ protected HotelBooking() {}
+ }
+
+ @ToString
+ public static class RoomAssociation {
+ private @Getter String hotelOfferId;
+ private GuestReference[] guestReferences;
+ private @Getter String specialRequest;
+
+ protected RoomAssociation() {}
+ }
+
+ @ToString
+ public static class GuestReference {
+ private @Getter String guestReference;
+ private @Getter String hotelLoyaltyId;
+
+ protected GuestReference() {}
+ }
+
+ @ToString
+ public static class Guest {
+ private @Getter int tid;
+ private @Getter int id;
+ private @Getter FrequentTraveler[] frequentTraveler;
+ private @Getter String phone;
+ private @Getter String email;
+ private @Getter String title;
+ private @Getter String firstName;
+ private @Getter String lastName;
+ private @Getter Integer childAge;
+
+ protected Guest() {}
+ }
+
+ @ToString
+ public static class FrequentTraveler {
+ private @Getter String airlineCode;
+ private @Getter String frequentTravelerId;
+
+ protected FrequentTraveler() {}
+ }
+
+ @ToString
+ public static class AssociatedRecord {
+ private @Getter String reference;
+ private @Getter String originSystemCode;
+
+ protected AssociatedRecord() {}
+ }
+
+ @ToString
+ public static class Hotel {
+ private @Getter String hotelId;
+ private @Getter String chainCode;
+ private @Getter String name;
+ private @Getter String self;
+
+ protected Hotel() {}
+ }
+}
diff --git a/src/test/java/com/amadeus/NamespaceTest.java b/src/test/java/com/amadeus/NamespaceTest.java
index be526366..fa01fb8d 100644
--- a/src/test/java/com/amadeus/NamespaceTest.java
+++ b/src/test/java/com/amadeus/NamespaceTest.java
@@ -10,6 +10,7 @@
import com.amadeus.booking.FlightOrder;
import com.amadeus.booking.FlightOrders;
import com.amadeus.booking.HotelBookings;
+import com.amadeus.booking.HotelOrders;
import com.amadeus.ereputation.HotelSentiments;
import com.amadeus.exceptions.ResponseException;
import com.amadeus.location.analytics.CategoryRatedAreas;
@@ -27,6 +28,7 @@
import com.amadeus.referencedata.locations.hotels.ByGeocode;
import com.amadeus.referencedata.locations.hotels.ByHotels;
import com.amadeus.referencedata.urls.CheckinLinks;
+import com.amadeus.resources.HotelOrder;
import com.amadeus.resources.TransferCancellation;
import com.amadeus.schedule.Flights;
import com.amadeus.shopping.Activities;
@@ -95,6 +97,7 @@ public class NamespaceTest {
assertNotNull(client.airport.predictions.onTime);
assertNotNull(client.booking.flightOrder("XXX"));
assertNotNull(client.booking.hotelBookings);
+ assertNotNull(client.booking.hotelOrders);
assertNotNull(client.schedule.flights);
assertNotNull(client.travel.tripParser);
assertNotNull(client.airport.directDestinations);
@@ -674,6 +677,20 @@ public void testHotelBookings() throws ResponseException {
assertNotNull(hotel.post(body));
}
+ @Test
+ public void testHotelOrders() throws ResponseException {
+ // Test Trip Parser
+ Mockito.when(client.post("/v2/booking/hotel-orders", (String) null))
+ .thenReturn(singleResponse);
+ Mockito.when(client.post("/v2/booking/hotel-orders", body))
+ .thenReturn(singleResponse);
+ Mockito.when(client.post("/v2/booking/hotel-orders", jsonObject))
+ .thenReturn(singleResponse);
+ HotelOrders hotelOrder = new HotelOrders(client);
+ assertNotNull(hotelOrder.post());
+ assertNotNull(hotelOrder.post(body));
+ }
+
@Test
public void testTripParser() throws ResponseException {
// Test Trip Parser
diff --git a/src/test/java/com/amadeus/booking/HotelOrdersIT.java b/src/test/java/com/amadeus/booking/HotelOrdersIT.java
new file mode 100644
index 00000000..25c6aa3f
--- /dev/null
+++ b/src/test/java/com/amadeus/booking/HotelOrdersIT.java
@@ -0,0 +1,99 @@
+package com.amadeus.booking;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.amadeus.Amadeus;
+import com.amadeus.exceptions.ResponseException;
+import com.amadeus.resources.HotelOrder;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+// https://developers.amadeus.com/self-service/category/hotels/api-doc/hotel-booking
+public class HotelOrdersIT {
+
+ WireMockServer wireMockServer;
+
+ private Amadeus amadeus;
+
+ /**
+ * In every tests, we will authenticate.
+ */
+ @BeforeEach
+ public void setup() {
+ wireMockServer = new WireMockServer(8080);
+ wireMockServer.start();
+
+ // API at https://developers.amadeus.com/self-service/apis-docs/guides/authorization-262
+ String address = "/v1/security/oauth2/token"
+ + "?grant_type=client_credentials&client_secret=DEMO&client_id=DEMO";
+ wireMockServer.stubFor(post(urlEqualTo(address))
+ .willReturn(aResponse().withHeader("Content-Type", "application/json")
+ .withStatus(200)
+ .withBodyFile("auth_ok.json")));
+
+ amadeus = Amadeus
+ .builder("DEMO", "DEMO")
+ .setHost("localhost")
+ .setPort(8080)
+ .setSsl(false)
+ .setLogLevel("debug")
+ .build();
+ }
+
+ @AfterEach
+ public void teardown() {
+ wireMockServer.stop();
+ }
+
+ @Test
+ public void given_client_when_call_hotel_orders_with_params_then_ok()
+ throws ResponseException, IOException {
+
+ // Given
+ String address = "/v2/booking/hotel-orders";
+
+ wireMockServer.stubFor(post(urlEqualTo(address))
+ .willReturn(aResponse().withHeader("Content-Type", "application/json")
+ .withStatus(200)
+ .withBodyFile("hotel_orders_response_ok.json")));
+
+
+ JsonObject request = getRequestFromResources("hotel_orders_request_ok.json");
+
+ // When
+ HotelOrder result = amadeus.booking.hotelOrders.post(request);
+
+ // Then
+ assertNotNull(result);
+ }
+
+ private JsonObject getRequestFromResources(String jsonFile) throws IOException {
+
+ final String folder = "__files/";
+
+ ClassLoader classLoader = getClass().getClassLoader();
+ File file = new File(classLoader.getResource(folder + jsonFile).getFile());
+ String jsonString = new String(Files.readAllBytes(file.toPath()));
+
+ return new JsonParser().parse(jsonString).getAsJsonObject();
+ }
+
+ private File getFileRequestFromResources(String jsonFile) throws IOException {
+
+ final String folder = "__files/";
+
+ ClassLoader classLoader = getClass().getClassLoader();
+ return new File(classLoader.getResource(folder + jsonFile).getFile());
+ }
+
+}
diff --git a/src/test/resources/__files/hotel_orders_request_ok.json b/src/test/resources/__files/hotel_orders_request_ok.json
new file mode 100644
index 00000000..3879e0dd
--- /dev/null
+++ b/src/test/resources/__files/hotel_orders_request_ok.json
@@ -0,0 +1,41 @@
+{
+ "data": {
+ "type": "hotel-order",
+ "guests": [
+ {
+ "tid": 1,
+ "title": "MR",
+ "firstName": "BOB",
+ "lastName": "SMITH",
+ "phone": "+33679278416",
+ "email": "bob.smith@email.com"
+ }
+ ],
+ "travelAgent": {
+ "contact": {
+ "email": "bob.smith@email.com"
+ }
+ },
+ "roomAssociations": [
+ {
+ "guestReferences": [
+ {
+ "guestReference": "1"
+ }
+ ],
+ "hotelOfferId": "4L8PRJPEN7"
+ }
+ ],
+ "payment": {
+ "method": "CREDIT_CARD",
+ "paymentCard": {
+ "paymentCardInfo": {
+ "vendorCode": "VI",
+ "cardNumber": "4151289722471370",
+ "expiryDate": "2026-08",
+ "holderName": "BOB SMITH"
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/test/resources/__files/hotel_orders_response_ok.json b/src/test/resources/__files/hotel_orders_response_ok.json
new file mode 100644
index 00000000..99a2f84d
--- /dev/null
+++ b/src/test/resources/__files/hotel_orders_response_ok.json
@@ -0,0 +1,119 @@
+{
+ "data": {
+ "type": "hotel-order",
+ "id": "V0g2VFJaLzIwMjQtMDYtMDc=",
+ "hotelBookings": [
+ {
+ "type": "hotel-booking",
+ "id": "MS84OTkyMjcxMC85MDIyNDU0OQ==",
+ "bookingStatus": "CONFIRMED",
+ "hotelProviderInformation": [
+ {
+ "hotelProviderCode": "AR",
+ "confirmationNumber": "89922710"
+ }
+ ],
+ "roomAssociations": [
+ {
+ "hotelOfferId": "******",
+ "guestReferences": [
+ {
+ "guestReference": "1"
+ }
+ ]
+ }
+ ],
+ "hotelOffer": {
+ "id": "******",
+ "type": "hotel-offer",
+ "category": "TYPE_CONDITIONAL",
+ "checkInDate": "2024-06-07",
+ "checkOutDate": "2024-06-08",
+ "guests": {
+ "adults": 1
+ },
+ "policies": {
+ "cancellations": [
+ {
+ "amount": "215.05",
+ "deadline": "2024-06-06T23:59:00+02:00"
+ }
+ ],
+ "paymentType": "GUARANTEE"
+ },
+ "price": {
+ "base": "195.50",
+ "currency": "EUR",
+ "sellingTotal": "215.05",
+ "taxes": [
+ {
+ "amount": "19.55",
+ "code": "VALUE_ADDED_TAX",
+ "currency": "EUR",
+ "included": false,
+ "pricingFrequency": "PER_STAY",
+ "pricingMode": "PER_PRODUCT"
+ }
+ ],
+ "total": "215.05",
+ "variations": {
+ "changes": [
+ {
+ "endDate": "2024-06-08",
+ "startDate": "2024-06-07",
+ "base": "195.50",
+ "currency": "EUR"
+ }
+ ]
+ }
+ },
+ "rateCode": "S9R",
+ "room": {
+ "description": {
+ "lang": "EN",
+ "text": "Marriott Senior Discount, includes"
+ },
+ "type": "XMI"
+ },
+ "roomQuantity": 1
+ },
+ "hotel": {
+ "hotelId": "ARMADAIT",
+ "chainCode": "AR",
+ "name": "AC BY MARRIOTT HOTEL AITANA",
+ "self": "https://test.travel.api.amadeus.com/v1/reference-data/locations/by-hotel/ARMADAIT"
+ },
+ "payment": {
+ "method": "CREDIT_CARD",
+ "paymentCard": {
+ "paymentCardInfo": {
+ "vendorCode": "VI",
+ "cardNumber": "415128XXXXXX1370",
+ "expiryDate": "0826",
+ "holderName": "BOB SMITH"
+ }
+ }
+ },
+ "travelAgentId": "00000000"
+ }
+ ],
+ "guests": [
+ {
+ "tid": 1,
+ "id": 1,
+ "title": "MR",
+ "firstName": "BOB",
+ "lastName": "SMITH",
+ "phone": "+33679278416",
+ "email": "bob.smith@email.com"
+ }
+ ],
+ "associatedRecords": [
+ {
+ "reference": "WH6TRZ",
+ "originSystemCode": "GDS"
+ }
+ ],
+ "self": "http://test.api.amadeus.com/v2/booking/hotel-orders/V0g2VFJaLzIwMjQtMDYtMDc="
+ }
+ }
\ No newline at end of file