Skip to content

Commit

Permalink
Merge pull request #24 from jurumarble/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
jonghyunhub authored Aug 31, 2023
2 parents 454e864 + 2baab0f commit 8356e78
Show file tree
Hide file tree
Showing 25 changed files with 303 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
import co.kr.jurumarble.drink.service.DrinkService;
import co.kr.jurumarble.drink.service.response.GetDrinkServiceResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Slice;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/drinks")
@Tag(name = "drink", description = "drink api")
public class DrinkController {

private final DrinkService drinkService;
Expand All @@ -35,11 +39,11 @@ public ResponseEntity<HttpStatus> enjoyDrink(@RequestAttribute Long userId, @Req
return ResponseEntity.ok().build();
}

@Operation(summary = "전통주 인기순 조회(핫 전통주 - 일주일동안 즐겼어요 많은 순)", description = "요청시 쿼리 파라미터로 size를 같이 넣어서 보내주세요")
@Operation(summary = "전통주 인기순 조회(핫 전통주 10 - 일주일동안 즐겼어요 많은 순)", description = "항상 10개의 데이터가 고정으로 나오고 데이터가 부족하면 즐겼어요 누적으로 나옵니다.")
@GetMapping("/hot")
public ResponseEntity<Slice<GetHotDrinksResponse>> getHotDrinks(@RequestParam int size) {
public ResponseEntity<List<GetHotDrinksResponse>> getHotDrinks() {
return ResponseEntity.status(HttpStatus.OK)
.body(drinkService.getHotDrinks(size));
.body(drinkService.getHotDrinks());
}

@Operation(summary = "전통주 지도 조회", description = "요청시 쿼리 파라미터로 좌측상단 좌표, 우측상단 좌표 보내주세요")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
public interface DrinkEntityRepository {

Slice<HotDrinkData> getHotDrinks(Pageable pageable, LocalDateTime nowTime);
List<HotDrinkData> getHotDrinks(Pageable pageable, LocalDateTime nowTime);

List<HotDrinkData> findDrinksByPopular(Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
Expand All @@ -29,21 +27,20 @@ public DrinkEntityRepositoryImpl(EntityManager entityManager) {
* 지금 시간 기준으로 부터 7일간 즐겼어요가 많은 순으로 전통주 조회
*/
@Override
public Slice<HotDrinkData> getHotDrinks(Pageable pageable, LocalDateTime nowTime) {
public List<HotDrinkData> getHotDrinks(Pageable pageable, LocalDateTime nowTime) {
int pageNo = pageable.getPageNumber();
int pageSize = pageable.getPageSize();

LocalDateTime descendingHourTime = nowTime.withMinute(0);
LocalDateTime aWeekAgoTime = descendingHourTime.minus(7, ChronoUnit.DAYS);

List<HotDrinkData> hotDrinkDataList = jpaQueryFactory.select(
return jpaQueryFactory.select(
Projections.bean(HotDrinkData.class,
drink.id.as("drinkId"),
drink.name,
drink.manufactureAddress,
drink.image,
drink.id.count().as("enjoyedCount"),
enjoyDrink.createdDate.max().as("enjoyedDate")
drink.id.count().as("enjoyedCount")
))
.from(drink)
.leftJoin(enjoyDrink)
Expand All @@ -54,13 +51,29 @@ public Slice<HotDrinkData> getHotDrinks(Pageable pageable, LocalDateTime nowTime
.offset(pageNo * pageSize)
.limit(pageSize)
.fetch();
}

@Override
public List<HotDrinkData> findDrinksByPopular(Pageable pageable) {

boolean hasNext = false;
if (hotDrinkDataList.size() > pageSize) {
hasNext = true;
hotDrinkDataList = hotDrinkDataList.subList(0, pageSize);
}
int pageNo = pageable.getPageNumber();
int pageSize = pageable.getPageSize();

return new SliceImpl<>(hotDrinkDataList, pageable, hasNext);
return jpaQueryFactory.select(
Projections.bean(HotDrinkData.class,
drink.id.as("drinkId"),
drink.name,
drink.manufactureAddress,
drink.image,
drink.id.count().as("enjoyedCount")
))
.from(drink)
.leftJoin(enjoyDrink)
.on(drink.id.eq(enjoyDrink.drinkId))
.groupBy(drink.id)
.orderBy(drink.id.count().desc(), drink.name.asc())
.offset(pageNo * pageSize)
.limit(pageSize)
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

@Repository
public interface DrinkRepository extends JpaRepository<Drink, Long>, DrinkEntityRepository {

List<Drink> findDrinksByIdIn(List<Long> drinkIds);

@Query("SELECT new co.kr.jurumarble.drink.domain.dto.MapInDrinkData(d.id, d.name, d.region, d.latitude, d.longitude) FROM Drink d " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public class HotDrinkData {
private String manufactureAddress;
private String image;
private Long enjoyedCount;
private LocalDateTime enjoyedDate;

public GetHotDrinksResponse toHotDrinksResponse() {
return new GetHotDrinksResponse(drinkId, name, manufactureAddress, image);
Expand Down
21 changes: 16 additions & 5 deletions src/main/java/co/kr/jurumarble/drink/service/DrinkService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
public class DrinkService {

private static final int FIXED_INDEX_OF_GETTING_HOT_DRINKS = 0;
private static final int NUMBER_OF_HOT_DRINK = 10;

private final DrinkRepository drinkRepository;
private final EnjoyDrinkRepository enjoyDrinkRepository;
private final EnjoyDrinkValidator enjoyDrinkValidator;


public GetDrinkServiceResponse getDrinkData(Long drinkId) {
Drink drink = drinkRepository.findById(drinkId).orElseThrow(DrinkNotFoundException::new);
return new GetDrinkServiceResponse(drink);
Expand All @@ -45,13 +47,22 @@ public void enjoyDrink(Long userId, EnjoyDrinkServiceRequest request) {
enjoyDrinkRepository.save(enjoyDrink);
}

public Slice<GetHotDrinksResponse> getHotDrinks(int size) {
PageRequest pageRequest = PageRequest.of(FIXED_INDEX_OF_GETTING_HOT_DRINKS, size);
Slice<HotDrinkData> hotDrinks = drinkRepository.getHotDrinks(pageRequest, LocalDateTime.now());
return new SliceImpl<>(getGetHotDrinksResponses(hotDrinks), hotDrinks.getPageable(), hotDrinks.hasNext());
public List<GetHotDrinksResponse> getHotDrinks() {
PageRequest pageRequest = PageRequest.of(FIXED_INDEX_OF_GETTING_HOT_DRINKS, NUMBER_OF_HOT_DRINK);
List<HotDrinkData> hotDrinkData = drinkRepository.getHotDrinks(pageRequest, LocalDateTime.now());
makeHotDrinkDataHasTenData(hotDrinkData);
return getGetHotDrinksResponses(hotDrinkData);
}
private void makeHotDrinkDataHasTenData(List<HotDrinkData> hotDrinkData) {
if (hotDrinkData.size() < NUMBER_OF_HOT_DRINK) {
int shortageOfDrink = NUMBER_OF_HOT_DRINK - hotDrinkData.size();
PageRequest of = PageRequest.of(FIXED_INDEX_OF_GETTING_HOT_DRINKS, shortageOfDrink);
List<HotDrinkData> additionalDrinks = drinkRepository.findDrinksByPopular(of);
hotDrinkData.addAll(additionalDrinks);
}
}

private List<GetHotDrinksResponse> getGetHotDrinksResponses(Slice<HotDrinkData> hotDrinks) {
private List<GetHotDrinksResponse> getGetHotDrinksResponses(List<HotDrinkData> hotDrinks) {
return hotDrinks.stream()
.map(HotDrinkData::toHotDrinksResponse)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package co.kr.jurumarble.exception.vote;

import co.kr.jurumarble.exception.StatusEnum;
import co.kr.jurumarble.exception.common.CustomException;

public class VoteContentNotFoundException extends CustomException {

private static final String message = "해당 id를 가진 투표 컨텐츠가 없습니다. 아이디 값을 다시 한번 확인하세요.";
private final StatusEnum status;

public VoteContentNotFoundException() {
super(message);
this.status = StatusEnum.VOTE_NOT_FOUND;
}

@Override
public StatusEnum getStatus() {
return status;
}

@Override
public String getMessage() {
return message;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import co.kr.jurumarble.user.dto.response.TokenResponse;
import co.kr.jurumarble.user.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -18,6 +19,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/users")
@Tag(name = "user", description = "user api")
public class UserController {

private final UserService userService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
import co.kr.jurumarble.vote.dto.response.GetVoteRecommendListResponse;
import co.kr.jurumarble.vote.dto.response.GetVoteResponse;
import co.kr.jurumarble.vote.enums.SortByType;
import co.kr.jurumarble.vote.repository.dto.HotDrinkVoteData;
import co.kr.jurumarble.vote.service.GetVoteData;
import co.kr.jurumarble.vote.service.VoteService;
import co.kr.jurumarble.vote.service.NormalVoteService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand All @@ -30,70 +31,77 @@
@RequiredArgsConstructor
@Slf4j
@Tag(name = "vote", description = "vote api")
public class VoteController {
private final VoteService voteService;
public class NormalVoteController {
private final NormalVoteService normalVoteService;

@Operation(summary = "일반 투표 생성", description = "헤더에 토큰 담고, 바디에 {title, titleA, titleB, imageA, imageB, filteredGender, filteredAge, filteredMbti} json 형식으로 보내주시면 됩니다.")
@PostMapping("/normal")
public ResponseEntity createNormalVote(@Valid @RequestBody CreateNormalVoteRequest request, @RequestAttribute Long userId) {
voteService.createNormalVote(request.toServiceRequest(), userId);
normalVoteService.createNormalVote(request.toServiceRequest(), userId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@Operation(summary = "전통주 투표 생성", description = "헤더에 토큰 담고, 바디에 {title, titleA, titleB, imageA, imageB, filteredGender, filteredAge, filteredMbti} json 형식으로 보내주시면 됩니다.")
@PostMapping("/drink")
public ResponseEntity createDrinkVote(@Valid @RequestBody CreateDrinkVoteRequest request, @RequestAttribute Long userId) {
voteService.createDrinkVote(request.toServiceRequest(), userId);
normalVoteService.createDrinkVote(request.toServiceRequest(), userId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@Operation(summary = "투표 리스트 검색, 조회", description = "파라미터에 keyeword, sortBy, page, size, category 보내주시면 됩니다. 검색이 아니면 keyword = 에 값 없이 ")
@GetMapping("")
public ResponseEntity<GetVoteListResponse> getVoteList(@RequestParam(required = false) String keyword, @RequestParam SortByType sortBy, @RequestParam int page, @RequestParam int size) {
Slice<NormalVoteData> voteListData = voteService.getVoteList(keyword, sortBy, page, size);
Slice<NormalVoteData> voteListData = normalVoteService.getNormalVoteList(keyword, sortBy, page, size);
return new ResponseEntity(new GetVoteListResponse(voteListData), HttpStatus.OK);
}

@Operation(summary = "투표 단건 조회", description = "파라미터에 voteId 보내주시면 됩니다.")
@Operation(summary = "일반 투표 단건 조회", description = "파라미터에 voteId 보내주시면 됩니다.")
@GetMapping("/{voteId}")
public ResponseEntity<GetVoteResponse> getVote(@PathVariable Long voteId) {
GetVoteData data = voteService.getVote(voteId);
GetVoteData data = normalVoteService.getVote(voteId);
return new ResponseEntity(new GetVoteResponse(data), HttpStatus.OK);
}

@Operation(summary = "투표 수정", description = "파라미터에 voteId, 바디에 {title, detail, titleA, titleB} json 형식으로 보내주시면 됩니다.")
@Operation(summary = "일반 투표 수정", description = "파라미터에 voteId, 바디에 {title, detail, titleA, titleB} json 형식으로 보내주시면 됩니다.")
@PutMapping("/{voteId}")
public ResponseEntity updateVote(@PathVariable("voteId") Long voteId, @RequestBody UpdateVoteRequest request, @RequestAttribute Long userId) {
voteService.updateVote(request.toServiceRequest(voteId, userId, request));
normalVoteService.updateVote(request.toServiceRequest(voteId, userId, request));
return new ResponseEntity(HttpStatus.OK);
}

@Operation(summary = "투표 삭제", description = "헤더에 토큰 담고, 파라미터에 voteId 보내주시면 됩니다")
@Operation(summary = "일반 투표 삭제", description = "헤더에 토큰 담고, 파라미터에 voteId 보내주시면 됩니다")
@DeleteMapping("/{voteId}")
public ResponseEntity deleteVote(@PathVariable("voteId") Long voteId, @RequestAttribute Long userId) {
voteService.deleteVote(voteId, userId);
normalVoteService.deleteNormalVote(voteId, userId);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}

@Operation(summary = "투표 참여", description = "헤더에 토큰담고, 파라미터에 voteId, 바디에 {choice} json 형식으로 보내주시면 됩니다.")
@PostMapping("/{voteId}/vote")
public ResponseEntity doVote(@RequestBody DoVoteRequest request, @PathVariable("voteId") Long voteId, @RequestAttribute Long userId) {
voteService.doVote(request.toService(userId, voteId));
normalVoteService.doVote(request.toService(userId, voteId));
return new ResponseEntity(HttpStatus.OK);
}

@Operation(summary = "투표 검색어 추천", description = "파라미터에 keyword, category 보내주시면 됩니다.")
@GetMapping("/recommend")
public ResponseEntity recommendVote(@RequestParam String keyword) {
List<String> voteRecommendListData = voteService.getRecommendVoteList(keyword);
List<String> voteRecommendListData = normalVoteService.getRecommendVoteList(keyword);
return new ResponseEntity(new GetVoteRecommendListResponse(voteRecommendListData), HttpStatus.OK);
}

@Operation(summary = "투표 참여 여부 조회", description = "파라미터에 voteId, 헤더에 userId 보내주시면 됩니다.")
@GetMapping("/{voteId}/voted")
public ResponseEntity<GetIsUserVotedResponse> getIsUserVoted(@PathVariable Long voteId, @RequestAttribute Long userId) {
GetIsUserVoted userVoted = voteService.isUserVoted(voteId, userId);
GetIsUserVoted userVoted = normalVoteService.isUserVoted(voteId, userId);
return new ResponseEntity(new GetIsUserVotedResponse(userVoted), HttpStatus.OK);
}

@Operation(summary = "핫 전통주 투표", description = "현재 시간 기준 일주일간 핫한 전통주 투표 조회")
@GetMapping("/drinks/hot")
public ResponseEntity<HotDrinkVoteData> getHotDrinkVote() {
HotDrinkVoteData hotDrinkVote = normalVoteService.getHotDrinkVote();
return ResponseEntity.ok().body(hotDrinkVote);
}

}
1 change: 0 additions & 1 deletion src/main/java/co/kr/jurumarble/vote/domain/Vote.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,4 @@ public void update(UpdateVoteServiceRequest request) {
this.detail = request.getDetail();
}


}
18 changes: 16 additions & 2 deletions src/main/java/co/kr/jurumarble/vote/domain/VoteDrinkContent.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,30 @@ public class VoteDrinkContent {
@Column(name = "drink_b_type")
private String drinkBType;

@Column(name = "drink_a_image")
private String drinkAImage;

@Column(name = "drink_b_image")
private String drinkBImage;

private String region;

@Builder
public VoteDrinkContent(Long voteId, Long drinkAId, Long drinkBId, String drinkAName, String drinkAType, String drinkBName, String drinkBType) {
validateDrinksDuplicated(drinkAId, drinkBId);
public VoteDrinkContent(Long id, Long voteId, Long drinkAId, Long drinkBId, String drinkAName, String drinkAType, String drinkBName, String drinkBType, String drinkAImage, String drinkBImage, String region) {
this.id = id;
this.voteId = voteId;
this.drinkAId = drinkAId;
this.drinkBId = drinkBId;
this.drinkAName = drinkAName;
this.drinkAType = drinkAType;
this.drinkBName = drinkBName;
this.drinkBType = drinkBType;
this.drinkAImage = drinkAImage;
this.drinkBImage = drinkBImage;
this.region = region;
}


public static VoteDrinkContent createFromDrinks(DrinksUsedForVote drinksUsedForVote) {
Drink drinkA = drinksUsedForVote.getDrinkA();
Drink drinkB = drinksUsedForVote.getDrinkB();
Expand All @@ -65,6 +77,8 @@ public static VoteDrinkContent createFromDrinks(DrinksUsedForVote drinksUsedForV
.drinkBName(drinkB.getName())
.drinkAType(drinkA.getType())
.drinkBType(drinkB.getType())
.drinkAImage(drinkA.getImage())
.drinkBImage(drinkB.getImage())
.build();
}

Expand Down
Loading

0 comments on commit 8356e78

Please sign in to comment.