Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

import com.wayble.server.common.response.CommonResponse;
import com.wayble.server.review.dto.ReviewRegisterDto;
import com.wayble.server.review.dto.ReviewResponseDto;
import com.wayble.server.review.service.ReviewService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Pattern;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;


import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/wayble-zones/{waybleZoneId}/reviews")
Expand All @@ -38,4 +43,17 @@ public CommonResponse<String> registerReview(
reviewService.registerReview(waybleZoneId, dto, authorizationHeader);
return CommonResponse.success("리뷰가 등록되었습니다.");
}

@GetMapping
@Operation(summary = "웨이블존 리뷰 목록 조회", description = "웨이블존에 대한 리뷰를 최신순 또는 평점순으로 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "리뷰 목록 조회 성공"),
@ApiResponse(responseCode = "404", description = "해당 웨이블존이 존재하지 않음")
})
public CommonResponse<List<ReviewResponseDto>> getReviews(
@PathVariable Long waybleZoneId,
@RequestParam(defaultValue = "latest") String sort
) {
return CommonResponse.success(reviewService.getReviews(waybleZoneId, sort));
}
}
14 changes: 12 additions & 2 deletions src/main/java/com/wayble/server/review/dto/ReviewResponseDto.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
package com.wayble.server.review.dto;

public record ReviewResponseDto() {
}
import java.time.LocalDate;
import java.util.List;

public record ReviewResponseDto(
Long reviewId,
String userNickname,
double rating,
String content,
LocalDate visitDate,
int likes,
List<String> images
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
import com.wayble.server.review.entity.Review;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ReviewRepository extends JpaRepository<Review, Long> {
List<Review> findByWaybleZoneIdOrderByCreatedAtDesc(Long waybleZoneId); // 최신순
List<Review> findByWaybleZoneIdOrderByRatingDesc(Long waybleZoneId); // 평점순
}
29 changes: 29 additions & 0 deletions src/main/java/com/wayble/server/review/service/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.wayble.server.common.exception.ApplicationException;
import com.wayble.server.review.dto.ReviewRegisterDto;
import com.wayble.server.review.dto.ReviewResponseDto;
import com.wayble.server.review.entity.Review;
import com.wayble.server.review.entity.ReviewImage;
import com.wayble.server.review.repository.ReviewImageRepository;
Expand All @@ -15,6 +16,9 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ReviewService {
Expand Down Expand Up @@ -43,4 +47,29 @@ public void registerReview(Long zoneId, ReviewRegisterDto dto, String token) {

// visitDate 및 facilities 저장은 필요시 추가 구현
}

public List<ReviewResponseDto> getReviews(Long zoneId, String sort) {
WaybleZone zone = waybleZoneRepository.findById(zoneId)
.orElseThrow(() -> new ApplicationException(WaybleZoneErrorCase.WAYBLE_ZONE_NOT_FOUND));

List<Review> reviews = switch (sort) {
case "rating" -> reviewRepository.findByWaybleZoneIdOrderByRatingDesc(zoneId);
case "latest" -> reviewRepository.findByWaybleZoneIdOrderByCreatedAtDesc(zoneId);
default -> reviewRepository.findByWaybleZoneIdOrderByCreatedAtDesc(zoneId);
};

return reviews.stream()
.map(review -> new ReviewResponseDto(
review.getId(),
review.getUser().getNickname(),
review.getRating(),
review.getContent(),
review.getCreatedAt().toLocalDate(),
review.getLikeCount(),
review.getReviewImageList().stream()
.map(ReviewImage::getImageUrl)
.collect(Collectors.toList())
))
.collect(Collectors.toList());
}
Comment thread
seung-in-Yoo marked this conversation as resolved.
}
29 changes: 29 additions & 0 deletions src/main/java/com/wayble/server/user/entity/UserPlace.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.wayble.server.user.entity;

import com.wayble.server.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;


@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "user_place") // 유져가 저장한 장소
public class UserPlace extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "title", nullable = false)
private String title;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.wayble.server.user.entity;

import com.wayble.server.wayblezone.entity.WaybleZone;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "user_place_wayble_zone_mapping") // 유저 장소와 웨이블존 다대다 매핑
public class UserPlaceWaybleZoneMapping {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_place_id", nullable = false)
private UserPlace userPlace;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "wayble_zone_id", nullable = false)
private WaybleZone waybleZone;
}
36 changes: 18 additions & 18 deletions src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.wayble.server.common.entity.Address;
import com.wayble.server.common.entity.BaseEntity;
import com.wayble.server.review.entity.Review;
import com.wayble.server.user.entity.UserPlaceWaybleZoneMapping;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.SQLDelete;
Expand All @@ -18,43 +19,42 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SQLDelete(sql = "UPDATE wayble_zone SET deleted_at = now() WHERE id = ?")
@SQLRestriction("deleted_at IS NULL")
@Table(name = "wayble_zone")
@Table(name = "wayble_zone") // 웨이블 존
public class WaybleZone extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String zoneName;
private String zoneName; // 가게 이름

