Skip to content

Commit

Permalink
#20 [feat] 소원권 입력 Api 구현 (#22)
Browse files Browse the repository at this point in the history
* feat: Fix ErrorType

* feat: WishCoupon Patch Api

* feat: Fix for exception

* chore: Change isContainApiPath

* feat: Fix to use record

* feat: Fix setter method

* feat: Fix to record

* chore: Fix code style
  • Loading branch information
2zerozu authored Jul 11, 2023
1 parent 1c9148c commit 25728f7
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import com.universe.uni.service.JwtManager;

import io.jsonwebtoken.JwtException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(
HttpStatus status,
WebRequest request
) {
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.VALIDATION_REQUEST_MISSING_EXCEPTION);
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.INVALID_REQUEST_METHOD);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

Expand All @@ -46,7 +46,7 @@ protected ResponseEntity<Object> handleMissingServletRequestParameter(
HttpStatus status,
WebRequest request
) {
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.VALIDATION_REQUEST_MISSING_EXCEPTION);
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.INVALID_REQUEST_METHOD);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

Expand All @@ -57,15 +57,15 @@ protected ResponseEntity<Object> handleMissingPathVariable(
HttpStatus status,
WebRequest request
) {
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.VALIDATION_REQUEST_MISSING_EXCEPTION);
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.INVALID_REQUEST_METHOD);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(MissingRequestHeaderException.class)
protected ResponseEntity<Object> handleMissingRequestHeaderException(
MissingRequestHeaderException exception
) {
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.VALIDATION_EXCEPTION);
ErrorResponse errorResponse = ErrorResponse.businessErrorOf(ErrorType.INVALID_REQUEST_METHOD);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.universe.uni.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.universe.uni.dto.request.UpdateWishCouponRequestDto;
import com.universe.uni.dto.response.UpdateWishCouponResponseDto;
import com.universe.uni.service.WishCouponService;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/wish")
public class WishCouponController {

private final WishCouponService wishCouponService;

@PatchMapping
@ResponseStatus(HttpStatus.OK)
public UpdateWishCouponResponseDto updateWishCoupon(
@RequestBody UpdateWishCouponRequestDto requestDto
) {
return wishCouponService.uploadWishCoupon(requestDto);
}
}
29 changes: 26 additions & 3 deletions src/main/java/com/universe/uni/domain/entity/WishCoupon.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.universe.uni.domain.entity;

import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

import java.time.LocalDateTime;

import javax.persistence.Column;
Expand All @@ -15,12 +18,10 @@
import com.universe.uni.domain.GameType;
import com.universe.uni.domain.entity.convertor.GameTypeAttributeConverter;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

@Entity
@Table(name = "wish_coupon")
@NoArgsConstructor(access = PROTECTED)
Expand Down Expand Up @@ -58,4 +59,26 @@ public class WishCoupon {
@Column(name = "game_type", nullable = false)
@Convert(converter = GameTypeAttributeConverter.class)
private GameType gameType;

@Builder
public WishCoupon(Long id, String image, String content, boolean isVisible, boolean isUsed, LocalDateTime usedAt,
User user, Game game, GameType gameType) {
this.id = id;
this.image = image;
this.content = content;
this.isVisible = isVisible;
this.isUsed = isUsed;
this.usedAt = usedAt;
this.user = user;
this.game = game;
this.gameType = gameType;
}

public void updateContent(String content) {
this.content = content;
}

public void makeVisible() {
this.isVisible = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.universe.uni.dto.request;

public record UpdateWishCouponRequestDto(String gameType, String content) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.universe.uni.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import lombok.Builder;

@JsonPropertyOrder({"id", "image", "content", "isVisible", "isUsed", "usedAt", "gameType"})
@Builder
public record UpdateWishCouponResponseDto(
Long id,
String image,
String content,
@JsonProperty("isVisible") boolean visible,
@JsonProperty("isUsed") boolean used,
String usedAt,
String gameType
) {
}
36 changes: 23 additions & 13 deletions src/main/java/com/universe/uni/exception/dto/ErrorType.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,55 @@ public enum ErrorType {
/**
* 400 BAD REQUEST
*/
VALIDATION_EXCEPTION(HttpStatus.BAD_REQUEST, "UE1001", "잘못된 요청입니다."),
VALIDATION_REQUEST_MISSING_EXCEPTION(HttpStatus.BAD_REQUEST, "UE1002", "요청값이 입력되지 않았습니다."),
INVALID_REQUEST_METHOD(HttpStatus.BAD_REQUEST, "UE1001",
"요청 방식이 잘못된 경우입니다. 요청 방식 자체가 잘못된 경우입니다."),
VALIDATION_TOKEN_MISSING_EXCEPTION(HttpStatus.BAD_REQUEST, "UE1002",
"요청 시 토큰이 누락되어 토큰 값이 없는 경우입니다."),

/**
* 401 UNAUTHORIZED
* 401 Unauthorized
*/
EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "UE2001", "만료된 토큰 입니다."),
UNSUPPORTED_TOKEN(HttpStatus.UNAUTHORIZED, "UE2002", "잘못된 토큰 입니다"),
EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "UE2001", "토큰이 만료된 경우입니다."),
UNSUPPORTED_TOKEN(HttpStatus.UNAUTHORIZED, "UE2002",
"서버에서 인증하지 않는 방식의 토큰 혹은 변조된 토큰을 사용한 경우입니다."),

/**
* 404 NOT FOUND
*/
METHOD_NOT_SUPPORTED(HttpStatus.NOT_FOUND, "UE5001", "존제하지 않는 EndPoint 입니다"),
NOT_FOUND_USER_EXCEPTION(HttpStatus.NOT_FOUND, "UE5002", "존재하지 않는 유저입니다"),
INVALID_ENDPOINT_EXCEPTION(HttpStatus.NOT_FOUND, "UE5001",
"잘못된 endpoint에 요청한 경우입니다."),
USER_NOT_FOUND_EXCEPTION(HttpStatus.NOT_FOUND, "UE5002",
"조회한 유저가 존재하지 않는 경우 입니다."),

/**
* 406 Not Acceptable
*/
NOT_ACCEPTABLE(HttpStatus.NOT_ACCEPTABLE, "UE7001", "Accept 헤더에 유효하지 않거나 지원되지 않는 미디어 유형을 지정되었습니다."),
UNSUPPORTED_MEDIA_TYPE_EXCEPTION(HttpStatus.NOT_ACCEPTABLE, "UE7001",
"Accept 헤더에 유효하지 않거나 지원되지 않는 미디어 유형을 지정한 경우입니다."),

/**
* 409 CONFLICT
*/
ALREADY_EXIST_USER_EXCEPTION(HttpStatus.CONFLICT, "UE10001", "이미 존재하는 유저입니다"),
USER_ALREADY_EXISTS_EXCEPTION(HttpStatus.CONFLICT, "UE10001",
"이미 존재하는 유저에 대한 생성에 대한 경우입니다."),

/**
* 415 Unsupported Media Type.
* 415 Unsupported Media Type
*/
UNSUPPORTED_METHOD_TYPE(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "UE16001", "지원하지 않는 미디어 포멧입니다."),
UNSUPPORTED_MEDIA_FORMAT_EXCEPTION(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "UE16001",
"지원하지 않는 미디어 포멧으로 요청한 경우 입니다."),

/**
* 500 INTERNAL SERVER ERROR
*/
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "UE0500", "예상치 못한 서버 에러가 발생하였습니다."),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "UE500",
"서버 내부 오류입니다."),

