-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #106 from cvs-go/feature#105
프로모션 조회 기능 추가
- Loading branch information
Showing
13 changed files
with
369 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/main/java/com/cvsgo/controller/PromotionController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.cvsgo.controller; | ||
|
||
import com.cvsgo.dto.SuccessResponse; | ||
import com.cvsgo.dto.promotion.ReadPromotionResponseDto; | ||
import com.cvsgo.service.PromotionService; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/promotions") | ||
public class PromotionController { | ||
|
||
private final PromotionService promotionService; | ||
|
||
@GetMapping | ||
private SuccessResponse<List<ReadPromotionResponseDto>> readPromotionList() { | ||
return SuccessResponse.from(promotionService.readPromotionList()); | ||
} | ||
|
||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/com/cvsgo/dto/promotion/ReadPromotionResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.cvsgo.dto.promotion; | ||
|
||
import com.cvsgo.entity.Promotion; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class ReadPromotionResponseDto { | ||
|
||
private final Long id; | ||
|
||
private final String imageUrl; | ||
|
||
private final String landingUrl; | ||
|
||
public ReadPromotionResponseDto(Promotion promotion) { | ||
this.id = promotion.getId(); | ||
this.imageUrl = promotion.getImageUrl(); | ||
this.landingUrl = promotion.getLandingUrl(); | ||
} | ||
|
||
public static ReadPromotionResponseDto from(Promotion promotion) { | ||
return new ReadPromotionResponseDto(promotion); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/main/java/com/cvsgo/repository/PromotionCustomRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.cvsgo.repository; | ||
|
||
import com.cvsgo.entity.Promotion; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
public interface PromotionCustomRepository { | ||
|
||
List<Promotion> findActivePromotions(LocalDateTime now); | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/com/cvsgo/repository/PromotionCustomRepositoryImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.cvsgo.repository; | ||
|
||
import static com.cvsgo.entity.QPromotion.promotion; | ||
|
||
import com.cvsgo.entity.Promotion; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@RequiredArgsConstructor | ||
@Repository | ||
public class PromotionCustomRepositoryImpl implements PromotionCustomRepository { | ||
|
||
private final JPAQueryFactory queryFactory; | ||
|
||
public List<Promotion> findActivePromotions(LocalDateTime now) { | ||
return queryFactory.selectFrom(promotion) | ||
.where(promotion.startAt.loe(now).and(promotion.endAt.goe(now))) | ||
.orderBy(promotion.priority.asc()) | ||
.fetch(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,13 @@ | ||
package com.cvsgo.repository; | ||
|
||
import com.cvsgo.entity.Promotion; | ||
import java.time.LocalDateTime; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.data.repository.query.Param; | ||
|
||
public interface PromotionRepository extends JpaRepository<Promotion, Long> { | ||
public interface PromotionRepository extends JpaRepository<Promotion, Long>, PromotionCustomRepository { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.cvsgo.service; | ||
|
||
import com.cvsgo.dto.promotion.ReadPromotionResponseDto; | ||
import com.cvsgo.repository.PromotionRepository; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class PromotionService { | ||
|
||
private final PromotionRepository promotionRepository; | ||
|
||
/** | ||
* 현재 로컬 날짜 및 시간 기준 활성된 프로모션 목록을 우선순위 순으로 조회한다. | ||
* | ||
* @return 프로모션 목록 | ||
*/ | ||
@Transactional(readOnly = true) | ||
public List<ReadPromotionResponseDto> readPromotionList() { | ||
List<ReadPromotionResponseDto> promotionResponseDtos = promotionRepository.findActivePromotions(LocalDateTime.now()).stream() | ||
.map(ReadPromotionResponseDto::from).toList(); | ||
return promotionResponseDtos; | ||
} | ||
|
||
} |
97 changes: 97 additions & 0 deletions
97
src/test/java/com/cvsgo/controller/PromotionControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package com.cvsgo.controller; | ||
|
||
import static com.cvsgo.ApiDocumentUtils.documentIdentifier; | ||
import static com.cvsgo.ApiDocumentUtils.getDocumentRequest; | ||
import static com.cvsgo.ApiDocumentUtils.getDocumentResponse; | ||
import static org.mockito.BDDMockito.given; | ||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; | ||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; | ||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; | ||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; | ||
import static org.springframework.restdocs.payload.PayloadDocumentation.relaxedResponseFields; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
import static org.springframework.test.web.servlet.setup.SharedHttpSessionConfigurer.sharedHttpSession; | ||
|
||
import com.cvsgo.argumentresolver.LoginUserArgumentResolver; | ||
import com.cvsgo.config.WebConfig; | ||
import com.cvsgo.dto.promotion.ReadPromotionResponseDto; | ||
import com.cvsgo.entity.Promotion; | ||
import com.cvsgo.interceptor.AuthInterceptor; | ||
import com.cvsgo.service.PromotionService; | ||
import java.util.List; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; | ||
import org.springframework.boot.test.mock.mockito.MockBean; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.restdocs.RestDocumentationContextProvider; | ||
import org.springframework.restdocs.RestDocumentationExtension; | ||
import org.springframework.restdocs.payload.JsonFieldType; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
import org.springframework.web.context.WebApplicationContext; | ||
import org.springframework.web.filter.CharacterEncodingFilter; | ||
|
||
@ExtendWith(RestDocumentationExtension.class) | ||
@WebMvcTest(PromotionController.class) | ||
class PromotionControllerTest { | ||
|
||
@MockBean | ||
LoginUserArgumentResolver loginUserArgumentResolver; | ||
|
||
@MockBean | ||
WebConfig webConfig; | ||
|
||
@MockBean | ||
AuthInterceptor authInterceptor; | ||
|
||
@MockBean | ||
private PromotionService promotionService; | ||
|
||
private MockMvc mockMvc; | ||
|
||
@BeforeEach | ||
void setup(WebApplicationContext webApplicationContext, | ||
RestDocumentationContextProvider restDocumentation) { | ||
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) | ||
.apply(documentationConfiguration(restDocumentation)) | ||
.apply(sharedHttpSession()) | ||
.addFilters(new CharacterEncodingFilter("UTF-8", true)) | ||
.build(); | ||
} | ||
|
||
@Test | ||
@DisplayName("프로모션 목록을 정상적으로 조회하면 HTTP 200을 응답한다") | ||
void respond_200_when_read_promotion_list_successfully() throws Exception { | ||
List<ReadPromotionResponseDto> responseDto = List.of(new ReadPromotionResponseDto(promotion1), new ReadPromotionResponseDto(promotion2)); | ||
given(promotionService.readPromotionList()).willReturn(responseDto); | ||
|
||
mockMvc.perform(get("/api/promotions").contentType(MediaType.APPLICATION_JSON)) | ||
.andExpect(status().isOk()) | ||
.andDo(print()) | ||
.andDo(document(documentIdentifier, | ||
getDocumentRequest(), | ||
getDocumentResponse(), | ||
relaxedResponseFields( | ||
fieldWithPath("data.[].id").type(JsonFieldType.NUMBER).description("프로모션 ID"), | ||
fieldWithPath("data.[].imageUrl").type(JsonFieldType.STRING).description("프로모션 이미지 url"), | ||
fieldWithPath("data.[].landingUrl").type(JsonFieldType.STRING).description("프로모션 랜딩 url") | ||
) | ||
)); | ||
} | ||
|
||
Promotion promotion1 = Promotion.builder() | ||
.id(1L) | ||
.imageUrl("imageUrl1") | ||
.landingUrl("landindUrl1") | ||
.build(); | ||
|
||
Promotion promotion2 = Promotion.builder() | ||
.id(2L) | ||
.imageUrl("imageUrl2") | ||
.landingUrl("landindUrl2") | ||
.build(); | ||
} |
55 changes: 55 additions & 0 deletions
55
src/test/java/com/cvsgo/repository/PromotionRepositoryTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.cvsgo.repository; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import com.cvsgo.config.TestConfig; | ||
import com.cvsgo.entity.Promotion; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; | ||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||
import org.springframework.context.annotation.Import; | ||
|
||
@Import(TestConfig.class) | ||
@DataJpaTest | ||
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) | ||
class PromotionRepositoryTest { | ||
|
||
@Autowired | ||
PromotionRepository promotionRepository; | ||
|
||
@BeforeEach | ||
void initData() { | ||
promotion1 = Promotion.builder().id(1L).name("프로모션1").imageUrl("imageUrl1").landingUrl("landindUrl1") | ||
.priority(3).startAt(LocalDateTime.now().minusDays(3)).endAt(LocalDateTime.now().minusDays(1)).build(); | ||
promotion2 = Promotion.builder().id(2L).name("프로모션2").imageUrl("imageUrl2").landingUrl("landindUrl2") | ||
.priority(2).startAt(LocalDateTime.now().minusDays(1)).endAt(LocalDateTime.now().plusDays(1)).build(); | ||
promotion3 = Promotion.builder().id(3L).name("프로모션3").imageUrl("imageUrl3").landingUrl("landindUrl3") | ||
.priority(1).startAt(LocalDateTime.now().minusDays(5)).endAt(LocalDateTime.now().plusDays(6)).build(); | ||
promotion4 = Promotion.builder().id(2L).name("프로모션4").imageUrl("imageUrl2").landingUrl("landindUrl2") | ||
.priority(1).startAt(LocalDateTime.now().plusDays(1)).endAt(LocalDateTime.now().plusDays(3)).build(); | ||
promotionRepository.saveAll(List.of(promotion1, promotion2, promotion3, promotion4)); | ||
} | ||
|
||
@Test | ||
@DisplayName("활성된 프로모션을 조회한다") | ||
void find_active_promotions() { | ||
// when | ||
LocalDateTime now = LocalDateTime.now(); | ||
List<Promotion> foundPromotions = promotionRepository.findActivePromotions(now); | ||
|
||
// then | ||
assertThat(foundPromotions).hasSize(2); | ||
assertThat(foundPromotions.get(0).getPriority()).isEqualTo(1); | ||
assertThat(foundPromotions.get(1).getPriority()).isEqualTo(2); | ||
} | ||
|
||
private Promotion promotion1; | ||
private Promotion promotion2; | ||
private Promotion promotion3; | ||
private Promotion promotion4; | ||
} |
Oops, something went wrong.