Skip to content

Commit

Permalink
hotfix: 쿠폰 발급 횟수 버그 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
hongdosan committed Dec 1, 2023
1 parent aa8c32f commit ed0a711
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.BadRequestException;
import com.moabam.global.error.exception.ConflictException;
import com.moabam.global.error.exception.NotFoundException;
import com.moabam.global.error.model.ErrorMessage;

import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -75,15 +76,15 @@ public void registerQueue(String couponName, Long memberId) {
couponManageRepository.addIfAbsentQueue(couponName, memberId, registerTime);
}

public void deleteQueue(String couponName) {
public void delete(String couponName) {
couponManageRepository.deleteQueue(couponName);
couponManageRepository.deleteCount(couponName);
}

private void validateRegisterQueue(String couponName, Long memberId) {
LocalDate now = clockHolder.date();
Coupon coupon = couponRepository.findByNameAndStartAt(couponName, now)
.orElseThrow(() -> new BadRequestException(ErrorMessage.INVALID_COUPON_PERIOD));
.orElseThrow(() -> new NotFoundException(ErrorMessage.INVALID_COUPON_PERIOD));

if (couponManageRepository.hasValue(couponName, memberId)) {
throw new ConflictException(ErrorMessage.CONFLICT_COUPON_ISSUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void delete(Long couponId, Role role) {
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON));

couponRepository.delete(coupon);
couponManageService.deleteQueue(coupon.getName());
couponManageService.delete(coupon.getName());
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ public int rankQueue(String couponName, Long memberId) {

public int getCount(String couponName) {
String couponCountKey = String.format(COUPON_COUNT_KEY, requireNonNull(couponName));
return Integer.parseInt(valueRedisRepository.get(couponCountKey));
String count = valueRedisRepository.get(couponCountKey);

if (isNull(count)) {
return 0;
}

return Integer.parseInt(count);
}

public void increase(String couponName, long count) {
Expand Down
14 changes: 7 additions & 7 deletions src/main/resources/static/docs/coupon.html
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ <h3 id="_쿠폰_삭제">쿠폰 삭제</h3>
<h4 id="_요청_2" class="discrete">요청</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-http" data-lang="http">DELETE /admins/coupons/33 HTTP/1.1
<pre class="highlight nowrap"><code class="language-http" data-lang="http">DELETE /admins/coupons/36 HTTP/1.1
Host: localhost:8080</code></pre>
</div>
</div>
Expand Down Expand Up @@ -526,7 +526,7 @@ <h3 id="_특정_쿠폰_조회">특정 쿠폰 조회</h3>
<h4 id="_요청_3">요청</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-http" data-lang="http">GET /coupons/21 HTTP/1.1
<pre class="highlight nowrap"><code class="language-http" data-lang="http">GET /coupons/24 HTTP/1.1
Host: localhost:8080</code></pre>
</div>
</div>
Expand All @@ -543,7 +543,7 @@ <h4 id="_응답_3" class="discrete">응답</h4>
Content-Length: 201

{
"id" : 21,
"id" : 24,
"adminName" : "ID : 1",
"name" : "couponName",
"description" : "",
Expand Down Expand Up @@ -593,7 +593,7 @@ <h4 id="_응답_4" class="discrete">응답</h4>
Content-Length: 202

[ {
"id" : 22,
"id" : 25,
"adminName" : "ID : 1",
"name" : "coupon1",
"description" : "",
Expand Down Expand Up @@ -630,17 +630,17 @@ <h4 id="_요청_5">요청</h4>
<h4 id="_응답_5" class="discrete">응답</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 400 Bad Request
<pre class="highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 409 Conflict
Access-Control-Allow-Origin:
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Access-Control-Allow-Headers: Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600
Content-Type: application/json
Content-Length: 64
Content-Length: 63

{
"message" : "쿠폰 발급 가능 기간이 아닙니다."
"message" : "이미 쿠폰 발급에 성공했습니다!"
}</code></pre>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import com.moabam.api.domain.coupon.repository.CouponRepository;
import com.moabam.api.domain.coupon.repository.CouponWalletRepository;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.BadRequestException;
import com.moabam.global.error.exception.NotFoundException;
import com.moabam.global.error.model.ErrorMessage;
import com.moabam.support.common.FilterProcessExtension;
import com.moabam.support.fixture.CouponFixture;
Expand Down Expand Up @@ -140,7 +140,7 @@ void registerQueue_No_BadRequestException() {

// When & Then
assertThatThrownBy(() -> couponManageService.registerQueue("couponName", 1L))
.isInstanceOf(BadRequestException.class)
.isInstanceOf(NotFoundException.class)
.hasMessage(ErrorMessage.INVALID_COUPON_PERIOD.getMessage());
}

Expand All @@ -151,7 +151,7 @@ void deleteQueue_success() {
String couponName = "couponName";

// When
couponManageService.deleteQueue(couponName);
couponManageService.delete(couponName);

// Then
verify(couponManageRepository).deleteQueue(couponName);
Expand All @@ -166,7 +166,7 @@ void deleteQueue_NullPointerException() {
.deleteQueue(any(String.class));

// When & Then
assertThatThrownBy(() -> couponManageService.deleteQueue("null"))
assertThatThrownBy(() -> couponManageService.delete("null"))
.isInstanceOf(NullPointerException.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ void delete_success() {

// Then
verify(couponRepository).delete(coupon);
verify(couponManageService).deleteQueue(any(String.class));
verify(couponManageService).delete(any(String.class));
}

@DisplayName("권한 없는 사용자가 쿠폰을 삭제한다. - NotFoundException")
Expand Down
58 changes: 45 additions & 13 deletions src/test/java/com/moabam/api/presentation/CouponControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.moabam.api.domain.member.repository.MemberRepository;
import com.moabam.api.dto.coupon.CouponStatusRequest;
import com.moabam.api.dto.coupon.CreateCouponRequest;
import com.moabam.api.infrastructure.redis.ValueRedisRepository;
import com.moabam.api.infrastructure.redis.ZSetRedisRepository;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.model.ErrorMessage;
Expand Down Expand Up @@ -73,6 +74,9 @@ class CouponControllerTest extends WithoutFilterSupporter {
@MockBean
ZSetRedisRepository zSetRedisRepository;

@MockBean
ValueRedisRepository valueRedisRepository;

@WithMember(role = Role.ADMIN)
@DisplayName("POST - 쿠폰을 성공적으로 발행한다. - Void")
@Test
Expand Down Expand Up @@ -420,9 +424,31 @@ void use_BadRequestException() throws Exception {
}

@WithMember
@DisplayName("POST - 발급 가능 날짜가 아닌 쿠폰에 발급 요청을 한다. (Not found) - BadRequestException")
@DisplayName("POST - 쿠폰 발급을 성공적으로 한다. - Void")
@Test
void registerQueue_Zero_StartAt_BadRequestException() throws Exception {
void registerQueue_success() throws Exception {
// Given
Coupon couponFixture = CouponFixture.coupon("CouponName", 2, 1);
Coupon coupon = couponRepository.save(couponFixture);

given(clockHolder.date()).willReturn(LocalDate.of(2023, 2, 1));
given(zSetRedisRepository.score(anyString(), anyLong())).willReturn(null);
given(zSetRedisRepository.size(anyString())).willReturn((long)(coupon.getMaxCount() - 1));

// When & Then
mockMvc.perform(post("/coupons")
.param("couponName", coupon.getName()))
.andDo(print())
.andDo(document("coupons",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint())))
.andExpect(status().isOk());
}

@WithMember
@DisplayName("POST - 발급 가능 날짜가 아닌 쿠폰에 발급 요청을 한다. - NotFoundException")
@Test
void registerQueue_NotFoundException() throws Exception {
// Given
Coupon couponFixture = CouponFixture.coupon();
Coupon coupon = couponRepository.save(couponFixture);
Expand All @@ -437,39 +463,45 @@ void registerQueue_Zero_StartAt_BadRequestException() throws Exception {
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
ErrorSnippet.ERROR_MESSAGE_RESPONSE))
.andExpect(status().isBadRequest())
.andExpect(status().isNotFound())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.message").value(ErrorMessage.INVALID_COUPON_PERIOD.getMessage()));
}

@WithMember
@DisplayName("POST - 발급 가능 날짜가 아닌 쿠폰에 발급 요청을 한다. (Not equals) - BadRequestException")
@DisplayName("POST - 동일한 쿠폰 이벤트에 중복으로 요청한다. - ConflictException")
@Test
void registerQueue_Not_StartAt_BadRequestException() throws Exception {
void registerQueue_ConflictException() throws Exception {
// Given
given(clockHolder.date()).willReturn(LocalDate.of(2022, 2, 1));
Coupon coupon = couponRepository.save(CouponFixture.coupon());

given(clockHolder.date()).willReturn(LocalDate.of(2023, 2, 1));
given(zSetRedisRepository.score(anyString(), anyLong())).willReturn(7.0);

// When & Then
mockMvc.perform(post("/coupons")
.param("couponName", "not start couponName"))
.param("couponName", coupon.getName()))
.andDo(print())
.andDo(document("coupons",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
ErrorSnippet.ERROR_MESSAGE_RESPONSE))
.andExpect(status().isBadRequest())
.andExpect(status().isConflict())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.message").value(ErrorMessage.INVALID_COUPON_PERIOD.getMessage()));
.andExpect(jsonPath("$.message").value(ErrorMessage.CONFLICT_COUPON_ISSUE.getMessage()));
}

@WithMember
@DisplayName("POST - 존재하지 않는 쿠폰에 발급 요청을 한다. - NotFoundException")
@DisplayName("POST - 선착순 이벤트가 마감된 쿠폰에 발급 요청을 한다. - BadRequestException")
@Test
void registerQueue_NotFoundException() throws Exception {
void registerQueue_BadRequestException() throws Exception {
// Given
Coupon coupon = CouponFixture.coupon("Not found couponName", 2, 1);
Coupon couponFixture = CouponFixture.coupon();
Coupon coupon = couponRepository.save(couponFixture);

given(clockHolder.date()).willReturn(LocalDate.of(2023, 2, 1));
given(zSetRedisRepository.score(anyString(), anyLong())).willReturn(null);
given(zSetRedisRepository.size(anyString())).willReturn((long)(coupon.getMaxCount()));

// When & Then
mockMvc.perform(post("/coupons")
Expand All @@ -481,6 +513,6 @@ void registerQueue_NotFoundException() throws Exception {
ErrorSnippet.ERROR_MESSAGE_RESPONSE))
.andExpect(status().isBadRequest())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.message").value(ErrorMessage.INVALID_COUPON_PERIOD.getMessage()));
.andExpect(jsonPath("$.message").value(ErrorMessage.INVALID_COUPON_STOCK_END.getMessage()));
}
}

0 comments on commit ed0a711

Please sign in to comment.