From a5b0c8130fc87f1bee5f96cf34aee44bfed15ece Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:46:06 +0900 Subject: [PATCH 01/37] =?UTF-8?q?feat:=20lombok=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/user/enums/Gender.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/be/src/main/java/yeonba/be/user/enums/Gender.java b/be/src/main/java/yeonba/be/user/enums/Gender.java index 0668205c..f5cabdc3 100644 --- a/be/src/main/java/yeonba/be/user/enums/Gender.java +++ b/be/src/main/java/yeonba/be/user/enums/Gender.java @@ -1,7 +1,11 @@ package yeonba.be.user.enums; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.apache.commons.lang3.StringUtils; +@Getter +@AllArgsConstructor public enum Gender { MALE("남", true), @@ -10,11 +14,6 @@ public enum Gender { public final String genderString; public final boolean genderBoolean; - Gender(String genderString, boolean genderBoolean) { - this.genderString = genderString; - this.genderBoolean = genderBoolean; - } - public static Gender from(String genderString) { if (StringUtils.equals(genderString, MALE.genderString)) { From babf288902616579fbaf6cfc92ab367c457d9960 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:49:41 +0900 Subject: [PATCH 02/37] =?UTF-8?q?feat:=20gender=20boolean=20=EA=B0=92=20st?= =?UTF-8?q?ring=20=EB=B3=80=ED=99=98=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/user/enums/Gender.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/be/src/main/java/yeonba/be/user/enums/Gender.java b/be/src/main/java/yeonba/be/user/enums/Gender.java index f5cabdc3..ce7df7c6 100644 --- a/be/src/main/java/yeonba/be/user/enums/Gender.java +++ b/be/src/main/java/yeonba/be/user/enums/Gender.java @@ -23,4 +23,14 @@ public static Gender from(String genderString) { return FEMALE; } + + public static String genderBooleanToString(boolean genderBoolean) { + + if (genderBoolean == MALE.genderBoolean) { + + return MALE.genderString; + } + + return FEMALE.genderString; + } } From d615581d2044ec62a42582eb34391551f1d295a3 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:51:25 +0900 Subject: [PATCH 03/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 같은 사용자(자기 자신) 검증 로직, UserException 이용토록 수정 - 성별 boolean, string 두 타입으로 제공하는 메서드 추가 - 같은 성별 사용자인 지 검증하는 메서드 추가 --- .../main/java/yeonba/be/user/entity/User.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/be/src/main/java/yeonba/be/user/entity/User.java b/be/src/main/java/yeonba/be/user/entity/User.java index 493b1d5c..9d727752 100644 --- a/be/src/main/java/yeonba/be/user/entity/User.java +++ b/be/src/main/java/yeonba/be/user/entity/User.java @@ -23,6 +23,8 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import yeonba.be.exception.ArrowException; import yeonba.be.exception.GeneralException; +import yeonba.be.exception.UserException; +import yeonba.be.user.enums.Gender; @Table(name = "users") @Getter @@ -147,7 +149,7 @@ public User( public void validateNotSameUser(User user) { if (this.equals(user)) { - throw new IllegalArgumentException("동일한 사용자입니다."); + throw new GeneralException(UserException.SAME_USER); } } @@ -198,14 +200,14 @@ public void minusArrow(int arrow) { this.arrow -= arrow; } - public String getGender() { + public String getGenderString() { - if (this.gender) { + return Gender.genderBooleanToString(this.gender); + } - return "남"; - } + public boolean getGenderBoolean() { - return "여"; + return this.gender; } public List getProfilePhotoUrls() { @@ -229,4 +231,11 @@ public void updateRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } + + public void validateSameGender(User user) { + + if (this.gender == user.getGenderBoolean()) { + throw new GeneralException(UserException.SAME_GENDER_USER); + } + } } From 65aac96da925c0976aa1b9425f31744b072ef0da Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:52:22 +0900 Subject: [PATCH 04/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=97=B0=EA=B4=80=20=EC=98=88=EC=99=B8=20=EC=B6=94=EA=B0=80(#6?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 같은 사용자(자기 자신)일 경우 - 같은 성별 사용자인 경우 - 휴면 상태 사용자인 경우 --- .../yeonba/be/exception/UserException.java | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/be/src/main/java/yeonba/be/exception/UserException.java b/be/src/main/java/yeonba/be/exception/UserException.java index 0e7d2a11..c5c481af 100644 --- a/be/src/main/java/yeonba/be/exception/UserException.java +++ b/be/src/main/java/yeonba/be/exception/UserException.java @@ -1,28 +1,29 @@ package yeonba.be.exception; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.springframework.http.HttpStatus; +@Getter +@AllArgsConstructor public enum UserException implements BaseException { - USER_NOT_FOUND( - HttpStatus.BAD_REQUEST, - "해당 사용자가 존재하지 않습니다."); + SAME_USER( + HttpStatus.BAD_REQUEST, + "같은 사용자(자기 자신) 입니다."), - private final HttpStatus httpStatus; - private final String reason; + SAME_GENDER_USER( + HttpStatus.BAD_REQUEST, + "같은 성별 사용자 입니다."), - UserException(HttpStatus httpStatus, String reason) { - this.httpStatus = httpStatus; - this.reason = reason; - } + USER_NOT_FOUND( + HttpStatus.BAD_REQUEST, + "해당 사용자가 존재하지 않습니다."), - @Override - public HttpStatus getHttpStatus() { - return httpStatus; - } + INACTIVE_USER( + HttpStatus.BAD_REQUEST, + "휴면 상태 사용자입니다. 휴면 해제가 필요합니다."); - @Override - public String getReason() { - return reason; - } + private final HttpStatus httpStatus; + private final String reason; } From 69bdf2f572b386d8f3c0daab38b59ba18da02451 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:53:33 +0900 Subject: [PATCH 05/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20boolean=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=84=B1=EB=B3=84=20getter=20=EC=82=AC=EC=9A=A9=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - getter 메서드명 변경에 따른 사용위치 수정 --- .../be/mypage/dto/response/UserProfileDetailResponse.java | 2 +- be/src/main/java/yeonba/be/user/service/UserService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/be/src/main/java/yeonba/be/mypage/dto/response/UserProfileDetailResponse.java b/be/src/main/java/yeonba/be/mypage/dto/response/UserProfileDetailResponse.java index cf7f13ab..18cb4318 100644 --- a/be/src/main/java/yeonba/be/mypage/dto/response/UserProfileDetailResponse.java +++ b/be/src/main/java/yeonba/be/mypage/dto/response/UserProfileDetailResponse.java @@ -87,7 +87,7 @@ public class UserProfileDetailResponse { public UserProfileDetailResponse(User user) { this.profilePhotoUrls = user.getProfilePhotoUrls(); - this.gender = user.getGender(); + this.gender = user.getGenderString(); this.name = user.getName(); this.birth = user.getBirth(); this.height = user.getHeight(); diff --git a/be/src/main/java/yeonba/be/user/service/UserService.java b/be/src/main/java/yeonba/be/user/service/UserService.java index 9dd4f912..f30a1f4e 100644 --- a/be/src/main/java/yeonba/be/user/service/UserService.java +++ b/be/src/main/java/yeonba/be/user/service/UserService.java @@ -61,7 +61,7 @@ public UserProfileResponse getTargetUserProfile(long userId, long targetUserId) return new UserProfileResponse( targetUser.getProfilePhotoUrls(), - targetUser.getGender(), + targetUser.getGenderString(), targetUser.getNickname(), targetUser.getArrow(), targetUser.getAge(), From a57eb4eac95f998a831afb03b1094494e3abbd74 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:54:22 +0900 Subject: [PATCH 06/37] =?UTF-8?q?feat:=20=ED=9C=B4=EB=A9=B4=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=97=90=EA=B2=8C=20?= =?UTF-8?q?=ED=99=94=EC=82=B4=20=EB=B3=B4=EB=83=84=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yeonba/be/exception/ArrowException.java | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/be/src/main/java/yeonba/be/exception/ArrowException.java b/be/src/main/java/yeonba/be/exception/ArrowException.java index e5c070ec..04ab96bd 100644 --- a/be/src/main/java/yeonba/be/exception/ArrowException.java +++ b/be/src/main/java/yeonba/be/exception/ArrowException.java @@ -1,7 +1,11 @@ package yeonba.be.exception; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.springframework.http.HttpStatus; +@Getter +@AllArgsConstructor public enum ArrowException implements BaseException { @@ -19,25 +23,12 @@ public enum ArrowException implements BaseException { NOT_ENOUGH_ARROW_TO_SEND( HttpStatus.BAD_REQUEST, - "화살이 부족하여 화살을 보낼 수 없습니다."); + "화살이 부족하여 화살을 보낼 수 없습니다."), + + CAN_NOT_SEND_ARROW_TO_INACTIVE_USER( + HttpStatus.BAD_REQUEST, + "휴면 상태인 사용자에겐 화살을 보낼 수 없습니다."); private final HttpStatus httpStatus; private final String reason; - - ArrowException(HttpStatus httpStatus, String reason) { - this.httpStatus = httpStatus; - this.reason = reason; - } - - @Override - public HttpStatus getHttpStatus() { - - return httpStatus; - } - - @Override - public String getReason() { - - return reason; - } } From 1c8cda84c17bb307eb2c61ec21287b84815e2cb1 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:56:47 +0900 Subject: [PATCH 07/37] =?UTF-8?q?feat:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=99=94=EC=82=B4=20=EB=B3=B4=EB=82=B4=EA=B8=B0=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20DTO=20=EC=82=AD=EC=A0=9C(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/arrow/dto/request/ArrowSendRequest.java | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 be/src/main/java/yeonba/be/arrow/dto/request/ArrowSendRequest.java diff --git a/be/src/main/java/yeonba/be/arrow/dto/request/ArrowSendRequest.java b/be/src/main/java/yeonba/be/arrow/dto/request/ArrowSendRequest.java deleted file mode 100644 index 8e3616e9..00000000 --- a/be/src/main/java/yeonba/be/arrow/dto/request/ArrowSendRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package yeonba.be.arrow.dto.request; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Positive; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class ArrowSendRequest { - - @Schema( - type = "number", - description = "보낼 화살 수", - example = "10") - @Positive(message = "화살은 1개 이상부터 보낼 수 있습니다.") - private int arrows; -} From c90bcf99cb5fc47fdaed31ceb54a0900ef1f795b Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:58:32 +0900 Subject: [PATCH 08/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EB=B3=B4?= =?UTF-8?q?=EB=82=B4=EA=B8=B0=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 보내는 사용자 휴면 상태 검증 추가 - 받는 사용자 휴면 상태 검증 추가 - 보내는 사용자와 받는 사용자 성별 동일 여부 검증 추가 - 화살 개수 1개만 보낼 수 있도록 수정 --- .../yeonba/be/arrow/service/ArrowService.java | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java index e871040c..d494f5b2 100644 --- a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java +++ b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java @@ -6,12 +6,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import yeonba.be.arrow.dto.UserArrowsResponse; -import yeonba.be.arrow.dto.request.ArrowSendRequest; import yeonba.be.arrow.entity.ArrowTransaction; import yeonba.be.arrow.repository.ArrowCommand; import yeonba.be.arrow.repository.ArrowQuery; import yeonba.be.exception.ArrowException; import yeonba.be.exception.GeneralException; +import yeonba.be.exception.UserException; import yeonba.be.user.entity.User; import yeonba.be.user.repository.UserQuery; @@ -25,13 +25,13 @@ public class ArrowService { private final ArrowCommand arrowCommand; private final ArrowQuery arrowQuery; - /* - 출석 체크는 다음 과정을 거쳐 이뤄진다. - 1. 사용자 최종 접속 일시를 통해 이미 출석 체크하였는지 확인 - 2. 화살 송수신 내역 저장 - 3. 사용자 최종 접속 일시 갱신 - 4. 사용자 화살 개수 증가 - */ + /* + 출석 체크는 다음 과정을 거쳐 이뤄진다. + 1. 사용자 최종 접속 일시를 통해 이미 출석 체크하였는지 확인 + 2. 화살 송수신 내역 저장 + 3. 사용자 최종 접속 일시 갱신 + 4. 사용자 화살 개수 증가 + */ @Transactional public void dailyCheck(long userId) { @@ -57,38 +57,40 @@ public UserArrowsResponse getUserArrows(long userId) { return new UserArrowsResponse(user.getArrow()); } - /* - 화살 보내기 비즈니스 로직은 다음 과정을 거친다. - 1. 자기 자신에게 화살을 보내는 상황 검증 - 2. 화살을 보낸 사용자에게 또 보내는 상황 검증 - 3. 화살 내역 저장 - 4. 보내는 사용자 화살 감소, 화살이 부족할 경우 예외 발생 - 5. 받는 사용자 화살 증가 - */ @Transactional - public void sendArrow( - long senderId, - long recipientId, - ArrowSendRequest request) { + public void sendArrow(long senderId, long receiverId) { User sender = userQuery.findById(senderId); - User receiver = userQuery.findById(recipientId); + User receiver = userQuery.findById(receiverId); + + // 휴면 상태에선 화살을 보낼 수 없음 + if (sender.isInactive()) { + throw new GeneralException(UserException.INACTIVE_USER); + } + // 휴면 상태인 사용자에게 화살을 보낼 수 없음 + if (receiver.isInactive()) { + throw new GeneralException(ArrowException.CAN_NOT_SEND_ARROW_TO_INACTIVE_USER); + } + + // 자기 자신에게 화살을 보낼 수 없음 sender.validateNotSameUser(receiver); + // 같은 성별 사용자에게 화살을 보낼 수 없음 + sender.validateSameGender(receiver); + + // 이미 화살을 보낸 사용자에게 화살을 보낼 수 없음 if (arrowQuery.isArrowTransactionExist(sender, receiver)) { throw new GeneralException(ArrowException.ALREADY_SENT_ARROW_USER); } - int arrows = request.getArrows(); - ArrowTransaction arrowTransaction = new ArrowTransaction( - sender, - receiver, - arrows); + // 화살은 1개만 보낼 수 있음 + int sendArrow = 1; + ArrowTransaction arrowTransaction = new ArrowTransaction(sender, receiver, sendArrow); arrowCommand.save(arrowTransaction); - sender.minusArrow(arrows); - receiver.plusArrow(arrows); + sender.minusArrow(sendArrow); + receiver.plusArrow(sendArrow); } @Transactional From 3212b5560f21b9eca5c19a8391981204616ce26f Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sat, 20 Apr 2024 20:59:44 +0900 Subject: [PATCH 09/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EB=B3=B4?= =?UTF-8?q?=EB=82=B4=EA=B8=B0=20API=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 한 번에 하나의 화살만 보낼 수 있기 때문에 별도의 요청 DTO(request body) 없이 작업을 수행하도록 API 수정 --- .../be/arrow/controller/ArrowController.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java index 15200374..b3c6560d 100644 --- a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java +++ b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java @@ -10,10 +10,8 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import yeonba.be.arrow.dto.UserArrowsResponse; -import yeonba.be.arrow.dto.request.ArrowSendRequest; import yeonba.be.arrow.service.ArrowService; import yeonba.be.util.CustomResponse; @@ -38,7 +36,7 @@ public ResponseEntity> arrows( } @Operation(summary = "출석 체크", description = "출석 체크를 통해 사용자가 10개의 화살을 획득할 수 있습니다.") - @ApiResponse(responseCode = "202", description = "출석 체크 정상 처리") + @ApiResponse(responseCode = "200", description = "출석 체크 정상 처리") @PostMapping("/daily-check") public ResponseEntity> dailyCheck( @RequestAttribute("userId") long userId) { @@ -46,31 +44,27 @@ public ResponseEntity> dailyCheck( arrowService.dailyCheck(userId); return ResponseEntity - .accepted() + .ok() .body(new CustomResponse<>()); } - @Operation(summary = "화살 보내기", description = "다른 사용자에게 화살을 보낼 수 있습니다.") - @ApiResponse(responseCode = "202", description = "화살 전송 정상 처리") + @Operation(summary = "화살 보내기", description = "다른 사용자에게 화살을 1개 보낼 수 있습니다.") + @ApiResponse(responseCode = "200", description = "화살 전송 정상 처리") @PostMapping("/users/{userId}/arrow") public ResponseEntity> sendArrow( @RequestAttribute("userId") long senderId, @Parameter(description = "화살 받는 사용자 ID", example = "1") - @PathVariable("userId") long receiverId, - @RequestBody ArrowSendRequest request) { + @PathVariable("userId") long receiverId) { - arrowService.sendArrow( - senderId, - receiverId, - request); + arrowService.sendArrow(senderId, receiverId); return ResponseEntity - .accepted() + .ok() .body(new CustomResponse<>()); } @Operation(summary = "화살 충전", description = "광고 시청시 화살 5개를 충전할 수 있습니다.") - @ApiResponse(responseCode = "202", description = "화살 충전 정상 처리") + @ApiResponse(responseCode = "200", description = "화살 충전 정상 처리") @PostMapping("/users/arrows") public ResponseEntity> chargeArrows( @RequestAttribute("userId") long userId) { @@ -78,7 +72,7 @@ public ResponseEntity> chargeArrows( arrowService.chargeArrows(userId); return ResponseEntity - .accepted() + .ok() .body(new CustomResponse<>()); } } From 9729fbbbb7de2718fd335049db53880a701f77e1 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:21:45 +0900 Subject: [PATCH 10/37] =?UTF-8?q?feat:=20=EB=B3=B4=EB=82=B4=EB=8A=94=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90,=20=EB=B0=9B=EB=8A=94=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=ED=95=84=EB=93=9C=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/arrow/entity/ArrowTransaction.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java b/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java index e96cf9c1..b2159278 100644 --- a/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java +++ b/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java @@ -28,12 +28,12 @@ public class ArrowTransaction { private Long id; @ManyToOne - @JoinColumn(name = "sent_user_id") - private User sentUser; + @JoinColumn(name = "sender_id") + private User sender; @ManyToOne - @JoinColumn(name = "received_user_id") - private User receivedUser; + @JoinColumn(name = "receiver_id") + private User receiver; @Column(nullable = false) private int arrows; @@ -43,20 +43,20 @@ public class ArrowTransaction { private LocalDateTime createdAt; public ArrowTransaction( - User receivedUser, + User receiver, int arrows) { - this.receivedUser = receivedUser; + this.receiver = receiver; this.arrows = arrows; } public ArrowTransaction( - User sentUser, - User receivedUser, + User sender, + User receiver, int arrows) { - this.sentUser = sentUser; - this.receivedUser = receivedUser; + this.sender = sender; + this.receiver = receiver; this.arrows = arrows; } } From 138f5a30934103188e74331b03f57325ebe2b745 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:23:01 +0900 Subject: [PATCH 11/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95(#6?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java | 2 +- .../be/arrow/repository/ArrowTransactionRepository.java | 2 +- .../be/arrow/repository/ArrowTransactionRepositoryImpl.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java b/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java index bd8e07f5..64b4384c 100644 --- a/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java +++ b/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java @@ -16,7 +16,7 @@ public class ArrowQuery { public boolean isArrowTransactionExist(User sentUser, User receivedUser) { return arrowTransactionRepository - .existsBySentUserAndReceivedUser(sentUser, receivedUser); + .existsBySenderAndReceiver(sentUser, receivedUser); } public void validateAdvertisementArrowCount(long userId, LocalDateTime today) { diff --git a/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepository.java b/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepository.java index 1ce41c92..fec891b7 100644 --- a/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepository.java +++ b/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepository.java @@ -9,5 +9,5 @@ public interface ArrowTransactionRepository extends JpaRepository, ArrowTransactionRepositoryCustom { - boolean existsBySentUserAndReceivedUser(User sentUser, User receivedUser); + boolean existsBySenderAndReceiver(User sender, User receiver); } diff --git a/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java b/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java index 294b08c0..7c7f613d 100644 --- a/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java +++ b/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java @@ -20,10 +20,10 @@ public boolean canChargeByAdvertisement(long userId, LocalDateTime today) { queryFactory .select(arrowTransaction.count()) .from(arrowTransaction) - .innerJoin(arrowTransaction.receivedUser, user) + .innerJoin(arrowTransaction.receiver, user) .where( - arrowTransaction.sentUser.isNull(), - arrowTransaction.receivedUser.id.eq(userId), + arrowTransaction.sender.isNull(), + arrowTransaction.receiver.id.eq(userId), arrowTransaction.createdAt.after(today) ) .fetchOne()) From a4a6faa353b5b94e798e7be099a9f7c94efd9985 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:24:00 +0900 Subject: [PATCH 12/37] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B2=BD=EB=A1=9C=20=EC=9D=B4=EB=8F=99(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arrow/dto/{ => response}/UserArrowsResponse.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename be/src/main/java/yeonba/be/arrow/dto/{ => response}/UserArrowsResponse.java (50%) diff --git a/be/src/main/java/yeonba/be/arrow/dto/UserArrowsResponse.java b/be/src/main/java/yeonba/be/arrow/dto/response/UserArrowsResponse.java similarity index 50% rename from be/src/main/java/yeonba/be/arrow/dto/UserArrowsResponse.java rename to be/src/main/java/yeonba/be/arrow/dto/response/UserArrowsResponse.java index 229737e1..cf162620 100644 --- a/be/src/main/java/yeonba/be/arrow/dto/UserArrowsResponse.java +++ b/be/src/main/java/yeonba/be/arrow/dto/response/UserArrowsResponse.java @@ -1,4 +1,4 @@ -package yeonba.be.arrow.dto; +package yeonba.be.arrow.dto.response; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; @@ -8,9 +8,9 @@ @AllArgsConstructor public class UserArrowsResponse { - @Schema( - type = "number", - description = "사용자 화살 개수", - example = "10") - private int arrows; + @Schema( + type = "number", + description = "사용자 화살 개수", + example = "10") + private int arrows; } From b5b4a04d686fcd612beea56028d25a1e467b1301 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:24:58 +0900 Subject: [PATCH 13/37] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EA=B0=B1=EC=8B=A0=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/user/entity/User.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/be/src/main/java/yeonba/be/user/entity/User.java b/be/src/main/java/yeonba/be/user/entity/User.java index 9d727752..29431210 100644 --- a/be/src/main/java/yeonba/be/user/entity/User.java +++ b/be/src/main/java/yeonba/be/user/entity/User.java @@ -181,9 +181,9 @@ public String getRepresentativeProfilePhoto() { return this.profilePhotos.get(0).getPhotoUrl(); } - public void updateLastAccessedAt(LocalDateTime accessedAt) { + public void updateLastAccessedAt(LocalDateTime accessAt) { - this.lastAccessedAt = accessedAt; + this.lastAccessedAt = accessAt; } public void plusArrow(int arrow) { From b1d29b3d717e1f58689368add7f605ebc5f5f895 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:25:46 +0900 Subject: [PATCH 14/37] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EA=B0=B1=EC=8B=A0=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 출석 체크 요청시 무조건적인 최종 접속 일시 갱신을 위해 사용 --- be/src/main/java/yeonba/be/user/service/UserService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/be/src/main/java/yeonba/be/user/service/UserService.java b/be/src/main/java/yeonba/be/user/service/UserService.java index f30a1f4e..9866d88d 100644 --- a/be/src/main/java/yeonba/be/user/service/UserService.java +++ b/be/src/main/java/yeonba/be/user/service/UserService.java @@ -1,6 +1,7 @@ package yeonba.be.user.service; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.Period; import java.util.List; import lombok.RequiredArgsConstructor; @@ -174,4 +175,11 @@ public void saveUserPreference(User user, UserJoinRequest request) { preferredAnimal); userPreferenceCommand.save(userPreference); } + + @Transactional + public void updateLastAccessedAt(long userId, LocalDateTime accessAt) { + + User user = userQuery.findById(userId); + user.updateLastAccessedAt(accessAt); + } } From 3c34858c725d901e6b36be2edb749c9ae1f47443 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:26:26 +0900 Subject: [PATCH 15/37] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yeonba/be/exception/LoginException.java | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/be/src/main/java/yeonba/be/exception/LoginException.java b/be/src/main/java/yeonba/be/exception/LoginException.java index deb5f8fd..75be63a0 100644 --- a/be/src/main/java/yeonba/be/exception/LoginException.java +++ b/be/src/main/java/yeonba/be/exception/LoginException.java @@ -1,31 +1,21 @@ package yeonba.be.exception; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.springframework.http.HttpStatus; +@Getter +@AllArgsConstructor public enum LoginException implements BaseException { VERIFICATION_CODE_NOT_FOUND( HttpStatus.BAD_REQUEST, - "해당 인증 코드 내역이 존재하지 않습니다."); + "해당 인증 코드 내역이 존재하지 않습니다."), + + UNAUTHORIZED( + HttpStatus.UNAUTHORIZED, + "인증되지 않은 사용자입니다. 로그인이 필요합니다."); private final HttpStatus httpStatus; private final String reason; - - LoginException(HttpStatus httpStatus, String reason) { - - this.httpStatus = httpStatus; - this.reason = reason; - } - - @Override - public HttpStatus getHttpStatus() { - - return httpStatus; - } - - @Override - public String getReason() { - - return reason; - } } From aaf778776131c8894a24b35a1ef9096aeb8a7bbe Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:28:36 +0900 Subject: [PATCH 16/37] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EA=B0=B1=EC=8B=A0=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=EC=85=89=ED=84=B0=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 출석 체크 성공/실패 여부와 상관 없이 사용자 최종 접속 일시는 무조건 갱신 - 이 인터셉터를 통해 출석 체크 요청 이후 무조건적으로 최종 접속 일시를 업데이트 처리 --- .../UpdateLastAccessedAtInterceptor.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java diff --git a/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java b/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java new file mode 100644 index 00000000..12c87650 --- /dev/null +++ b/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java @@ -0,0 +1,35 @@ +package yeonba.be.config; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.time.LocalDateTime; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import yeonba.be.exception.GeneralException; +import yeonba.be.exception.LoginException; +import yeonba.be.user.service.UserService; + +@Component +@RequiredArgsConstructor +public class UpdateLastAccessedAtInterceptor implements HandlerInterceptor { + + private final UserService userService; + + @Override + public void afterCompletion( + HttpServletRequest request, + HttpServletResponse response, + Object handler, + Exception ex) throws Exception { + + Optional userId = Optional.ofNullable((Long) request.getAttribute("userId")); + if (userId.isEmpty()) { + throw new GeneralException(LoginException.UNAUTHORIZED); + } + + LocalDateTime accessAt = LocalDateTime.now(); + userService.updateLastAccessedAt(userId.get(), accessAt); + } +} From 560f40b78e8e1b2af1efecd30802e7d29f475253 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:29:42 +0900 Subject: [PATCH 17/37] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EA=B0=B1=EC=8B=A0=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=EC=85=89=ED=84=B0=20=EB=93=B1=EB=A1=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 출석 체크 요청시에만 최종 접속 일시 갱신을 수행하도록 인터셉터 등록 --- be/src/main/java/yeonba/be/config/WebConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/be/src/main/java/yeonba/be/config/WebConfig.java b/be/src/main/java/yeonba/be/config/WebConfig.java index 2d996c0a..1822f004 100644 --- a/be/src/main/java/yeonba/be/config/WebConfig.java +++ b/be/src/main/java/yeonba/be/config/WebConfig.java @@ -10,6 +10,7 @@ public class WebConfig implements WebMvcConfigurer { private final DevAuthInterceptor devAuthInterceptor; + private final UpdateLastAccessedAtInterceptor updateLastAccessedAtInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { @@ -26,5 +27,8 @@ public void addInterceptors(InterceptorRegistry registry) { "/users/pw-inquiry", "/users/login", "/users/refresh"); + + registry.addInterceptor(updateLastAccessedAtInterceptor) + .addPathPatterns("/daily-check"); } } From 125b0cda1b765dc0cc9cd9f7f1e752999f06dbe5 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:32:10 +0900 Subject: [PATCH 18/37] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 최종 접속 일시 갱신을 별도의 인터셉터가 수행하도록 분리 - 휴면 상태 사용자는 출석 체크 불가하도록 검증 - 처음 가입한 사용자는 최종 접속 일시가 null이므로 접속 일시 검증을 수행하지 않음 --- .../yeonba/be/arrow/service/ArrowService.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java index d494f5b2..7cd8985b 100644 --- a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java +++ b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java @@ -2,10 +2,11 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import java.util.Objects; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import yeonba.be.arrow.dto.UserArrowsResponse; +import yeonba.be.arrow.dto.response.UserArrowsResponse; import yeonba.be.arrow.entity.ArrowTransaction; import yeonba.be.arrow.repository.ArrowCommand; import yeonba.be.arrow.repository.ArrowQuery; @@ -19,34 +20,32 @@ @RequiredArgsConstructor public class ArrowService { - private final int DAILY_CHECK_ARROW_COUNT = 10; private final int ADVERTISEMENT_ARROW_COUNT = 5; private final UserQuery userQuery; private final ArrowCommand arrowCommand; private final ArrowQuery arrowQuery; - /* - 출석 체크는 다음 과정을 거쳐 이뤄진다. - 1. 사용자 최종 접속 일시를 통해 이미 출석 체크하였는지 확인 - 2. 화살 송수신 내역 저장 - 3. 사용자 최종 접속 일시 갱신 - 4. 사용자 화살 개수 증가 - */ @Transactional public void dailyCheck(long userId) { User dailyCheckUser = userQuery.findById(userId); - LocalDateTime dailyCheckedAt = LocalDateTime.now(); - dailyCheckUser.validateDailyCheck(dailyCheckedAt.toLocalDate()); + // 휴면 상태 사용자는 출석 체크 불가 + if (dailyCheckUser.isInactive()) { + throw new GeneralException(UserException.INACTIVE_USER); + } - ArrowTransaction arrowTransaction = new ArrowTransaction( - dailyCheckUser, - DAILY_CHECK_ARROW_COUNT); + // 처음 가입한 사용자는 최종 접속 일시가 null, 이 경우 출석 체크를 그냥 진행함 + if (!Objects.isNull(dailyCheckUser.getLastAccessedAt())) { + LocalDateTime dailyCheckedAt = LocalDateTime.now(); + dailyCheckUser.validateDailyCheck(dailyCheckedAt.toLocalDate()); + } + + int dailyCheckArrows = 10; + ArrowTransaction arrowTransaction = new ArrowTransaction(dailyCheckUser, dailyCheckArrows); arrowCommand.save(arrowTransaction); - dailyCheckUser.updateLastAccessedAt(dailyCheckedAt); - dailyCheckUser.plusArrow(DAILY_CHECK_ARROW_COUNT); + dailyCheckUser.plusArrow(dailyCheckArrows); } @Transactional(readOnly = true) From d8bb5e0e88aef6ef53c42fbf40578ab4340bf299 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Sun, 21 Apr 2024 15:33:40 +0900 Subject: [PATCH 19/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=99=94=EC=82=B4=20=EA=B0=9C=EC=88=98=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?DTO=20=EC=82=AC=EC=9A=A9=20=EC=9C=84=EC=B9=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/yeonba/be/arrow/controller/ArrowController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java index b3c6560d..a4627a5f 100644 --- a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java +++ b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RestController; -import yeonba.be.arrow.dto.UserArrowsResponse; +import yeonba.be.arrow.dto.response.UserArrowsResponse; import yeonba.be.arrow.service.ArrowService; import yeonba.be.util.CustomResponse; From f66740df7e36f44cb79eeabd4dc84e1e9e8275c1 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 22 Apr 2024 22:02:19 +0900 Subject: [PATCH 20/37] =?UTF-8?q?feat:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java b/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java index 64b4384c..de932411 100644 --- a/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java +++ b/be/src/main/java/yeonba/be/arrow/repository/ArrowQuery.java @@ -13,10 +13,10 @@ public class ArrowQuery { private final ArrowTransactionRepository arrowTransactionRepository; - public boolean isArrowTransactionExist(User sentUser, User receivedUser) { + public boolean isArrowTransactionExist(User sender, User receiver) { return arrowTransactionRepository - .existsBySenderAndReceiver(sentUser, receivedUser); + .existsBySenderAndReceiver(sender, receiver); } public void validateAdvertisementArrowCount(long userId, LocalDateTime today) { From ff3b6afa6c51beef7e3edd7b1e969cbda3c991ca Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 22 Apr 2024 22:03:14 +0900 Subject: [PATCH 21/37] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EB=A1=9C=EC=A7=81,=20=EC=B6=9C=EC=84=9D=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=EB=82=A0=EC=A7=9C=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 테스트 가능한 형태로 외부에서 출석 체크 날짜를 주입받도록 수정 --- be/src/main/java/yeonba/be/arrow/service/ArrowService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java index 7cd8985b..1b29f18e 100644 --- a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java +++ b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java @@ -26,7 +26,7 @@ public class ArrowService { private final ArrowQuery arrowQuery; @Transactional - public void dailyCheck(long userId) { + public void dailyCheck(long userId, LocalDate dailyCheckDay) { User dailyCheckUser = userQuery.findById(userId); @@ -37,8 +37,7 @@ public void dailyCheck(long userId) { // 처음 가입한 사용자는 최종 접속 일시가 null, 이 경우 출석 체크를 그냥 진행함 if (!Objects.isNull(dailyCheckUser.getLastAccessedAt())) { - LocalDateTime dailyCheckedAt = LocalDateTime.now(); - dailyCheckUser.validateDailyCheck(dailyCheckedAt.toLocalDate()); + dailyCheckUser.validateDailyCheck(dailyCheckDay); } int dailyCheckArrows = 10; From c136b4083f61cb0bc9121a3a05932fe70b6dbcad Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 22 Apr 2024 22:04:13 +0900 Subject: [PATCH 22/37] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20API=20=EB=A1=9C=EC=A7=81,=20=EC=B6=9C=EC=84=9D=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=EB=82=A0=EC=A7=9C=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/yeonba/be/arrow/controller/ArrowController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java index a4627a5f..36011b5b 100644 --- a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java +++ b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; +import java.time.LocalDate; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -41,7 +42,8 @@ public ResponseEntity> arrows( public ResponseEntity> dailyCheck( @RequestAttribute("userId") long userId) { - arrowService.dailyCheck(userId); + LocalDate dailyCheckDay = LocalDate.now(); + arrowService.dailyCheck(userId, dailyCheckDay); return ResponseEntity .ok() From 12ac0d27c9a73ebfd244063c4f8ab4725cd14d90 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Tue, 23 Apr 2024 20:56:49 +0900 Subject: [PATCH 23/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EC=B6=A9?= =?UTF-8?q?=EC=A0=84=20=EB=A1=9C=EC=A7=81,=20=EC=B6=A9=EC=A0=84=EC=9D=BC?= =?UTF-8?q?=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80(#6?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 로직은 로직 실행일 기준으로 충전 최대 횟수 검증 수행 - 테스트하기 어려운 구조, 외부에서 충전일을 전달받도록 변경 --- be/src/main/java/yeonba/be/arrow/service/ArrowService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java index 1b29f18e..57e510fe 100644 --- a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java +++ b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java @@ -92,12 +92,12 @@ public void sendArrow(long senderId, long receiverId) { } @Transactional - public void chargeArrows(long userId) { + public void chargeArrows(long userId, LocalDate chargeDay) { User user = userQuery.findById(userId); - LocalDateTime today = LocalDate.now().atStartOfDay(); - arrowQuery.validateAdvertisementArrowCount(userId, today); + LocalDateTime chargeDayStartTime = chargeDay.atStartOfDay(); + arrowQuery.validateAdvertisementArrowCount(userId, chargeDayStartTime); ArrowTransaction arrowTransaction = new ArrowTransaction( user, From 25756fd801c795df0a5d99b57ba470b91b17170b Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Tue, 23 Apr 2024 20:57:44 +0900 Subject: [PATCH 24/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EC=B6=A9?= =?UTF-8?q?=EC=A0=84=20API,=20=EC=B6=A9=EC=A0=84=EC=9D=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화살 충전 버즈니스 로직이 충전일을 외부에서 제공받는 형태로 변경됨에 따라 충전일 생성하는 코드 추가 --- .../main/java/yeonba/be/arrow/controller/ArrowController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java index 36011b5b..f1c62fa1 100644 --- a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java +++ b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java @@ -71,7 +71,8 @@ public ResponseEntity> sendArrow( public ResponseEntity> chargeArrows( @RequestAttribute("userId") long userId) { - arrowService.chargeArrows(userId); + LocalDate chargeDay = LocalDate.now(); + arrowService.chargeArrows(userId, chargeDay); return ResponseEntity .ok() From b47c90301acdccf89a32ac3e063bd388654e769f Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Fri, 3 May 2024 21:51:25 +0900 Subject: [PATCH 25/37] =?UTF-8?q?feat:=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=A1=9C=EC=A7=81,=20=EA=B0=84=EB=8B=A8=ED=95=9C?= =?UTF-8?q?=20=ED=98=95=ED=83=9C=EB=A1=9C=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yeonba/be/config/UpdateLastAccessedAtInterceptor.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java b/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java index 12c87650..790e2159 100644 --- a/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java +++ b/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java @@ -24,12 +24,10 @@ public void afterCompletion( Object handler, Exception ex) throws Exception { - Optional userId = Optional.ofNullable((Long) request.getAttribute("userId")); - if (userId.isEmpty()) { - throw new GeneralException(LoginException.UNAUTHORIZED); - } + long userId = (long) Optional.ofNullable(request.getAttribute("userId")) + .orElseThrow(() -> new GeneralException(LoginException.UNAUTHORIZED)); LocalDateTime accessAt = LocalDateTime.now(); - userService.updateLastAccessedAt(userId.get(), accessAt); + userService.updateLastAccessedAt(userId, accessAt); } } From c3ed2807fa5d5ae0e9d6e7d960f5b4af25f1c59f Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Fri, 3 May 2024 21:56:32 +0900 Subject: [PATCH 26/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화살 내역을 경우에 따라 구분하기 위해 추가한 열거형, 다음 종류들이 존재 - 출석 체크 - 광고 시청을 통한 화살 획득 - 사용자간 송수신 --- .../be/arrow/enums/ArrowTransactionType.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 be/src/main/java/yeonba/be/arrow/enums/ArrowTransactionType.java diff --git a/be/src/main/java/yeonba/be/arrow/enums/ArrowTransactionType.java b/be/src/main/java/yeonba/be/arrow/enums/ArrowTransactionType.java new file mode 100644 index 00000000..030b56cc --- /dev/null +++ b/be/src/main/java/yeonba/be/arrow/enums/ArrowTransactionType.java @@ -0,0 +1,17 @@ +package yeonba.be.arrow.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ArrowTransactionType { + + DAILY_CHECK("출석 체크"), + + REWARDS_FOR_WATCHING_ADVERTISEMENTS("광고 시청 통한 화살 획득"), + + USER_TO_USER("사용자간 송수신"); + + private final String description; +} From aa3f868fcb2c0c758f7f1254f7cce3841e3d0b07 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Fri, 3 May 2024 21:57:22 +0900 Subject: [PATCH 27/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=ED=83=80=EC=9E=85=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/yeonba/be/arrow/entity/ArrowTransaction.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java b/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java index b2159278..ee3bb487 100644 --- a/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java +++ b/be/src/main/java/yeonba/be/arrow/entity/ArrowTransaction.java @@ -3,6 +3,8 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -14,6 +16,7 @@ import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import yeonba.be.arrow.enums.ArrowTransactionType; import yeonba.be.user.entity.User; @Table(name = "arrows_transactions") @@ -38,23 +41,30 @@ public class ArrowTransaction { @Column(nullable = false) private int arrows; + @Enumerated(EnumType.STRING) + private ArrowTransactionType type; + @CreatedDate @Column(nullable = false) private LocalDateTime createdAt; public ArrowTransaction( + ArrowTransactionType type, User receiver, int arrows) { + this.type = type; this.receiver = receiver; this.arrows = arrows; } public ArrowTransaction( + ArrowTransactionType type, User sender, User receiver, int arrows) { + this.type = type; this.sender = sender; this.receiver = receiver; this.arrows = arrows; From 19f3216f61b9d9faebdc85d493789df0647440c6 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Fri, 3 May 2024 21:59:03 +0900 Subject: [PATCH 28/37] =?UTF-8?q?feat:=20=EA=B4=91=EA=B3=A0=20=EC=8B=9C?= =?UTF-8?q?=EC=B2=AD=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EB=A1=9C=EC=A7=81,=20=ED=99=94=EC=82=B4=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=20=ED=83=80=EC=9E=85=20=EB=B9=84=EA=B5=90=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/arrow/repository/ArrowTransactionRepositoryImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java b/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java index 7c7f613d..5d9d8b70 100644 --- a/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java +++ b/be/src/main/java/yeonba/be/arrow/repository/ArrowTransactionRepositoryImpl.java @@ -1,6 +1,7 @@ package yeonba.be.arrow.repository; import static yeonba.be.arrow.entity.QArrowTransaction.arrowTransaction; +import static yeonba.be.arrow.enums.ArrowTransactionType.REWARDS_FOR_WATCHING_ADVERTISEMENTS; import static yeonba.be.user.entity.QUser.user; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -22,6 +23,7 @@ public boolean canChargeByAdvertisement(long userId, LocalDateTime today) { .from(arrowTransaction) .innerJoin(arrowTransaction.receiver, user) .where( + arrowTransaction.type.eq(REWARDS_FOR_WATCHING_ADVERTISEMENTS), arrowTransaction.sender.isNull(), arrowTransaction.receiver.id.eq(userId), arrowTransaction.createdAt.after(today) From 7719b79fe12bcf84e3dc5442da4b45e7ed0e926e Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Fri, 3 May 2024 22:02:34 +0900 Subject: [PATCH 29/37] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=20=EB=A1=9C=EC=A7=81=EB=93=A4=20=EC=88=98=EC=A0=95(#6?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 화살 내역 생성시 화살 내역 타입을 함께 포함하여 내역마다 구분이 가능하도록 수정 - 불필요한 상수, 지역 변수로 구성 - 의미가 더 잘 드러나도록 변수명 적절히 수정 --- .../yeonba/be/arrow/service/ArrowService.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java index b4094b69..1f38bcac 100644 --- a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java +++ b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java @@ -1,5 +1,9 @@ package yeonba.be.arrow.service; +import static yeonba.be.arrow.enums.ArrowTransactionType.DAILY_CHECK; +import static yeonba.be.arrow.enums.ArrowTransactionType.REWARDS_FOR_WATCHING_ADVERTISEMENTS; +import static yeonba.be.arrow.enums.ArrowTransactionType.USER_TO_USER; + import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Objects; @@ -20,7 +24,6 @@ @RequiredArgsConstructor public class ArrowService { - private final int ADVERTISEMENT_ARROW_COUNT = 5; private final UserQuery userQuery; private final ArrowCommand arrowCommand; private final ArrowQuery arrowQuery; @@ -41,7 +44,10 @@ public void dailyCheck(long userId, LocalDate dailyCheckDay) { } int dailyCheckArrows = 10; - ArrowTransaction arrowTransaction = new ArrowTransaction(dailyCheckUser, dailyCheckArrows); + ArrowTransaction arrowTransaction = new ArrowTransaction( + DAILY_CHECK, + dailyCheckUser, + dailyCheckArrows); arrowCommand.save(arrowTransaction); dailyCheckUser.plusArrow(dailyCheckArrows); @@ -84,7 +90,8 @@ public void sendArrow(long senderId, long receiverId) { // 화살은 1개만 보낼 수 있음 int sendArrow = 1; - ArrowTransaction arrowTransaction = new ArrowTransaction(sender, receiver, sendArrow); + ArrowTransaction arrowTransaction = + new ArrowTransaction(USER_TO_USER, sender, receiver, sendArrow); arrowCommand.save(arrowTransaction); sender.minusArrow(sendArrow); @@ -94,16 +101,18 @@ public void sendArrow(long senderId, long receiverId) { @Transactional public void chargeArrows(long userId, LocalDate chargeDay) { - User user = userQuery.findById(userId); + User arrowChargeUser = userQuery.findById(userId); LocalDateTime chargeDayStartTime = chargeDay.atStartOfDay(); arrowQuery.validateAdvertisementArrowCount(userId, chargeDayStartTime); + int chargeArrows = 5; ArrowTransaction arrowTransaction = new ArrowTransaction( - user, - ADVERTISEMENT_ARROW_COUNT); + REWARDS_FOR_WATCHING_ADVERTISEMENTS, + arrowChargeUser, + chargeArrows); arrowCommand.save(arrowTransaction); - user.plusArrow(ADVERTISEMENT_ARROW_COUNT); + arrowChargeUser.plusArrow(chargeArrows); } } From a26f8e1ec4d51c7efa612bcdef2bae92554118e1 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:07:29 +0900 Subject: [PATCH 30/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B8=ED=84=B0=EC=85=89=ED=84=B0=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UpdateLastAccessedAtInterceptor.java | 33 ------------------- .../main/java/yeonba/be/config/WebConfig.java | 4 --- 2 files changed, 37 deletions(-) delete mode 100644 be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java diff --git a/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java b/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java deleted file mode 100644 index 790e2159..00000000 --- a/be/src/main/java/yeonba/be/config/UpdateLastAccessedAtInterceptor.java +++ /dev/null @@ -1,33 +0,0 @@ -package yeonba.be.config; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.time.LocalDateTime; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; -import yeonba.be.exception.GeneralException; -import yeonba.be.exception.LoginException; -import yeonba.be.user.service.UserService; - -@Component -@RequiredArgsConstructor -public class UpdateLastAccessedAtInterceptor implements HandlerInterceptor { - - private final UserService userService; - - @Override - public void afterCompletion( - HttpServletRequest request, - HttpServletResponse response, - Object handler, - Exception ex) throws Exception { - - long userId = (long) Optional.ofNullable(request.getAttribute("userId")) - .orElseThrow(() -> new GeneralException(LoginException.UNAUTHORIZED)); - - LocalDateTime accessAt = LocalDateTime.now(); - userService.updateLastAccessedAt(userId, accessAt); - } -} diff --git a/be/src/main/java/yeonba/be/config/WebConfig.java b/be/src/main/java/yeonba/be/config/WebConfig.java index 27c7961b..6cea811a 100644 --- a/be/src/main/java/yeonba/be/config/WebConfig.java +++ b/be/src/main/java/yeonba/be/config/WebConfig.java @@ -10,7 +10,6 @@ public class WebConfig implements WebMvcConfigurer { private final DevAuthInterceptor devAuthInterceptor; - private final UpdateLastAccessedAtInterceptor updateLastAccessedAtInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { @@ -25,8 +24,5 @@ public void addInterceptors(InterceptorRegistry registry) { "/users/join/**", "/users/login", "/users/refresh"); - - registry.addInterceptor(updateLastAccessedAtInterceptor) - .addPathPatterns("/daily-check"); } } From a8925cf5701b69bfd77ad2e8f42eba5f56608ff8 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:10:48 +0900 Subject: [PATCH 31/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=98=88=EC=99=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/exception/ArrowException.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/be/src/main/java/yeonba/be/exception/ArrowException.java b/be/src/main/java/yeonba/be/exception/ArrowException.java index 04ab96bd..5c4563dc 100644 --- a/be/src/main/java/yeonba/be/exception/ArrowException.java +++ b/be/src/main/java/yeonba/be/exception/ArrowException.java @@ -13,10 +13,6 @@ public enum ArrowException implements BaseException { HttpStatus.BAD_REQUEST, "1일 광고 시청은 최대 3회입니다."), - ALREADY_CHECKED_USER( - HttpStatus.BAD_REQUEST, - "이미 출석 체크한 사용자입니다."), - ALREADY_SENT_ARROW_USER( HttpStatus.BAD_REQUEST, "이미 화살을 보낸 사용자입니다."), From 4b44a1c26d321d0ee5b77e3aa11d5c7994f165cd Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:11:08 +0900 Subject: [PATCH 32/37] =?UTF-8?q?feat:=20=EC=BD=94=EB=93=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/yeonba/be/util/CustomResponse.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/be/src/main/java/yeonba/be/util/CustomResponse.java b/be/src/main/java/yeonba/be/util/CustomResponse.java index c863b4c5..3c5367fa 100644 --- a/be/src/main/java/yeonba/be/util/CustomResponse.java +++ b/be/src/main/java/yeonba/be/util/CustomResponse.java @@ -5,38 +5,38 @@ @Getter public class CustomResponse { - private final String status; + private final String status; - private final String message; + private final String message; - private final T data; + private final T data; - public CustomResponse(String message) { - this.status = "fail"; - this.message = message; - this.data = null; - } + public CustomResponse(String message) { + this.status = "fail"; + this.message = message; + this.data = null; + } - public CustomResponse(T data) { - this.status = "success"; - this.message = null; - this.data = data; - } + public CustomResponse(T data) { + this.status = "success"; + this.message = null; + this.data = data; + } - public CustomResponse() { - this.status = "success"; - this.message = null; - this.data = null; - } + public CustomResponse() { + this.status = "success"; + this.message = null; + this.data = null; + } - private CustomResponse(String message, T data) { - this.status = "fail"; - this.message = message; - this.data = data; - } + private CustomResponse(String message, T data) { + this.status = "fail"; + this.message = message; + this.data = data; + } - public static CustomResponse onFailure(String message, T data) { + public static CustomResponse onFailure(String message, T data) { - return new CustomResponse<>(message, data); - } + return new CustomResponse<>(message, data); + } } From dbeae6dcaacc088df958d8b00dbd82183f5282f6 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:14:06 +0900 Subject: [PATCH 33/37] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 로직에서는 이미 출석 체크한 상황을 예외로 다룸 - 사용자 화살 증가와 최종 접속 일시 갱신을 한 트랜잭션으로 다루기 어려운 구조 - 이미 출석 체크한 상황을 예외로 다루지 않고, 출석 체크일과 최종 접속 일시 비교 결과 반환 - 출석 체크 로직에서 비교 결과에 따라 진행 토록 로직 변경 --- be/src/main/java/yeonba/be/user/entity/User.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/be/src/main/java/yeonba/be/user/entity/User.java b/be/src/main/java/yeonba/be/user/entity/User.java index a2dd81a6..f8bcdc60 100644 --- a/be/src/main/java/yeonba/be/user/entity/User.java +++ b/be/src/main/java/yeonba/be/user/entity/User.java @@ -16,6 +16,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -155,11 +156,14 @@ public void delete() { this.phoneNumber = "deleted"; } - public void validateDailyCheck(LocalDate dailyCheckDay) { + public boolean canDailyCheckAt(LocalDate dailyCheckDay) { - if (this.lastAccessedAt.isAfter(dailyCheckDay.atStartOfDay())) { - throw new GeneralException(ArrowException.ALREADY_CHECKED_USER); + if (Optional.ofNullable(this.lastAccessedAt).isEmpty()) { + + return true; } + + return this.lastAccessedAt.isBefore(dailyCheckDay.atStartOfDay()); } public String getRepresentativeProfilePhoto() { From 9f555a0d2862e923bb4ff22d72212ecee3e01785 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:15:14 +0900 Subject: [PATCH 34/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=B5=9C=EC=A2=85=20=EC=A0=91?= =?UTF-8?q?=EC=86=8D=20=EC=9D=BC=EC=8B=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/src/main/java/yeonba/be/user/service/UserService.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/be/src/main/java/yeonba/be/user/service/UserService.java b/be/src/main/java/yeonba/be/user/service/UserService.java index cf3c8206..e65e6d2c 100644 --- a/be/src/main/java/yeonba/be/user/service/UserService.java +++ b/be/src/main/java/yeonba/be/user/service/UserService.java @@ -1,7 +1,6 @@ package yeonba.be.user.service; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.Period; import java.util.List; import lombok.RequiredArgsConstructor; @@ -157,11 +156,4 @@ public void saveUserPreference(User user, UserJoinRequest request) { preferredAnimal); userPreferenceCommand.save(userPreference); } - - @Transactional - public void updateLastAccessedAt(long userId, LocalDateTime accessAt) { - - User user = userQuery.findById(userId); - user.updateLastAccessedAt(accessAt); - } } From 7afbdb632824248686aa00bd50816f9f9c59cbb0 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:18:01 +0900 Subject: [PATCH 35/37] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 출석 체크 내역 저장, 사용자 화살 증가와 최종 접속 일시 갱신을 한 트랜잭션으로 다루도록 변경 - 이를 위해 이미 출석 체크한 상황을 예외로 다루지 않음 - 출석 체크 진행 여부를 반환하여 출석 체크 진행 여부를 판단하도록 구성 --- .../yeonba/be/arrow/service/ArrowService.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java index 1f38bcac..ae5b3e26 100644 --- a/be/src/main/java/yeonba/be/arrow/service/ArrowService.java +++ b/be/src/main/java/yeonba/be/arrow/service/ArrowService.java @@ -6,7 +6,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.Objects; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,7 +28,7 @@ public class ArrowService { private final ArrowQuery arrowQuery; @Transactional - public void dailyCheck(long userId, LocalDate dailyCheckDay) { + public boolean dailyCheck(long userId, LocalDate dailyCheckDay) { User dailyCheckUser = userQuery.findById(userId); @@ -38,19 +37,24 @@ public void dailyCheck(long userId, LocalDate dailyCheckDay) { throw new GeneralException(UserException.INACTIVE_USER); } - // 처음 가입한 사용자는 최종 접속 일시가 null, 이 경우 출석 체크를 그냥 진행함 - if (!Objects.isNull(dailyCheckUser.getLastAccessedAt())) { - dailyCheckUser.validateDailyCheck(dailyCheckDay); + boolean canDailyCheck = dailyCheckUser.canDailyCheckAt(dailyCheckDay); + + // 출석 체크 화살 내역 저장, 사용자 화살 증가 + if (canDailyCheck) { + int dailyCheckArrows = 10; + ArrowTransaction arrowTransaction = new ArrowTransaction( + DAILY_CHECK, + dailyCheckUser, + dailyCheckArrows); + arrowCommand.save(arrowTransaction); + + dailyCheckUser.plusArrow(dailyCheckArrows); } - int dailyCheckArrows = 10; - ArrowTransaction arrowTransaction = new ArrowTransaction( - DAILY_CHECK, - dailyCheckUser, - dailyCheckArrows); - arrowCommand.save(arrowTransaction); + // 사용자 최종 접속 일시 갱신 + dailyCheckUser.updateLastAccessedAt(LocalDateTime.now()); - dailyCheckUser.plusArrow(dailyCheckArrows); + return canDailyCheck; } @Transactional(readOnly = true) From ff79f51f092f777c44e19ef0ecd7a12c961682b2 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:23:49 +0900 Subject: [PATCH 36/37] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20API=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 서비스 로직을 출석 체크 진행 여부를 반환하도록 변경 - 결과 값에 따라 적절한 응답을 클라이언트에 전달 --- .../be/arrow/controller/ArrowController.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java index f1c62fa1..7e00ce88 100644 --- a/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java +++ b/be/src/main/java/yeonba/be/arrow/controller/ArrowController.java @@ -42,12 +42,18 @@ public ResponseEntity> arrows( public ResponseEntity> dailyCheck( @RequestAttribute("userId") long userId) { - LocalDate dailyCheckDay = LocalDate.now(); - arrowService.dailyCheck(userId, dailyCheckDay); - - return ResponseEntity + ResponseEntity> response = ResponseEntity .ok() .body(new CustomResponse<>()); + + LocalDate dailyCheckDay = LocalDate.now(); + if (!arrowService.dailyCheck(userId, dailyCheckDay)) { + response = ResponseEntity + .badRequest() + .body(new CustomResponse<>("이미 출석 체크한 사용자입니다.")); + } + + return response; } @Operation(summary = "화살 보내기", description = "다른 사용자에게 화살을 1개 보낼 수 있습니다.") From 943eb41ec56a9e0cfca4e39600d5dfa3e69ec1d8 Mon Sep 17 00:00:00 2001 From: Minjae-An Date: Mon, 13 May 2024 21:27:30 +0900 Subject: [PATCH 37/37] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=98=88=EC=99=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yeonba/be/exception/LoginException.java | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 be/src/main/java/yeonba/be/exception/LoginException.java diff --git a/be/src/main/java/yeonba/be/exception/LoginException.java b/be/src/main/java/yeonba/be/exception/LoginException.java deleted file mode 100644 index 75be63a0..00000000 --- a/be/src/main/java/yeonba/be/exception/LoginException.java +++ /dev/null @@ -1,21 +0,0 @@ -package yeonba.be.exception; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.springframework.http.HttpStatus; - -@Getter -@AllArgsConstructor -public enum LoginException implements BaseException { - - VERIFICATION_CODE_NOT_FOUND( - HttpStatus.BAD_REQUEST, - "해당 인증 코드 내역이 존재하지 않습니다."), - - UNAUTHORIZED( - HttpStatus.UNAUTHORIZED, - "인증되지 않은 사용자입니다. 로그인이 필요합니다."); - - private final HttpStatus httpStatus; - private final String reason; -}