Skip to content

Commit

Permalink
Merge pull request #75 from tukcomCD2024/backend/feature/67-amadeus-h…
Browse files Browse the repository at this point in the history
…otel

[Backend] feat : 편도 항공권 조회, 좌표로 호텔 조회 API 추가
  • Loading branch information
Dayon-Hong authored May 14, 2024
2 parents bf75983 + 9a8179a commit 1fda51b
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ public class FlightOfferProcessor {
public String processFlightOffers(String flightOffersJson) {
JsonArray flightOffersArray = new Gson().fromJson(flightOffersJson, JsonArray.class);

// 필요한 정보만 객체로 변환
JsonArray filteredFlightOffers = new JsonArray();
for (JsonElement flightOfferElement : flightOffersArray) {
JsonObject flightOffer = flightOfferElement.getAsJsonObject();
JsonObject filteredFlightOffer = filterFlightOffer(flightOffer);
filteredFlightOffers.add(filteredFlightOffer);
}

return filteredFlightOffers.toString();
}

Expand All @@ -38,18 +36,15 @@ public JsonObject filterFlightOffer(JsonObject flightOffer) {
.getAsJsonArray("segments").get(0).getAsJsonObject().get("carrierCode").getAsString();
Double price = flightOffer.getAsJsonObject("price").get("total").getAsDouble();

// 왕복-편도 여행 여부 확인 (itineraries 배열 길이 확인)
boolean isRoundTrip = flightOffer.getAsJsonArray("itineraries").size() == 2;

// 출국 정보 추출
JsonObject abroadItinerary = flightOffer.getAsJsonArray("itineraries").get(0).getAsJsonObject();
String abroadDuration = abroadItinerary.get("duration").getAsString();
String abroadDepartureTime = abroadItinerary.getAsJsonArray("segments").get(0).getAsJsonObject().getAsJsonObject("departure").get("at").getAsString();
String abroadArrivalTime = abroadItinerary.getAsJsonArray("segments").get(0).getAsJsonObject().getAsJsonObject("arrival").get("at").getAsString();

// 입국 정보 추출
JsonObject homeItinerary = flightOffer.getAsJsonArray("itineraries").get(1).getAsJsonObject();
String homeDuration = homeItinerary.get("duration").getAsString();
String homeDepartureTime = homeItinerary.getAsJsonArray("segments").get(0).getAsJsonObject().getAsJsonObject("departure").get("at").getAsString();
String homeArrivalTime = homeItinerary.getAsJsonArray("segments").get(1).getAsJsonObject().getAsJsonObject("arrival").get("at").getAsString();

// 출발지 및 도착지 정보 추출
JsonArray segments = flightOffer.getAsJsonArray("itineraries").get(0).getAsJsonObject().getAsJsonArray("segments");
JsonObject lastSegment = segments.get(segments.size() - 1).getAsJsonObject();
Expand All @@ -62,34 +57,46 @@ public JsonObject filterFlightOffer(JsonObject flightOffer) {
// 시간 변환 및 저장
String filteredAbroadDepartureTime = formatTime(abroadDepartureTime);
String filteredAbroadArrivalTime = formatTime(abroadArrivalTime);
String filteredHomeDepartureTime = formatTime(homeDepartureTime);
String filteredHomeArrivalTime = formatTime(homeArrivalTime);

// duration 변환 및 저장
String filteredAbroadDuration = formatDuration(abroadItinerary);
String filteredHomeDuration = formatDuration(homeItinerary);
String filteredAbroadDuration = formatDuration(abroadDuration);

// 경유 및 직항 여부 추출
boolean nonstop = segments.size() == 1; // 직항일 경우 segments 배열의 크기는 1이 됨

// 필터링된 정보로 객체 생성
filteredFlightOffer.addProperty("id", id);
filteredFlightOffer.addProperty("carrierCode", carrierCode);
filteredFlightOffer.addProperty("totalPrice", price);
filteredFlightOffer.addProperty("abroadDuration", filteredAbroadDuration);
filteredFlightOffer.addProperty("abroadDepartureTime", filteredAbroadDepartureTime);
filteredFlightOffer.addProperty("abroadArrivalTime", filteredAbroadArrivalTime);
filteredFlightOffer.addProperty("homeDuration", filteredHomeDuration);
filteredFlightOffer.addProperty("homeDepartureTime", filteredHomeDepartureTime);
filteredFlightOffer.addProperty("homeArrivalTime", filteredHomeArrivalTime);
filteredFlightOffer.addProperty("departureIataCode", departureIataCode);
filteredFlightOffer.addProperty("arrivalIataCode", arrivalIataCode);
filteredFlightOffer.addProperty("nonstop", nonstop);
filteredFlightOffer.addProperty("transferCount", transferCount);

filteredFlightOffer.addProperty("abroadDuration", filteredAbroadDuration);
filteredFlightOffer.addProperty("abroadDepartureTime", filteredAbroadDepartureTime);
filteredFlightOffer.addProperty("abroadArrivalTime", filteredAbroadArrivalTime);


// 왕복 여행의 경우
if (isRoundTrip) {
// 입국 여행 정보 추출
JsonObject homeItinerary = flightOffer.getAsJsonArray("itineraries").get(1).getAsJsonObject();
String homeDuration = homeItinerary.get("duration").getAsString();
String homeDepartureTime = homeItinerary.getAsJsonArray("segments").get(0).getAsJsonObject().getAsJsonObject("departure").get("at").getAsString();
String homeArrivalTime = homeItinerary.getAsJsonArray("segments").get(1).getAsJsonObject().getAsJsonObject("arrival").get("at").getAsString();
String filteredHomeDepartureTime = formatTime(homeDepartureTime);
String filteredHomeArrivalTime = formatTime(homeArrivalTime);
String filteredHomeDuration = formatDuration(homeDuration);

// 응답 값에 추가
filteredFlightOffer.addProperty("homeDuration", filteredHomeDuration);
filteredFlightOffer.addProperty("homeDepartureTime", filteredHomeDepartureTime);
filteredFlightOffer.addProperty("homeArrivalTime", filteredHomeArrivalTime);
}
return filteredFlightOffer;
}


/** 경유 횟수 확인 **/
private int countTransfers(JsonArray segments) {
// 직항일 경우 경유 없음
Expand All @@ -100,16 +107,18 @@ private int countTransfers(JsonArray segments) {
return segments.size() - 1;
}


/** 시간 변환 **/
private String formatTime(String timeStr) {
LocalDateTime time = LocalDateTime.parse(timeStr, DateTimeFormatter.ISO_DATE_TIME);
return time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}


/** duration 비행 시간 변환 **/
private String formatDuration(JsonObject itinerary) {
String durationString = itinerary.get("duration").getAsString();
Duration duration = Duration.parse(durationString);
private String formatDuration(String durationStr) {
Duration duration = Duration.parse(durationStr);

long hours = duration.toHours();
long minutes = duration.minusHours(hours).toMinutes();
return String.format("%d:%02d", hours, minutes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,21 @@ public String getFlightOffers(FlightSearchRequest request) throws ResponseExcept
String originLocationCode = findAirportCode(request.getOriginCity());
String destinationLocationCode = findAirportCode(request.getDestinationCity());

FlightOfferSearch[] flightOffers = amadeus.shopping.flightOffersSearch.get(
Params.with("originLocationCode", originLocationCode)
.and("destinationLocationCode", destinationLocationCode)
.and("departureDate", request.getDepartureDate())
.and("returnDate", request.getReturnDate())
.and("adults", request.getAdults())
.and("children", request.getChildren())
.and("max", request.getMax())
.and("nonStop", request.isNonStop())
.and("currencyCode","KRW") // 원화 설정 -> 추후 유저에게 입력받을 수 있게 남겨둠
);
Params params = Params.with("originLocationCode", originLocationCode)
.and("destinationLocationCode", destinationLocationCode)
.and("departureDate", request.getDepartureDate())
.and("adults", request.getAdults())
.and("children", request.getChildren())
.and("max", request.getMax())
.and("nonStop", request.isNonStop())
.and("currencyCode", "KRW"); // 원화 설정 -> 추후 유저에게 입력받을 수 있게 남겨둠

// returnDate가 빈 문자열이 아닌 경우에만 파라미터 추가
if (request.getReturnDate() != null && !request.getReturnDate().isEmpty()) {
params.and("returnDate", request.getReturnDate());
}

FlightOfferSearch[] flightOffers = amadeus.shopping.flightOffersSearch.get(params);

Gson gson = new Gson();
String flightOffersJson = gson.toJson(flightOffers);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
package com.isp.backend.domain.hotel.controller;

import com.amadeus.exceptions.ResponseException;
import com.isp.backend.domain.hotel.dto.request.SearchGeocodeRequest;
import com.isp.backend.domain.hotel.service.HotelService;
import com.isp.backend.global.exception.flight.AmadeusSearchFailedException;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/bookings/hotels")
@RequiredArgsConstructor
public class HotelController {

private final HotelService hotelService ;

/** 좌표 주변 호텔 리스트 API **/
@PostMapping("/search")
public ResponseEntity<String> searchHotelsByGeocode(@RequestBody SearchGeocodeRequest request) {
try {
String hotelsJson = hotelService.searchHotelsByGeocode(request);
return ResponseEntity.ok(hotelsJson);
} catch (ResponseException e) {
throw new AmadeusSearchFailedException();
}
}

/** 호텔 선택시 스카이스캐너 사이트로 연결 API **/


/** 호텔 좋아요 저장 API **/


/** 호텔 좋아요 목록 불러오기 API **/


/** 호텔 좋아요 삭제하기 API **/




Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ public class SearchGeocodeRequest {

private String longitude;

private int radius ;

private String ratings ; // 호텔 등급

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.isp.backend.domain.hotel.service;

import com.amadeus.exceptions.ResponseException;
import com.amadeus.resources.Hotel;
import com.isp.backend.domain.hotel.dto.request.SearchGeocodeRequest;

public interface HotelService {
public String searchHotelsByGeocode(SearchGeocodeRequest request) throws ResponseException;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.isp.backend.domain.hotel.service;

import com.amadeus.Amadeus;
import com.amadeus.Params;
import com.amadeus.exceptions.ResponseException;
import com.amadeus.resources.Hotel;
import com.amadeus.shopping.HotelOffersSearch;
import com.google.gson.Gson;
import com.isp.backend.domain.hotel.dto.request.SearchGeocodeRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class HotelServiceImpl implements HotelService {
private final Amadeus amadeus;

/**
* 좌표 주변 호텔 리스트 API
**/
@Override
public String searchHotelsByGeocode(SearchGeocodeRequest request) throws ResponseException {
String latitude = request.getLatitude();
String longitude = request.getLongitude();
int radius = request.getRadius();
String ratings = request.getRatings();

Hotel[] hotelSearch = amadeus.referenceData.locations.hotels.byGeocode.get(
Params.with("latitude", latitude)
.and("longitude", longitude)
.and("radius", radius)
.and("radiusUnit", "KM")
.and("ratings", ratings)
.and("hotelSource", "ALL")
);
Gson gson = new Gson();
String hotelSearchJson = gson.toJson(hotelSearch);
return hotelSearchJson;
}


}

0 comments on commit 1fda51b

Please sign in to comment.