diff --git a/src/main/java/com/mindway/server/v2/domain/book/service/impl/BookWriteServiceImpl.java b/src/main/java/com/mindway/server/v2/domain/book/service/impl/BookWriteServiceImpl.java index db8ae11..b323d60 100644 --- a/src/main/java/com/mindway/server/v2/domain/book/service/impl/BookWriteServiceImpl.java +++ b/src/main/java/com/mindway/server/v2/domain/book/service/impl/BookWriteServiceImpl.java @@ -5,6 +5,8 @@ import com.mindway.server.v2.domain.book.repository.BookRepository; import com.mindway.server.v2.domain.book.service.BookWriteService; import com.mindway.server.v2.domain.book.util.BookConverter; +import com.mindway.server.v2.domain.rank.entity.Ranks; +import com.mindway.server.v2.domain.rank.repository.RankRepository; import com.mindway.server.v2.domain.user.entity.User; import com.mindway.server.v2.domain.user.util.UserUtil; import com.mindway.server.v2.global.annotation.ServiceWithTransaction; @@ -17,11 +19,28 @@ public class BookWriteServiceImpl implements BookWriteService { private final BookRepository bookRepository; private final BookConverter bookConverter; private final UserUtil userUtil; + private final RankRepository rankRepository; public void execute(BookWriteRequest bookWriteRequest) { User user = userUtil.getCurrentUser(); Book book = bookConverter.toEntity(bookWriteRequest, user); + accrue(user); bookRepository.save(book); } + + private void accrue(User user) { + Ranks rank = rankRepository.findByUser(user) + .orElseGet(() -> saveUserRank(user)); + + rank.accrue(); + rankRepository.save(rank); + } + + private Ranks saveUserRank (User user) { + return Ranks.builder() + .user(user) + .accrue(0) + .build(); + } } diff --git a/src/main/java/com/mindway/server/v2/domain/rank/entity/Ranks.java b/src/main/java/com/mindway/server/v2/domain/rank/entity/Ranks.java new file mode 100644 index 0000000..2c5704e --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/entity/Ranks.java @@ -0,0 +1,31 @@ +package com.mindway.server.v2.domain.rank.entity; + +import com.mindway.server.v2.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class Ranks { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Integer accrue; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + public void accrue() { + accrue++; + } + +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/presentation/RankController.java b/src/main/java/com/mindway/server/v2/domain/rank/presentation/RankController.java new file mode 100644 index 0000000..a184910 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/presentation/RankController.java @@ -0,0 +1,24 @@ +package com.mindway.server.v2.domain.rank.presentation; + +import com.mindway.server.v2.domain.rank.presentation.dto.response.RankResponse; +import com.mindway.server.v2.domain.rank.service.GetRankService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/rank") +public class RankController { + private final GetRankService getRankService; + + @GetMapping + public ResponseEntity> getRank() { + List rank = getRankService.execute(); + return ResponseEntity.ok(rank); + } +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/presentation/dto/response/RankResponse.java b/src/main/java/com/mindway/server/v2/domain/rank/presentation/dto/response/RankResponse.java new file mode 100644 index 0000000..079baff --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/presentation/dto/response/RankResponse.java @@ -0,0 +1,11 @@ +package com.mindway.server.v2.domain.rank.presentation.dto.response; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class RankResponse { + private String name; + private Integer accrue; +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/repository/RankRepository.java b/src/main/java/com/mindway/server/v2/domain/rank/repository/RankRepository.java new file mode 100644 index 0000000..30c3507 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/repository/RankRepository.java @@ -0,0 +1,14 @@ +package com.mindway.server.v2.domain.rank.repository; + +import com.mindway.server.v2.domain.rank.entity.Ranks; +import com.mindway.server.v2.domain.user.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface RankRepository extends JpaRepository { + List findTop3ByOrderByAccrueDesc(); + + Optional findByUser(User user); +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/scheduler/RankScheduler.java b/src/main/java/com/mindway/server/v2/domain/rank/scheduler/RankScheduler.java new file mode 100644 index 0000000..5910ec6 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/scheduler/RankScheduler.java @@ -0,0 +1,16 @@ +package com.mindway.server.v2.domain.rank.scheduler; + +import com.mindway.server.v2.domain.rank.service.DeleteRankService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; + +@RequiredArgsConstructor +public class RankScheduler { + + private final DeleteRankService deleteRankService; + + @Scheduled(cron = "0 0 0 1 * *", zone = "Asia/Seoul") + public void run() { + deleteRankService.execute(); + } +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/service/DeleteRankService.java b/src/main/java/com/mindway/server/v2/domain/rank/service/DeleteRankService.java new file mode 100644 index 0000000..1831402 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/service/DeleteRankService.java @@ -0,0 +1,5 @@ +package com.mindway.server.v2.domain.rank.service; + +public interface DeleteRankService { + void execute(); +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/service/GetRankService.java b/src/main/java/com/mindway/server/v2/domain/rank/service/GetRankService.java new file mode 100644 index 0000000..103696f --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/service/GetRankService.java @@ -0,0 +1,9 @@ +package com.mindway.server.v2.domain.rank.service; + +import com.mindway.server.v2.domain.rank.presentation.dto.response.RankResponse; + +import java.util.List; + +public interface GetRankService { + List execute(); +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/service/impl/DeleteRankServiceImpl.java b/src/main/java/com/mindway/server/v2/domain/rank/service/impl/DeleteRankServiceImpl.java new file mode 100644 index 0000000..fe3e9ac --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/service/impl/DeleteRankServiceImpl.java @@ -0,0 +1,15 @@ +package com.mindway.server.v2.domain.rank.service.impl; + +import com.mindway.server.v2.domain.rank.repository.RankRepository; +import com.mindway.server.v2.domain.rank.service.DeleteRankService; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class DeleteRankServiceImpl implements DeleteRankService { + + private final RankRepository rankRepository; + + public void execute() { + rankRepository.deleteAll(); + } +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/service/impl/GetRankServiceImpl.java b/src/main/java/com/mindway/server/v2/domain/rank/service/impl/GetRankServiceImpl.java new file mode 100644 index 0000000..a38aa74 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/service/impl/GetRankServiceImpl.java @@ -0,0 +1,28 @@ +package com.mindway.server.v2.domain.rank.service.impl; + +import com.mindway.server.v2.domain.rank.entity.Ranks; +import com.mindway.server.v2.domain.rank.presentation.dto.response.RankResponse; +import com.mindway.server.v2.domain.rank.repository.RankRepository; +import com.mindway.server.v2.domain.rank.service.GetRankService; +import com.mindway.server.v2.domain.rank.util.RankConverter; +import com.mindway.server.v2.global.annotation.ServiceWithReadOnlyTransaction; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; + +@ServiceWithReadOnlyTransaction +@RequiredArgsConstructor +public class GetRankServiceImpl implements GetRankService { + + private final RankRepository rankRepository; + private final RankConverter rankConverter; + + public List execute() { + List ranks = rankRepository.findTop3ByOrderByAccrueDesc(); + + return ranks.stream() + .map(rankConverter::toDto) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/util/RankConverter.java b/src/main/java/com/mindway/server/v2/domain/rank/util/RankConverter.java new file mode 100644 index 0000000..8215291 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/util/RankConverter.java @@ -0,0 +1,8 @@ +package com.mindway.server.v2.domain.rank.util; + +import com.mindway.server.v2.domain.rank.entity.Ranks; +import com.mindway.server.v2.domain.rank.presentation.dto.response.RankResponse; + +public interface RankConverter { + RankResponse toDto (Ranks rank); +} diff --git a/src/main/java/com/mindway/server/v2/domain/rank/util/impl/RankConverterImpl.java b/src/main/java/com/mindway/server/v2/domain/rank/util/impl/RankConverterImpl.java new file mode 100644 index 0000000..2dbe3e1 --- /dev/null +++ b/src/main/java/com/mindway/server/v2/domain/rank/util/impl/RankConverterImpl.java @@ -0,0 +1,17 @@ +package com.mindway.server.v2.domain.rank.util.impl; + +import com.mindway.server.v2.domain.rank.entity.Ranks; +import com.mindway.server.v2.domain.rank.presentation.dto.response.RankResponse; +import com.mindway.server.v2.domain.rank.util.RankConverter; +import org.springframework.stereotype.Component; + +@Component +public class RankConverterImpl implements RankConverter { + + public RankResponse toDto(Ranks rank) { + return RankResponse.builder() + .name(rank.getUser().getName()) + .accrue(rank.getAccrue()) + .build(); + } +} diff --git a/src/main/java/com/mindway/server/v2/global/security/config/SecurityConfig.java b/src/main/java/com/mindway/server/v2/global/security/config/SecurityConfig.java index f953269..31013c6 100644 --- a/src/main/java/com/mindway/server/v2/global/security/config/SecurityConfig.java +++ b/src/main/java/com/mindway/server/v2/global/security/config/SecurityConfig.java @@ -78,6 +78,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // event .requestMatchers(HttpMethod.POST, "/api/v2/event").hasAnyAuthority(Authority.ROLE_TEACHER.name(), Authority.ROLE_HELPER.name()) + // rank + .requestMatchers(HttpMethod.GET, "/api/v2/rank").authenticated() .anyRequest().authenticated() )