Skip to content

Commit

Permalink
Merge pull request #74 from nathan29849/be/feature/#43-search_accommo…
Browse files Browse the repository at this point in the history
…dattions_by_keywords_api

[Backend] [43] 검색 조건에 따른 숙소 목록 조회 기능 구현
  • Loading branch information
nathan29849 committed Jun 7, 2022
2 parents 3cda973 + 5bee4d2 commit 55ffa5b
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,40 +1,43 @@
package team15.airbnb.accommodation.application;

import java.util.List;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team15.airbnb.accommodation.domain.Accommodation;
import team15.airbnb.accommodation.infrastructure.AccommodationRepository;
import team15.airbnb.accommodation.presentation.dto.AccommodationDetailsResponse;
import team15.airbnb.accommodation.presentation.dto.AccommodationFeeDto;
import team15.airbnb.accommodation.presentation.dto.AccommodationFeesResponse;
import team15.airbnb.accommodation.presentation.dto.*;
import team15.airbnb.user.infrastructure.UserRepository;

@Slf4j
@Service
public class AccommodationService {

private final AccommodationRepository accommodationRepository;
private final UserRepository userRepository;
private final AccommodationRepository accommodationRepository;
private final UserRepository userRepository;

public AccommodationService(AccommodationRepository accommodationRepository, UserRepository userRepository) {
this.accommodationRepository = accommodationRepository;
this.userRepository = userRepository;
}
public AccommodationService(AccommodationRepository accommodationRepository, UserRepository userRepository) {
this.accommodationRepository = accommodationRepository;
this.userRepository = userRepository;
}

@Transactional(readOnly = true)
public AccommodationDetailsResponse searchById(Long accommodationId) {
Accommodation accommodation = accommodationRepository.findById(accommodationId);
@Transactional(readOnly = true)
public AccommodationDetailsResponse searchById(Long accommodationId) {
Accommodation accommodation = accommodationRepository.findById(accommodationId);
/*
TODO 유저 조회 (JWT 에 sign 된 user id를 통해서..) 후 like 여부 판단
*/
return AccommodationDetailsResponse.convertFrom(accommodation, true);
}

@Transactional(readOnly = true)
public AccommodationFeesResponse searchByFeeRange(int minPrice, int maxPrice) {
List<AccommodationFeeDto> accommodations = accommodationRepository.findByFee(minPrice, maxPrice);
return AccommodationFeesResponse.convertFrom(accommodations);
}
return AccommodationDetailsResponse.convertFrom(accommodation, true);
}

@Transactional(readOnly = true)
public AccommodationFeesResponse searchByFeeRange(int minPrice, int maxPrice) {
List<AccommodationFeeDto> accommodations = accommodationRepository.findByFee(minPrice, maxPrice);
return AccommodationFeesResponse.convertFrom(accommodations);
}

public SearchAccommodationsByOptionsResponse searchByOptions(SearchAccommodationsOptionsRequest request, Long userId) {
return new SearchAccommodationsByOptionsResponse(new AccommodationListResponse(accommodationRepository.findByOptions(request, userId)));
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package team15.airbnb.accommodation.infrastructure;

import java.util.List;
import org.springframework.stereotype.Repository;
import team15.airbnb.accommodation.domain.Accommodation;
import team15.airbnb.accommodation.presentation.dto.AccommodationFeeDto;
import team15.airbnb.accommodation.presentation.dto.AccommodationSimpleInfoResponse;
import team15.airbnb.accommodation.presentation.dto.SearchAccommodationsOptionsRequest;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import team15.airbnb.accommodation.presentation.dto.AccommodationFeeDto;
import team15.airbnb.accommodation.presentation.dto.AccommodationFeesResponse;
import team15.airbnb.category.presentation.dto.RegionDistanceDto;
import java.time.LocalDate;
import java.util.List;

@Repository
public class AccommodationRepository {

@PersistenceContext
private EntityManager em;


public void save(Accommodation accommodation) {
em.persist(accommodation);
}
Expand All @@ -34,4 +34,34 @@ public List<AccommodationFeeDto> findByFee(int minPrice, int maxPrice) {
.setParameter("maxPrice", maxPrice)
.getResultList();
}

public List<AccommodationSimpleInfoResponse> findByOptions(SearchAccommodationsOptionsRequest request, Long userId) {

LocalDate checkIn = LocalDate.parse(request.getCheckIn());
LocalDate checkOut = LocalDate.parse(request.getCheckOut());

return em.createQuery(
"select new team15.airbnb.accommodation.presentation.dto.AccommodationSimpleInfoResponse(" +
"a.id, (exists(select a.id from Favorite f where f.user.id = :userId and f.accommodation=a.id)) ,a.host.type, a.accommodationName, a.mainImage, (select avg(r.starRating) from Review r where r.accommodation.id = a.id), a.reviews.size, a.price, astext(a.address.coordinate)" +
") " +
"from Accommodation a " +
"where a.price between :minPrice and :maxPrice " +
"and a.details.maximumGuestNumber >= :guestNumber " +
"and a.address.firstAddress like :address " +
"and not exists (select r.accommodation.id from Reservation r " +
"where r.accommodation.id = a.id " +
"and r.checkInDate >= :checkIn and r.checkInDate < :checkOut) " +
"group by a.id "
, AccommodationSimpleInfoResponse.class)
.setParameter("userId", userId)
.setParameter("minPrice", request.getMinPrice())
.setParameter("maxPrice", request.getMaxPrice())
.setParameter("guestNumber", request.getAdult()+request.getChild())
.setParameter("address", "%"+ request.getLocation()+"%")
.setParameter("checkIn", checkIn)
.setParameter("checkOut", checkOut)
.setParameter("checkIn", checkIn)
.setParameter("checkOut", checkOut)
.getResultList();
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package team15.airbnb.accommodation.presentation.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import team15.airbnb.accommodation.application.AccommodationService;
import team15.airbnb.accommodation.presentation.dto.AccommodationDetailsResponse;
import team15.airbnb.accommodation.presentation.dto.AccommodationFeesResponse;
import team15.airbnb.accommodation.presentation.dto.SearchAccommodationsByOptionsResponse;
import team15.airbnb.accommodation.presentation.dto.SearchAccommodationsOptionsRequest;


@RestController
@RequestMapping("/accommodations")
Expand All @@ -33,4 +32,12 @@ public ResponseEntity<AccommodationFeesResponse> searchAccommodationsByFeeRange(
@RequestParam(defaultValue = MAX_VALUE) int maxPrice) {
return ResponseEntity.ok().body(accommodationService.searchByFeeRange(minPrice, maxPrice));
}

@GetMapping
public ResponseEntity<SearchAccommodationsByOptionsResponse> searchAccommodationsWithOptions(SearchAccommodationsOptionsRequest request) {
/*
Todo : jwt 토큰으로부터 UserId 꺼내오는 작업 / 현재는 임시로 2번 유저를 기준으로 조회하도록 작성
*/
return ResponseEntity.ok().body(accommodationService.searchByOptions(request, 2L));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package team15.airbnb.accommodation.presentation.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Getter
@NoArgsConstructor
public class AccommodationListResponse {

private int totalCount;
private List<AccommodationSimpleInfoResponse> accommodations = new ArrayList<>();

public AccommodationListResponse(List<AccommodationSimpleInfoResponse> accommodations) {
totalCount = accommodations.size();
this.accommodations = accommodations;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package team15.airbnb.accommodation.presentation.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import team15.airbnb.user.domain.UserType;


@Getter
@NoArgsConstructor
public class AccommodationSimpleInfoResponse {

private Long accommodationId;
private boolean like;
private boolean superHost;
private String accommodationName;
private String mainImage;
private Double starRating;
private Integer reviewCount;
private Integer price;
private int totalPrice;
private double longitude;
private double latitude;

public AccommodationSimpleInfoResponse(Long accommodationId, Boolean like, UserType host, String accommodationName, String mainImage, Double starRating, Integer reviewCount, Integer price, String coordinate) throws ParseException {
this.accommodationId = accommodationId;
this.like = like;
this.superHost = host.isSuperHost();
this.accommodationName = accommodationName;
this.mainImage = mainImage;
this.starRating = starRating;
this.reviewCount = reviewCount;
this.price = price;
this.totalPrice = 0;
Point point = (Point) new WKTReader().read(coordinate);
this.longitude = point.getY();
this.latitude = point.getX();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package team15.airbnb.accommodation.presentation.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class SearchAccommodationsByOptionsResponse {

/*
Todo: 페이징 처리를 완료하면 hasNext값을 설정할 것.
*/
private boolean hasNext;
private AccommodationListResponse data;

public SearchAccommodationsByOptionsResponse(AccommodationListResponse data) {
this.data = data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package team15.airbnb.accommodation.presentation.dto;

import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@ToString
public class SearchAccommodationsOptionsRequest{

private String location="";
private String checkIn;
private String checkOut;
private int minPrice;
private int maxPrice = 1000000;
private int adult;
private int child;
private int baby;

}
11 changes: 11 additions & 0 deletions backend/src/main/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,14 @@ values ('2022-01-01 00:10:01', '2022-01-01 00:10:01', false, '개 별 로.', 0.7

insert into review(created_at, last_modified_at, is_deleted, content, star_rating, accommodation_id, user_id)
values ('2022-01-01 00:10:01', '2022-01-01 00:10:01', false, '코브스 선정 최악의 숙소 1위', 1.7, 1, 3);


-- reservation 예약
insert into reservation(created_at, is_deleted, last_modified_at, check_in_date, check_out_date, accommodation_id, user_id)
values('2022-01-01 00:10:01',false,'2022-01-01 00:10:01', '2022-05-24', '2022-05-26', 1, 4);

insert into reservation(created_at, is_deleted, last_modified_at, check_in_date, check_out_date, accommodation_id, user_id)
values('2022-01-01 00:10:01',false,'2022-01-01 00:10:01', '2022-06-10', '2022-06-11', 2, 4);

insert into reservation(created_at, is_deleted, last_modified_at, check_in_date, check_out_date, accommodation_id, user_id)
values('2022-01-01 00:10:01',false,'2022-01-01 00:10:01', '2022-05-22', '2022-05-23', 3, 4);

0 comments on commit 55ffa5b

Please sign in to comment.