From 84ed2b0e63c3511a221d048f2bf12df58d79698e Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 18:36:06 +0900 Subject: [PATCH 01/32] =?UTF-8?q?refactor:=20Penalty=20enum=20java=20->=20?= =?UTF-8?q?kotlin=EC=9C=BC=EB=A1=9C=20=ED=8F=B4=EB=8D=94=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/{java/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.java => kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt} (100%) diff --git a/src/main/java/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.java b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.java rename to src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt From f152335dbab77da4826ce052679ba68a4dec2c72 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 18:42:56 +0900 Subject: [PATCH 02/32] =?UTF-8?q?refactor:=20Penalty=20enum=20kotlin?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EB=B2=95=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weeth/domain/penalty/domain/entity/enums/PenaltyType.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt index 44031768..4ea3aeb3 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt @@ -1,7 +1,7 @@ -package com.weeth.domain.penalty.domain.entity.enums; +package com.weeth.domain.penalty.domain.entity.enums -public enum PenaltyType { +enum class PenaltyType { PENALTY, AUTO_PENALTY, - WARNING + WARNING, } From c1c285cb0a0649f46a50091da8da716bd4c2e114 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 18:44:13 +0900 Subject: [PATCH 03/32] =?UTF-8?q?refactor:=20Penalty=20entity,=20repositor?= =?UTF-8?q?y=20java=20->=20kotlin=EC=9C=BC=EB=A1=9C=20=ED=8F=B4=EB=8D=94?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/weeth/domain/penalty/domain/entity/Penalty.kt} | 0 .../weeth/domain/penalty/domain/repository/PenaltyRepository.kt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{java/com/weeth/domain/penalty/domain/entity/Penalty.java => kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/domain/repository/PenaltyRepository.java => kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt} (100%) diff --git a/src/main/java/com/weeth/domain/penalty/domain/entity/Penalty.java b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/domain/entity/Penalty.java rename to src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt diff --git a/src/main/java/com/weeth/domain/penalty/domain/repository/PenaltyRepository.java b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/domain/repository/PenaltyRepository.java rename to src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt From c59cc0cc52cb6f5b247e8e4604669f00e8b70e99 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 19:23:58 +0900 Subject: [PATCH 04/32] =?UTF-8?q?refactor:=20Penalty=20dto,=20mapper=20jav?= =?UTF-8?q?a=20->=20kotlin=EC=9C=BC=EB=A1=9C=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/weeth/domain/penalty/application/dto/PenaltyDTO.kt} | 0 .../com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{java/com/weeth/domain/penalty/application/dto/PenaltyDTO.java => kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/application/mapper/PenaltyMapper.java => kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt} (100%) diff --git a/src/main/java/com/weeth/domain/penalty/application/dto/PenaltyDTO.java b/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/dto/PenaltyDTO.java rename to src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt diff --git a/src/main/java/com/weeth/domain/penalty/application/mapper/PenaltyMapper.java b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/mapper/PenaltyMapper.java rename to src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt From 0cfe1190bab9b880171889ac69300d6b3af53959 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 19:24:44 +0900 Subject: [PATCH 05/32] =?UTF-8?q?refactor:=20Penalty=20entity,=20repositor?= =?UTF-8?q?y=20kotlin=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EB=B2=95=20=EB=B3=80?= =?UTF-8?q?=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/penalty/domain/entity/Penalty.kt | 59 +++++++++---------- .../domain/repository/PenaltyRepository.kt | 35 ++++++----- 2 files changed, 46 insertions(+), 48 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt index 67c82810..430b50fc 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt @@ -1,41 +1,36 @@ -package com.weeth.domain.penalty.domain.entity; - -import jakarta.persistence.*; -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType; -import com.weeth.domain.user.domain.entity.Cardinal; -import com.weeth.domain.user.domain.entity.User; -import com.weeth.global.common.entity.BaseEntity; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; +package com.weeth.domain.penalty.domain.entity + +import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.user.domain.entity.Cardinal +import com.weeth.domain.user.domain.entity.User +import com.weeth.global.common.entity.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.ManyToOne @Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@SuperBuilder -public class Penalty extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "penalty_id") - private Long id; - +class Penalty( @ManyToOne @JoinColumn(name = "user_id") - private User user; - + val user: User, @ManyToOne @JoinColumn(name = "cardinal_id") - private Cardinal cardinal; - + val cardinal: Cardinal, @Enumerated(EnumType.STRING) - private PenaltyType penaltyType; - - private String penaltyDescription; - - public void update(String penaltyDescription) { - this.penaltyDescription = penaltyDescription; + val penaltyType: PenaltyType, + var penaltyDescription: String, + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "penalty_id") + val id: Long = 0, +) : BaseEntity() { + fun update(penaltyDescription: String) { + this.penaltyDescription = penaltyDescription } - } diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt index 95d14c91..80699fe7 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt @@ -1,21 +1,24 @@ -package com.weeth.domain.penalty.domain.repository; +package com.weeth.domain.penalty.domain.repository -import com.weeth.domain.penalty.domain.entity.Penalty; -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType; -import com.weeth.domain.user.domain.entity.Cardinal; -import com.weeth.domain.user.domain.entity.User; -import org.springframework.data.jpa.repository.JpaRepository; +import com.weeth.domain.penalty.domain.entity.Penalty +import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.user.domain.entity.Cardinal +import com.weeth.domain.user.domain.entity.User +import org.springframework.data.jpa.repository.JpaRepository +import java.time.LocalDateTime -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; +interface PenaltyRepository : JpaRepository { + fun findByUserIdAndCardinalIdOrderByIdDesc( + userId: Long, + cardinalId: Long, + ): List -public interface PenaltyRepository extends JpaRepository { + fun findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( + user: User, + cardinal: Cardinal, + penaltyType: PenaltyType, + createdAt: LocalDateTime, + ): Penalty? - List findByUserIdAndCardinalIdOrderByIdDesc(Long userId, Long cardinalId); - - Optional findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( - User user, Cardinal cardinal, PenaltyType penaltyType, LocalDateTime createdAt); - - List findByCardinalIdOrderByIdDesc(Long cardinalId); + fun findByCardinalIdOrderByIdDesc(cardinalId: Long): List } From 7090c0a8c709d2e131b28b7ab82665eb90987205 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 19:26:02 +0900 Subject: [PATCH 06/32] =?UTF-8?q?refactor:=20Penalty=20dto,=20mapper=20kot?= =?UTF-8?q?lin=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EB=B2=95=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../penalty/application/dto/PenaltyDTO.kt | 92 +++++++------- .../application/mapper/PenaltyMapper.kt | 112 ++++++++++-------- 2 files changed, 104 insertions(+), 100 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt index 0284ceb9..ed24d437 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt @@ -1,51 +1,43 @@ -package com.weeth.domain.penalty.application.dto; - -import jakarta.validation.constraints.NotNull; -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType; -import lombok.Builder; - -import java.time.LocalDateTime; -import java.util.List; - -public class PenaltyDTO { - - @Builder - public record Save( - @NotNull Long userId, - @NotNull PenaltyType penaltyType, - String penaltyDescription - ){} - - @Builder - public record Update( - @NotNull Long penaltyId, - String penaltyDescription - ){} - - @Builder - public record ResponseAll( - Integer cardinal, - List responses - ){} - - @Builder - public record Response( - Long userId, - Integer penaltyCount, - Integer warningCount, - String name, - List cardinals, - List Penalties - ){} - - @Builder - public record Penalties( - Long penaltyId, - PenaltyType penaltyType, - Integer cardinal, - String penaltyDescription, - LocalDateTime time - ){} - +package com.weeth.domain.penalty.application.dto + +import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import jakarta.validation.constraints.NotNull +import java.time.LocalDateTime + +class PenaltyDTO { + data class Save( + @field:NotNull + val userId: Long, + @field:NotNull + val penaltyType: PenaltyType, + val penaltyDescription: String?, + ) + + data class Update( + @field:NotNull + val penaltyId: Long, + val penaltyDescription: String?, + ) + + data class ResponseAll( + val cardinal: Int?, + val responses: List, + ) + + data class Response( + val userId: Long?, + val penaltyCount: Int?, + val warningCount: Int?, + val name: String?, + val cardinals: List, + val penalties: List, + ) + + data class Penalties( + val penaltyId: Long?, + val penaltyType: PenaltyType?, + val cardinal: Int?, + val penaltyDescription: String?, + val time: LocalDateTime?, + ) } - diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt index 06544027..6dff26e7 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt @@ -1,57 +1,69 @@ -package com.weeth.domain.penalty.application.mapper; +package com.weeth.domain.penalty.application.mapper -import com.weeth.domain.penalty.application.dto.PenaltyDTO; -import com.weeth.domain.penalty.domain.entity.Penalty; -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType; -import com.weeth.domain.user.domain.entity.Cardinal; -import com.weeth.domain.user.domain.entity.User; -import com.weeth.domain.user.domain.entity.UserCardinal; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.MappingConstants; -import org.mapstruct.ReportingPolicy; +import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.domain.entity.Penalty +import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.user.domain.entity.Cardinal +import com.weeth.domain.user.domain.entity.User +import com.weeth.domain.user.domain.entity.UserCardinal +import org.springframework.stereotype.Component -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; +@Component +class PenaltyMapper { + fun fromPenaltyDto( + dto: PenaltyDTO.Save, + user: User, + cardinal: Cardinal, + ): Penalty = + Penalty( + user = user, + cardinal = cardinal, + penaltyType = dto.penaltyType, + penaltyDescription = dto.penaltyDescription ?: "", + ) -@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface PenaltyMapper { + fun toAutoPenalty( + penaltyDescription: String, + user: User, + cardinal: Cardinal, + penaltyType: PenaltyType, + ): Penalty = + Penalty( + user = user, + cardinal = cardinal, + penaltyType = penaltyType, + penaltyDescription = penaltyDescription, + ) - @Mapping(target = "user", source = "user") - @Mapping(target = "cardinal", source = "cardinal") - @Mapping(target = "id", ignore = true) - @Mapping(target = "createdAt", ignore = true) - @Mapping(target = "modifiedAt", ignore = true) - Penalty fromPenaltyDto(PenaltyDTO.Save dto, User user, Cardinal cardinal); + fun toPenaltyDto( + user: User, + penalties: List, + userCardinals: List, + ): PenaltyDTO.Response = + PenaltyDTO.Response( + userId = user.id, + penaltyCount = null, + warningCount = null, + name = null, + cardinals = userCardinals.map { it.cardinal.cardinalNumber }, + penalties = penalties, + ) - @Mapping(target = "id", ignore = true) - @Mapping(target = "createdAt", ignore = true) - @Mapping(target = "modifiedAt", ignore = true) - Penalty toAutoPenalty(String penaltyDescription, User user, Cardinal cardinal, PenaltyType penaltyType); - - @Mapping(target = "Penalties", source = "penalties") - @Mapping(target = "userId", source = "user.id") - @Mapping(target = "cardinals", expression = "java( toCardinalNumbers(userCardinals) )") - PenaltyDTO.Response toPenaltyDto(User user, List penalties, List userCardinals); - - @Mapping(target = "time", source = "modifiedAt") - @Mapping(target = "penaltyId", source = "id") - @Mapping(target = "cardinal", - expression = "java(penalty.getCardinal() != null ? penalty.getCardinal().getCardinalNumber() : null)") - - PenaltyDTO.Penalties toPenalties(Penalty penalty); - - PenaltyDTO.ResponseAll toResponseAll(Integer cardinal, List responses); - - default List toCardinalNumbers(List userCardinals) { - if (userCardinals == null || userCardinals.isEmpty()) { - return Collections.emptyList(); - } - - return userCardinals.stream() - .map(uc -> uc.getCardinal().getCardinalNumber()) - .collect(Collectors.toList()); - } + fun toPenalties(penalty: Penalty): PenaltyDTO.Penalties = + PenaltyDTO.Penalties( + penaltyId = penalty.id, + penaltyType = penalty.penaltyType, + cardinal = penalty.cardinal?.cardinalNumber, + penaltyDescription = penalty.penaltyDescription, + time = penalty.modifiedAt, + ) + fun toResponseAll( + cardinal: Int?, + responses: List, + ): PenaltyDTO.ResponseAll = + PenaltyDTO.ResponseAll( + cardinal = cardinal, + responses = responses, + ) } From 68fd379d292bf970ea2515271fad85d4a4a2fb56 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 19:28:32 +0900 Subject: [PATCH 07/32] =?UTF-8?q?build:=20Lombok=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20Kotlin=20=ED=98=B8=ED=99=98=EC=84=B1=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index 6b528cbf..cc9b1410 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,6 +8,7 @@ plugins { kotlin("jvm") version "2.1.0" kotlin("plugin.spring") version "2.1.0" kotlin("plugin.jpa") version "2.1.0" + kotlin("plugin.lombok") version "2.1.0" id("org.jlleitschuh.gradle.ktlint") version "12.1.2" } From b0dea58e8e1689045daaee34ca436dfffa1a9cde Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 19:30:01 +0900 Subject: [PATCH 08/32] =?UTF-8?q?refactor:=20Kotlin=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20Java=20=ED=98=B8=EC=B6=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../penalty/application/usecase/PenaltyUsecaseImpl.java | 6 +++--- .../domain/penalty/domain/service/PenaltyFindService.java | 2 +- .../domain/penalty/domain/service/PenaltyUpdateService.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java b/src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java index ee906d6d..57995c29 100644 --- a/src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java +++ b/src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java @@ -46,7 +46,7 @@ public class PenaltyUsecaseImpl implements PenaltyUsecase{ @Override @Transactional public void save(PenaltyDTO.Save dto) { - User user = userGetService.find(dto.userId()); + User user = userGetService.find(dto.getUserId()); Cardinal cardinal = userCardinalGetService.getCurrentCardinal(user); Penalty penalty = mapper.fromPenaltyDto(dto, user, cardinal); @@ -71,7 +71,7 @@ public void save(PenaltyDTO.Save dto) { @Override @Transactional public void update(PenaltyDTO.Update dto) { - Penalty penalty = penaltyFindService.find(dto.penaltyId()); + Penalty penalty = penaltyFindService.find(dto.getPenaltyId()); penaltyUpdateService.update(penalty, dto); } @@ -93,7 +93,7 @@ public List findAll(Integer cardinalNumber) { List responses = penaltiesByUser.entrySet().stream() .map(entry -> toPenaltyDto(entry.getKey(), entry.getValue())) - .sorted(Comparator.comparing(PenaltyDTO.Response::userId)) + .sorted(Comparator.comparing(PenaltyDTO.Response::getUserId)) .toList(); result.add(mapper.toResponseAll(cardinal.getCardinalNumber(), responses)); diff --git a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java index 7972de54..a6319f9c 100644 --- a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java +++ b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java @@ -35,7 +35,7 @@ public Penalty getRelatedAutoPenalty(Penalty penalty) { penalty.getCardinal(), PenaltyType.AUTO_PENALTY, penalty.getCreatedAt() - ).orElse(null); + ); } public List findAllByCardinalId(Long cardinalId) { diff --git a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java index a4148162..1d41e633 100644 --- a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java +++ b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java @@ -8,8 +8,8 @@ public class PenaltyUpdateService { public void update(Penalty penalty, PenaltyDTO.Update dto) { - if (dto.penaltyDescription() != null && !dto.penaltyDescription().isBlank()) { - penalty.update(dto.penaltyDescription()); + if (dto.getPenaltyDescription() != null && !dto.getPenaltyDescription().isBlank()) { + penalty.update(dto.getPenaltyDescription()); } } } From 3289ea6ecd2976f56551b01fa4b2a63a9d0b4d5b Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:45:06 +0900 Subject: [PATCH 09/32] =?UTF-8?q?refactor:=20Penalty=20exception=20java=20?= =?UTF-8?q?->=20kotlin=EC=9C=BC=EB=A1=9C=20=ED=8F=B4=EB=8D=94=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/AutoPenaltyDeleteNotAllowedException.kt} | 0 .../domain/penalty/application/exception/PenaltyErrorCode.kt} | 0 .../penalty/application/exception/PenaltyNotFoundException.kt} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{java/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.java => kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.java => kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.java => kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt} (100%) diff --git a/src/main/java/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.java b/src/main/kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.java rename to src/main/kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt diff --git a/src/main/java/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.java b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.java rename to src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt diff --git a/src/main/java/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.java b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.java rename to src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt From 176fb190ab91077a9e7b225e44261e156d5c43dd Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:47:03 +0900 Subject: [PATCH 10/32] =?UTF-8?q?refactor:=20Penalty=20exception=20kotlin?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EB=B2=95=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AutoPenaltyDeleteNotAllowedException.kt | 10 +++----- .../application/exception/PenaltyErrorCode.kt | 24 ++++++++----------- .../exception/PenaltyNotFoundException.kt | 10 +++----- 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt b/src/main/kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt index 6ff34a58..23cef4fe 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/exception/AutoPenaltyDeleteNotAllowedException.kt @@ -1,9 +1,5 @@ -package com.weeth.domain.penalty.application.exception; +package com.weeth.domain.penalty.application.exception -import com.weeth.global.common.exception.BaseException; +import com.weeth.global.common.exception.BaseException -public class AutoPenaltyDeleteNotAllowedException extends BaseException { - public AutoPenaltyDeleteNotAllowedException() { - super(PenaltyErrorCode.AUTO_PENALTY_DELETE_NOT_ALLOWED); - } -} +class AutoPenaltyDeleteNotAllowedException : BaseException(PenaltyErrorCode.AUTO_PENALTY_DELETE_NOT_ALLOWED) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt index f5a341a1..304db529 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt @@ -1,22 +1,18 @@ -package com.weeth.domain.penalty.application.exception; +package com.weeth.domain.penalty.application.exception -import com.weeth.global.common.exception.ErrorCodeInterface; -import com.weeth.global.common.exception.ExplainError; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.springframework.http.HttpStatus; +import com.weeth.global.common.exception.ErrorCodeInterface +import com.weeth.global.common.exception.ExplainError +import org.springframework.http.HttpStatus -@Getter -@AllArgsConstructor -public enum PenaltyErrorCode implements ErrorCodeInterface { +enum class PenaltyErrorCode( + override val code: Int, + override val status: HttpStatus, + override val message: String, +) : ErrorCodeInterface { @ExplainError("요청한 패널티 ID가 존재하지 않을 때 발생합니다.") PENALTY_NOT_FOUND(2600, HttpStatus.NOT_FOUND, "존재하지 않는 패널티입니다."), @ExplainError("시스템에 의해 자동 부여된 패널티를 수동으로 삭제하려 할 때 발생합니다.") - AUTO_PENALTY_DELETE_NOT_ALLOWED(2601, HttpStatus.BAD_REQUEST, "자동 생성된 패널티는 삭제할 수 없습니다"); - - private final int code; - private final HttpStatus status; - private final String message; + AUTO_PENALTY_DELETE_NOT_ALLOWED(2601, HttpStatus.BAD_REQUEST, "자동 생성된 패널티는 삭제할 수 없습니다"), } diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt index cceb0ad6..820c80df 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyNotFoundException.kt @@ -1,9 +1,5 @@ -package com.weeth.domain.penalty.application.exception; +package com.weeth.domain.penalty.application.exception -import com.weeth.global.common.exception.BaseException; +import com.weeth.global.common.exception.BaseException -public class PenaltyNotFoundException extends BaseException { - public PenaltyNotFoundException() { - super(PenaltyErrorCode.PENALTY_NOT_FOUND); - } -} +class PenaltyNotFoundException : BaseException(PenaltyErrorCode.PENALTY_NOT_FOUND) From 432fefc0fe43e0c2564f72defc0666234ffc1429 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:47:54 +0900 Subject: [PATCH 11/32] =?UTF-8?q?refactor:=20Penalty=20usecase=20java=20->?= =?UTF-8?q?=20kotlin=EC=9C=BC=EB=A1=9C=20=ED=8F=B4=EB=8D=94=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weeth/domain/penalty/application/usecase/PenaltyUsecase.kt} | 0 .../domain/penalty/application/usecase/PenaltyUsecaseImpl.kt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{java/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.java => kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java => kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt} (100%) diff --git a/src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.java b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.java rename to src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt diff --git a/src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.java rename to src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt From 167edd54d9a02037056e392936ba80a6476b14e9 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:50:35 +0900 Subject: [PATCH 12/32] =?UTF-8?q?refactor:=20Penalty=20service=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/service/PenaltyDeleteService.java | 17 ------- .../domain/service/PenaltyFindService.java | 44 ------------------- .../domain/service/PenaltySaveService.java | 18 -------- .../domain/service/PenaltyUpdateService.java | 15 ------- 4 files changed, 94 deletions(-) delete mode 100644 src/main/java/com/weeth/domain/penalty/domain/service/PenaltyDeleteService.java delete mode 100644 src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java delete mode 100644 src/main/java/com/weeth/domain/penalty/domain/service/PenaltySaveService.java delete mode 100644 src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java diff --git a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyDeleteService.java b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyDeleteService.java deleted file mode 100644 index 457e239e..00000000 --- a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyDeleteService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.weeth.domain.penalty.domain.service; - -import com.weeth.domain.penalty.domain.repository.PenaltyRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class PenaltyDeleteService { - - private final PenaltyRepository penaltyRepository; - - public void delete(Long penaltyId){ - penaltyRepository.deleteById(penaltyId); - } - -} diff --git a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java deleted file mode 100644 index a6319f9c..00000000 --- a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyFindService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.weeth.domain.penalty.domain.service; - -import com.weeth.domain.penalty.domain.entity.Penalty; -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType; -import com.weeth.domain.penalty.domain.repository.PenaltyRepository; -import com.weeth.domain.penalty.application.exception.PenaltyNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class PenaltyFindService { - - private final PenaltyRepository penaltyRepository; - - public Penalty find(Long penaltyId){ - return penaltyRepository.findById(penaltyId) - .orElseThrow(PenaltyNotFoundException::new); - } - - public List findAllByUserIdAndCardinalId(Long userId, Long cardinalId){ - return penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, cardinalId); - } - - public List findAll(){ - return penaltyRepository.findAll(); - } - - public Penalty getRelatedAutoPenalty(Penalty penalty) { - return penaltyRepository - .findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( - penalty.getUser(), - penalty.getCardinal(), - PenaltyType.AUTO_PENALTY, - penalty.getCreatedAt() - ); - } - - public List findAllByCardinalId(Long cardinalId) { - return penaltyRepository.findByCardinalIdOrderByIdDesc(cardinalId); - } -} diff --git a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltySaveService.java b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltySaveService.java deleted file mode 100644 index 9b40dff7..00000000 --- a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltySaveService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.weeth.domain.penalty.domain.service; - -import com.weeth.domain.penalty.domain.entity.Penalty; -import com.weeth.domain.penalty.domain.repository.PenaltyRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class PenaltySaveService { - - private final PenaltyRepository penaltyRepository; - - public void save(Penalty penalty){ - penaltyRepository.save(penalty); - } - -} diff --git a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java b/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java deleted file mode 100644 index 1d41e633..00000000 --- a/src/main/java/com/weeth/domain/penalty/domain/service/PenaltyUpdateService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.weeth.domain.penalty.domain.service; - -import com.weeth.domain.penalty.application.dto.PenaltyDTO; -import com.weeth.domain.penalty.domain.entity.Penalty; -import org.springframework.stereotype.Service; - -@Service -public class PenaltyUpdateService { - - public void update(Penalty penalty, PenaltyDTO.Update dto) { - if (dto.getPenaltyDescription() != null && !dto.getPenaltyDescription().isBlank()) { - penalty.update(dto.getPenaltyDescription()); - } - } -} From 8b6637f7d5682d9dc48e258fbcf88c511d0a197e Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:56:42 +0900 Subject: [PATCH 13/32] =?UTF-8?q?refactor:=20Penalty=20controller,=20respo?= =?UTF-8?q?nsecode=20java=20->=20kotlin=EC=9C=BC=EB=A1=9C=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weeth/domain/penalty/presentation/PenaltyAdminController.kt} | 0 .../com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt} | 0 .../weeth/domain/penalty/presentation/PenaltyUserController.kt} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{java/com/weeth/domain/penalty/presentation/PenaltyAdminController.java => kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/presentation/PenaltyResponseCode.java => kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt} (100%) rename src/main/{java/com/weeth/domain/penalty/presentation/PenaltyUserController.java => kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt} (100%) diff --git a/src/main/java/com/weeth/domain/penalty/presentation/PenaltyAdminController.java b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/presentation/PenaltyAdminController.java rename to src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt diff --git a/src/main/java/com/weeth/domain/penalty/presentation/PenaltyResponseCode.java b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/presentation/PenaltyResponseCode.java rename to src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt diff --git a/src/main/java/com/weeth/domain/penalty/presentation/PenaltyUserController.java b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt similarity index 100% rename from src/main/java/com/weeth/domain/penalty/presentation/PenaltyUserController.java rename to src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt From c3b7cdb09ceefa6374e18a12bace59bc5af1266f Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:57:22 +0900 Subject: [PATCH 14/32] =?UTF-8?q?refactor:=20=EC=BD=94=ED=8B=80=EB=A6=B0?= =?UTF-8?q?=20=EB=AC=B8=EB=B2=95=EC=97=90=20=EB=A7=9E=EA=B2=8C=20Penalty?= =?UTF-8?q?=20errorcode=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/exception/PenaltyErrorCode.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt index 304db529..d5218937 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/exception/PenaltyErrorCode.kt @@ -5,14 +5,20 @@ import com.weeth.global.common.exception.ExplainError import org.springframework.http.HttpStatus enum class PenaltyErrorCode( - override val code: Int, - override val status: HttpStatus, - override val message: String, + private val code: Int, + private val status: HttpStatus, + private val message: String, ) : ErrorCodeInterface { - @ExplainError("요청한 패널티 ID가 존재하지 않을 때 발생합니다.") PENALTY_NOT_FOUND(2600, HttpStatus.NOT_FOUND, "존재하지 않는 패널티입니다."), @ExplainError("시스템에 의해 자동 부여된 패널티를 수동으로 삭제하려 할 때 발생합니다.") AUTO_PENALTY_DELETE_NOT_ALLOWED(2601, HttpStatus.BAD_REQUEST, "자동 생성된 패널티는 삭제할 수 없습니다"), + ; + + override fun getCode(): Int = code + + override fun getStatus(): HttpStatus = status + + override fun getMessage(): String = message } From 56864e397249d060e50c9d149495f229464836d6 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 22:59:58 +0900 Subject: [PATCH 15/32] =?UTF-8?q?refactor:=20Penalty=20usecase=20kotlin?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EB=B2=95=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/usecase/PenaltyUsecase.kt | 20 +- .../application/usecase/PenaltyUsecaseImpl.kt | 228 +++++++++--------- 2 files changed, 123 insertions(+), 125 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt index 3d30b4ca..26ed997b 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt @@ -1,19 +1,15 @@ -package com.weeth.domain.penalty.application.usecase; +package com.weeth.domain.penalty.application.usecase -import com.weeth.domain.penalty.application.dto.PenaltyDTO; +import com.weeth.domain.penalty.application.dto.PenaltyDTO -import java.util.List; +interface PenaltyUsecase { + fun save(dto: PenaltyDTO.Save) -public interface PenaltyUsecase { + fun update(dto: PenaltyDTO.Update) - void save(PenaltyDTO.Save dto); + fun findAll(cardinalNumber: Int?): List - void update(PenaltyDTO.Update dto); - - List findAll(Integer cardinalNumber); - - PenaltyDTO.Response find(Long userId); - - void delete(Long penaltyId); + fun find(userId: Long): PenaltyDTO.Response + fun delete(penaltyId: Long) } diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt index 57995c29..6ac53b9e 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt @@ -1,150 +1,152 @@ -package com.weeth.domain.penalty.application.usecase; - -import jakarta.transaction.Transactional; -import com.weeth.domain.penalty.application.dto.PenaltyDTO; -import com.weeth.domain.penalty.application.exception.AutoPenaltyDeleteNotAllowedException; -import com.weeth.domain.penalty.application.mapper.PenaltyMapper; -import com.weeth.domain.penalty.domain.entity.Penalty; -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType; -import com.weeth.domain.penalty.domain.service.PenaltyDeleteService; -import com.weeth.domain.penalty.domain.service.PenaltyFindService; -import com.weeth.domain.penalty.domain.service.PenaltySaveService; -import com.weeth.domain.penalty.domain.service.PenaltyUpdateService; -import com.weeth.domain.user.domain.entity.Cardinal; -import com.weeth.domain.user.domain.entity.User; -import com.weeth.domain.user.domain.entity.UserCardinal; -import com.weeth.domain.user.domain.service.CardinalGetService; -import com.weeth.domain.user.domain.service.UserCardinalGetService; -import com.weeth.domain.user.domain.service.UserGetService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; +package com.weeth.domain.penalty.application.usecase + +import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.application.exception.AutoPenaltyDeleteNotAllowedException +import com.weeth.domain.penalty.application.exception.PenaltyNotFoundException +import com.weeth.domain.penalty.application.mapper.PenaltyMapper +import com.weeth.domain.penalty.domain.entity.Penalty +import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.domain.service.CardinalGetService +import com.weeth.domain.user.domain.service.UserCardinalGetService +import com.weeth.domain.user.domain.service.UserGetService +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service -@RequiredArgsConstructor -public class PenaltyUsecaseImpl implements PenaltyUsecase{ - - private static final String AUTO_PENALTY_DESCRIPTION = "누적경고 %d회"; - - private final PenaltySaveService penaltySaveService; - private final PenaltyFindService penaltyFindService; - private final PenaltyUpdateService penaltyUpdateService; - private final PenaltyDeleteService penaltyDeleteService; - - private final UserGetService userGetService; - - private final UserCardinalGetService userCardinalGetService; - private final CardinalGetService cardinalGetService; - - private final PenaltyMapper mapper; +class PenaltyUsecaseImpl( + private val penaltyRepository: PenaltyRepository, + private val userGetService: UserGetService, + private val userCardinalGetService: UserCardinalGetService, + private val cardinalGetService: CardinalGetService, + private val mapper: PenaltyMapper, +) : PenaltyUsecase { + companion object { + private const val AUTO_PENALTY_DESCRIPTION = "누적경고 %d회" + } - @Override @Transactional - public void save(PenaltyDTO.Save dto) { - User user = userGetService.find(dto.getUserId()); - Cardinal cardinal = userCardinalGetService.getCurrentCardinal(user); + override fun save(dto: PenaltyDTO.Save) { + val user = userGetService.find(dto.userId) + val cardinal = userCardinalGetService.getCurrentCardinal(user) - Penalty penalty = mapper.fromPenaltyDto(dto, user, cardinal); + val penalty = mapper.fromPenaltyDto(dto, user, cardinal) + penaltyRepository.save(penalty) - penaltySaveService.save(penalty); + when (penalty.penaltyType) { + PenaltyType.PENALTY -> { + user.incrementPenaltyCount() + } - if(penalty.getPenaltyType().equals(PenaltyType.PENALTY)){ - user.incrementPenaltyCount(); - } else if (penalty.getPenaltyType().equals(PenaltyType.WARNING)){ - user.incrementWarningCount(); + PenaltyType.WARNING -> { + user.incrementWarningCount() - Integer warningCount = user.getWarningCount(); - if(warningCount % 2 == 0){ - String penaltyDescription = String.format(AUTO_PENALTY_DESCRIPTION, warningCount); - Penalty autoPenalty = mapper.toAutoPenalty(penaltyDescription, user, cardinal, PenaltyType.AUTO_PENALTY); - penaltySaveService.save(autoPenalty); - user.incrementPenaltyCount(); + val warningCount = user.warningCount + if (warningCount % 2 == 0) { + val description = AUTO_PENALTY_DESCRIPTION.format(warningCount) + val autoPenalty = mapper.toAutoPenalty(description, user, cardinal, PenaltyType.AUTO_PENALTY) + penaltyRepository.save(autoPenalty) + user.incrementPenaltyCount() + } } + + else -> {} } } - @Override @Transactional - public void update(PenaltyDTO.Update dto) { - Penalty penalty = penaltyFindService.find(dto.getPenaltyId()); - penaltyUpdateService.update(penalty, dto); + override fun update(dto: PenaltyDTO.Update) { + val penalty = + penaltyRepository.findByIdOrNull(dto.penaltyId) + ?: throw PenaltyNotFoundException() + if (!dto.penaltyDescription.isNullOrBlank()) { + penalty.update(dto.penaltyDescription) + } } - // Todo: 쿼리 최적화 필요 - @Override - public List findAll(Integer cardinalNumber) { - List cardinals = (cardinalNumber == null) - ? cardinalGetService.findAllCardinalNumberDesc() - : List.of(cardinalGetService.findByAdminSide(cardinalNumber)); - - List result = new ArrayList<>(); - - for (Cardinal cardinal : cardinals) { - List penalties = penaltyFindService.findAllByCardinalId(cardinal.getId()); + // TODO: 쿼리 최적화 필요 + @Transactional(readOnly = true) + override fun findAll(cardinalNumber: Int?): List { + val cardinals = + if (cardinalNumber == null) { + cardinalGetService.findAllCardinalNumberDesc() + } else { + listOf(cardinalGetService.findByAdminSide(cardinalNumber)) + } - Map> penaltiesByUser = penalties.stream() - .collect(Collectors.groupingBy(p -> p.getUser().getId())); + return cardinals.map { cardinal -> + val penalties = penaltyRepository.findByCardinalIdOrderByIdDesc(cardinal.id) - List responses = penaltiesByUser.entrySet().stream() - .map(entry -> toPenaltyDto(entry.getKey(), entry.getValue())) - .sorted(Comparator.comparing(PenaltyDTO.Response::getUserId)) - .toList(); + val responses = + penalties + .groupBy { it.user.id } + .entries + .map { (userId, userPenalties) -> toPenaltyDto(userId, userPenalties) } + .sortedBy { it.userId } - result.add(mapper.toResponseAll(cardinal.getCardinalNumber(), responses)); + mapper.toResponseAll(cardinal.cardinalNumber, responses) } - return result; } - @Override - public PenaltyDTO.Response find(Long userId) { - User user = userGetService.find(userId); - Cardinal currentCardinal = userCardinalGetService.getCurrentCardinal(user); - List penalties = penaltyFindService.findAllByUserIdAndCardinalId(userId, currentCardinal.getId()); + @Transactional(readOnly = true) + override fun find(userId: Long): PenaltyDTO.Response { + val user = userGetService.find(userId) + val currentCardinal = userCardinalGetService.getCurrentCardinal(user) + val penalties = penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, currentCardinal.id) - return toPenaltyDto(userId, penalties); + return toPenaltyDto(userId, penalties) } - @Override @Transactional - public void delete(Long penaltyId) { - Penalty penalty = penaltyFindService.find(penaltyId); - if(penalty.getPenaltyType().equals(PenaltyType.AUTO_PENALTY)){ - throw new AutoPenaltyDeleteNotAllowedException(); + override fun delete(penaltyId: Long) { + val penalty = + penaltyRepository.findByIdOrNull(penaltyId) + ?: throw PenaltyNotFoundException() + + if (penalty.penaltyType == PenaltyType.AUTO_PENALTY) { + throw AutoPenaltyDeleteNotAllowedException() } - User user = penalty.getUser(); + val user = penalty.user + + when (penalty.penaltyType) { + PenaltyType.PENALTY -> { + user.decrementPenaltyCount() + } - if(penalty.getPenaltyType().equals(PenaltyType.PENALTY)){ - penalty.getUser().decrementPenaltyCount(); - } else if (penalty.getPenaltyType().equals(PenaltyType.WARNING)) { - if(user.getWarningCount() % 2 == 0){ - Penalty relatedAutoPenalty = penaltyFindService.getRelatedAutoPenalty(penalty); - if(relatedAutoPenalty != null){ - penaltyDeleteService.delete(relatedAutoPenalty.getId()); + PenaltyType.WARNING -> { + if (user.warningCount % 2 == 0) { + val relatedAutoPenalty = + penaltyRepository + .findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( + penalty.user, + penalty.cardinal, + PenaltyType.AUTO_PENALTY, + penalty.createdAt, + ) + if (relatedAutoPenalty != null) { + penaltyRepository.deleteById(relatedAutoPenalty.id) + } + user.decrementPenaltyCount() } - user.decrementPenaltyCount(); + user.decrementWarningCount() } - penalty.getUser().decrementWarningCount(); + + else -> {} } - penaltyDeleteService.delete(penaltyId); + penaltyRepository.deleteById(penaltyId) } - private PenaltyDTO.Response toPenaltyDto(Long userId, List penalties) { - User user = userGetService.find(userId); - List userCardinals = userCardinalGetService.getUserCardinals(user); - - List penaltyDTOs = penalties.stream() - .map(mapper::toPenalties) - .toList(); - - return mapper.toPenaltyDto(user, penaltyDTOs, userCardinals); + private fun toPenaltyDto( + userId: Long, + penalties: List, + ): PenaltyDTO.Response { + val user = userGetService.find(userId) + val userCardinals = userCardinalGetService.getUserCardinals(user) + val penaltyDTOs = penalties.map(mapper::toPenalties) + return mapper.toPenaltyDto(user, penaltyDTOs, userCardinals) } - } From 102bea6ec23b22fa7ac07d2d96eef8031d675c3d Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 23:00:41 +0900 Subject: [PATCH 16/32] =?UTF-8?q?refactor:=20Penalty=20controller,=20respo?= =?UTF-8?q?nseCode=20kotlin=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EB=B2=95=20?= =?UTF-8?q?=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/PenaltyAdminController.kt | 82 ++++++++++--------- .../presentation/PenaltyResponseCode.kt | 28 ++----- .../presentation/PenaltyUserController.kt | 50 +++++------ 3 files changed, 75 insertions(+), 85 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt index ed1adb92..c3f7ac5f 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt @@ -1,54 +1,60 @@ -package com.weeth.domain.penalty.presentation; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import com.weeth.domain.penalty.application.dto.PenaltyDTO; -import com.weeth.domain.penalty.application.exception.PenaltyErrorCode; -import com.weeth.domain.penalty.application.usecase.PenaltyUsecase; -import com.weeth.global.common.exception.ApiErrorCodeExample; -import com.weeth.global.common.response.CommonResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static com.weeth.domain.penalty.presentation.PenaltyResponseCode.*; +package com.weeth.domain.penalty.presentation + +import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.application.exception.PenaltyErrorCode +import com.weeth.domain.penalty.application.usecase.PenaltyUsecase +import com.weeth.global.common.exception.ApiErrorCodeExample +import com.weeth.global.common.response.CommonResponse +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.tags.Tag +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PatchMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController @Tag(name = "PENALTY ADMIN", description = "[ADMIN] 패널티 어드민 API") @RestController -@RequiredArgsConstructor @RequestMapping("/api/v1/admin/penalties") -@ApiErrorCodeExample(PenaltyErrorCode.class) -public class PenaltyAdminController { - - private final PenaltyUsecase penaltyUsecase; - +@ApiErrorCodeExample(PenaltyErrorCode::class) +class PenaltyAdminController( + private val penaltyUsecase: PenaltyUsecase, +) { @PostMapping - @Operation(summary="패널티 부여") - public CommonResponse assignPenalty(@Valid @RequestBody PenaltyDTO.Save dto){ - penaltyUsecase.save(dto); - return CommonResponse.success(PENALTY_ASSIGN_SUCCESS); + @Operation(summary = "패널티 부여") + fun assignPenalty( + @Valid @RequestBody dto: PenaltyDTO.Save, + ): CommonResponse { + penaltyUsecase.save(dto) + return CommonResponse.success(PenaltyResponseCode.PENALTY_ASSIGN_SUCCESS) } @PatchMapping @Operation(summary = "패널티 수정") - public CommonResponse update(@Valid @RequestBody PenaltyDTO.Update dto){ - penaltyUsecase.update(dto); - return CommonResponse.success(PENALTY_UPDATE_SUCCESS); + fun update( + @Valid @RequestBody dto: PenaltyDTO.Update, + ): CommonResponse { + penaltyUsecase.update(dto) + return CommonResponse.success(PenaltyResponseCode.PENALTY_UPDATE_SUCCESS) } @GetMapping - @Operation(summary="전체 패널티 조회") - public CommonResponse> findAll(@RequestParam(required = false) Integer cardinal){ - return CommonResponse.success(PENALTY_FIND_ALL_SUCCESS, penaltyUsecase.findAll(cardinal)); - } + @Operation(summary = "전체 패널티 조회") + fun findAll( + @RequestParam(required = false) cardinal: Int?, + ): CommonResponse> = + CommonResponse.success(PenaltyResponseCode.PENALTY_FIND_ALL_SUCCESS, penaltyUsecase.findAll(cardinal)) @DeleteMapping - @Operation(summary="패널티 삭제") - public CommonResponse delete(@RequestParam Long penaltyId){ - penaltyUsecase.delete(penaltyId); - return CommonResponse.success(PENALTY_DELETE_SUCCESS); + @Operation(summary = "패널티 삭제") + fun delete( + @RequestParam penaltyId: Long, + ): CommonResponse { + penaltyUsecase.delete(penaltyId) + return CommonResponse.success(PenaltyResponseCode.PENALTY_DELETE_SUCCESS) } - } diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt index e73bdca4..f6b05674 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyResponseCode.kt @@ -1,26 +1,16 @@ -package com.weeth.domain.penalty.presentation; +package com.weeth.domain.penalty.presentation -import com.weeth.global.common.response.ResponseCodeInterface; -import lombok.Getter; -import org.springframework.http.HttpStatus; +import com.weeth.global.common.response.ResponseCodeInterface +import org.springframework.http.HttpStatus -@Getter -public enum PenaltyResponseCode implements ResponseCodeInterface { - // penaltyAdminController 관련 +enum class PenaltyResponseCode( + override val code: Int, + override val status: HttpStatus, + override val message: String, +) : ResponseCodeInterface { PENALTY_ASSIGN_SUCCESS(1600, HttpStatus.OK, "페널티가 성공적으로 부여되었습니다."), PENALTY_FIND_ALL_SUCCESS(1601, HttpStatus.OK, "모든 패널티가 성공적으로 조회되었습니다."), PENALTY_DELETE_SUCCESS(1602, HttpStatus.OK, "패널티가 성공적으로 삭제되었습니다."), PENALTY_UPDATE_SUCCESS(1603, HttpStatus.OK, "패널티를 성공적으로 수정했습니다."), - // penaltyUserController - PENALTY_USER_FIND_SUCCESS(1604, HttpStatus.OK, "패널티가 성공적으로 조회되었습니다."); - - private final int code; - private final HttpStatus status; - private final String message; - - PenaltyResponseCode(int code, HttpStatus status, String message) { - this.code = code; - this.status = status; - this.message = message; - } + PENALTY_USER_FIND_SUCCESS(1604, HttpStatus.OK, "패널티가 성공적으로 조회되었습니다."), } diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt index aed2feea..eaa45a57 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt @@ -1,35 +1,29 @@ -package com.weeth.domain.penalty.presentation; +package com.weeth.domain.penalty.presentation -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import com.weeth.domain.penalty.application.dto.PenaltyDTO; -import com.weeth.domain.penalty.application.exception.PenaltyErrorCode; -import com.weeth.domain.penalty.application.usecase.PenaltyUsecase; -import com.weeth.global.auth.annotation.CurrentUser; -import com.weeth.global.common.exception.ApiErrorCodeExample; -import com.weeth.global.common.response.CommonResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import static com.weeth.domain.penalty.presentation.PenaltyResponseCode.PENALTY_USER_FIND_SUCCESS; +import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.application.exception.PenaltyErrorCode +import com.weeth.domain.penalty.application.usecase.PenaltyUsecase +import com.weeth.global.auth.annotation.CurrentUser +import com.weeth.global.common.exception.ApiErrorCodeExample +import com.weeth.global.common.response.CommonResponse +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController @Tag(name = "PENALTY", description = "패널티 API") @RestController -@RequiredArgsConstructor @RequestMapping("/api/v1/penalties") -@ApiErrorCodeExample(PenaltyErrorCode.class) -public class PenaltyUserController { - - private final PenaltyUsecase penaltyUsecase; - +@ApiErrorCodeExample(PenaltyErrorCode::class) +class PenaltyUserController( + private val penaltyUsecase: PenaltyUsecase, +) { @GetMapping - @Operation(summary="본인 패널티 조회") - public CommonResponse findAllPenalties(@Parameter(hidden = true) @CurrentUser Long userId) { - PenaltyDTO.Response penalties = penaltyUsecase.find(userId); - return CommonResponse.success(PENALTY_USER_FIND_SUCCESS,penalties); - } - + @Operation(summary = "본인 패널티 조회") + fun findAllPenalties( + @Parameter(hidden = true) @CurrentUser userId: Long, + ): CommonResponse = + CommonResponse.success(PenaltyResponseCode.PENALTY_USER_FIND_SUCCESS, penaltyUsecase.find(userId)) } From bbbb06f5a726a513d378e71641daccbae4672962 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 23:39:59 +0900 Subject: [PATCH 17/32] =?UTF-8?q?refactor:=20PenaltyType=20enum=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt | 2 +- .../domain/penalty/domain/{entity => }/enums/PenaltyType.kt | 2 +- .../weeth/domain/penalty/domain/repository/PenaltyRepository.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/main/kotlin/com/weeth/domain/penalty/domain/{entity => }/enums/PenaltyType.kt (57%) diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt index 430b50fc..77714533 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt @@ -1,6 +1,6 @@ package com.weeth.domain.penalty.domain.entity -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.user.domain.entity.Cardinal import com.weeth.domain.user.domain.entity.User import com.weeth.global.common.entity.BaseEntity diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/enums/PenaltyType.kt similarity index 57% rename from src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt rename to src/main/kotlin/com/weeth/domain/penalty/domain/enums/PenaltyType.kt index 4ea3aeb3..8822b075 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/enums/PenaltyType.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/enums/PenaltyType.kt @@ -1,4 +1,4 @@ -package com.weeth.domain.penalty.domain.entity.enums +package com.weeth.domain.penalty.domain.enums enum class PenaltyType { PENALTY, diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt index 80699fe7..5d600857 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt @@ -1,7 +1,7 @@ package com.weeth.domain.penalty.domain.repository import com.weeth.domain.penalty.domain.entity.Penalty -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.user.domain.entity.Cardinal import com.weeth.domain.user.domain.entity.User import org.springframework.data.jpa.repository.JpaRepository From 47e7915a4a057a513e8f43f22cfc32d99864ad61 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 23:40:31 +0900 Subject: [PATCH 18/32] =?UTF-8?q?refactor:=20Penalty=20DTO=20=EA=B0=9C?= =?UTF-8?q?=EB=B3=84=20=ED=8C=8C=EC=9D=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../penalty/application/dto/PenaltyDTO.kt | 43 ------------------- .../dto/request/SavePenaltyRequest.kt | 12 ++++++ .../dto/request/UpdatePenaltyRequest.kt | 9 ++++ .../dto/response/PenaltyByCardinalResponse.kt | 6 +++ .../dto/response/PenaltyDetailResponse.kt | 12 ++++++ .../dto/response/PenaltyResponse.kt | 10 +++++ 6 files changed, 49 insertions(+), 43 deletions(-) delete mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt deleted file mode 100644 index ed24d437..00000000 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/PenaltyDTO.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.weeth.domain.penalty.application.dto - -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType -import jakarta.validation.constraints.NotNull -import java.time.LocalDateTime - -class PenaltyDTO { - data class Save( - @field:NotNull - val userId: Long, - @field:NotNull - val penaltyType: PenaltyType, - val penaltyDescription: String?, - ) - - data class Update( - @field:NotNull - val penaltyId: Long, - val penaltyDescription: String?, - ) - - data class ResponseAll( - val cardinal: Int?, - val responses: List, - ) - - data class Response( - val userId: Long?, - val penaltyCount: Int?, - val warningCount: Int?, - val name: String?, - val cardinals: List, - val penalties: List, - ) - - data class Penalties( - val penaltyId: Long?, - val penaltyType: PenaltyType?, - val cardinal: Int?, - val penaltyDescription: String?, - val time: LocalDateTime?, - ) -} diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt new file mode 100644 index 00000000..69c68526 --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt @@ -0,0 +1,12 @@ +package com.weeth.domain.penalty.application.dto.request + +import com.weeth.domain.penalty.domain.enums.PenaltyType +import jakarta.validation.constraints.NotNull + +data class SavePenaltyRequest( + @field:NotNull + val userId: Long, + @field:NotNull + val penaltyType: PenaltyType, + val penaltyDescription: String?, +) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt new file mode 100644 index 00000000..28e1304a --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt @@ -0,0 +1,9 @@ +package com.weeth.domain.penalty.application.dto.request + +import jakarta.validation.constraints.NotNull + +data class UpdatePenaltyRequest( + @field:NotNull + val penaltyId: Long, + val penaltyDescription: String?, +) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt new file mode 100644 index 00000000..59c0d9a2 --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt @@ -0,0 +1,6 @@ +package com.weeth.domain.penalty.application.dto.response + +data class PenaltyByCardinalResponse( + val cardinal: Int?, + val responses: List, +) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt new file mode 100644 index 00000000..64993000 --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt @@ -0,0 +1,12 @@ +package com.weeth.domain.penalty.application.dto.response + +import com.weeth.domain.penalty.domain.enums.PenaltyType +import java.time.LocalDateTime + +data class PenaltyDetailResponse( + val penaltyId: Long?, + val penaltyType: PenaltyType?, + val cardinal: Int?, + val penaltyDescription: String?, + val time: LocalDateTime?, +) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt new file mode 100644 index 00000000..509d50f1 --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt @@ -0,0 +1,10 @@ +package com.weeth.domain.penalty.application.dto.response + +data class PenaltyResponse( + val userId: Long?, + val penaltyCount: Int?, + val warningCount: Int?, + val name: String?, + val cardinals: List, + val penalties: List, +) From dce510ac5961ed05f3bfc80a4feaaaae2be626d5 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 23:40:54 +0900 Subject: [PATCH 19/32] =?UTF-8?q?refactor:=20Penalty=20usecase=20command/q?= =?UTF-8?q?uery=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/usecase/PenaltyUsecase.kt | 15 -- .../application/usecase/PenaltyUsecaseImpl.kt | 152 ------------------ .../usecase/command/DeletePenaltyUseCase.kt | 55 +++++++ .../usecase/command/SavePenaltyUseCase.kt | 51 ++++++ .../usecase/command/UpdatePenaltyUseCase.kt | 24 +++ .../usecase/query/GetPenaltyQueryService.kt | 64 ++++++++ 6 files changed, 194 insertions(+), 167 deletions(-) delete mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt delete mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt create mode 100644 src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt deleted file mode 100644 index 26ed997b..00000000 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.weeth.domain.penalty.application.usecase - -import com.weeth.domain.penalty.application.dto.PenaltyDTO - -interface PenaltyUsecase { - fun save(dto: PenaltyDTO.Save) - - fun update(dto: PenaltyDTO.Update) - - fun findAll(cardinalNumber: Int?): List - - fun find(userId: Long): PenaltyDTO.Response - - fun delete(penaltyId: Long) -} diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt deleted file mode 100644 index 6ac53b9e..00000000 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/PenaltyUsecaseImpl.kt +++ /dev/null @@ -1,152 +0,0 @@ -package com.weeth.domain.penalty.application.usecase - -import com.weeth.domain.penalty.application.dto.PenaltyDTO -import com.weeth.domain.penalty.application.exception.AutoPenaltyDeleteNotAllowedException -import com.weeth.domain.penalty.application.exception.PenaltyNotFoundException -import com.weeth.domain.penalty.application.mapper.PenaltyMapper -import com.weeth.domain.penalty.domain.entity.Penalty -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType -import com.weeth.domain.penalty.domain.repository.PenaltyRepository -import com.weeth.domain.user.domain.service.CardinalGetService -import com.weeth.domain.user.domain.service.UserCardinalGetService -import com.weeth.domain.user.domain.service.UserGetService -import org.springframework.data.repository.findByIdOrNull -import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Transactional - -@Service -class PenaltyUsecaseImpl( - private val penaltyRepository: PenaltyRepository, - private val userGetService: UserGetService, - private val userCardinalGetService: UserCardinalGetService, - private val cardinalGetService: CardinalGetService, - private val mapper: PenaltyMapper, -) : PenaltyUsecase { - companion object { - private const val AUTO_PENALTY_DESCRIPTION = "누적경고 %d회" - } - - @Transactional - override fun save(dto: PenaltyDTO.Save) { - val user = userGetService.find(dto.userId) - val cardinal = userCardinalGetService.getCurrentCardinal(user) - - val penalty = mapper.fromPenaltyDto(dto, user, cardinal) - penaltyRepository.save(penalty) - - when (penalty.penaltyType) { - PenaltyType.PENALTY -> { - user.incrementPenaltyCount() - } - - PenaltyType.WARNING -> { - user.incrementWarningCount() - - val warningCount = user.warningCount - if (warningCount % 2 == 0) { - val description = AUTO_PENALTY_DESCRIPTION.format(warningCount) - val autoPenalty = mapper.toAutoPenalty(description, user, cardinal, PenaltyType.AUTO_PENALTY) - penaltyRepository.save(autoPenalty) - user.incrementPenaltyCount() - } - } - - else -> {} - } - } - - @Transactional - override fun update(dto: PenaltyDTO.Update) { - val penalty = - penaltyRepository.findByIdOrNull(dto.penaltyId) - ?: throw PenaltyNotFoundException() - - if (!dto.penaltyDescription.isNullOrBlank()) { - penalty.update(dto.penaltyDescription) - } - } - - // TODO: 쿼리 최적화 필요 - @Transactional(readOnly = true) - override fun findAll(cardinalNumber: Int?): List { - val cardinals = - if (cardinalNumber == null) { - cardinalGetService.findAllCardinalNumberDesc() - } else { - listOf(cardinalGetService.findByAdminSide(cardinalNumber)) - } - - return cardinals.map { cardinal -> - val penalties = penaltyRepository.findByCardinalIdOrderByIdDesc(cardinal.id) - - val responses = - penalties - .groupBy { it.user.id } - .entries - .map { (userId, userPenalties) -> toPenaltyDto(userId, userPenalties) } - .sortedBy { it.userId } - - mapper.toResponseAll(cardinal.cardinalNumber, responses) - } - } - - @Transactional(readOnly = true) - override fun find(userId: Long): PenaltyDTO.Response { - val user = userGetService.find(userId) - val currentCardinal = userCardinalGetService.getCurrentCardinal(user) - val penalties = penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, currentCardinal.id) - - return toPenaltyDto(userId, penalties) - } - - @Transactional - override fun delete(penaltyId: Long) { - val penalty = - penaltyRepository.findByIdOrNull(penaltyId) - ?: throw PenaltyNotFoundException() - - if (penalty.penaltyType == PenaltyType.AUTO_PENALTY) { - throw AutoPenaltyDeleteNotAllowedException() - } - - val user = penalty.user - - when (penalty.penaltyType) { - PenaltyType.PENALTY -> { - user.decrementPenaltyCount() - } - - PenaltyType.WARNING -> { - if (user.warningCount % 2 == 0) { - val relatedAutoPenalty = - penaltyRepository - .findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( - penalty.user, - penalty.cardinal, - PenaltyType.AUTO_PENALTY, - penalty.createdAt, - ) - if (relatedAutoPenalty != null) { - penaltyRepository.deleteById(relatedAutoPenalty.id) - } - user.decrementPenaltyCount() - } - user.decrementWarningCount() - } - - else -> {} - } - - penaltyRepository.deleteById(penaltyId) - } - - private fun toPenaltyDto( - userId: Long, - penalties: List, - ): PenaltyDTO.Response { - val user = userGetService.find(userId) - val userCardinals = userCardinalGetService.getUserCardinals(user) - val penaltyDTOs = penalties.map(mapper::toPenalties) - return mapper.toPenaltyDto(user, penaltyDTOs, userCardinals) - } -} diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt new file mode 100644 index 00000000..e8fa1fa4 --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt @@ -0,0 +1,55 @@ +package com.weeth.domain.penalty.application.usecase.command + +import com.weeth.domain.penalty.application.exception.AutoPenaltyDeleteNotAllowedException +import com.weeth.domain.penalty.application.exception.PenaltyNotFoundException +import com.weeth.domain.penalty.domain.enums.PenaltyType +import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class DeletePenaltyUseCase( + private val penaltyRepository: PenaltyRepository, +) { + @Transactional + fun execute(penaltyId: Long) { + val penalty = + penaltyRepository.findByIdOrNull(penaltyId) + ?: throw PenaltyNotFoundException() + + if (penalty.penaltyType == PenaltyType.AUTO_PENALTY) { + throw AutoPenaltyDeleteNotAllowedException() + } + + val user = penalty.user + + when (penalty.penaltyType) { + PenaltyType.PENALTY -> { + user.decrementPenaltyCount() + } + + PenaltyType.WARNING -> { + if (user.warningCount % 2 == 0) { + val relatedAutoPenalty = + penaltyRepository + .findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( + penalty.user, + penalty.cardinal, + PenaltyType.AUTO_PENALTY, + penalty.createdAt, + ) + if (relatedAutoPenalty != null) { + penaltyRepository.deleteById(relatedAutoPenalty.id) + } + user.decrementPenaltyCount() + } + user.decrementWarningCount() + } + + else -> {} + } + + penaltyRepository.deleteById(penaltyId) + } +} diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt new file mode 100644 index 00000000..586fb60c --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt @@ -0,0 +1,51 @@ +package com.weeth.domain.penalty.application.usecase.command + +import com.weeth.domain.penalty.application.dto.request.SavePenaltyRequest +import com.weeth.domain.penalty.application.mapper.PenaltyMapper +import com.weeth.domain.penalty.domain.enums.PenaltyType +import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.domain.service.UserCardinalGetService +import com.weeth.domain.user.domain.service.UserGetService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class SavePenaltyUseCase( + private val penaltyRepository: PenaltyRepository, + private val userGetService: UserGetService, + private val userCardinalGetService: UserCardinalGetService, + private val mapper: PenaltyMapper, +) { + companion object { + private const val AUTO_PENALTY_DESCRIPTION = "누적경고 %d회" + } + + @Transactional + fun execute(request: SavePenaltyRequest) { + val user = userGetService.find(request.userId) + val cardinal = userCardinalGetService.getCurrentCardinal(user) + + val penalty = mapper.toEntity(request, user, cardinal) + penaltyRepository.save(penalty) + + when (penalty.penaltyType) { + PenaltyType.PENALTY -> { + user.incrementPenaltyCount() + } + + PenaltyType.WARNING -> { + user.incrementWarningCount() + + val warningCount = user.warningCount + if (warningCount % 2 == 0) { + val description = AUTO_PENALTY_DESCRIPTION.format(warningCount) + val autoPenalty = mapper.toAutoPenalty(description, user, cardinal, PenaltyType.AUTO_PENALTY) + penaltyRepository.save(autoPenalty) + user.incrementPenaltyCount() + } + } + + else -> {} + } + } +} diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt new file mode 100644 index 00000000..51565262 --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt @@ -0,0 +1,24 @@ +package com.weeth.domain.penalty.application.usecase.command + +import com.weeth.domain.penalty.application.dto.request.UpdatePenaltyRequest +import com.weeth.domain.penalty.application.exception.PenaltyNotFoundException +import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class UpdatePenaltyUseCase( + private val penaltyRepository: PenaltyRepository, +) { + @Transactional + fun execute(request: UpdatePenaltyRequest) { + val penalty = + penaltyRepository.findByIdOrNull(request.penaltyId) + ?: throw PenaltyNotFoundException() + + if (!request.penaltyDescription.isNullOrBlank()) { + penalty.update(request.penaltyDescription) + } + } +} diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt new file mode 100644 index 00000000..17a382ab --- /dev/null +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt @@ -0,0 +1,64 @@ +package com.weeth.domain.penalty.application.usecase.query + +import com.weeth.domain.penalty.application.dto.response.PenaltyByCardinalResponse +import com.weeth.domain.penalty.application.dto.response.PenaltyResponse +import com.weeth.domain.penalty.application.mapper.PenaltyMapper +import com.weeth.domain.penalty.domain.entity.Penalty +import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.domain.service.CardinalGetService +import com.weeth.domain.user.domain.service.UserCardinalGetService +import com.weeth.domain.user.domain.service.UserGetService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class GetPenaltyQueryService( + private val penaltyRepository: PenaltyRepository, + private val userGetService: UserGetService, + private val userCardinalGetService: UserCardinalGetService, + private val cardinalGetService: CardinalGetService, + private val mapper: PenaltyMapper, +) { + // TODO: 쿼리 최적화 필요 + @Transactional(readOnly = true) + fun findAll(cardinalNumber: Int?): List { + val cardinals = + if (cardinalNumber == null) { + cardinalGetService.findAllCardinalNumberDesc() + } else { + listOf(cardinalGetService.findByAdminSide(cardinalNumber)) + } + + return cardinals.map { cardinal -> + val penalties = penaltyRepository.findByCardinalIdOrderByIdDesc(cardinal.id) + + val responses = + penalties + .groupBy { it.user.id } + .entries + .map { (userId, userPenalties) -> toPenaltyResponse(userId, userPenalties) } + .sortedBy { it.userId } + + mapper.toByCardinalResponse(cardinal.cardinalNumber, responses) + } + } + + @Transactional(readOnly = true) + fun find(userId: Long): PenaltyResponse { + val user = userGetService.find(userId) + val currentCardinal = userCardinalGetService.getCurrentCardinal(user) + val penalties = penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, currentCardinal.id) + + return toPenaltyResponse(userId, penalties) + } + + private fun toPenaltyResponse( + userId: Long, + penalties: List, + ): PenaltyResponse { + val user = userGetService.find(userId) + val userCardinals = userCardinalGetService.getUserCardinals(user) + val penaltyDetails = penalties.map(mapper::toDetailResponse) + return mapper.toResponse(user, penaltyDetails, userCardinals) + } +} From 1e3830989f3a8af6a5f88a3ca45e16bf34bec6cc Mon Sep 17 00:00:00 2001 From: soo0711 Date: Wed, 18 Feb 2026 23:41:54 +0900 Subject: [PATCH 20/32] =?UTF-8?q?refactor:=20Penalty=20mapper,=20controlle?= =?UTF-8?q?r=20=EC=83=88=20=EA=B5=AC=EC=A1=B0=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/PenaltyMapper.kt | 35 ++++++++++--------- .../presentation/PenaltyAdminController.kt | 28 +++++++++------ .../presentation/PenaltyUserController.kt | 10 +++--- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt index 6dff26e7..11d2744b 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt @@ -1,8 +1,11 @@ package com.weeth.domain.penalty.application.mapper -import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.application.dto.request.SavePenaltyRequest +import com.weeth.domain.penalty.application.dto.response.PenaltyByCardinalResponse +import com.weeth.domain.penalty.application.dto.response.PenaltyDetailResponse +import com.weeth.domain.penalty.application.dto.response.PenaltyResponse import com.weeth.domain.penalty.domain.entity.Penalty -import com.weeth.domain.penalty.domain.entity.enums.PenaltyType +import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.user.domain.entity.Cardinal import com.weeth.domain.user.domain.entity.User import com.weeth.domain.user.domain.entity.UserCardinal @@ -10,16 +13,16 @@ import org.springframework.stereotype.Component @Component class PenaltyMapper { - fun fromPenaltyDto( - dto: PenaltyDTO.Save, + fun toEntity( + request: SavePenaltyRequest, user: User, cardinal: Cardinal, ): Penalty = Penalty( user = user, cardinal = cardinal, - penaltyType = dto.penaltyType, - penaltyDescription = dto.penaltyDescription ?: "", + penaltyType = request.penaltyType, + penaltyDescription = request.penaltyDescription ?: "", ) fun toAutoPenalty( @@ -35,12 +38,12 @@ class PenaltyMapper { penaltyDescription = penaltyDescription, ) - fun toPenaltyDto( + fun toResponse( user: User, - penalties: List, + penalties: List, userCardinals: List, - ): PenaltyDTO.Response = - PenaltyDTO.Response( + ): PenaltyResponse = + PenaltyResponse( userId = user.id, penaltyCount = null, warningCount = null, @@ -49,8 +52,8 @@ class PenaltyMapper { penalties = penalties, ) - fun toPenalties(penalty: Penalty): PenaltyDTO.Penalties = - PenaltyDTO.Penalties( + fun toDetailResponse(penalty: Penalty): PenaltyDetailResponse = + PenaltyDetailResponse( penaltyId = penalty.id, penaltyType = penalty.penaltyType, cardinal = penalty.cardinal?.cardinalNumber, @@ -58,11 +61,11 @@ class PenaltyMapper { time = penalty.modifiedAt, ) - fun toResponseAll( + fun toByCardinalResponse( cardinal: Int?, - responses: List, - ): PenaltyDTO.ResponseAll = - PenaltyDTO.ResponseAll( + responses: List, + ): PenaltyByCardinalResponse = + PenaltyByCardinalResponse( cardinal = cardinal, responses = responses, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt index c3f7ac5f..e5d5f18b 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt @@ -1,8 +1,13 @@ package com.weeth.domain.penalty.presentation -import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.application.dto.request.SavePenaltyRequest +import com.weeth.domain.penalty.application.dto.request.UpdatePenaltyRequest +import com.weeth.domain.penalty.application.dto.response.PenaltyByCardinalResponse import com.weeth.domain.penalty.application.exception.PenaltyErrorCode -import com.weeth.domain.penalty.application.usecase.PenaltyUsecase +import com.weeth.domain.penalty.application.usecase.command.DeletePenaltyUseCase +import com.weeth.domain.penalty.application.usecase.command.SavePenaltyUseCase +import com.weeth.domain.penalty.application.usecase.command.UpdatePenaltyUseCase +import com.weeth.domain.penalty.application.usecase.query.GetPenaltyQueryService import com.weeth.global.common.exception.ApiErrorCodeExample import com.weeth.global.common.response.CommonResponse import io.swagger.v3.oas.annotations.Operation @@ -22,23 +27,26 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping("/api/v1/admin/penalties") @ApiErrorCodeExample(PenaltyErrorCode::class) class PenaltyAdminController( - private val penaltyUsecase: PenaltyUsecase, + private val savePenaltyUseCase: SavePenaltyUseCase, + private val updatePenaltyUseCase: UpdatePenaltyUseCase, + private val deletePenaltyUseCase: DeletePenaltyUseCase, + private val getPenaltyQueryService: GetPenaltyQueryService, ) { @PostMapping @Operation(summary = "패널티 부여") fun assignPenalty( - @Valid @RequestBody dto: PenaltyDTO.Save, + @Valid @RequestBody request: SavePenaltyRequest, ): CommonResponse { - penaltyUsecase.save(dto) + savePenaltyUseCase.execute(request) return CommonResponse.success(PenaltyResponseCode.PENALTY_ASSIGN_SUCCESS) } @PatchMapping @Operation(summary = "패널티 수정") fun update( - @Valid @RequestBody dto: PenaltyDTO.Update, + @Valid @RequestBody request: UpdatePenaltyRequest, ): CommonResponse { - penaltyUsecase.update(dto) + updatePenaltyUseCase.execute(request) return CommonResponse.success(PenaltyResponseCode.PENALTY_UPDATE_SUCCESS) } @@ -46,15 +54,15 @@ class PenaltyAdminController( @Operation(summary = "전체 패널티 조회") fun findAll( @RequestParam(required = false) cardinal: Int?, - ): CommonResponse> = - CommonResponse.success(PenaltyResponseCode.PENALTY_FIND_ALL_SUCCESS, penaltyUsecase.findAll(cardinal)) + ): CommonResponse> = + CommonResponse.success(PenaltyResponseCode.PENALTY_FIND_ALL_SUCCESS, getPenaltyQueryService.findAll(cardinal)) @DeleteMapping @Operation(summary = "패널티 삭제") fun delete( @RequestParam penaltyId: Long, ): CommonResponse { - penaltyUsecase.delete(penaltyId) + deletePenaltyUseCase.execute(penaltyId) return CommonResponse.success(PenaltyResponseCode.PENALTY_DELETE_SUCCESS) } } diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt index eaa45a57..82018d03 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt @@ -1,8 +1,8 @@ package com.weeth.domain.penalty.presentation -import com.weeth.domain.penalty.application.dto.PenaltyDTO +import com.weeth.domain.penalty.application.dto.response.PenaltyResponse import com.weeth.domain.penalty.application.exception.PenaltyErrorCode -import com.weeth.domain.penalty.application.usecase.PenaltyUsecase +import com.weeth.domain.penalty.application.usecase.query.GetPenaltyQueryService import com.weeth.global.auth.annotation.CurrentUser import com.weeth.global.common.exception.ApiErrorCodeExample import com.weeth.global.common.response.CommonResponse @@ -18,12 +18,12 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping("/api/v1/penalties") @ApiErrorCodeExample(PenaltyErrorCode::class) class PenaltyUserController( - private val penaltyUsecase: PenaltyUsecase, + private val getPenaltyQueryService: GetPenaltyQueryService, ) { @GetMapping @Operation(summary = "본인 패널티 조회") fun findAllPenalties( @Parameter(hidden = true) @CurrentUser userId: Long, - ): CommonResponse = - CommonResponse.success(PenaltyResponseCode.PENALTY_USER_FIND_SUCCESS, penaltyUsecase.find(userId)) + ): CommonResponse = + CommonResponse.success(PenaltyResponseCode.PENALTY_USER_FIND_SUCCESS, getPenaltyQueryService.find(userId)) } From 174beff996b30291539c756d3a011a78ff36bb1a Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 00:06:12 +0900 Subject: [PATCH 21/32] =?UTF-8?q?refactor:=20GetPenaltyQueryService=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20N+1=20=EC=BF=BC=EB=A6=AC=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/usecase/query/GetPenaltyQueryService.kt | 9 ++++----- .../penalty/domain/repository/PenaltyRepository.kt | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt index 17a382ab..41c91b4c 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt @@ -5,6 +5,7 @@ import com.weeth.domain.penalty.application.dto.response.PenaltyResponse import com.weeth.domain.penalty.application.mapper.PenaltyMapper import com.weeth.domain.penalty.domain.entity.Penalty import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.domain.entity.User import com.weeth.domain.user.domain.service.CardinalGetService import com.weeth.domain.user.domain.service.UserCardinalGetService import com.weeth.domain.user.domain.service.UserGetService @@ -19,7 +20,6 @@ class GetPenaltyQueryService( private val cardinalGetService: CardinalGetService, private val mapper: PenaltyMapper, ) { - // TODO: 쿼리 최적화 필요 @Transactional(readOnly = true) fun findAll(cardinalNumber: Int?): List { val cardinals = @@ -36,7 +36,7 @@ class GetPenaltyQueryService( penalties .groupBy { it.user.id } .entries - .map { (userId, userPenalties) -> toPenaltyResponse(userId, userPenalties) } + .map { (_, userPenalties) -> toPenaltyResponse(userPenalties.first().user, userPenalties) } .sortedBy { it.userId } mapper.toByCardinalResponse(cardinal.cardinalNumber, responses) @@ -49,14 +49,13 @@ class GetPenaltyQueryService( val currentCardinal = userCardinalGetService.getCurrentCardinal(user) val penalties = penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, currentCardinal.id) - return toPenaltyResponse(userId, penalties) + return toPenaltyResponse(user, penalties) } private fun toPenaltyResponse( - userId: Long, + user: User, penalties: List, ): PenaltyResponse { - val user = userGetService.find(userId) val userCardinals = userCardinalGetService.getUserCardinals(user) val penaltyDetails = penalties.map(mapper::toDetailResponse) return mapper.toResponse(user, penaltyDetails, userCardinals) diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt index 5d600857..445a2bde 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt @@ -5,9 +5,11 @@ import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.user.domain.entity.Cardinal import com.weeth.domain.user.domain.entity.User import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query import java.time.LocalDateTime interface PenaltyRepository : JpaRepository { + @Query("SELECT p FROM Penalty p JOIN FETCH p.cardinal WHERE p.user.id = :userId AND p.cardinal.id = :cardinalId ORDER BY p.id DESC") fun findByUserIdAndCardinalIdOrderByIdDesc( userId: Long, cardinalId: Long, @@ -20,5 +22,6 @@ interface PenaltyRepository : JpaRepository { createdAt: LocalDateTime, ): Penalty? + @Query("SELECT p FROM Penalty p JOIN FETCH p.user JOIN FETCH p.cardinal WHERE p.cardinal.id = :cardinalId ORDER BY p.id DESC") fun findByCardinalIdOrderByIdDesc(cardinalId: Long): List } From f9bda2304bbe21f510e8439f2e607f0fd7196f79 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 00:21:50 +0900 Subject: [PATCH 22/32] =?UTF-8?q?refactor:=20Penalty=20=EC=B9=B4=EC=9A=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20User=20=EB=B9=84?= =?UTF-8?q?=EA=B4=80=EC=A0=81=20=EB=9D=BD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/domain/repository/UserRepository.java | 9 +++++++++ .../application/usecase/command/DeletePenaltyUseCase.kt | 8 +++++++- .../application/usecase/command/SavePenaltyUseCase.kt | 5 +++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/weeth/domain/user/domain/repository/UserRepository.java b/src/main/java/com/weeth/domain/user/domain/repository/UserRepository.java index ea074aae..586ce952 100644 --- a/src/main/java/com/weeth/domain/user/domain/repository/UserRepository.java +++ b/src/main/java/com/weeth/domain/user/domain/repository/UserRepository.java @@ -5,8 +5,12 @@ import com.weeth.domain.user.domain.entity.enums.Status; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import jakarta.persistence.LockModeType; +import jakarta.persistence.QueryHint; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.jpa.repository.QueryHints; import org.springframework.data.repository.query.Param; import java.util.List; @@ -14,6 +18,11 @@ public interface UserRepository extends JpaRepository { + @Lock(LockModeType.PESSIMISTIC_WRITE) + @QueryHints(@QueryHint(name = "jakarta.persistence.lock.timeout", value = "2000")) + @Query("SELECT u FROM User u WHERE u.id = :id") + Optional findByIdWithLock(@Param("id") Long id); + Optional findByEmail(String email); Optional findByKakaoId(long kakaoId); diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt index e8fa1fa4..8608b8b4 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt @@ -4,6 +4,8 @@ import com.weeth.domain.penalty.application.exception.AutoPenaltyDeleteNotAllowe import com.weeth.domain.penalty.application.exception.PenaltyNotFoundException import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.application.exception.UserNotFoundException +import com.weeth.domain.user.domain.repository.UserRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -11,6 +13,7 @@ import org.springframework.transaction.annotation.Transactional @Service class DeletePenaltyUseCase( private val penaltyRepository: PenaltyRepository, + private val userRepository: UserRepository, ) { @Transactional fun execute(penaltyId: Long) { @@ -22,7 +25,10 @@ class DeletePenaltyUseCase( throw AutoPenaltyDeleteNotAllowedException() } - val user = penalty.user + val user = + userRepository + .findByIdWithLock(penalty.user.id) + .orElseThrow { UserNotFoundException() } when (penalty.penaltyType) { PenaltyType.PENALTY -> { diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt index 586fb60c..609693e0 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt @@ -4,6 +4,7 @@ import com.weeth.domain.penalty.application.dto.request.SavePenaltyRequest import com.weeth.domain.penalty.application.mapper.PenaltyMapper import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.domain.repository.UserRepository import com.weeth.domain.user.domain.service.UserCardinalGetService import com.weeth.domain.user.domain.service.UserGetService import org.springframework.stereotype.Service @@ -12,6 +13,7 @@ import org.springframework.transaction.annotation.Transactional @Service class SavePenaltyUseCase( private val penaltyRepository: PenaltyRepository, + private val userRepository: UserRepository, private val userGetService: UserGetService, private val userCardinalGetService: UserCardinalGetService, private val mapper: PenaltyMapper, @@ -28,6 +30,9 @@ class SavePenaltyUseCase( val penalty = mapper.toEntity(request, user, cardinal) penaltyRepository.save(penalty) + // 카운트 수정 직전에만 비관적 락 획득 + userRepository.findByIdWithLock(request.userId) + when (penalty.penaltyType) { PenaltyType.PENALTY -> { user.incrementPenaltyCount() From d1770cd2248eb9cbfef8f9c20ff3ec127ccbd307 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 00:42:00 +0900 Subject: [PATCH 23/32] =?UTF-8?q?fix:=20SavePenaltyUseCase=20=EB=B9=84?= =?UTF-8?q?=EA=B4=80=EC=A0=81=20=EB=9D=BD=20=EC=A0=95=ED=99=95=EC=84=B1=20?= =?UTF-8?q?=EC=9A=B0=EC=84=A0=EC=8B=9C=ED=95=98=EC=97=AC=20stale=20read=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/usecase/command/SavePenaltyUseCase.kt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt index 609693e0..b11a062d 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt @@ -4,9 +4,9 @@ import com.weeth.domain.penalty.application.dto.request.SavePenaltyRequest import com.weeth.domain.penalty.application.mapper.PenaltyMapper import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.penalty.domain.repository.PenaltyRepository +import com.weeth.domain.user.application.exception.UserNotFoundException import com.weeth.domain.user.domain.repository.UserRepository import com.weeth.domain.user.domain.service.UserCardinalGetService -import com.weeth.domain.user.domain.service.UserGetService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -14,7 +14,6 @@ import org.springframework.transaction.annotation.Transactional class SavePenaltyUseCase( private val penaltyRepository: PenaltyRepository, private val userRepository: UserRepository, - private val userGetService: UserGetService, private val userCardinalGetService: UserCardinalGetService, private val mapper: PenaltyMapper, ) { @@ -24,15 +23,15 @@ class SavePenaltyUseCase( @Transactional fun execute(request: SavePenaltyRequest) { - val user = userGetService.find(request.userId) + val user = + userRepository + .findByIdWithLock(request.userId) + .orElseThrow { UserNotFoundException() } val cardinal = userCardinalGetService.getCurrentCardinal(user) val penalty = mapper.toEntity(request, user, cardinal) penaltyRepository.save(penalty) - // 카운트 수정 직전에만 비관적 락 획득 - userRepository.findByIdWithLock(request.userId) - when (penalty.penaltyType) { PenaltyType.PENALTY -> { user.incrementPenaltyCount() From 5f8a3c27fffa124a8fd638caabe0c7bc14f6499b Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 00:46:48 +0900 Subject: [PATCH 24/32] =?UTF-8?q?refactor:=20GetPenaltyQueryService=20User?= =?UTF-8?q?Cardinal=20N+1=20=EC=BF=BC=EB=A6=AC=20=EB=B0=B0=EC=B9=98=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EB=A1=9C=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/query/GetPenaltyQueryService.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt index 41c91b4c..5cead662 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt @@ -6,6 +6,7 @@ import com.weeth.domain.penalty.application.mapper.PenaltyMapper import com.weeth.domain.penalty.domain.entity.Penalty import com.weeth.domain.penalty.domain.repository.PenaltyRepository import com.weeth.domain.user.domain.entity.User +import com.weeth.domain.user.domain.entity.UserCardinal import com.weeth.domain.user.domain.service.CardinalGetService import com.weeth.domain.user.domain.service.UserCardinalGetService import com.weeth.domain.user.domain.service.UserGetService @@ -31,13 +32,20 @@ class GetPenaltyQueryService( return cardinals.map { cardinal -> val penalties = penaltyRepository.findByCardinalIdOrderByIdDesc(cardinal.id) + val users = penalties.map { it.user }.distinct() + val userCardinalsMap = + userCardinalGetService + .findAll(users) + .groupBy { it.user.id } val responses = penalties .groupBy { it.user.id } .entries - .map { (_, userPenalties) -> toPenaltyResponse(userPenalties.first().user, userPenalties) } - .sortedBy { it.userId } + .map { (userId, userPenalties) -> + val userCardinals = userCardinalsMap[userId] ?: emptyList() + toPenaltyResponse(userPenalties.first().user, userPenalties, userCardinals) + }.sortedBy { it.userId } mapper.toByCardinalResponse(cardinal.cardinalNumber, responses) } @@ -48,15 +56,16 @@ class GetPenaltyQueryService( val user = userGetService.find(userId) val currentCardinal = userCardinalGetService.getCurrentCardinal(user) val penalties = penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, currentCardinal.id) + val userCardinals = userCardinalGetService.getUserCardinals(user) - return toPenaltyResponse(user, penalties) + return toPenaltyResponse(user, penalties, userCardinals) } private fun toPenaltyResponse( user: User, penalties: List, + userCardinals: List, ): PenaltyResponse { - val userCardinals = userCardinalGetService.getUserCardinals(user) val penaltyDetails = penalties.map(mapper::toDetailResponse) return mapper.toResponse(user, penaltyDetails, userCardinals) } From 277c0faf8f0cb5b98a3b8af190fa3dd5aba6e3d9 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 00:52:20 +0900 Subject: [PATCH 25/32] =?UTF-8?q?refactor:=20PenaltyRepository=20=EB=8F=99?= =?UTF-8?q?=EC=A0=81=20=EC=BF=BC=EB=A6=AC=EB=A5=BC=20=EB=AA=85=EC=8B=9C?= =?UTF-8?q?=EC=A0=81=20@Query=EB=A1=9C=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/command/DeletePenaltyUseCase.kt | 6 +++--- .../domain/repository/PenaltyRepository.kt | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt index 8608b8b4..e72f9ebf 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt @@ -39,9 +39,9 @@ class DeletePenaltyUseCase( if (user.warningCount % 2 == 0) { val relatedAutoPenalty = penaltyRepository - .findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( - penalty.user, - penalty.cardinal, + .findFirstAutoPenaltyAfter( + penalty.user.id, + penalty.cardinal.id, PenaltyType.AUTO_PENALTY, penalty.createdAt, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt index 445a2bde..ced4e272 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt @@ -2,8 +2,6 @@ package com.weeth.domain.penalty.domain.repository import com.weeth.domain.penalty.domain.entity.Penalty import com.weeth.domain.penalty.domain.enums.PenaltyType -import com.weeth.domain.user.domain.entity.Cardinal -import com.weeth.domain.user.domain.entity.User import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Query import java.time.LocalDateTime @@ -15,9 +13,18 @@ interface PenaltyRepository : JpaRepository { cardinalId: Long, ): List - fun findFirstByUserAndCardinalAndPenaltyTypeAndCreatedAtAfterOrderByCreatedAtAsc( - user: User, - cardinal: Cardinal, + @Query( + """ + SELECT p FROM Penalty p + WHERE p.user.id = :userId AND p.cardinal.id = :cardinalId + AND p.penaltyType = :penaltyType AND p.createdAt > :createdAt + ORDER BY p.createdAt ASC + LIMIT 1 + """, + ) + fun findFirstAutoPenaltyAfter( + userId: Long, + cardinalId: Long, penaltyType: PenaltyType, createdAt: LocalDateTime, ): Penalty? From 84f416fd187017cf8987c022954bbf3384f47d52 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 00:57:54 +0900 Subject: [PATCH 26/32] =?UTF-8?q?fix:=20PenaltyResponse=EC=97=90=20?= =?UTF-8?q?=ED=95=AD=EC=83=81=20null=20=EB=B0=98=ED=99=98=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=ED=95=84=EB=93=9C=EC=97=90=20=EC=8B=A4=EC=A0=9C=20?= =?UTF-8?q?=EA=B0=92=20=EB=A7=A4=ED=95=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../penalty/application/dto/response/PenaltyResponse.kt | 8 ++++---- .../domain/penalty/application/mapper/PenaltyMapper.kt | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt index 509d50f1..55e85139 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt @@ -1,10 +1,10 @@ package com.weeth.domain.penalty.application.dto.response data class PenaltyResponse( - val userId: Long?, - val penaltyCount: Int?, - val warningCount: Int?, - val name: String?, + val userId: Long, + val name: String, + val penaltyCount: Int, + val warningCount: Int, val cardinals: List, val penalties: List, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt index 11d2744b..6ce6f64e 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt @@ -45,9 +45,9 @@ class PenaltyMapper { ): PenaltyResponse = PenaltyResponse( userId = user.id, - penaltyCount = null, - warningCount = null, - name = null, + name = user.name, + penaltyCount = user.penaltyCount, + warningCount = user.warningCount, cardinals = userCardinals.map { it.cardinal.cardinalNumber }, penalties = penalties, ) From 680c098c27e70b12ccba6b3524d03fdedb9a9d82 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 01:03:34 +0900 Subject: [PATCH 27/32] =?UTF-8?q?refactor:=20Penalty=20UseCase=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=AA=85=20execute=EB=A5=BC=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=8F=99=EC=9E=91=EB=AA=85=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/usecase/command/DeletePenaltyUseCase.kt | 2 +- .../application/usecase/command/SavePenaltyUseCase.kt | 2 +- .../application/usecase/command/UpdatePenaltyUseCase.kt | 2 +- .../domain/penalty/presentation/PenaltyAdminController.kt | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt index e72f9ebf..4c193773 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt @@ -16,7 +16,7 @@ class DeletePenaltyUseCase( private val userRepository: UserRepository, ) { @Transactional - fun execute(penaltyId: Long) { + fun delete(penaltyId: Long) { val penalty = penaltyRepository.findByIdOrNull(penaltyId) ?: throw PenaltyNotFoundException() diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt index b11a062d..66c844fc 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt @@ -22,7 +22,7 @@ class SavePenaltyUseCase( } @Transactional - fun execute(request: SavePenaltyRequest) { + fun save(request: SavePenaltyRequest) { val user = userRepository .findByIdWithLock(request.userId) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt index 51565262..aa55fe2d 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/UpdatePenaltyUseCase.kt @@ -12,7 +12,7 @@ class UpdatePenaltyUseCase( private val penaltyRepository: PenaltyRepository, ) { @Transactional - fun execute(request: UpdatePenaltyRequest) { + fun update(request: UpdatePenaltyRequest) { val penalty = penaltyRepository.findByIdOrNull(request.penaltyId) ?: throw PenaltyNotFoundException() diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt index e5d5f18b..b450f2fe 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt @@ -37,7 +37,7 @@ class PenaltyAdminController( fun assignPenalty( @Valid @RequestBody request: SavePenaltyRequest, ): CommonResponse { - savePenaltyUseCase.execute(request) + savePenaltyUseCase.save(request) return CommonResponse.success(PenaltyResponseCode.PENALTY_ASSIGN_SUCCESS) } @@ -46,7 +46,7 @@ class PenaltyAdminController( fun update( @Valid @RequestBody request: UpdatePenaltyRequest, ): CommonResponse { - updatePenaltyUseCase.execute(request) + updatePenaltyUseCase.update(request) return CommonResponse.success(PenaltyResponseCode.PENALTY_UPDATE_SUCCESS) } @@ -62,7 +62,7 @@ class PenaltyAdminController( fun delete( @RequestParam penaltyId: Long, ): CommonResponse { - deletePenaltyUseCase.execute(penaltyId) + deletePenaltyUseCase.delete(penaltyId) return CommonResponse.success(PenaltyResponseCode.PENALTY_DELETE_SUCCESS) } } From 2ae0b68153c9171cc4458384ed00f867a0341a3b Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 01:08:26 +0900 Subject: [PATCH 28/32] =?UTF-8?q?refactor:=20Penalty=20DTO=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20nullable=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20Mapper=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/PenaltyDetailResponse.kt | 8 ++++---- .../domain/penalty/application/mapper/PenaltyMapper.kt | 3 +-- .../application/usecase/command/SavePenaltyUseCase.kt | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt index 64993000..082795ee 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt @@ -4,9 +4,9 @@ import com.weeth.domain.penalty.domain.enums.PenaltyType import java.time.LocalDateTime data class PenaltyDetailResponse( - val penaltyId: Long?, - val penaltyType: PenaltyType?, + val penaltyId: Long, + val penaltyType: PenaltyType, val cardinal: Int?, - val penaltyDescription: String?, - val time: LocalDateTime?, + val penaltyDescription: String, + val time: LocalDateTime, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt index 6ce6f64e..f61feb63 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt @@ -29,12 +29,11 @@ class PenaltyMapper { penaltyDescription: String, user: User, cardinal: Cardinal, - penaltyType: PenaltyType, ): Penalty = Penalty( user = user, cardinal = cardinal, - penaltyType = penaltyType, + penaltyType = PenaltyType.AUTO_PENALTY, penaltyDescription = penaltyDescription, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt index 66c844fc..b9391d0a 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt @@ -43,7 +43,7 @@ class SavePenaltyUseCase( val warningCount = user.warningCount if (warningCount % 2 == 0) { val description = AUTO_PENALTY_DESCRIPTION.format(warningCount) - val autoPenalty = mapper.toAutoPenalty(description, user, cardinal, PenaltyType.AUTO_PENALTY) + val autoPenalty = mapper.toAutoPenalty(description, user, cardinal) penaltyRepository.save(autoPenalty) user.incrementPenaltyCount() } From e0f942e1e4108d27196f3034b3efbd1650757466 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 01:14:30 +0900 Subject: [PATCH 29/32] =?UTF-8?q?refactor:=20QueryService=20DTO=20?= =?UTF-8?q?=EC=A1=B0=ED=95=A9=20=EB=A1=9C=EC=A7=81=20Mapper=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EB=B0=8F=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/PenaltyMapper.kt | 4 ++-- .../usecase/query/GetPenaltyQueryService.kt | 20 ++++--------------- .../presentation/PenaltyAdminController.kt | 2 +- .../presentation/PenaltyUserController.kt | 2 +- 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt index f61feb63..9089ed74 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt @@ -39,7 +39,7 @@ class PenaltyMapper { fun toResponse( user: User, - penalties: List, + penalties: List, userCardinals: List, ): PenaltyResponse = PenaltyResponse( @@ -48,7 +48,7 @@ class PenaltyMapper { penaltyCount = user.penaltyCount, warningCount = user.warningCount, cardinals = userCardinals.map { it.cardinal.cardinalNumber }, - penalties = penalties, + penalties = penalties.map(::toDetailResponse), ) fun toDetailResponse(penalty: Penalty): PenaltyDetailResponse = diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt index 5cead662..e2483271 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt @@ -3,10 +3,7 @@ package com.weeth.domain.penalty.application.usecase.query import com.weeth.domain.penalty.application.dto.response.PenaltyByCardinalResponse import com.weeth.domain.penalty.application.dto.response.PenaltyResponse import com.weeth.domain.penalty.application.mapper.PenaltyMapper -import com.weeth.domain.penalty.domain.entity.Penalty import com.weeth.domain.penalty.domain.repository.PenaltyRepository -import com.weeth.domain.user.domain.entity.User -import com.weeth.domain.user.domain.entity.UserCardinal import com.weeth.domain.user.domain.service.CardinalGetService import com.weeth.domain.user.domain.service.UserCardinalGetService import com.weeth.domain.user.domain.service.UserGetService @@ -22,7 +19,7 @@ class GetPenaltyQueryService( private val mapper: PenaltyMapper, ) { @Transactional(readOnly = true) - fun findAll(cardinalNumber: Int?): List { + fun findAllByCardinal(cardinalNumber: Int?): List { val cardinals = if (cardinalNumber == null) { cardinalGetService.findAllCardinalNumberDesc() @@ -44,7 +41,7 @@ class GetPenaltyQueryService( .entries .map { (userId, userPenalties) -> val userCardinals = userCardinalsMap[userId] ?: emptyList() - toPenaltyResponse(userPenalties.first().user, userPenalties, userCardinals) + mapper.toResponse(userPenalties.first().user, userPenalties, userCardinals) }.sortedBy { it.userId } mapper.toByCardinalResponse(cardinal.cardinalNumber, responses) @@ -52,21 +49,12 @@ class GetPenaltyQueryService( } @Transactional(readOnly = true) - fun find(userId: Long): PenaltyResponse { + fun findByUser(userId: Long): PenaltyResponse { val user = userGetService.find(userId) val currentCardinal = userCardinalGetService.getCurrentCardinal(user) val penalties = penaltyRepository.findByUserIdAndCardinalIdOrderByIdDesc(userId, currentCardinal.id) val userCardinals = userCardinalGetService.getUserCardinals(user) - return toPenaltyResponse(user, penalties, userCardinals) - } - - private fun toPenaltyResponse( - user: User, - penalties: List, - userCardinals: List, - ): PenaltyResponse { - val penaltyDetails = penalties.map(mapper::toDetailResponse) - return mapper.toResponse(user, penaltyDetails, userCardinals) + return mapper.toResponse(user, penalties, userCardinals) } } diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt index b450f2fe..061dd1d6 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyAdminController.kt @@ -55,7 +55,7 @@ class PenaltyAdminController( fun findAll( @RequestParam(required = false) cardinal: Int?, ): CommonResponse> = - CommonResponse.success(PenaltyResponseCode.PENALTY_FIND_ALL_SUCCESS, getPenaltyQueryService.findAll(cardinal)) + CommonResponse.success(PenaltyResponseCode.PENALTY_FIND_ALL_SUCCESS, getPenaltyQueryService.findAllByCardinal(cardinal)) @DeleteMapping @Operation(summary = "패널티 삭제") diff --git a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt index 82018d03..965fe5f9 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/presentation/PenaltyUserController.kt @@ -25,5 +25,5 @@ class PenaltyUserController( fun findAllPenalties( @Parameter(hidden = true) @CurrentUser userId: Long, ): CommonResponse = - CommonResponse.success(PenaltyResponseCode.PENALTY_USER_FIND_SUCCESS, getPenaltyQueryService.find(userId)) + CommonResponse.success(PenaltyResponseCode.PENALTY_USER_FIND_SUCCESS, getPenaltyQueryService.findByUser(userId)) } From 4f8caee2b15ec94d21dce7df7b1dc586a47ccf07 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 01:20:49 +0900 Subject: [PATCH 30/32] =?UTF-8?q?style:=20Penalty=20DTO=EC=97=90=20Swagger?= =?UTF-8?q?=20@Schema=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../penalty/application/dto/request/SavePenaltyRequest.kt | 7 ++++--- .../application/dto/request/UpdatePenaltyRequest.kt | 5 +++-- .../application/dto/response/PenaltyByCardinalResponse.kt | 4 ++++ .../application/dto/response/PenaltyDetailResponse.kt | 6 ++++++ .../penalty/application/dto/response/PenaltyResponse.kt | 8 ++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt index 69c68526..5acd0f5b 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt @@ -1,12 +1,13 @@ package com.weeth.domain.penalty.application.dto.request import com.weeth.domain.penalty.domain.enums.PenaltyType -import jakarta.validation.constraints.NotNull +import io.swagger.v3.oas.annotations.media.Schema data class SavePenaltyRequest( - @field:NotNull + @field:Schema(description = "패널티 대상 사용자 ID", example = "1") val userId: Long, - @field:NotNull + @field:Schema(description = "패널티 유형", example = "WARNING") val penaltyType: PenaltyType, + @field:Schema(description = "패널티 사유", example = "정기모임 무단 불참") val penaltyDescription: String?, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt index 28e1304a..443c8d1e 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/request/UpdatePenaltyRequest.kt @@ -1,9 +1,10 @@ package com.weeth.domain.penalty.application.dto.request -import jakarta.validation.constraints.NotNull +import io.swagger.v3.oas.annotations.media.Schema data class UpdatePenaltyRequest( - @field:NotNull + @field:Schema(description = "수정할 패널티 ID", example = "1") val penaltyId: Long, + @field:Schema(description = "수정할 패널티 사유", example = "정기모임 무단 불참 (수정)") val penaltyDescription: String?, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt index 59c0d9a2..ec2353b6 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyByCardinalResponse.kt @@ -1,6 +1,10 @@ package com.weeth.domain.penalty.application.dto.response +import io.swagger.v3.oas.annotations.media.Schema + data class PenaltyByCardinalResponse( + @field:Schema(description = "기수 번호", example = "4") val cardinal: Int?, + @field:Schema(description = "해당 기수의 유저별 패널티 목록") val responses: List, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt index 082795ee..b6e1ab5e 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt @@ -1,12 +1,18 @@ package com.weeth.domain.penalty.application.dto.response import com.weeth.domain.penalty.domain.enums.PenaltyType +import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDateTime data class PenaltyDetailResponse( + @field:Schema(description = "패널티 ID", example = "1") val penaltyId: Long, + @field:Schema(description = "패널티 유형", example = "WARNING") val penaltyType: PenaltyType, + @field:Schema(description = "기수 번호", example = "4") val cardinal: Int?, + @field:Schema(description = "패널티 사유", example = "정기모임 무단 불참") val penaltyDescription: String, + @field:Schema(description = "최종 수정 시간", example = "2026-02-19T01:00:00") val time: LocalDateTime, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt index 55e85139..fa4a4b4e 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyResponse.kt @@ -1,10 +1,18 @@ package com.weeth.domain.penalty.application.dto.response +import io.swagger.v3.oas.annotations.media.Schema + data class PenaltyResponse( + @field:Schema(description = "사용자 ID", example = "1") val userId: Long, + @field:Schema(description = "사용자 이름", example = "홍길동") val name: String, + @field:Schema(description = "패널티 횟수", example = "2") val penaltyCount: Int, + @field:Schema(description = "경고 횟수", example = "3") val warningCount: Int, + @field:Schema(description = "소속 기수 목록", example = "[3, 4]") val cardinals: List, + @field:Schema(description = "패널티 상세 목록") val penalties: List, ) From 5c402268416d618111b0ea9a600f05471cae0411 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 01:35:01 +0900 Subject: [PATCH 31/32] =?UTF-8?q?refactor:=20Penalty=20=EC=BF=BC=EB=A6=AC?= =?UTF-8?q?=20=ED=91=9C=EC=A4=80=ED=99=94=20=EB=B0=8F=20LAZY=20fetch=20?= =?UTF-8?q?=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weeth/domain/penalty/application/mapper/PenaltyMapper.kt | 2 +- .../application/usecase/command/DeletePenaltyUseCase.kt | 4 +++- .../kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt | 5 +++-- .../domain/penalty/domain/repository/PenaltyRepository.kt | 5 +++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt index 9089ed74..f4929e52 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.kt @@ -55,7 +55,7 @@ class PenaltyMapper { PenaltyDetailResponse( penaltyId = penalty.id, penaltyType = penalty.penaltyType, - cardinal = penalty.cardinal?.cardinalNumber, + cardinal = penalty.cardinal.cardinalNumber, penaltyDescription = penalty.penaltyDescription, time = penalty.modifiedAt, ) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt index 4c193773..1cd077aa 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt @@ -6,6 +6,7 @@ import com.weeth.domain.penalty.domain.enums.PenaltyType import com.weeth.domain.penalty.domain.repository.PenaltyRepository import com.weeth.domain.user.application.exception.UserNotFoundException import com.weeth.domain.user.domain.repository.UserRepository +import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -44,7 +45,8 @@ class DeletePenaltyUseCase( penalty.cardinal.id, PenaltyType.AUTO_PENALTY, penalty.createdAt, - ) + Pageable.ofSize(1), + ).firstOrNull() if (relatedAutoPenalty != null) { penaltyRepository.deleteById(relatedAutoPenalty.id) } diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt index 77714533..25f0db0c 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.kt @@ -8,6 +8,7 @@ import jakarta.persistence.Column import jakarta.persistence.Entity import jakarta.persistence.EnumType import jakarta.persistence.Enumerated +import jakarta.persistence.FetchType import jakarta.persistence.GeneratedValue import jakarta.persistence.GenerationType import jakarta.persistence.Id @@ -16,10 +17,10 @@ import jakarta.persistence.ManyToOne @Entity class Penalty( - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") val user: User, - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "cardinal_id") val cardinal: Cardinal, @Enumerated(EnumType.STRING) diff --git a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt index ced4e272..0fb0a166 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/domain/repository/PenaltyRepository.kt @@ -2,6 +2,7 @@ package com.weeth.domain.penalty.domain.repository import com.weeth.domain.penalty.domain.entity.Penalty import com.weeth.domain.penalty.domain.enums.PenaltyType +import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Query import java.time.LocalDateTime @@ -19,7 +20,6 @@ interface PenaltyRepository : JpaRepository { WHERE p.user.id = :userId AND p.cardinal.id = :cardinalId AND p.penaltyType = :penaltyType AND p.createdAt > :createdAt ORDER BY p.createdAt ASC - LIMIT 1 """, ) fun findFirstAutoPenaltyAfter( @@ -27,7 +27,8 @@ interface PenaltyRepository : JpaRepository { cardinalId: Long, penaltyType: PenaltyType, createdAt: LocalDateTime, - ): Penalty? + pageable: Pageable, + ): List @Query("SELECT p FROM Penalty p JOIN FETCH p.user JOIN FETCH p.cardinal WHERE p.cardinal.id = :cardinalId ORDER BY p.id DESC") fun findByCardinalIdOrderByIdDesc(cardinalId: Long): List From 9597c523eef73647128a55c012e649e344ddc8f4 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Thu, 19 Feb 2026 11:28:33 +0900 Subject: [PATCH 32/32] =?UTF-8?q?refactor:=20QueryService=20@Transactional?= =?UTF-8?q?=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=A0=88=EB=B2=A8=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/usecase/query/GetPenaltyQueryService.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt index e2483271..cb842e2f 100644 --- a/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt +++ b/src/main/kotlin/com/weeth/domain/penalty/application/usecase/query/GetPenaltyQueryService.kt @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service +@Transactional(readOnly = true) class GetPenaltyQueryService( private val penaltyRepository: PenaltyRepository, private val userGetService: UserGetService, @@ -18,7 +19,6 @@ class GetPenaltyQueryService( private val cardinalGetService: CardinalGetService, private val mapper: PenaltyMapper, ) { - @Transactional(readOnly = true) fun findAllByCardinal(cardinalNumber: Int?): List { val cardinals = if (cardinalNumber == null) { @@ -48,7 +48,6 @@ class GetPenaltyQueryService( } } - @Transactional(readOnly = true) fun findByUser(userId: Long): PenaltyResponse { val user = userGetService.find(userId) val currentCardinal = userCardinalGetService.getCurrentCardinal(user)