private String contactNumber;
private String contactNumber; // 가게 전화 번호

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private WaybleZoneType zoneType;
private WaybleZoneType zoneType; // 가게 타입 (음식점,카페,편의점)

@Embedded
private Address address;
private Address address; // 주소

@Column(nullable = false)
private double rating = 0.0; // 누적 평균 평점

@Column(nullable = false)
private int reviewCount = 0; // 리뷰 수

@OneToMany(mappedBy = "waybleZone", cascade = CascadeType.ALL, orphanRemoval = true)
private List<WaybleZoneImage> waybleZoneImageList = new ArrayList<>();

@OneToMany(mappedBy = "waybleZone", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Review> reviewList = new ArrayList<>();

/**
* TODO: 영업 시간 구현 필요
*/

/**
* TODO: 장애 시설 정보 구현 필요
*/
@OneToMany(mappedBy = "waybleZone", cascade = CascadeType.ALL, orphanRemoval = true)
private List<WaybleZoneOperatingHour> operatingHours = new ArrayList<>();

/**
* TODO: Review 관련 엔티티 구현 필요
*/
@OneToOne(mappedBy = "waybleZone", cascade = CascadeType.ALL, orphanRemoval = true)
private WaybleZoneFacility facility;

/**
* TODO: 내가 저장한 장소 관련 엔티티 구현 필요
*/
@OneToMany(mappedBy = "waybleZone", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserPlaceWaybleZoneMapping> userPlaceMappings = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.wayble.server.wayblezone.entity;

import com.wayble.server.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.*;


@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "wayble_zone_facility") // 웨이블존 편의 시설 정보
public class WaybleZoneFacility extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// 웨이블존 연관관계 (1:1로 가정 => 웨이블존당 시설 1세트)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "wayble_zone_id", nullable = false)
private WaybleZone waybleZone;

// 시설 정보 (있음/없음 여부)
@Column(nullable = false)
private boolean hasSlope; // 경사로

@Column(nullable = false)
private boolean hasNoDoorStep; // 문턱

@Column(nullable = false)
private boolean hasElevator; // 엘리베이터

@Column(nullable = false)
private boolean hasTableSeat; // 테이블석

@Column(nullable = false)
private boolean hasDisabledToilet; // 장애인 화장실

@Column(length = 20)
private String floorInfo; // 층수 정보 (ex: "1층", "B1", "2층")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.wayble.server.wayblezone.entity;

import com.wayble.server.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.DayOfWeek;
import java.time.LocalTime;


@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "wayble_zone_operating_hours",
uniqueConstraints = @UniqueConstraint(columnNames = {"wayble_zone_id", "day_of_week"})) // 웨이블존 영업 정보
public class WaybleZoneOperatingHour extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "wayble_zone_id", nullable = false)
private WaybleZone waybleZone;

@Enumerated(EnumType.STRING)
@Column(name = "day_of_week", nullable = false)
private DayOfWeek dayOfWeek; // 요일 정보
Comment thread
seung-in-Yoo marked this conversation as resolved.

@Column(name = "start_time", nullable = false)
private LocalTime startTime; // 영업 시작 시간

@Column(name = "close_time", nullable = false)
private LocalTime closeTime; // 영업 종료 시간
Comment thread
seung-in-Yoo marked this conversation as resolved.

@Column(name = "is_closed", nullable = false)
private Boolean isClosed = false; // 영업 여부

/* 필요하게 되면 나중에 사용
@PrePersist
@PreUpdate
private void validateTimes() {
if (isClosed) {
// 휴무일에는 시간 정보가 있어서는 안 됨
if (startTime != null || closeTime != null) {
throw new IllegalStateException("휴무일에는 시간 정보가 있을 수 없습니다.");
}
} else {
// 영업일에는 시간 정보가 필수
if (startTime == null || closeTime == null) {
throw new IllegalStateException("영업일에는 시작 시간과 종료 시간이 필요합니다.");
}
if (startTime.equals(closeTime)) {
throw new IllegalStateException("시작 시간과 종료 시간이 동일할 수 없습니다.");
}
}
}
*/
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@RequiredArgsConstructor
public enum WaybleZoneErrorCase implements ErrorCase {

WAYBLE_ZONE_NOT_FOUND(400, 2001, "웨이블존을 찾을 수 없습니다.");
WAYBLE_ZONE_NOT_FOUND(404, 2001, "해당 웨이블존을 찾을 수 없습니다.");

private final Integer httpStatusCode;
private final Integer errorCode;
Expand Down