diff --git a/src/main/java/leets/weeth/domain/admin/controller/AdminController.java b/src/main/java/leets/weeth/domain/admin/controller/AdminController.java index c0237c83..7becd0ca 100644 --- a/src/main/java/leets/weeth/domain/admin/controller/AdminController.java +++ b/src/main/java/leets/weeth/domain/admin/controller/AdminController.java @@ -17,6 +17,9 @@ import leets.weeth.domain.event.service.EventService; import leets.weeth.domain.notice.dto.RequestNotice; import leets.weeth.domain.notice.service.NoticeService; +import leets.weeth.domain.penalty.dto.RequestPenalty; +import leets.weeth.domain.penalty.dto.ResponsePenalty; +import leets.weeth.domain.penalty.service.PenaltyService; import leets.weeth.domain.user.service.UserService; import leets.weeth.global.auth.annotation.CurrentUser; import leets.weeth.global.common.error.exception.custom.BusinessLogicException; @@ -43,6 +46,7 @@ public class AdminController { private final AccountService accountService; private final ReceiptService receiptService; private final WeekService weekService; + private final PenaltyService penaltyService; /* Event 관련 admin api @@ -174,4 +178,25 @@ public CommonResponse cancel(@PathVariable Long receiptId) { public CommonResponse> getWeekCode(@PathVariable Integer cardinal) { return CommonResponse.createSuccess(weekService.getWeekCode(cardinal)); } + + @Operation(summary = "패널티 부여") + @PostMapping("/penalty") + public CommonResponse assignPenalty(@RequestBody RequestPenalty requestPenalty) { + penaltyService.assignPenalty(requestPenalty); + return CommonResponse.createSuccess(); + } + + @Operation(summary = "패널티 삭제") + @DeleteMapping("/penalty") + public CommonResponse removePenalty(@RequestParam Long penaltyId) { + penaltyService.removePenalty(penaltyId); + return CommonResponse.createSuccess(); + } + + @Operation(summary = "모든 유저의 패널티 확인") + @GetMapping("/penalty/all") + public CommonResponse> showAllPenalty() { + List allPenalties = penaltyService.getAllPenaltiesSortedByUserId(); + return CommonResponse.createSuccess(allPenalties); + } } diff --git a/src/main/java/leets/weeth/domain/penalty/controller/PenaltyController.java b/src/main/java/leets/weeth/domain/penalty/controller/PenaltyController.java new file mode 100644 index 00000000..ba54cf02 --- /dev/null +++ b/src/main/java/leets/weeth/domain/penalty/controller/PenaltyController.java @@ -0,0 +1,23 @@ +package leets.weeth.domain.penalty.controller; + +import leets.weeth.domain.penalty.dto.ResponsePenalty; +import leets.weeth.domain.penalty.service.PenaltyService; +import leets.weeth.global.auth.annotation.CurrentUser; +import leets.weeth.global.common.response.CommonResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/penalty") +public class PenaltyController { + private final PenaltyService penaltyService; + @GetMapping() + public CommonResponse> showMyPenalty(@CurrentUser Long userId){ + List myPenalties= penaltyService.getMyPenalties(userId); + return CommonResponse.createSuccess(myPenalties); + } + +} diff --git a/src/main/java/leets/weeth/domain/penalty/dto/RequestPenalty.java b/src/main/java/leets/weeth/domain/penalty/dto/RequestPenalty.java new file mode 100644 index 00000000..1b245eaf --- /dev/null +++ b/src/main/java/leets/weeth/domain/penalty/dto/RequestPenalty.java @@ -0,0 +1,13 @@ +package leets.weeth.domain.penalty.dto; + +import lombok.*; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@ToString +@Setter +public class RequestPenalty { + private Long userId; + private String penaltyDescription; +} diff --git a/src/main/java/leets/weeth/domain/penalty/dto/ResponsePenalty.java b/src/main/java/leets/weeth/domain/penalty/dto/ResponsePenalty.java new file mode 100644 index 00000000..1afc3d89 --- /dev/null +++ b/src/main/java/leets/weeth/domain/penalty/dto/ResponsePenalty.java @@ -0,0 +1,31 @@ +package leets.weeth.domain.penalty.dto; + +import leets.weeth.domain.penalty.entity.Penalty; +import lombok.*; +import java.time.LocalDateTime; + + +@AllArgsConstructor +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@ToString +public class ResponsePenalty { + private Long userId; + private String userName; + private Long penaltyId; + private String penaltyDescription; + private LocalDateTime time; + private int penaltyCount; + + public static ResponsePenalty createResponsePenaltyDTO(Penalty penalty) { + return ResponsePenalty.builder() + .userId(penalty.getUser().getId()) + .userName(penalty.getUser().getName()) + .penaltyId(penalty.getId()) + .penaltyDescription(penalty.getPenaltyDescription()) + .time(penalty.getCreatedAt()) + .penaltyCount(penalty.getUser().getPenalties().size()) + .build(); + } +} diff --git a/src/main/java/leets/weeth/domain/penalty/entity/Penalty.java b/src/main/java/leets/weeth/domain/penalty/entity/Penalty.java new file mode 100644 index 00000000..4dcf6432 --- /dev/null +++ b/src/main/java/leets/weeth/domain/penalty/entity/Penalty.java @@ -0,0 +1,36 @@ +package leets.weeth.domain.penalty.entity; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import leets.weeth.domain.penalty.dto.RequestPenalty; +import leets.weeth.domain.user.entity.User; +import leets.weeth.global.common.entity.BaseEntity; +import lombok.*; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Getter +@Table +public class Penalty extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "penalty_id") + private Long id; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @NotEmpty + private String penaltyDescription; + + public static Penalty toEntity(RequestPenalty dto, User user){ + return Penalty.builder() + .user(user) + .penaltyDescription(dto.getPenaltyDescription()) + .build(); + } +} diff --git a/src/main/java/leets/weeth/domain/penalty/repository/PenaltyRepository.java b/src/main/java/leets/weeth/domain/penalty/repository/PenaltyRepository.java new file mode 100644 index 00000000..17629841 --- /dev/null +++ b/src/main/java/leets/weeth/domain/penalty/repository/PenaltyRepository.java @@ -0,0 +1,11 @@ +package leets.weeth.domain.penalty.repository; + +import leets.weeth.domain.penalty.entity.Penalty; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PenaltyRepository extends JpaRepository { + List findByUserId(Long userId, Sort sort); +} diff --git a/src/main/java/leets/weeth/domain/penalty/service/PenaltyService.java b/src/main/java/leets/weeth/domain/penalty/service/PenaltyService.java new file mode 100644 index 00000000..8a50c09b --- /dev/null +++ b/src/main/java/leets/weeth/domain/penalty/service/PenaltyService.java @@ -0,0 +1,54 @@ +package leets.weeth.domain.penalty.service; + +import jakarta.transaction.Transactional; +import leets.weeth.domain.penalty.dto.RequestPenalty; +import leets.weeth.domain.penalty.dto.ResponsePenalty; +import leets.weeth.domain.penalty.entity.Penalty; +import leets.weeth.domain.penalty.repository.PenaltyRepository; +import leets.weeth.domain.user.entity.User; +import leets.weeth.domain.user.repository.UserRepository; +import leets.weeth.global.common.error.exception.custom.PenaltyNotFoundException; +import leets.weeth.global.common.error.exception.custom.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Comparator; +import java.util.List; + +@RequiredArgsConstructor +@Slf4j +@Service +public class PenaltyService { + private final PenaltyRepository penaltyRepository; + private final UserRepository userRepository; + @Transactional + public void assignPenalty(RequestPenalty requestPenalty){ + User userToBan = userRepository.findById(requestPenalty.getUserId()).orElseThrow(UserNotFoundException::new); + Penalty penalty = penaltyRepository.save(Penalty.toEntity(requestPenalty, userToBan)); + userToBan.addPenalty(penalty); + } + + public List getMyPenalties(Long userId){ + User currentUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + currentUser.getPenalties().sort(Comparator.comparing(Penalty::getId)); + + return currentUser.getPenalties().stream() + .map(ResponsePenalty::createResponsePenaltyDTO) // Post -> ResponsePostDTO 변환 + .toList(); + } + + public void removePenalty(Long penaltyId) { + Penalty penaltyToRemove = penaltyRepository.findById(penaltyId) + .orElseThrow(PenaltyNotFoundException::new); + penaltyRepository.delete(penaltyToRemove); + } + + public List getAllPenaltiesSortedByUserId() { + List allPenalties = penaltyRepository.findAll(); + return allPenalties.stream() + .sorted(Comparator.comparing(Penalty-> Penalty.getUser().getId())) + .map(ResponsePenalty::createResponsePenaltyDTO) + .toList(); + } +} diff --git a/src/main/java/leets/weeth/domain/user/entity/User.java b/src/main/java/leets/weeth/domain/user/entity/User.java index f42e5d8e..b9a5f6b5 100644 --- a/src/main/java/leets/weeth/domain/user/entity/User.java +++ b/src/main/java/leets/weeth/domain/user/entity/User.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import leets.weeth.domain.attendance.entity.Attendance; +import leets.weeth.domain.penalty.entity.Penalty; import leets.weeth.domain.user.converter.CardinalListConverter; import leets.weeth.domain.user.dto.UserDTO; import leets.weeth.domain.user.entity.enums.Department; @@ -13,6 +14,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; @Entity @@ -60,7 +62,10 @@ public class User extends BaseEntity { private Integer attendanceRate; @OneToMany(mappedBy = "user") - private List attendances; + private List attendances = new ArrayList<>(); + + @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE, orphanRemoval = true) + private List penalties = new ArrayList<>(); @PrePersist public void init() { @@ -123,4 +128,8 @@ private Integer getCurrentWeek() { .filter(week -> week.getDate().isEqual(LocalDate.now()) || week.getDate().isBefore(LocalDate.now())) .count(); } + + public void addPenalty(Penalty penalty){ + this.penalties.add(penalty); + } } diff --git a/src/main/java/leets/weeth/global/common/error/exception/custom/PenaltyNotFoundException.java b/src/main/java/leets/weeth/global/common/error/exception/custom/PenaltyNotFoundException.java new file mode 100644 index 00000000..f63ff2c6 --- /dev/null +++ b/src/main/java/leets/weeth/global/common/error/exception/custom/PenaltyNotFoundException.java @@ -0,0 +1,9 @@ +package leets.weeth.global.common.error.exception.custom; + +import jakarta.persistence.EntityNotFoundException; + +public class PenaltyNotFoundException extends EntityNotFoundException { + public PenaltyNotFoundException() { + super("존재하지 않는 패널티입니다."); + } +} \ No newline at end of file