/**
* 503 Service Unavailable
*/
SERVICE_UNAVAILABLE(HttpStatus.SERVICE_UNAVAILABLE, "UE0503", "서버가 작동중이지 않거나 과부하 상태입니다.");
SERVICE_UNAVAILABLE_EXCEPTION(HttpStatus.SERVICE_UNAVAILABLE, "UE503",
"서버가 작동중이지 않거나 과부하 상태입니다.");

private final HttpStatus httpStatus;
private final String uniErrorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.universe.uni.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import com.universe.uni.domain.GameType;
import com.universe.uni.domain.entity.WishCoupon;

public interface WishCouponRepository extends JpaRepository<WishCoupon, Long> {

List<WishCoupon> findByGameTypeAndIsVisibleFalseAndIsUsedFalseAndUsedAtIsNull(GameType gameType);

}
56 changes: 56 additions & 0 deletions src/main/java/com/universe/uni/service/WishCouponService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.universe.uni.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.universe.uni.domain.GameType;
import com.universe.uni.domain.entity.WishCoupon;
import com.universe.uni.dto.request.UpdateWishCouponRequestDto;
import com.universe.uni.dto.response.UpdateWishCouponResponseDto;
import com.universe.uni.exception.BadRequestException;
import com.universe.uni.exception.dto.ErrorType;
import com.universe.uni.repository.WishCouponRepository;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class WishCouponService {

private final WishCouponRepository wishCouponRepository;

@Transactional
public UpdateWishCouponResponseDto uploadWishCoupon(UpdateWishCouponRequestDto requestDto) {
GameType gameType = GameType.valueOf(requestDto.gameType());
List<WishCoupon> wishCouponList = wishCouponRepository.findByGameTypeAndIsVisibleFalseAndIsUsedFalseAndUsedAtIsNull(
gameType);

if (wishCouponList.isEmpty()) {
throw new BadRequestException(ErrorType.INVALID_REQUEST_METHOD);
}

WishCoupon wishCoupon = wishCouponList.get(0);

wishCoupon.updateContent(requestDto.content());
wishCoupon.makeVisible();

return fromWishCoupon(wishCoupon);
}

private UpdateWishCouponResponseDto fromWishCoupon(WishCoupon wishCoupon) {
String usedAt = wishCoupon.getUsedAt() != null ? wishCoupon.getUsedAt().toString() : null;

return UpdateWishCouponResponseDto.builder()
.id(wishCoupon.getId())
.image(wishCoupon.getImage())
.content(wishCoupon.getContent())
.visible(wishCoupon.isVisible())
.used(wishCoupon.isUsed())
.usedAt(usedAt)
.gameType(String.valueOf(wishCoupon.getGameType()))
.build();
}
}

0 comments on commit 25728f7

Please sign in to comment.