From c3e3afb3633b6db8d569011b7cf2887ac496e391 Mon Sep 17 00:00:00 2001 From: worldii Date: Sat, 14 Oct 2023 21:04:41 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=BB=A4=EC=84=9C=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EB=B6=80=EB=B6=84=EC=97=90=20=EC=A0=95=EB=A0=AC=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=ED=81=B4=EB=A6=AD=EB=A5=A0=20=EC=88=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#220)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: statistic 네이밍 수정 * test: statistics service Test * test: statistics service Test * feat: 정렬 기준에 추천 수 추가 * refactor : 테스트 변경 * refactor: statistic 원상복구 * refactor: 클릭률은 통계테이블이 아닌 클릭률 테이블에서 가져오는 걸로 변경 * refactor: test failed * refactor: 커서 네이밍 변경 * refactor: 잘못 들어간 커밋 삭제 * refactor: 잘못 들어간 커밋 삭제 * refactor: 네이밍 수정 * Update src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorService.java Co-authored-by: Jeonggyu Choi <97666463+whatasame@users.noreply.github.com> * test: 커서, 클릭 수 not null일 때 추가 * refactor: 병합 * refactor: 피드백 반영 * refactor : 패키지 변경 * refactor : click Response 따로 생성 * refactor : click Response 따로 생성하여 관련 메서드들 수정 * refactor : PageClickResponse 메서드명 수정 * refactor : click, latest 순 나눔 * fix: test failed * test : 커서 방식 테스트 추가 * refactor: 피드백 반영 * Update src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorServiceIntegrationTest.java Co-authored-by: Jeonggyu Choi <97666463+whatasame@users.noreply.github.com> * refactor: dto->response 분리 * refactor: 리팩터링 --------- Co-authored-by: Jeonggyu Choi <97666463+whatasame@users.noreply.github.com> --- .../liquor/controller/LiquorController.java | 64 +++++---- .../controller/LiquorStockController.java | 2 +- .../soolsool/core/liquor/domain/Liquor.java | 2 +- .../core/liquor/domain/LiquorCtr.java | 9 +- .../converter/LiquorCtrClickConverter.java | 2 +- .../core/liquor/domain/vo/LiquorCtrClick.java | 12 +- .../liquor/dto/request/LiquorListRequest.java | 26 ++++ .../{ => request}/LiquorModifyRequest.java | 2 +- .../dto/{ => request}/LiquorSaveRequest.java | 2 +- .../{ => request}/LiquorSearchCondition.java | 2 +- .../{ => request}/LiquorStockSaveRequest.java | 2 +- .../dto/response/LiquorClickElementDto.java | 29 ++++ .../{ => response}/LiquorDetailResponse.java | 2 +- .../{ => response}/LiquorElementResponse.java | 27 ++-- .../{ => response}/PageLiquorResponse.java | 15 +- .../repository/LiquorQueryDslRepository.java | 52 +++++-- .../core/liquor/service/LiquorService.java | 84 ++++++++--- .../liquor/service/LiquorStockService.java | 2 +- .../core/statistics/domain/StatisticId.java | 8 +- .../infra/StatisticJpaRepository.java | 9 +- .../acceptance/LiquorAcceptanceTest.java | 10 +- .../acceptance/LiquorStockAcceptanceTest.java | 2 +- .../acceptance/fixture/RestLiquorFixture.java | 2 +- .../fixture/RestLiquorStockFixture.java | 2 +- .../LiquorQueryDslRepositoryTest.java | 132 ++++++++++++++---- .../service/LiquorServiceIntegrationTest.java | 8 +- .../LiquorStockServiceIntegrationTest.java | 2 +- 27 files changed, 364 insertions(+), 147 deletions(-) create mode 100644 src/main/java/com/woowacamp/soolsool/core/liquor/dto/request/LiquorListRequest.java rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => request}/LiquorModifyRequest.java (91%) rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => request}/LiquorSaveRequest.java (94%) rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => request}/LiquorSearchCondition.java (89%) rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => request}/LiquorStockSaveRequest.java (92%) create mode 100644 src/main/java/com/woowacamp/soolsool/core/liquor/dto/response/LiquorClickElementDto.java rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => response}/LiquorDetailResponse.java (93%) rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => response}/LiquorElementResponse.java (66%) rename src/main/java/com/woowacamp/soolsool/core/liquor/dto/{ => response}/PageLiquorResponse.java (71%) diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorController.java b/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorController.java index f187db02..9f30fc63 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorController.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorController.java @@ -6,14 +6,12 @@ import static com.woowacamp.soolsool.core.liquor.code.LiquorResultCode.LIQUOR_UPDATED; import com.woowacamp.soolsool.core.liquor.code.LiquorResultCode; -import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorBrewType; -import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorRegionType; -import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorStatusType; -import com.woowacamp.soolsool.core.liquor.dto.LiquorDetailResponse; -import com.woowacamp.soolsool.core.liquor.dto.LiquorElementResponse; -import com.woowacamp.soolsool.core.liquor.dto.LiquorModifyRequest; -import com.woowacamp.soolsool.core.liquor.dto.LiquorSaveRequest; -import com.woowacamp.soolsool.core.liquor.dto.PageLiquorResponse; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorListRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorModifyRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorDetailResponse; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorElementResponse; +import com.woowacamp.soolsool.core.liquor.dto.response.PageLiquorResponse; import com.woowacamp.soolsool.core.liquor.service.LiquorService; import com.woowacamp.soolsool.global.aop.RequestLogging; import com.woowacamp.soolsool.global.auth.dto.NoAuth; @@ -28,15 +26,14 @@ import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; -import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; 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; @RestController @@ -76,8 +73,8 @@ public ResponseEntity> liquorDetail( public ResponseEntity>> liquorPurchasedTogether( @PathVariable final Long liquorId ) { - final List response = - liquorService.liquorPurchasedTogether(liquorId); + final List response = liquorService.liquorPurchasedTogether( + liquorId); return ResponseEntity.ok( ApiResponse.of(LiquorResultCode.LIQUOR_PURCHASED_TOGETHER_FOUND, response)); @@ -89,11 +86,7 @@ public ResponseEntity>> liquorPurchasedT public ResponseEntity> getLiquorFirstList( @PageableDefault final Pageable pageable ) { - final PageRequest sortPageable = PageRequest.of( - pageable.getPageNumber(), - pageable.getPageSize(), - Sort.by("createdAt").descending() - ); + final PageRequest sortPageable = getSortedPageable(pageable); final PageLiquorResponse response = liquorService.getFirstPage(sortPageable); @@ -104,25 +97,40 @@ public ResponseEntity> getLiquorFirstList( @RequestLogging @GetMapping public ResponseEntity> liquorList( - @RequestParam("brew") @Nullable final LiquorBrewType brew, - @RequestParam("region") @Nullable final LiquorRegionType region, - @RequestParam("status") @Nullable final LiquorStatusType status, - @RequestParam("brand") @Nullable final String brand, - @RequestParam @Nullable final Long cursorId, + @ModelAttribute final LiquorListRequest liquorListRequest, @PageableDefault final Pageable pageable ) { - final PageRequest sortPageable = PageRequest.of( - pageable.getPageNumber(), - pageable.getPageSize(), - Sort.by("createdAt").descending() - ); + final PageRequest sortPageable = getSortedPageable(pageable); + + final PageLiquorResponse response = liquorService + .liquorListByLatest(liquorListRequest, sortPageable); + + return ResponseEntity.ok(ApiResponse.of(LIQUOR_LIST_FOUND, response)); + } + + @NoAuth + @RequestLogging + @GetMapping("/click") + public ResponseEntity> liquorListByClick( + @ModelAttribute final LiquorListRequest liquorListRequest, + @PageableDefault final Pageable pageable + ) { + final PageRequest sortPageable = getSortedPageable(pageable); final PageLiquorResponse response = liquorService - .liquorList(brew, region, status, brand, sortPageable, cursorId); + .liquorListByClick(liquorListRequest, sortPageable); return ResponseEntity.ok(ApiResponse.of(LIQUOR_LIST_FOUND, response)); } + private PageRequest getSortedPageable(Pageable pageable) { + return PageRequest.of( + pageable.getPageNumber(), + pageable.getPageSize(), + Sort.by("createdAt").descending() + ); + } + @Vendor @RequestLogging @PutMapping("/{liquorId}") diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorStockController.java b/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorStockController.java index 41cebaf8..bcee2c51 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorStockController.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/controller/LiquorStockController.java @@ -1,6 +1,6 @@ package com.woowacamp.soolsool.core.liquor.controller; -import com.woowacamp.soolsool.core.liquor.dto.LiquorStockSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorStockSaveRequest; import com.woowacamp.soolsool.core.liquor.service.LiquorStockService; import com.woowacamp.soolsool.global.aop.RequestLogging; import com.woowacamp.soolsool.global.auth.dto.Vendor; diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/domain/Liquor.java b/src/main/java/com/woowacamp/soolsool/core/liquor/domain/Liquor.java index dccdd296..1fdabdd7 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/domain/Liquor.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/domain/Liquor.java @@ -15,7 +15,7 @@ import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorStatusType; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorStockCount; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorVolume; -import com.woowacamp.soolsool.core.liquor.dto.LiquorModifyRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorModifyRequest; import com.woowacamp.soolsool.global.common.BaseEntity; import java.math.BigInteger; import javax.persistence.Column; diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/domain/LiquorCtr.java b/src/main/java/com/woowacamp/soolsool/core/liquor/domain/LiquorCtr.java index dcdd0b59..62aa74f7 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/domain/LiquorCtr.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/domain/LiquorCtr.java @@ -3,7 +3,6 @@ import static javax.persistence.GenerationType.IDENTITY; import com.woowacamp.soolsool.core.liquor.code.LiquorCtrErrorCode; -import com.woowacamp.soolsool.core.liquor.domain.converter.LiquorCtrClickConverter; import com.woowacamp.soolsool.core.liquor.domain.converter.LiquorCtrImpressionConverter; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorCtrClick; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorCtrImpression; @@ -11,6 +10,7 @@ import com.woowacamp.soolsool.global.exception.SoolSoolException; import javax.persistence.Column; import javax.persistence.Convert; +import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @@ -38,8 +38,7 @@ public class LiquorCtr extends BaseEntity { @Convert(converter = LiquorCtrImpressionConverter.class) private LiquorCtrImpression impression; - @Column(name = "click", nullable = false) - @Convert(converter = LiquorCtrClickConverter.class) + @Embedded private LiquorCtrClick click; public LiquorCtr(@NonNull final Long liquorId) { @@ -62,7 +61,7 @@ public double getCtr() { throw new SoolSoolException(LiquorCtrErrorCode.DIVIDE_BY_ZERO_IMPRESSION); } - final double ratio = (double) click.getClick() / impression.getImpression(); + final double ratio = (double) click.getCount() / impression.getImpression(); return Math.round(ratio * 100) / 100.0; } @@ -72,6 +71,6 @@ public Long getImpression() { } public Long getClick() { - return click.getClick(); + return click.getCount(); } } diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/domain/converter/LiquorCtrClickConverter.java b/src/main/java/com/woowacamp/soolsool/core/liquor/domain/converter/LiquorCtrClickConverter.java index b4846e64..50c71205 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/domain/converter/LiquorCtrClickConverter.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/domain/converter/LiquorCtrClickConverter.java @@ -7,7 +7,7 @@ public class LiquorCtrClickConverter implements AttributeConverter from(final Page liquors) { - return liquors.getContent().stream() - .map(LiquorElementResponse::from) - .collect(Collectors.toList()); - } } diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/dto/PageLiquorResponse.java b/src/main/java/com/woowacamp/soolsool/core/liquor/dto/response/PageLiquorResponse.java similarity index 71% rename from src/main/java/com/woowacamp/soolsool/core/liquor/dto/PageLiquorResponse.java rename to src/main/java/com/woowacamp/soolsool/core/liquor/dto/response/PageLiquorResponse.java index bff2e8a5..5029e1f5 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/dto/PageLiquorResponse.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/dto/response/PageLiquorResponse.java @@ -1,9 +1,7 @@ -package com.woowacamp.soolsool.core.liquor.dto; +package com.woowacamp.soolsool.core.liquor.dto.response; import com.fasterxml.jackson.annotation.JsonCreator; -import com.woowacamp.soolsool.core.liquor.domain.Liquor; import java.util.List; -import java.util.stream.Collectors; import lombok.Getter; import org.springframework.data.domain.Pageable; @@ -24,22 +22,17 @@ public PageLiquorResponse( this.nextCursorId = nextCursorId; this.liquors = liquors; } - public static PageLiquorResponse of( final Pageable pageable, - final List liquors + final List liquors ) { - final List liquorElements = liquors.stream() - .map(LiquorElementResponse::from) - .collect(Collectors.toList()); - if (liquors.size() < pageable.getPageSize()) { - return new PageLiquorResponse(false, liquorElements); + return new PageLiquorResponse(false, liquors); } final Long lastReadLiquorId = liquors.get(liquors.size() - 1).getId(); - return new PageLiquorResponse(true, lastReadLiquorId, liquorElements); + return new PageLiquorResponse(true, lastReadLiquorId, liquors); } private PageLiquorResponse(final boolean hasNext, final List liquors) { diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/repository/LiquorQueryDslRepository.java b/src/main/java/com/woowacamp/soolsool/core/liquor/repository/LiquorQueryDslRepository.java index ef18754e..dc04a6f6 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/repository/LiquorQueryDslRepository.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/repository/LiquorQueryDslRepository.java @@ -1,7 +1,9 @@ package com.woowacamp.soolsool.core.liquor.repository; import static com.woowacamp.soolsool.core.liquor.domain.QLiquor.liquor; +import static com.woowacamp.soolsool.core.liquor.domain.QLiquorCtr.liquorCtr; +import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import com.woowacamp.soolsool.core.liquor.domain.Liquor; @@ -9,7 +11,8 @@ import com.woowacamp.soolsool.core.liquor.domain.LiquorRegion; import com.woowacamp.soolsool.core.liquor.domain.LiquorStatus; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorBrand; -import com.woowacamp.soolsool.core.liquor.dto.LiquorSearchCondition; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorSearchCondition; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorClickElementDto; import java.util.List; import java.util.Objects; import lombok.RequiredArgsConstructor; @@ -28,7 +31,7 @@ public class LiquorQueryDslRepository { public List getList( final LiquorSearchCondition condition, final Pageable pageable, - final Long cursorId + final Long liquorId ) { return queryFactory.select(liquor) .from(liquor) @@ -37,7 +40,7 @@ public List getList( eqBrew(condition.getLiquorBrew()), eqStatus(condition.getLiquorStatus()), eqBrand(condition.getBrand()), - cursorId(cursorId) + cursorId(liquorId, null) ) .orderBy(liquor.id.desc()) .limit(pageable.getPageSize()) @@ -45,7 +48,9 @@ public List getList( } @Cacheable(value = "liquorsFirstPage") - public List getCachedList(final Pageable pageable) { + public List getCachedList( + final Pageable pageable + ) { log.info("LiquorQueryDslRepository getCachedList"); return queryFactory.select(liquor) .from(liquor) @@ -54,6 +59,32 @@ public List getCachedList(final Pageable pageable) { .fetch(); } + public List getListByClick( + final LiquorSearchCondition condition, + final Pageable pageable, + final Long liquorId, + final Long clickCount + ) { + return queryFactory.select( + Projections.constructor( + LiquorClickElementDto.class, + liquor, + liquorCtr.click + ) + ) + .from(liquor) + .join(liquorCtr).on(liquor.id.eq(liquorCtr.liquorId)) + .where( + eqRegion(condition.getLiquorRegion()), + eqBrew(condition.getLiquorBrew()), + eqStatus(condition.getLiquorStatus()), + eqBrand(condition.getBrand()), + cursorId(liquorId, clickCount) + ) + .orderBy(liquorCtr.click.count.desc(), liquor.id.desc()) + .limit(pageable.getPageSize()) + .fetch(); + } private BooleanExpression eqRegion(final LiquorRegion liquorRegion) { if (Objects.isNull(liquorRegion)) { @@ -73,7 +104,7 @@ private BooleanExpression eqStatus(final LiquorStatus liquorStatus) { if (Objects.isNull(liquorStatus)) { return null; } - return liquor.status.type.eq(liquorStatus.getType()); + return liquor.status.eq(liquorStatus); } private BooleanExpression eqBrand(final String brand) { @@ -83,10 +114,15 @@ private BooleanExpression eqBrand(final String brand) { return liquor.brand.eq(new LiquorBrand(brand)); } - private BooleanExpression cursorId(final Long cursorId) { - if (cursorId == null) { + private BooleanExpression cursorId(final Long liquorId, final Long click) { + if (liquorId == null) { return null; } - return liquor.id.lt(cursorId); + if (click == null) { + return liquor.id.lt(liquorId); + } + + return liquorCtr.click.count.lt(click).or( + liquorCtr.click.count.eq(click).and(liquor.id.lt(liquorId))); } } diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorService.java b/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorService.java index 0324e15a..da65a9eb 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorService.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorService.java @@ -13,12 +13,14 @@ import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorBrewType; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorRegionType; import com.woowacamp.soolsool.core.liquor.domain.vo.LiquorStatusType; -import com.woowacamp.soolsool.core.liquor.dto.LiquorDetailResponse; -import com.woowacamp.soolsool.core.liquor.dto.LiquorElementResponse; -import com.woowacamp.soolsool.core.liquor.dto.LiquorModifyRequest; -import com.woowacamp.soolsool.core.liquor.dto.LiquorSaveRequest; -import com.woowacamp.soolsool.core.liquor.dto.LiquorSearchCondition; -import com.woowacamp.soolsool.core.liquor.dto.PageLiquorResponse; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorListRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorModifyRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorSearchCondition; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorClickElementDto; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorDetailResponse; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorElementResponse; +import com.woowacamp.soolsool.core.liquor.dto.response.PageLiquorResponse; import com.woowacamp.soolsool.core.liquor.repository.LiquorBrewCache; import com.woowacamp.soolsool.core.liquor.repository.LiquorCtrRepository; import com.woowacamp.soolsool.core.liquor.repository.LiquorQueryDslRepository; @@ -84,32 +86,72 @@ public List liquorPurchasedTogether(final Long liquorId) } @Transactional - public PageLiquorResponse liquorList( - final LiquorBrewType brewType, - final LiquorRegionType regionType, - final LiquorStatusType statusType, - final String brand, - final Pageable pageable, - final Long cursorId + public PageLiquorResponse liquorListByClick( + final LiquorListRequest liquorListRequest, + final Pageable pageable ) { final LiquorSearchCondition liquorSearchCondition = new LiquorSearchCondition( - liquorRegionCache.findByType(regionType).orElse(null), - liquorBrewCache.findByType(brewType).orElse(null), - liquorStatusCache.findByType(statusType).orElse(null), - brand + liquorRegionCache.findByType(liquorListRequest.getRegion()).orElse(null), + liquorBrewCache.findByType(liquorListRequest.getBrew()).orElse(null), + liquorStatusCache.findByType(liquorListRequest.getStatus()).orElse(null), + liquorListRequest.getBrand() ); - final List liquors = liquorQueryDslRepository - .getList(liquorSearchCondition, pageable, cursorId); + final List liquors = liquorQueryDslRepository + .getListByClick( + liquorSearchCondition, pageable, + liquorListRequest.getLiquorId(), + liquorListRequest.getClickCount() + ); - return PageLiquorResponse.of(pageable, liquors); + return PageLiquorResponse.of(pageable, getLiquorElementResponseFromClick(liquors)); + } + + private List getLiquorElementResponseFromClick( + List liquors) { + return liquors.stream().map( + liquor -> new LiquorElementResponse( + liquor.getId(), + liquor.getName(), + liquor.getPrice(), + liquor.getImageUrl(), + liquor.getStock() + ) + ).collect(Collectors.toList()); + } + + + @Transactional + public PageLiquorResponse liquorListByLatest( + final LiquorListRequest liquorListRequest, + final Pageable pageable + ) { + final LiquorSearchCondition liquorSearchCondition = new LiquorSearchCondition( + liquorRegionCache.findByType(liquorListRequest.getRegion()).orElse(null), + liquorBrewCache.findByType(liquorListRequest.getBrew()).orElse(null), + liquorStatusCache.findByType(liquorListRequest.getStatus()).orElse(null), + liquorListRequest.getBrand() + ); + + final List liquors = liquorQueryDslRepository.getList( + liquorSearchCondition, pageable, + liquorListRequest.getLiquorId() + ); + + return PageLiquorResponse.of(pageable, getLiquorElementsFromLiquor(liquors)); + } + + private static List getLiquorElementsFromLiquor(List liquors) { + return liquors.stream() + .map(LiquorElementResponse::from) + .collect(Collectors.toList()); } @Transactional public PageLiquorResponse getFirstPage(final Pageable pageable) { final List liquors = liquorQueryDslRepository.getCachedList(pageable); - return PageLiquorResponse.of(pageable, liquors); + return PageLiquorResponse.of(pageable, getLiquorElementsFromLiquor(liquors)); } @CacheEvict(value = "liquorsFirstPage") diff --git a/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockService.java b/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockService.java index bbe97f2d..22cdfbf8 100644 --- a/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockService.java +++ b/src/main/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockService.java @@ -4,7 +4,7 @@ import com.woowacamp.soolsool.core.liquor.domain.Liquor; import com.woowacamp.soolsool.core.liquor.domain.LiquorStocks; -import com.woowacamp.soolsool.core.liquor.dto.LiquorStockSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorStockSaveRequest; import com.woowacamp.soolsool.core.liquor.repository.LiquorRepository; import com.woowacamp.soolsool.core.liquor.repository.LiquorStockRepository; import com.woowacamp.soolsool.global.exception.SoolSoolException; diff --git a/src/main/java/com/woowacamp/soolsool/core/statistics/domain/StatisticId.java b/src/main/java/com/woowacamp/soolsool/core/statistics/domain/StatisticId.java index c2836f01..d67229fa 100644 --- a/src/main/java/com/woowacamp/soolsool/core/statistics/domain/StatisticId.java +++ b/src/main/java/com/woowacamp/soolsool/core/statistics/domain/StatisticId.java @@ -13,16 +13,16 @@ @Embeddable public class StatisticId implements Serializable { - @Column(name = "year") + @Column(name = "statistic_year") private int year; - @Column(name = "month") + @Column(name = "statistic_month") private int month; - @Column(name = "week") + @Column(name = "statistic_week") private int week; - @Column(name = "day") + @Column(name = "statistic_day") private int day; @Column(name = "liquor_id") diff --git a/src/main/java/com/woowacamp/soolsool/core/statistics/infra/StatisticJpaRepository.java b/src/main/java/com/woowacamp/soolsool/core/statistics/infra/StatisticJpaRepository.java index 7926f341..a952fe8f 100644 --- a/src/main/java/com/woowacamp/soolsool/core/statistics/infra/StatisticJpaRepository.java +++ b/src/main/java/com/woowacamp/soolsool/core/statistics/infra/StatisticJpaRepository.java @@ -15,7 +15,8 @@ public interface StatisticJpaRepository extends JpaRepository 커서첫번째 = liquorQueryDslRepository + final List liquors = liquorQueryDslRepository .getList(new LiquorSearchCondition(region, brew, status, brand), - Pageable.ofSize(10), null + Pageable.ofSize(2), null ); // then - assertThat(커서첫번째).hasSize(1); + assertThat(liquors).hasSize(2); } @Test - @DisplayName("커서 두번째를 조회하는 테스트") - void curSecondTest() { + @DisplayName("최신순 : 커서를 연속적으로 조회한다 ") + void cursorClickCountNullTestByLatest() { // given - LiquorBrew brew = liquorBrewRepository.findByType(LiquorBrewType.SOJU).get(); - LiquorRegion region = liquorRegionRepository.findByType(LiquorRegionType.GYEONGGI_DO).get(); - LiquorStatus status = liquorStatusRepository.findByType(LiquorStatusType.ON_SALE).get(); - String brand = "롯데"; + LiquorBrew brew = null; + LiquorRegion region = null; + LiquorStatus status = null; + String brand = null; // when + List 커서첫번째 = liquorQueryDslRepository + .getList(new LiquorSearchCondition(region, brew, status, brand), + Pageable.ofSize(1), null); + Long 커서첫번째_ID = 커서첫번째.get(커서첫번째.size() - 1).getId(); + List 커서두번째 = liquorQueryDslRepository .getList(new LiquorSearchCondition(region, brew, status, brand), - Pageable.ofSize(10), 1L - ); + Pageable.ofSize(1), 커서첫번째_ID); + Long 커서두번째_ID = 커서두번째.get(커서두번째.size() - 1).getId(); + + List 커서세번째 = liquorQueryDslRepository + .getList(new LiquorSearchCondition(region, brew, status, brand), + Pageable.ofSize(1), 커서두번째_ID); + Long 커서세번째_ID = 커서세번째.get(커서세번째.size() - 1).getId(); + + // then + assertThat(커서첫번째).hasSize(1); + assertThat(커서첫번째_ID).isGreaterThan(커서두번째_ID); + assertThat(커서두번째).hasSize(1); + assertThat(커서두번째_ID).isGreaterThan(커서세번째_ID); + } + + + @Test + @DisplayName("클릭순 + 최신순 : 커서 첫번째를 조회하는 테스트") + void cursorFirstTestByClickAndLatest() { + // given + LiquorBrew brew = null; + LiquorRegion region = null; + LiquorStatus status = null; + String brand = null; + Long liquorId = null; + Long clickCount = null; + + // when + final List 커서첫번째 = liquorQueryDslRepository + .getListByClick(new LiquorSearchCondition(region, brew, status, brand), + Pageable.ofSize(1), liquorId, clickCount); + + // then + assertThat(커서첫번째).hasSize(1); + } + + @Test + @DisplayName("클릭순 + 최신순 : 커서 click Count가 null일때, liquorId가 최신순인 것으로 정렬된다.") + void cursorClickCountNullTestByClickAndLatest() { + // given + LiquorBrew brew = null; + LiquorRegion region = null; + LiquorStatus status = null; + String brand = null; + Long liquorId = 3L; + Long clickCount = null; + + // when + List 커서첫번째 = liquorQueryDslRepository + .getListByClick(new LiquorSearchCondition(region, brew, status, brand), + Pageable.ofSize(1), liquorId, clickCount); + Long 커서첫번째_liquorId = 커서첫번째.get(커서첫번째.size() - 1).getId(); + + // then + assertThat(liquorId).isGreaterThan(커서첫번째_liquorId); + } + + @Test + @DisplayName("클릭순+최신순 : 커서 liquorId와 clickCount가 not null 일때, 클릭률 순으로, 클릭률 같다면 최신 순으로 정렬") + void cursorLiquorIdClickCCountNotNullTestByClickAndLatest() { + // given + LiquorBrew brew = null; + LiquorRegion region = null; + LiquorStatus status = null; + String brand = null; + Long liquorId = 3L; + Long clickCount = 100L; + + // when + List 커서첫번째 = liquorQueryDslRepository + .getListByClick(new LiquorSearchCondition(region, brew, status, brand), + Pageable.ofSize(1), liquorId, clickCount); + Long 커서첫번째_liquorId = 커서첫번째.get(커서첫번째.size() - 1).getClickCount(); + Long 커서첫번째_clickCount = 커서첫번째.get(커서첫번째.size() - 1).getClickCount(); + + List 커서두번째 = liquorQueryDslRepository + .getListByClick(new LiquorSearchCondition(region, brew, status, brand), + Pageable.ofSize(1), 커서첫번째_liquorId, 커서첫번째_clickCount); + Long 커서두번째_clickCount = 커서두번째.get(커서두번째.size() - 1).getClickCount(); // then - assertThat(커서두번째).isEmpty(); + assertThat(커서첫번째_clickCount).isGreaterThanOrEqualTo(커서두번째_clickCount); } } diff --git a/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorServiceIntegrationTest.java b/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorServiceIntegrationTest.java index 86b6ec55..8a5db5c2 100644 --- a/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorServiceIntegrationTest.java +++ b/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorServiceIntegrationTest.java @@ -5,10 +5,10 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.junit.jupiter.api.Assertions.assertAll; -import com.woowacamp.soolsool.core.liquor.dto.LiquorDetailResponse; -import com.woowacamp.soolsool.core.liquor.dto.LiquorElementResponse; -import com.woowacamp.soolsool.core.liquor.dto.LiquorModifyRequest; -import com.woowacamp.soolsool.core.liquor.dto.LiquorSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorModifyRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorDetailResponse; +import com.woowacamp.soolsool.core.liquor.dto.response.LiquorElementResponse; import com.woowacamp.soolsool.core.liquor.repository.LiquorBrewCache; import com.woowacamp.soolsool.core.liquor.repository.LiquorQueryDslRepository; import com.woowacamp.soolsool.core.liquor.repository.LiquorRegionCache; diff --git a/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockServiceIntegrationTest.java b/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockServiceIntegrationTest.java index 329aaf10..a14b88a6 100644 --- a/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockServiceIntegrationTest.java +++ b/src/test/java/com/woowacamp/soolsool/core/liquor/service/LiquorStockServiceIntegrationTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.woowacamp.soolsool.core.liquor.dto.LiquorStockSaveRequest; +import com.woowacamp.soolsool.core.liquor.dto.request.LiquorStockSaveRequest; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test;