diff --git a/src/main/java/org/kkumulkkum/server/controller/PromiseController.java b/src/main/java/org/kkumulkkum/server/controller/PromiseController.java index c0be657..b35f285 100644 --- a/src/main/java/org/kkumulkkum/server/controller/PromiseController.java +++ b/src/main/java/org/kkumulkkum/server/controller/PromiseController.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.kkumulkkum.server.annotation.IsMember; +import org.kkumulkkum.server.annotation.IsParticipant; import org.kkumulkkum.server.annotation.UserId; import org.kkumulkkum.server.dto.promise.PromiseCreateDto; import org.kkumulkkum.server.dto.promise.response.PromiseDto; @@ -31,12 +32,12 @@ public ResponseEntity createPromise( return ResponseEntity.created(URI.create(promiseId.toString())).build(); } + @IsParticipant(promiseIdParamIndex = 0) @PatchMapping("/promises/{promiseId}/completion") public ResponseEntity completePromise( - @UserId Long userId, @PathVariable Long promiseId ) { - promiseService.completePromise(userId, promiseId); + promiseService.completePromise(promiseId); return ResponseEntity.ok().build(); } diff --git a/src/main/java/org/kkumulkkum/server/domain/UserInfo.java b/src/main/java/org/kkumulkkum/server/domain/UserInfo.java index da25c5c..26e32b7 100644 --- a/src/main/java/org/kkumulkkum/server/domain/UserInfo.java +++ b/src/main/java/org/kkumulkkum/server/domain/UserInfo.java @@ -59,4 +59,27 @@ public void deleteImage() { public void updateName(String name) { this.name = name; } + + public void addPromiseCount() { + this.promiseCount++; + } + + public void addLateCount() { + this.tardyCount++; + } + + public void addLateTime(long time) { + this.tardySum += time; + } + + public void levelUp() { + int count = this.promiseCount - this.tardyCount; + if (count == 2) { + this.level = 2; + } else if (count == 5) { + this.level = 3; + } else if (count == 10) { + this.level = 4; + } + } } diff --git a/src/main/java/org/kkumulkkum/server/dto/user/response/UserDto.java b/src/main/java/org/kkumulkkum/server/dto/user/response/UserDto.java index a109d13..10f5f34 100644 --- a/src/main/java/org/kkumulkkum/server/dto/user/response/UserDto.java +++ b/src/main/java/org/kkumulkkum/server/dto/user/response/UserDto.java @@ -16,7 +16,7 @@ public static UserDto from(UserInfo userInfo) { userInfo.getLevel(), userInfo.getPromiseCount(), userInfo.getTardyCount(), - userInfo.getTardySum(), + userInfo.getTardySum()/60, userInfo.getProfileImg() ); } diff --git a/src/main/java/org/kkumulkkum/server/exception/code/PromiseErrorCode.java b/src/main/java/org/kkumulkkum/server/exception/code/PromiseErrorCode.java index 2f56ce0..5c407d2 100644 --- a/src/main/java/org/kkumulkkum/server/exception/code/PromiseErrorCode.java +++ b/src/main/java/org/kkumulkkum/server/exception/code/PromiseErrorCode.java @@ -6,8 +6,11 @@ @Getter @AllArgsConstructor -public enum PromiseErrorCode { - //404 Not Found +public enum PromiseErrorCode implements DefaultErrorCode { + // 400 Bad Request + NOT_PAST_DUE(HttpStatus.BAD_REQUEST, 40010, "약속 시간이 지나지 않았습니다."), + NOT_ARRIVED_PARTICIPANT_EXISTS(HttpStatus.BAD_REQUEST, 40020, "도착하지 않은 참여자가 있습니다."), + // 404 Not Found NOT_FOUND_PROMISE(HttpStatus.NOT_FOUND, 40430, "약속을 찾을 수 없습니다."), ; diff --git a/src/main/java/org/kkumulkkum/server/repository/ParticipantRepository.java b/src/main/java/org/kkumulkkum/server/repository/ParticipantRepository.java index 814fb79..a7d0e01 100644 --- a/src/main/java/org/kkumulkkum/server/repository/ParticipantRepository.java +++ b/src/main/java/org/kkumulkkum/server/repository/ParticipantRepository.java @@ -22,7 +22,7 @@ public interface ParticipantRepository extends JpaRepository "JOIN Member m ON p.member.id = m.id " + "JOIN UserInfo ui ON m.user.id = ui.user.id " + "WHERE p.promise.id = :promiseId") - List findAllByPromiseId(Long promiseId); + List findAllByPromiseIdWithUserInfo(Long promiseId); @Query("SELECT new org.kkumulkkum.server.dto.participant.response.LateComerDto " + "(p.id, ui.name, ui.profileImg) " + @@ -42,4 +42,6 @@ public interface ParticipantRepository extends JpaRepository ") THEN TRUE ELSE FALSE END " + "FROM Participant p") boolean existsByPromiseIdAndUserId(Long promiseId, Long userId); + + List findAllByPromiseId(Long promiseId); } diff --git a/src/main/java/org/kkumulkkum/server/repository/PromiseRepository.java b/src/main/java/org/kkumulkkum/server/repository/PromiseRepository.java index 8ec5b4a..b05ec44 100644 --- a/src/main/java/org/kkumulkkum/server/repository/PromiseRepository.java +++ b/src/main/java/org/kkumulkkum/server/repository/PromiseRepository.java @@ -2,10 +2,16 @@ import org.kkumulkkum.server.domain.Promise; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.List; public interface PromiseRepository extends JpaRepository { List findAllByMeetingId(Long meetingId); + + @Query("SELECT CASE WHEN EXISTS " + + "(SELECT p FROM Participant p WHERE p.promise.id = :promiseId AND p.arrivalAt IS NULL) " + + "THEN TRUE ELSE FALSE END FROM Participant p") + boolean existsByArrivedAtIsNull(Long promiseId); } diff --git a/src/main/java/org/kkumulkkum/server/repository/UserInfoRepository.java b/src/main/java/org/kkumulkkum/server/repository/UserInfoRepository.java index 19d308d..3a0d82f 100644 --- a/src/main/java/org/kkumulkkum/server/repository/UserInfoRepository.java +++ b/src/main/java/org/kkumulkkum/server/repository/UserInfoRepository.java @@ -2,10 +2,16 @@ import org.kkumulkkum.server.domain.UserInfo; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.Optional; public interface UserInfoRepository extends JpaRepository { Optional findByUserId(Long id); + + @Query("SELECT ui FROM UserInfo ui " + + "JOIN Participant p ON ui.user.id = p.member.user.id " + + "WHERE p.id = :id") + Optional findByParticipantId(Long id); } diff --git a/src/main/java/org/kkumulkkum/server/service/participant/ParticipantRetriever.java b/src/main/java/org/kkumulkkum/server/service/participant/ParticipantRetriever.java index 28da87d..defc504 100644 --- a/src/main/java/org/kkumulkkum/server/service/participant/ParticipantRetriever.java +++ b/src/main/java/org/kkumulkkum/server/service/participant/ParticipantRetriever.java @@ -22,10 +22,14 @@ public Participant findByPromiseIdAndUserId(Long promiseId, Long userId) { .orElseThrow(() -> new ParticipantException(ParticipantErrorCode.NOT_JOINED_PROMISE)); } - public List findAllByPromiseId(Long promiseId) { + public List findAllByPromiseId(Long promiseId) { return participantRepository.findAllByPromiseId(promiseId); } + public List findAllByPromiseIdWithUserInfo(Long promiseId) { + return participantRepository.findAllByPromiseIdWithUserInfo(promiseId); + } + public List findAllLateComersByPromiseId(Long promiseId) { return participantRepository.findAllLateComersByPromiseId(promiseId); } diff --git a/src/main/java/org/kkumulkkum/server/service/participant/ParticipantService.java b/src/main/java/org/kkumulkkum/server/service/participant/ParticipantService.java index b323b36..04abbf2 100644 --- a/src/main/java/org/kkumulkkum/server/service/participant/ParticipantService.java +++ b/src/main/java/org/kkumulkkum/server/service/participant/ParticipantService.java @@ -62,7 +62,7 @@ public PreparationStatusDto getPreparation(final Long userId, final Long promise @Transactional(readOnly = true) public ParticipantsDto getParticipants(final Long promiseId) { - List participants = participantRetriever.findAllByPromiseId(promiseId); + List participants = participantRetriever.findAllByPromiseIdWithUserInfo(promiseId); return ParticipantsDto.from( participants.stream() .map(this::createParticipantDto) diff --git a/src/main/java/org/kkumulkkum/server/service/promise/PromiseRetriever.java b/src/main/java/org/kkumulkkum/server/service/promise/PromiseRetriever.java index ec9ae7c..4ebd98c 100644 --- a/src/main/java/org/kkumulkkum/server/service/promise/PromiseRetriever.java +++ b/src/main/java/org/kkumulkkum/server/service/promise/PromiseRetriever.java @@ -23,4 +23,8 @@ public Promise findById(Long id) { return promiseRepository.findById(id) .orElseThrow(() -> new PromiseException(PromiseErrorCode.NOT_FOUND_PROMISE)); } + + public boolean existsByArrivedAtIsNull(Long promiseId) { + return promiseRepository.existsByArrivedAtIsNull(promiseId); + } } diff --git a/src/main/java/org/kkumulkkum/server/service/promise/PromiseService.java b/src/main/java/org/kkumulkkum/server/service/promise/PromiseService.java index 84cea51..dc4e494 100644 --- a/src/main/java/org/kkumulkkum/server/service/promise/PromiseService.java +++ b/src/main/java/org/kkumulkkum/server/service/promise/PromiseService.java @@ -2,18 +2,20 @@ import jakarta.persistence.EntityManager; import lombok.RequiredArgsConstructor; -import org.kkumulkkum.server.domain.Meeting; -import org.kkumulkkum.server.domain.Member; -import org.kkumulkkum.server.domain.Participant; -import org.kkumulkkum.server.domain.Promise; +import org.kkumulkkum.server.domain.*; import org.kkumulkkum.server.dto.promise.PromiseCreateDto; import org.kkumulkkum.server.dto.promise.response.PromiseDto; import org.kkumulkkum.server.dto.promise.response.PromisesDto; +import org.kkumulkkum.server.exception.PromiseException; +import org.kkumulkkum.server.exception.code.PromiseErrorCode; +import org.kkumulkkum.server.service.participant.ParticipantRetriever; import org.kkumulkkum.server.service.participant.ParticipantSaver; -import org.kkumulkkum.server.service.member.MemberRetreiver; +import org.kkumulkkum.server.service.userInfo.UserInfoRetriever; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.List; @Service @@ -24,6 +26,8 @@ public class PromiseService { private final PromiseRetriever promiseRetriever; private final PromiseEditor promiseEditor; private final ParticipantSaver participantSaver; + private final ParticipantRetriever participantRetriever; + private final UserInfoRetriever userInfoRetriever; private final EntityManager entityManager; @Transactional @@ -55,10 +59,19 @@ public Long createPromise(Long userId, Long meetingId, PromiseCreateDto createPr } @Transactional - public void completePromise(Long userId, Long promiseId) { - // TODO: PARTICIPANT 검증 + public void completePromise(Long promiseId) { Promise promise = promiseRetriever.findById(promiseId); + if (promise.getTime().isAfter(LocalDateTime.now())) { + throw new PromiseException(PromiseErrorCode.NOT_PAST_DUE); + } + + if (promiseRetriever.existsByArrivedAtIsNull(promiseId)) { + throw new PromiseException(PromiseErrorCode.NOT_ARRIVED_PARTICIPANT_EXISTS); + } + promiseEditor.completePromise(promise); + List participants = participantRetriever.findAllByPromiseId(promiseId); + participants.forEach(participant -> updateUserInfo(participant, promise.getTime())); } @Transactional(readOnly = true) @@ -77,4 +90,16 @@ public PromiseDto getPromise( Promise promise = promiseRetriever.findById(promiseId); return PromiseDto.from(promise); } + + private void updateUserInfo(Participant participant, LocalDateTime promiseTime) { + UserInfo userInfo = userInfoRetriever.findByParticipantId(participant.getId()); + userInfo.addPromiseCount(); + if (promiseTime.isBefore(participant.getArrivalAt())) { + userInfo.addLateCount(); + userInfo.addLateTime(Duration.between(promiseTime, participant.getArrivalAt()).getSeconds()); + } else { + userInfo.levelUp(); + } + } + } diff --git a/src/main/java/org/kkumulkkum/server/service/userInfo/UserInfoRetriever.java b/src/main/java/org/kkumulkkum/server/service/userInfo/UserInfoRetriever.java index 4088242..9f04945 100644 --- a/src/main/java/org/kkumulkkum/server/service/userInfo/UserInfoRetriever.java +++ b/src/main/java/org/kkumulkkum/server/service/userInfo/UserInfoRetriever.java @@ -17,4 +17,9 @@ public UserInfo findByUserId(final Long id) { return userInfoRepository.findByUserId(id) .orElseThrow(() -> new UserException(UserErrorCode.NOT_FOUND_USER)); } + + public UserInfo findByParticipantId(final Long id) { + return userInfoRepository.findByParticipantId(id) + .orElseThrow(() -> new UserException(UserErrorCode.NOT_FOUND_USER)); + } }