Skip to content

Commit

Permalink
Merge pull request #60 from everymeals/feature/meal-review
Browse files Browse the repository at this point in the history
[Feature/meal review] 학식 리뷰 API 기능 개발
  • Loading branch information
Qbeom0925 authored Nov 18, 2023
2 parents 1e50fc8 + ea07745 commit 52b063d
Show file tree
Hide file tree
Showing 36 changed files with 1,273 additions and 156 deletions.
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ sonar {
property 'sonar.language', 'java'
property 'sonar.sourceEncoding', 'UTF-8'
property("sonar.test.inclusions", "**/*Test.java")
property "sonar.exclusions", "**/test/**, **/*Application*.java, **/dto/**, **/entity/**, **/*Exception*.java, **/*RepositoryImpl.java, **/global/**, **/resources/**"
property "sonar.exclusions", "**/test/**, **/*Application*.java, **/dto/**, **/entity/**, **/*Exception*.java, **/*RepositoryImpl.java, **/global/**, **/resources/**, **/*Dao*.java"
property "sonar.java.coveragePlugin", "jacoco"
property 'sonar.coverage.jacoco.xmlReportPaths', 'build/reports/jacoco/test/jacocoTestReport.xml'
}
Expand Down Expand Up @@ -74,6 +74,7 @@ dependencies {
implementation 'org.hibernate.orm:hibernate-core:6.2.5.Final'

//QueryDSL
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
Expand Down Expand Up @@ -121,6 +122,7 @@ jacocoTestReport {
"**/exception/**",
"**/repository/**",
"**/global/*",
"**/*Dao*",
])
}))
}
Expand Down Expand Up @@ -154,6 +156,7 @@ jacocoTestCoverageVerification {
"**/exception/**",
"**/repository/**",
"**/global/*",
"**/*Dao*",
])
}))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public enum ExceptionList {

TOKEN_NOT_VALID("T0001", HttpStatus.NOT_ACCEPTABLE, "해당 토큰은 유효하지 않습니다."),
TOKEN_EXPIRATION("T0002", HttpStatus.FORBIDDEN, "토큰이 만료되었습니다."),

REVIEW_NOT_FOUND("R0001", HttpStatus.NOT_FOUND, "등록된 리뷰가 아닙니다."),
;

public final String CODE;
Expand Down
48 changes: 21 additions & 27 deletions src/main/java/everymeal/server/meal/controller/MealController.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -30,11 +31,9 @@ public class MealController {
private final MealService mealService;

/**
* ============================================================================================
* 학생식당 등록 API
*
* @param restaurantRegisterReq RestaurantRegisterReq 식당 정보 입력
* @return restID String 학생식당 고유 번호
* @author dldmsql
* ============================================================================================
*/
@PostMapping("/restaurant")
@Operation(summary = "학생식당 추가")
Expand All @@ -44,12 +43,9 @@ public ApplicationResponse<Boolean> createRestaurant(
}

/**
* ============================================================================================
* 학생식당 조회 API
*
* @param universityName String 학교 이름
* @param campusName String 캠퍼스 이름
* @return List<RestaurantListGetRes> 학교+캠퍼스로 등록된 식당 리스트
* @author dldmsql
* ============================================================================================
*/
@GetMapping("/restaurant")
@Operation(summary = "학교별 학생 식당 목록 조회")
Expand All @@ -64,11 +60,9 @@ public ApplicationResponse<List<RestaurantListGetRes>> getRestaurants(
}

/**
* ============================================================================================
* 주간 단위 식단 등록 API
*
* @param weekMealRegisterReq WeekMealRegisterReq 식당 정보 입력
* @return boolean 성공
* @author dldmsql
* ============================================================================================
*/
@PostMapping("/week")
@Operation(summary = "주간 단위 식단 추가")
Expand All @@ -78,38 +72,38 @@ public ApplicationResponse<Boolean> createWeekMeal(
}

/**
* ============================================================================================
* 하루 식단 조회 API
*
* @param restaurantIdx Long
* @return
* @author dldmsql
* ============================================================================================
*/
@GetMapping("/day")
@Operation(summary = "당일 식단 조회")
public ApplicationResponse<List<DayMealListGetRes>> getDayMeal(
@RequestParam @Schema(description = "학생식당 PK", defaultValue = "1") Long restaurantIdx,
public ApplicationResponse<Map<String, List<DayMealListGetRes>>> getDayMeal(
@RequestParam @Schema(description = "학교 이름", defaultValue = "명지대학교")
String universityName,
@RequestParam @Schema(description = "캠퍼스 이름", defaultValue = "인문캠퍼스") String campusName,
@RequestParam
@Schema(description = "조회하고자 하는 날짜 ( yyyy-MM-dd )", defaultValue = "2023-10-01")
String offeredAt) {
return ApplicationResponse.ok(mealService.getDayMealList(restaurantIdx, offeredAt));
return ApplicationResponse.ok(
mealService.getDayMealList(universityName, campusName, offeredAt));
}

/**
* 주간 단위 식단 조회 API
*
* @param restaurantIdx 식당 아이디
* @param offeredAt 조회날짜
* @author dldmsql
* ============================================================================================
* 주간 단위 식단 조회 API ( 리펙토링 이전 코드입니다. )
* ============================================================================================
*/
@GetMapping("/week")
@Operation(summary = "주간 식단 조회")
public ApplicationResponse<List<WeekMealListGetRes>> getWeekMeal(
@RequestParam @Schema(description = "학생식당 PK", defaultValue = "1") Long restaurantIdx,
@RequestParam @Schema(description = "학교 이름", defaultValue = "명지대학교")
String universityName,
@RequestParam
@Schema(
description = "조회하고자 하는 시작 날짜 ( yyyy-MM-dd )",
defaultValue = "2023-10-01")
String offeredAt) {
return ApplicationResponse.ok(mealService.getWeekMealListTest(restaurantIdx, offeredAt));
return ApplicationResponse.ok(mealService.getWeekMealListTest(universityName, offeredAt));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@

public record WeekMealRegisterReq(
@Schema(description = "등록하고자 하는 식단 데이터 객체") List<MealRegisterReq> registerReqList,
@Schema(description = "학생식당 PK", defaultValue = "1") Long restaurantIdx) {}
@Schema(description = "학생식당 PK", defaultValue = "1") Long restaurantIdx,
@Schema(description = "학교 이름", defaultValue = "명지대학교 인문캠퍼스") String universityName,
@Schema(description = "학생식당 이름", defaultValue = "MCC 식당") String restaurantName) {}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
import java.time.LocalDate;

public record DayMealListGetRes(
String menu,
MealType mealType,
MealStatus mealStatus,
Long mealIdx,
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd",
timezone = "Asia/Seoul")
LocalDate offeredAt,
MealStatus mealStatus,
MealType mealType,
String menu,
Double price,
MealCategory category,
String restaurantName) {}
String restaurantName,
String universityName) {}
6 changes: 6 additions & 0 deletions src/main/java/everymeal/server/meal/entity/Meal.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package everymeal.server.meal.entity;


import everymeal.server.review.entity.Review;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
Expand All @@ -9,8 +10,10 @@
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.time.LocalDate;
import java.util.Set;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -42,6 +45,9 @@ public class Meal {

@ManyToOne private Restaurant restaurant;

@OneToMany(mappedBy = "meal")
private Set<Review> reviews;

@Builder
public Meal(
String menu,
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/everymeal/server/meal/entity/Restaurant.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import everymeal.server.university.entity.University;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
Expand All @@ -22,22 +23,24 @@ public class Restaurant {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idx;

@Column(length = 20, nullable = false)
private String name;

private String address;
private Boolean useYn;
private Boolean isDeleted;

@ManyToOne private University university;

@Builder
public Restaurant(String name, String address, University university) {
this.name = name;
this.address = address;
this.useYn = Boolean.TRUE;
this.isDeleted = Boolean.TRUE;
this.university = university;
}

/** 학생식당 미운영 상태로 변경 폐업, 업체 변경 등의 이유일 경우, 해당 함수를 통해 상태 변경 */
public void updateUseYn() {
this.useYn = false;
this.isDeleted = false;
}
}
93 changes: 93 additions & 0 deletions src/main/java/everymeal/server/meal/repository/MealDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package everymeal.server.meal.repository;


import everymeal.server.meal.controller.dto.response.DayMealListGetRes;
import everymeal.server.meal.entity.Meal;
import jakarta.persistence.EntityManager;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@RequiredArgsConstructor
public class MealDao {
private final EntityManager em;

private final JdbcTemplate jdbcTemplate;

@Transactional
public void saveAll(List<Meal> mealList) {
String sql =
"INSERT INTO meal ( meal_status, meal_type, menu, offered_at, price, restaurant_idx, category) "
+ "VALUES ( ?, ?, ?, ?, ?, ?, ?)";

jdbcTemplate.batchUpdate(
sql,
mealList,
mealList.size(),
(PreparedStatement ps, Meal meal) -> {
ps.setString(1, meal.getMealStatus().toString());
ps.setString(2, meal.getMealType().toString());
ps.setString(3, meal.getMenu());
ps.setString(4, meal.getOfferedAt().toString());
ps.setDouble(5, meal.getPrice());
ps.setLong(6, meal.getRestaurant().getIdx());
ps.setString(7, meal.getCategory().toString());
});
}

public Map<String, List<DayMealListGetRes>> findDayListByOfferedAtAndUniversity(
Optional<String> offeredAt,
Optional<String> universityName,
Optional<String> campusName) {
// 쿼리 생성
String query =
"""
SELECT NEW everymeal.server.meal.controller.dto.response.DayMealListGetRes(
COALESCE(m.idx, 0) AS mealIdx,
COALESCE(m.offeredAt, :offeredAt) AS offeredAt,
COALESCE(m.mealStatus, 'OPEN') AS mealStatus,
meal_types.mealType,
COALESCE(m.menu, '등록된 식단이 없습니다.') AS menu,
COALESCE(m.price, 0) AS price,
COALESCE(m.category, 'DEFAULT') AS category,
r.name AS restaurantName,
CONCAT(u.name, ' ', u.campusName) AS universityName)
FROM Restaurant r
JOIN (SELECT DISTINCT mealType AS mealType FROM Meal) AS meal_types ON 1=1
LEFT JOIN Meal m ON m.restaurant = r AND m.offeredAt = DATE(:offeredAt) AND m.mealType = meal_types.mealType
INNER JOIN University u ON r.university = u
WHERE
u.name = :universityName AND u.campusName = :campusName
ORDER BY r.name ASC
""";
// 쿼리 옵션 추가 및 실행
List<DayMealListGetRes> result =
em.createQuery(query, DayMealListGetRes.class)
.setParameter("offeredAt", offeredAt.orElse(null))
.setParameter("universityName", universityName.orElse(null))
.setParameter("campusName", campusName.orElse(null))
.getResultList();
// 결과 반환용 변수 선언
Map<String, List<DayMealListGetRes>> map = new HashMap<>();
for (DayMealListGetRes meal : result) {
String restaurantName = meal.restaurantName();

// 해당 레스토랑 이름으로 맵에서 리스트를 가져오거나 없으면 새 리스트 생성
List<DayMealListGetRes> restaurantList =
map.computeIfAbsent(restaurantName, k -> new ArrayList<>());

// 현재 Meal을 레스토랑 리스트에 추가
restaurantList.add(meal);
}

return map;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
package everymeal.server.meal.repository;


import everymeal.server.meal.controller.dto.response.DayMealListGetRes;
import everymeal.server.meal.entity.Meal;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface MealRepository extends JpaRepository<Meal, String> {}
public interface MealRepository extends JpaRepository<Meal, Long> {
@Query(
value =
"SELECT new everymeal.server.meal.controller.dto.response.DayMealListGetRes("
+ " COALESCE(m.idx, 0) AS mealIdx,"
+ " COALESCE(m.offeredAt, :offeredAt) AS offeredAt,"
+ " COALESCE(m.mealStatus, 'OPEN') AS mealStatus,"
+ " meal_types.mealType,"
+ " COALESCE(m.menu, '등록된 식단이 없습니다.') AS menu,"
+ " COALESCE(m.price, 0) AS price,"
+ " COALESCE(m.category, 'DEFAULT') AS category,"
+ " r.name AS restaurantName,"
+ " CONCAT(u.name, ' ', u.campusName) AS universityName) "
+ "FROM Restaurant r "
+ "JOIN (SELECT DISTINCT mealType AS mealType FROM Meal) AS meal_types ON 1=1 "
+ "LEFT JOIN Meal m ON m.restaurant = r AND m.offeredAt = DATE(:offeredAt) AND m.mealType = meal_types.mealType "
+ "INNER JOIN University u ON r.university = u "
+ "WHERE u.name = :universityName AND u.campusName = :campusName "
+ "ORDER BY r.name ASC")
List<DayMealListGetRes> findDayListByOfferedAtAndUniversity(
@Param("offeredAt") Optional<String> offeredAt,
@Param("universityName") Optional<String> universityName,
@Param("campusName") Optional<String> campusName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
import everymeal.server.meal.controller.dto.response.WeekMealListGetRes;
import everymeal.server.meal.entity.Meal;
import everymeal.server.meal.entity.MealType;
import everymeal.server.meal.entity.Restaurant;
import java.time.LocalDate;
import java.util.List;
import org.springframework.stereotype.Repository;

@Repository
public interface MealRepositoryCustom {
List<Meal> findAllByOfferedAtOnDateAndMealType(
LocalDate offeredAt, MealType mealType, Restaurant restaurant);

List<DayMealListGetRes> findAllByOfferedAtOnDate(LocalDate offeredAt, Restaurant restaurant);
LocalDate offeredAt, MealType mealType, String universityName);
/** 23.11.16 기준 미사용 쿼리 */
List<DayMealListGetRes> findAllByOfferedAtOnDate(LocalDate offeredAt, String universityName);

List<WeekMealListGetRes> getWeekMealList(
Restaurant restaurant, LocalDate mondayInstant, LocalDate sundayInstant);
String universityName, LocalDate mondayInstant, LocalDate sundayInstant);
}
Loading

0 comments on commit 52b063d

Please sign in to comment.