Skip to content

Commit

Permalink
Merge pull request #84 from TravelCompass-UMC/refactor/74
Browse files Browse the repository at this point in the history
Refactor : 여행 계획 검색 기능 추가 및 스웨거 추가
  • Loading branch information
Enble authored Feb 13, 2024
2 parents 33bb08b + e4eee0a commit 857a234
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public enum ErrorCode implements BaseCode {
PLAN_NOT_FOUND(HttpStatus.NOT_FOUND, "PLAN_404", "여행계획을 찾을 수 없습니다."),
PLAN_LOCATION_NOT_FOUND(HttpStatus.NOT_FOUND,"PLAN_4042","여행장소를 찾을 수 없습니다."),
WRONG_INVITE_CODE(HttpStatus.NOT_FOUND, "PLAN_4043", "유효하지 않은 초대코드입니다."),
WRONG_SORTING_WAY(HttpStatus.BAD_REQUEST, "PLAN_400", "유효하지 않은 정렬 방법입니다."),
WRONG_SORTING_WAY(HttpStatus.BAD_REQUEST, "PLAN_4001", "유효하지 않은 정렬 방법입니다."),
WRONG_VEHICLE_PARAM(HttpStatus.BAD_REQUEST, "PLAN_4002", "유효하지 않은 교통수단 입니다."),

//Hashtag
HASHTAG_NOT_FOUND(HttpStatus.NOT_FOUND, "HASHTAG_404", "해시태그를 찾을 수 없습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class MypageController {
private final UserService userService;

// 나의 정보 조회
@Operation(summary = "나의 정보 조회 메서드", description = "나의 정보를 조회하는 메서드입니다.")
@Operation(summary = "나의 정보 조회 메서드", description = "나의 정보를 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "MYPAGE_2001", description = "나의 정보 조회 성공")
})
Expand All @@ -51,7 +51,7 @@ public ApiResponse<MyInfoDto> findMyInfo(
}

// 나의 계획 조회
@Operation(summary = "나의 여행계획 조회 메서드", description = "나의 여행계획을 조회하는 메서드입니다.")
@Operation(summary = "나의 여행계획 조회 메서드", description = "나의 여행계획을 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "MYPAGE_2002", description = "나의 계획 조회 성공")
})
Expand All @@ -71,7 +71,7 @@ public ApiResponse<PlanListResponseDto> searchMyPlans(
}

// 내가 좋아요한 여행계획 조회
@Operation(summary = "좋아요한 여행계획 조회", description = "내가 좋아요한 여행계획을 조회하는 메서드입니다.")
@Operation(summary = "좋아요한 여행계획 조회", description = "내가 좋아요한 여행계획을 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "MYPAGE_2003", description = "좋아요한 계획 조회 성공")
})
Expand All @@ -91,7 +91,7 @@ public ApiResponse<PlanListResponseDto> searchLikedPlans(
}

// 내가 좋아요한 장소 조회
@Operation(summary = "좋아요한 장소 조회", description = "내가 좋아요한 장소를 조회하는 메서드입니다.")
@Operation(summary = "좋아요한 장소 조회", description = "내가 좋아요한 장소를 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "MYPAGE_2004", description = "좋아요한 장소 조회 성공")
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
import com.travelcompass.api.plan.dto.PlanResponseDto.PlanListResponseDto;
import com.travelcompass.api.plan.dto.PlanResponseDto.PlanLocationListDto;
import com.travelcompass.api.plan.service.PlanService;
import com.travelcompass.api.region.service.RegionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import net.bytebuddy.description.type.TypeList;
import org.springframework.data.domain.Page;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.parameters.P;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand All @@ -39,9 +42,10 @@ public class PlanController {
private final UserService userService;
private final PlanService planService;
private final HashtagService hashtagService;
private final RegionService regionService;

// plan 새로 만들기
@Operation(summary = "여행 계획 생성 메서드", description = "여행 계획을 생성하는 메서드입니다.")
@Operation(summary = "여행 계획 생성 메서드", description = "여행 계획을 생성하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "PLAN_2011", description = "계획 생성 성공")
})
Expand All @@ -64,7 +68,7 @@ public ApiResponse<PlanLocationListDto> createNewPlan(
}

// plan 수정하기
@Operation(summary = "여행 계획 수정 메서드", description = "여행 계획을 수정하는 메서드입니다.")
@Operation(summary = "여행 계획 수정 메서드", description = "여행 계획을 수정하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "PLAN_2002", description = "계획 수정 성공")
})
Expand All @@ -85,7 +89,7 @@ public ApiResponse<PlanLocationListDto> modifyMyPlan(
}

// 초대코드로 초대하기
@Operation(summary = "여행 계획 초대 메서드", description = "여행 계획에 초대하는 메서드입니다.")
@Operation(summary = "여행 계획 초대 메서드", description = "여행 계획에 초대하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "PLAN_2012", description = "계획 초대 성공")
})
Expand All @@ -105,13 +109,13 @@ public ApiResponse<DetailPlanResponseDto> inviteUserToPlan(
}

