diff --git a/src/main/java/com/onna/onnaback/domain/place/adapter/in/web/PlaceController.java b/src/main/java/com/onna/onnaback/domain/place/adapter/in/web/PlaceController.java index a0a8811..4570b19 100644 --- a/src/main/java/com/onna/onnaback/domain/place/adapter/in/web/PlaceController.java +++ b/src/main/java/com/onna/onnaback/domain/place/adapter/in/web/PlaceController.java @@ -2,15 +2,20 @@ import java.util.List; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceDetailInfo; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceSearchDto; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +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 com.onna.onnaback.domain.place.adapter.in.web.response.PlaceDetailInfo; import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceReloadDto; +import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceSearchDto; import com.onna.onnaback.domain.place.application.port.in.PlaceUseCase; import com.onna.onnaback.domain.place.domain.PlaceType; import com.onna.onnaback.domain.spark.domain.DurationHour; +import com.onna.onnaback.domain.spark.domain.SortType; import com.onna.onnaback.domain.spark.domain.SparkType; import io.swagger.v3.oas.annotations.Operation; @@ -28,6 +33,7 @@ public ResponseEntity> reload( @RequestParam(value = "sparkType", required = false) SparkType sparkType, @RequestParam(value = "durationHour", required = false) DurationHour durationHour, @RequestParam(value = "placeType", required = false) PlaceType placeType, + @RequestParam(value = "sort", required = false) SortType sortType, @RequestParam(value = "southwestLongitude") Double southwestLongitude, @RequestParam(value = "northeastLongitude") Double northeastLongitude, @RequestParam(value = "southwestLatitude") Double southwestLatitude, @@ -38,6 +44,7 @@ public ResponseEntity> reload( sparkType, durationHour, placeType, + sortType, southwestLongitude, northeastLongitude, southwestLatitude, northeastLatitude) ); @@ -45,14 +52,13 @@ public ResponseEntity> reload( @Operation(description = "장소 키워드 검색 API") @GetMapping("/search/{value}") - public ResponseEntity> searchPlace(@PathVariable("value")String value){ + public ResponseEntity> searchPlace(@PathVariable("value") String value) { return ResponseEntity.ok().body(this.placeUseCase.searchPlace(value)); } @Operation(description = "장소 상세조회") @GetMapping("/{placeId}") - public ResponseEntity getPlaceDetail(@PathVariable("placeId") Long placeId) - { + public ResponseEntity getPlaceDetail(@PathVariable("placeId") Long placeId) { return ResponseEntity.ok().body(this.placeUseCase.getPlaceInfo(placeId)); } } diff --git a/src/main/java/com/onna/onnaback/domain/place/adapter/out/persistence/PlacePersistenceAdapter.java b/src/main/java/com/onna/onnaback/domain/place/adapter/out/persistence/PlacePersistenceAdapter.java index f1f65b3..e969222 100644 --- a/src/main/java/com/onna/onnaback/domain/place/adapter/out/persistence/PlacePersistenceAdapter.java +++ b/src/main/java/com/onna/onnaback/domain/place/adapter/out/persistence/PlacePersistenceAdapter.java @@ -19,6 +19,8 @@ import com.onna.onnaback.domain.place.domain.Place; import com.onna.onnaback.domain.place.domain.PlaceType; import com.onna.onnaback.domain.spark.domain.DurationHour; +import com.onna.onnaback.domain.spark.domain.RecruitType; +import com.onna.onnaback.domain.spark.domain.SortType; import com.onna.onnaback.domain.spark.domain.Spark; import com.onna.onnaback.domain.spark.domain.SparkType; @@ -32,6 +34,7 @@ public class PlacePersistenceAdapter implements LoadPlacePort { @Override public List getMarkers(SparkType sparkType, DurationHour durationHour, PlaceType placeType, + SortType sortType, Double southwestLongitude, Double northeastLongitude, Double southwestLatitude, Double northeastLatitude) { Specification spec = Specification.where(null); @@ -48,6 +51,11 @@ public List getMarkers(SparkType sparkType, DurationHour duratio spec = spec.and(hasPlaceType(placeType)); } + // 모집중 + if (sortType == SortType.RECRUITING) { + spec = spec.and(hasRecruiting()); + } + spec = spec.and(hasLocationBetween(southwestLongitude, northeastLongitude, southwestLatitude, northeastLatitude)); @@ -59,7 +67,7 @@ public List getMarkers(SparkType sparkType, DurationHour duratio for (Place place : places) { if (!uniquePlaceIds.contains(place.getPlaceId())) { - Long sparkCount = calculateSparkCount(place); + Long sparkCount = calculateSparkCount(place, sparkType, durationHour, sortType); result.add(new PlaceReloadDto(place.getPlaceId(), place.getPlaceType(), place.getLongitude(), @@ -72,8 +80,29 @@ public List getMarkers(SparkType sparkType, DurationHour duratio return result; } - private Long calculateSparkCount(Place place) { - return (long) place.getSparkList().size(); + // 필터에 맞는 스파크 클래스/미팅 개수 구함 + private Long calculateSparkCount(Place place, SparkType sparkType, + DurationHour durationHour, + SortType sortType) { + List sparks = place.getSparkList(); + Long sparkCnt = (long) place.getSparkList().size(); + + for (Spark spark : sparks) { + if (sparkType != null && spark.getType() != sparkType) { + sparkCnt--; + continue; + } + if (durationHour != null && spark.getDurationHour() != durationHour) { + sparkCnt--; + continue; + } + // 모집중 + if (sortType == SortType.RECRUITING && spark.getRecruitType() != RecruitType.RECRUITING) { + sparkCnt--; + } + } + + return sparkCnt; } @Override @@ -124,6 +153,18 @@ private Specification hasPlaceType(PlaceType placeType) { return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("placeType"), placeType); } + private Specification hasRecruiting() { + return (root, query, criteriaBuilder) -> { + List predicates = new ArrayList<>(); + + Join sparkJoin = root.join("sparkList"); + + predicates.add(criteriaBuilder.equal(sparkJoin.get("recruitType"), RecruitType.RECRUITING)); + + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + }; + } + private Specification hasLocationBetween(Double southwestLongitude, Double northeastLongitude, Double southwestLatitude, Double northeastLatitude) { return (root, query, criteriaBuilder) -> { diff --git a/src/main/java/com/onna/onnaback/domain/place/application/port/in/PlaceUseCase.java b/src/main/java/com/onna/onnaback/domain/place/application/port/in/PlaceUseCase.java index d7fd8e2..f57a989 100644 --- a/src/main/java/com/onna/onnaback/domain/place/application/port/in/PlaceUseCase.java +++ b/src/main/java/com/onna/onnaback/domain/place/application/port/in/PlaceUseCase.java @@ -4,17 +4,17 @@ import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceDetailInfo; import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceReloadDto; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceResponse; import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceSearchDto; import com.onna.onnaback.domain.place.domain.Place; import com.onna.onnaback.domain.place.domain.PlaceType; import com.onna.onnaback.domain.spark.domain.DurationHour; +import com.onna.onnaback.domain.spark.domain.SortType; import com.onna.onnaback.domain.spark.domain.SparkType; public interface PlaceUseCase { List reload( SparkType sparkType, DurationHour durationHour, PlaceType placeType, - Double southwestLongitude, Double northeastLongitude, + SortType sortType, Double southwestLongitude, Double northeastLongitude, Double southwestLatitude, Double northeastLatitude ); diff --git a/src/main/java/com/onna/onnaback/domain/place/application/port/out/LoadPlacePort.java b/src/main/java/com/onna/onnaback/domain/place/application/port/out/LoadPlacePort.java index e7cd9e1..a1ff253 100644 --- a/src/main/java/com/onna/onnaback/domain/place/application/port/out/LoadPlacePort.java +++ b/src/main/java/com/onna/onnaback/domain/place/application/port/out/LoadPlacePort.java @@ -3,19 +3,19 @@ import java.util.List; import java.util.Optional; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceReloadDto; import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceReloadDto; import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceSearchDto; import com.onna.onnaback.domain.place.domain.Place; import com.onna.onnaback.domain.place.domain.PlaceType; import com.onna.onnaback.domain.spark.domain.DurationHour; +import com.onna.onnaback.domain.spark.domain.SortType; import com.onna.onnaback.domain.spark.domain.SparkType; public interface LoadPlacePort { List getMarkers( SparkType sparkType, DurationHour durationHour, PlaceType placeType, - Double southwestLongitude, Double northeastLongitude, + SortType sortType, Double southwestLongitude, Double northeastLongitude, Double southwestLatitude, Double northeastLatitude ); diff --git a/src/main/java/com/onna/onnaback/domain/place/application/service/PlaceService.java b/src/main/java/com/onna/onnaback/domain/place/application/service/PlaceService.java index bef2bfa..951fc25 100644 --- a/src/main/java/com/onna/onnaback/domain/place/application/service/PlaceService.java +++ b/src/main/java/com/onna/onnaback/domain/place/application/service/PlaceService.java @@ -1,23 +1,22 @@ package com.onna.onnaback.domain.place.application.service; import java.util.List; -import java.util.Optional; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceDetailInfo; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceResponse; -import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceSearchDto; -import com.onna.onnaback.global.exception.BaseException; -import com.onna.onnaback.global.exception.ErrorCode; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceDetailInfo; import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceReloadDto; +import com.onna.onnaback.domain.place.adapter.in.web.response.PlaceSearchDto; import com.onna.onnaback.domain.place.application.port.in.PlaceUseCase; import com.onna.onnaback.domain.place.application.port.out.LoadPlacePort; import com.onna.onnaback.domain.place.domain.Place; import com.onna.onnaback.domain.place.domain.PlaceType; import com.onna.onnaback.domain.spark.domain.DurationHour; +import com.onna.onnaback.domain.spark.domain.SortType; import com.onna.onnaback.domain.spark.domain.SparkType; +import com.onna.onnaback.global.exception.BaseException; +import com.onna.onnaback.global.exception.ErrorCode; import lombok.RequiredArgsConstructor; @@ -30,7 +29,7 @@ public class PlaceService implements PlaceUseCase { @Override public List reload( SparkType sparkType, DurationHour durationHour, PlaceType placeType, - Double southwestLongitude, Double northeastLongitude, + SortType sortType, Double southwestLongitude, Double northeastLongitude, Double southwestLatitude, Double northeastLatitude ) { // todo: 부산 외곽의 경우 에러 처리 @@ -38,7 +37,7 @@ public List reload( // 스파크 클래스/미팅 카운트 가져오기 return loadPlacePort.getMarkers( sparkType, durationHour, placeType, - southwestLongitude, northeastLongitude, + sortType, southwestLongitude, northeastLongitude, southwestLatitude, northeastLatitude); } @@ -54,17 +53,17 @@ public List searchPlace(String value) { @Override public PlaceDetailInfo getPlaceInfo(Long placeId) { - Place place = loadPlacePort.getById(placeId).orElseThrow(()-> new BaseException(ErrorCode.NOT_FOUND)); + Place place = loadPlacePort.getById(placeId).orElseThrow(() -> new BaseException(ErrorCode.NOT_FOUND)); return PlaceDetailInfo.builder() - .id(placeId) - .detailInfo(place.getDetailInfo()) - .img(place.getImg()) - .detailAddress(place.getDetailAddress()) - .businessHour(place.getBusinessHour()) - .description(place.getDescription()) - .name(place.getName()) - .phoneNum(place.getPhoneNum()) - .build(); + .id(placeId) + .detailInfo(place.getDetailInfo()) + .img(place.getImg()) + .detailAddress(place.getDetailAddress()) + .businessHour(place.getBusinessHour()) + .description(place.getDescription()) + .name(place.getName()) + .phoneNum(place.getPhoneNum()) + .build(); } }