diff --git a/.gitignore b/.gitignore index 71ee9e4..dab71af 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,6 @@ out/ .vscode/ ### application.properties ### -src/main/resources/application-local.yml \ No newline at end of file +src/main/resources/application-local.yml + +src/main/generated/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 1bcbf3b..08f8da4 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,24 @@ dependencies { // implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' } +sourceSets { + main { + java { + srcDirs = ['src/main/java', 'src/main/resources'] + } + } +} + tasks.named('test') { useJUnitPlatform() } + +def querydslSrcDir = 'src/main/generated' + +clean { + delete file(querydslSrcDir) +} + +tasks.withType(JavaCompile) { + options.generatedSourceOutputDirectory = file(querydslSrcDir) +} \ No newline at end of file diff --git a/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java b/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java index 12b8144..21dd9fe 100644 --- a/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java +++ b/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java @@ -1,16 +1,26 @@ package com.sumte.guesthouse.controller; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.sumte.apiPayload.ApiResponse; +import com.sumte.apiPayload.exception.annotation.CheckPage; +import com.sumte.apiPayload.exception.annotation.CheckPageSize; +import com.sumte.guesthouse.dto.GuesthousePreviewDTO; import com.sumte.guesthouse.dto.GuesthouseRequestDTO; +import com.sumte.guesthouse.dto.GuesthouseSearchRequestDTO; import com.sumte.guesthouse.service.GuesthouseCommandService; +import com.sumte.guesthouse.service.GuesthouseQueryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -20,11 +30,12 @@ import lombok.RequiredArgsConstructor; @RestController -@Tag(name = "게스트 하우스 관련 api", description = "게스트하우스 생성/수정/삭제 api 입니다.") +@Tag(name = "게스트 하우스 관련 api", description = "게스트하우스 생성/수정/조회/삭제 api 입니다.") @RequiredArgsConstructor @RequestMapping("/guesthouse") public class GuesthouseController { private final GuesthouseCommandService guesthouseCommandService; + private final GuesthouseQueryService guesthouseQueryService; @Operation(summary = "게스트하우스 등록", description = "게스트하우스를 등록합니다.") @PostMapping @@ -61,4 +72,20 @@ public ApiResponse updateGuesthouse( } + @PostMapping("/search") + @Operation(summary = "게스트 하우스 필터링 조회", description = "게스트 하우스를 검색 조건에 맞게 조회합니다.") + @Parameters({ + @Parameter(name = "page", description = "몇 번째 페이지를 조회할지 입력해주세요(1 이상의 정수)"), + @Parameter(name = "size", description = "한번에 몇개의 게스트 하우스를 조회할지 입력해주세요(1 이상의 정수) ") + }) + public ResponseEntity>> searchGuesthouse( + @RequestBody @Valid GuesthouseSearchRequestDTO dto, + @CheckPage @RequestParam(name = "page", defaultValue = "1") int page, + @CheckPageSize @RequestParam(name = "size", defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page - 1, size); + Page result = guesthouseQueryService.getFilteredGuesthouse(dto, pageable); + return ResponseEntity.ok(ApiResponse.success(result)); + + } + } diff --git a/src/main/java/com/sumte/guesthouse/controller/OptionServiceController.java b/src/main/java/com/sumte/guesthouse/controller/OptionServiceController.java new file mode 100644 index 0000000..6be9b27 --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/controller/OptionServiceController.java @@ -0,0 +1,31 @@ +package com.sumte.guesthouse.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.sumte.apiPayload.ApiResponse; +import com.sumte.guesthouse.dto.OptionResponseDTO; +import com.sumte.guesthouse.service.OptionQueryService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + +@RestController +@Tag(name = "부가서비스 조회 api", description = "부가서비스 리스트를 조회하는 api 입니다.") +@RequiredArgsConstructor +@RequestMapping("/option") +public class OptionServiceController { + + private final OptionQueryService optionQueryService; + + @GetMapping + @Operation(summary = "부가서비스 목록 조회", description = "부가서비스 목록을 전체 조회합니다") + public ApiResponse getOptionServices() { + OptionResponseDTO.OptionList optionServiceList = optionQueryService.getAllOptionServices(); + + return ApiResponse.success(optionServiceList); + + } +} diff --git a/src/main/java/com/sumte/guesthouse/controller/TargetAudienceController.java b/src/main/java/com/sumte/guesthouse/controller/TargetAudienceController.java new file mode 100644 index 0000000..1e2a0bf --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/controller/TargetAudienceController.java @@ -0,0 +1,31 @@ +package com.sumte.guesthouse.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.sumte.apiPayload.ApiResponse; +import com.sumte.guesthouse.dto.OptionResponseDTO; +import com.sumte.guesthouse.service.TargetQeuryService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + +@RestController +@Tag(name = "이용대상 조회 api", description = "게스트하우스의 이용대상을 조회하는 api 입니다.") +@RequiredArgsConstructor +@RequestMapping("/target") +public class TargetAudienceController { + + private final TargetQeuryService targetQeuryService; + + @GetMapping + @Operation(summary = "이용대상 조회", description = "필터링 시 게스트 하우스의 이용대상 목록을 전체 조회합니다") + public ApiResponse getTargetAudience() { + OptionResponseDTO.TargetList targetAudienceList = targetQeuryService.getAllTargetAudience(); + + return ApiResponse.success(targetAudienceList); + + } +} diff --git a/src/main/java/com/sumte/guesthouse/converter/OptionServiceConverter.java b/src/main/java/com/sumte/guesthouse/converter/OptionServiceConverter.java new file mode 100644 index 0000000..d78f465 --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/converter/OptionServiceConverter.java @@ -0,0 +1,32 @@ +package com.sumte.guesthouse.converter; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import com.sumte.guesthouse.dto.OptionResponseDTO; +import com.sumte.guesthouse.entity.OptionServices; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class OptionServiceConverter { + public static OptionResponseDTO.Option toOption(OptionServices optionServices) { + return OptionResponseDTO.Option.builder() + .name(optionServices.getName()) + .build(); + } + + public static OptionResponseDTO.OptionList toOptionList(List optionServices) { + + List optionList = optionServices.stream() + .map(OptionServiceConverter::toOption).collect(Collectors.toList()); + + return OptionResponseDTO.OptionList.builder() + .options(optionList) + .build(); + + } +} diff --git a/src/main/java/com/sumte/guesthouse/converter/TargetAudienceConverter.java b/src/main/java/com/sumte/guesthouse/converter/TargetAudienceConverter.java new file mode 100644 index 0000000..f342ee9 --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/converter/TargetAudienceConverter.java @@ -0,0 +1,32 @@ +package com.sumte.guesthouse.converter; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import com.sumte.guesthouse.dto.OptionResponseDTO; +import com.sumte.guesthouse.entity.TargetAudience; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class TargetAudienceConverter { + public static OptionResponseDTO.Target toTarget(TargetAudience targetAudience) { + return OptionResponseDTO.Target.builder() + .name(targetAudience.getName()) + .build(); + } + + public static OptionResponseDTO.TargetList toTargetList(List targetAudiences) { + + List optionList = targetAudiences.stream() + .map(TargetAudienceConverter::toTarget).collect(Collectors.toList()); + + return OptionResponseDTO.TargetList.builder() + .targets(optionList) + .build(); + + } +} diff --git a/src/main/java/com/sumte/guesthouse/dto/GuesthousePreviewDTO.java b/src/main/java/com/sumte/guesthouse/dto/GuesthousePreviewDTO.java new file mode 100644 index 0000000..b99abc2 --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/dto/GuesthousePreviewDTO.java @@ -0,0 +1,30 @@ +package com.sumte.guesthouse.dto; + +import java.time.LocalTime; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GuesthousePreviewDTO { + private Long id; + private String name; + private Double averageScore; + private Long reviewCount; + private Long lowerPrice; + private String addressRegion; + private LocalTime checkinTime; + + public void setAverageScore(Double averageScore) { + this.averageScore = averageScore; + } + + public void setReviewCount(Long reviewCount) { + this.reviewCount = reviewCount; + } +} diff --git a/src/main/java/com/sumte/guesthouse/dto/GuesthouseSearchRequestDTO.java b/src/main/java/com/sumte/guesthouse/dto/GuesthouseSearchRequestDTO.java new file mode 100644 index 0000000..dd8e1db --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/dto/GuesthouseSearchRequestDTO.java @@ -0,0 +1,59 @@ +package com.sumte.guesthouse.dto; + +import java.time.LocalDate; +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GuesthouseSearchRequestDTO { + + @NotNull + private Boolean viewEnableReservation; + + @NotNull + @Schema(description = "체크인 날짜 (yyyy-MM-dd)", required = true) + private LocalDate checkIn; + + @NotNull + @Schema(description = "체크아웃 날짜 (yyyy-MM-dd)", required = true) + private LocalDate checkOut; + + @NotNull + @Schema(description = "인원 수", required = true) + private Long people; + + @Schema(description = "최소 가격(필터링 시 입력)", required = false) + private Long minPrice; + + @Schema(description = "최대 가격(필터링 시 입력)", required = false) + private Long maxPrice; + + @Schema(description = "최소 인원(필터링 시 입력)", required = false) + private Long minPeople; + + @Schema(description = "최대 인원(필터링 시 입력)", required = false) + private Long maxPeople; + + @Schema(description = "검색 키워드 입력 (제주 애월 끌림 게스트하우스)", required = false) + private String keyword; + + @Schema(description = "원하는 부가 서비스를 조회후 해당 목록에 있는 값들 중 원하는 것들을 list형태로 입력", required = false) + private List optionService; + + @Schema(description = "원하는 이용대상을 조회후 해당 목록에 있는 값들 중 원하는 것들을 list형태로 입력", required = false) + private List targetAudience; + + @Schema(description = "지역 키워드를 선택하여 list형태로 입력 (피그마에 나와있는 키워드 그대로 입력) ", required = false) + private List region; + +} + diff --git a/src/main/java/com/sumte/guesthouse/dto/OptionResponseDTO.java b/src/main/java/com/sumte/guesthouse/dto/OptionResponseDTO.java new file mode 100644 index 0000000..f64b137 --- /dev/null +++ b/src/main/java/com/sumte/guesthouse/dto/OptionResponseDTO.java @@ -0,0 +1,48 @@ +package com.sumte.guesthouse.dto; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class OptionResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class Target { + String name; + } + + // 페이징 처리 안한 이유는 어차피 targetAudience 나 OptionService같은 경우엔 + // 굳이 필요 없을 것 같기 때문입니다. 전체 조회 api 이기도 하구요 + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class TargetList { + List targets; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class Option { + String name; + } + + // 페이징 처리 안한 이유는 어차피 targetAudience 나 OptionService같은 경우엔 + // 굳이 필요 없을 것 같기 때문입니다. 전체 조회 api 이기도 하구요 + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class OptionList { + List