// 모든 일차 가져오기
@Operation(summary = "모든일자 조회 메서드", description = "여행 계획의 모든일자의 계획을 조회하는 메서드입니다.")
@Operation(summary = "모든일자 조회 메서드", description = "여행 계획의 모든일자의 계획을 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "PLAN_2001", description = "계획 조회 성공")
})
@Parameter(name = "plan-id", description = "여행계획의 아이디, path variable")
@GetMapping("/{plan-id}")
private ApiResponse<PlanLocationListDto> getAllPlanDetails(
public ApiResponse<PlanLocationListDto> getAllPlanDetails(
@PathVariable(name = "plan-id") Long planId,
@AuthenticationPrincipal CustomUserDetails customUserDetails
){
Expand All @@ -125,7 +129,7 @@ private ApiResponse<PlanLocationListDto> getAllPlanDetails(
}

// day 일차 가져오기
@Operation(summary = "특정일자 조회 메서드", description = "여행 계획의 특정일자의 계획을 조회하는 메서드입니다.")
@Operation(summary = "특정일자 조회 메서드", description = "여행 계획의 특정일자의 계획을 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "PLAN_2001", description = "계획 조회 성공")
})
Expand All @@ -134,7 +138,7 @@ private ApiResponse<PlanLocationListDto> getAllPlanDetails(
@Parameter(name = "day", description = "조회하고 싶은 날, path variable")
})
@GetMapping("/{plan-id}/{day}")
private ApiResponse<PlanLocationListDto> getDayPlanDetails(
public ApiResponse<PlanLocationListDto> getDayPlanDetails(
@PathVariable(name = "plan-id") Long planId,
@PathVariable(name = "day") Long day,
@AuthenticationPrincipal CustomUserDetails customUserDetails
Expand All @@ -148,24 +152,30 @@ private ApiResponse<PlanLocationListDto> getDayPlanDetails(
return ApiResponse.onSuccess(SuccessCode.PLAN_VIEW_SUCCESS, PlanConverter.planLocationListDto(planLocationByDay, planDto));
}

@Operation(summary = "여행계획 조회 메서드", description = "여행 계획 리스트를 조회하는 메서드입니다.")
@Operation(summary = "여행계획 조회 메서드", description = "여행 계획 리스트를 조회하는 메서드입니다. - 김현우")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "PLAN_2001", description = "계획 조회 성공")
})
@Parameters({
@Parameter(name = "page", description = "페이지 번호, 0번이 1페이지 입니다."),
@Parameter(name = "regionId", description = "조회하고 싶은 지역의 아이디"),
@Parameter(name = "way", description = "정렬 방식, 1.좋아요순, 2.조회수순, 3.최신순 ")
@Parameter(name = "days", description = "총 여행일수를 숫자로 설정 / 당일치기는 0, 음수를 넣으면 2일 이상인 모든 여행계획을 검색함/ 설정 안하면 모든 여행계획 중 검색"),
@Parameter(name = "regionId", description = "조회하고 싶은 지역의 아이디 / 설정 안하면 모든 지역의 여행계획 중에서 검색"),
@Parameter(name = "vehicle", description = "PUBLIC, PRIVATE 중에 설정 / 대중교통, 자가용 / 설정 안하면 모든 여행계획 중 검색"),
@Parameter(name = "way", description = "정렬 방식 / 1, 2, 3 중 설정 / 1.좋아요순, 2.조회수순, 3.최신순 "),
@Parameter(name = "hashtags", description = "문자열 리스트 / 해쉬태그가 하나라도 포함되어있는 여행계획을 반환")
})
@GetMapping("/search")
private ApiResponse<PlanListResponseDto> getPlanList(
public ApiResponse<PlanListResponseDto> getPlanList(
@RequestParam(name = "page") Integer page,
@RequestParam(name = "regionId") Long regionId,
@RequestParam(name = "way") Integer way
@RequestParam(name = "days", required = false) Integer days,
@RequestParam(name = "regionId", required = false) Long regionId,
@RequestParam(name = "vehicle", required = false) String vehicle,
@RequestParam(name = "way", defaultValue = "3") Integer way,
@RequestParam(name = "hashtags", required = false) List<String> hashtags
){
Page<Plan> planList = planService.getPlanList(page, regionId, way);

return ApiResponse.onSuccess(SuccessCode.PLAN_VIEW_SUCCESS, PlanConverter.planListResponseDto(planList));
Page<Plan> plans = planService.searchPlans(page, 12, way, days, regionId, vehicle, hashtags);
PlanConverter.planListResponseDto(plans);
return ApiResponse.onSuccess(SuccessCode.PLAN_VIEW_SUCCESS, PlanConverter.planListResponseDto(plans));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
Expand All @@ -30,6 +31,9 @@
public class PlanConverter {

public static Plan toPlan(PlanReqDto request, Region region){

Long days = ChronoUnit.DAYS.between(request.getStartDate(), request.getEndDate());

return Plan.builder()
.title(request.getTitle())
.startDate(request.getStartDate())
Expand All @@ -40,6 +44,7 @@ public static Plan toPlan(PlanReqDto request, Region region){
.adultCount(request.getAdultCount())
.childCount(request.getChildCount())
.hits(0L)
.days(days)
.likeCount(0L)
.hashtagPlans(new ArrayList<>())
.build();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/travelcompass/api/plan/domain/Plan.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class Plan extends BaseEntity {

private Long likeCount; // 좋아요 수

private Long days; // 총 일수, 당일치기는 0

@Enumerated(EnumType.STRING)
private PlanVehicle vehicle;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.travelcompass.api.plan.domain;

import com.travelcompass.api.global.api_payload.ErrorCode;
import com.travelcompass.api.global.exception.GeneralException;
import com.travelcompass.api.hashtag.domain.HashtagPlan;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Predicate;
import org.springframework.data.jpa.domain.Specification;

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

public class PlanSpecification {

public static Specification<Plan> filteredByParameters(Integer days, Long regionId, String vehicle, List<String> hashtags){
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();

if (days != null && days >= 0) {
predicates.add(criteriaBuilder.equal(root.get("days"), days));
} else if (days != null && days < 0) {
predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("days"), 2));
}
if (regionId != null) {
predicates.add(criteriaBuilder.equal(root.get("region").get("id"), regionId));
}
if (vehicle != null) {
try {
PlanVehicle planVehicle = PlanVehicle.valueOf(vehicle);
predicates.add(criteriaBuilder.equal(root.get("vehicle"), planVehicle));
} catch (IllegalArgumentException e) {
throw GeneralException.of(ErrorCode.WRONG_VEHICLE_PARAM);
}
}
if (hashtags != null && !hashtags.isEmpty()) {
Join<Plan, HashtagPlan> hashtagJoin = root.join("hashtagPlans");
predicates.add(hashtagJoin.get("hashtag").get("name").in(hashtags));
}

return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Repository
public interface PlanRepository extends JpaRepository<Plan, Long> {
public interface PlanRepository extends JpaRepository<Plan, Long>, JpaSpecificationExecutor<Plan> {
Optional<Plan> findByInviteCode(UUID inviteCode);

Page<Plan> findAllByRegion(Region region, PageRequest pageRequest);
List<Plan> findAllByRegion(Region region);
}
41 changes: 24 additions & 17 deletions src/main/java/com/travelcompass/api/plan/service/PlanService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import com.travelcompass.api.location.service.LocationService;
import com.travelcompass.api.oauth.domain.User;
import com.travelcompass.api.plan.converter.PlanConverter;
import com.travelcompass.api.plan.domain.Plan;
import com.travelcompass.api.plan.domain.PlanLocation;
import com.travelcompass.api.plan.domain.PlanUser;
import com.travelcompass.api.plan.domain.ViewCount;
import com.travelcompass.api.plan.domain.*;
import com.travelcompass.api.plan.dto.PlanRequestDto.CreatePlanLocationListDto;
import com.travelcompass.api.plan.dto.PlanRequestDto.PlanReqDto;
import com.travelcompass.api.plan.repository.PlanLocationRepository;
Expand All @@ -22,7 +19,9 @@
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -114,22 +113,30 @@ public Plan findPlanByInviteCode(String inviteCode) {
.orElseThrow(() -> GeneralException.of(ErrorCode.WRONG_INVITE_CODE));
}

public Page<Plan> getPlanList(Integer page, Long regionId, Integer way) {

Region region = regionService.findRegionById(regionId);
public Page<Plan> searchPlans(Integer page, Integer pageSize, Integer way, Integer days, Long regionId, String vehicle, List<String> hashtags){
Pageable pageable = createPageable(page, pageSize, way);
return planRepository.findAll(PlanSpecification.filteredByParameters(days, regionId, vehicle, hashtags), pageable);
}

if (way == 1) { // 좋아요 순
return planRepository
.findAllByRegion(region, PageRequest.of(page, 12, Sort.by("likeCount").descending()));
} else if (way == 2) { // 조회 많은 순
return planRepository
.findAllByRegion(region, PageRequest.of(page, 12, Sort.by("hits").descending()));
} else if (way == 3) { // 최신 순
return planRepository
.findAllByRegion(region, PageRequest.of(page, 12, Sort.by("createdAt").descending()));
private Pageable createPageable(Integer page, Integer pageSize, Integer way){
Sort sort;

if (way != null){
switch (way){
case 1:
sort = Sort.by(Sort.Direction.DESC, "likeCount");
break;
case 2:
sort = Sort.by(Sort.Direction.DESC, "hits");
break;
default:
sort = Sort.by(Sort.Direction.DESC, "id");
}
} else {
throw GeneralException.of(ErrorCode.WRONG_SORTING_WAY);
sort = Sort.by(Sort.Direction.DESC, "id");
}

return PageRequest.of(page, pageSize, sort);
}

}

0 comments on commit 857a234

Please sign in to comment.