From 6f1a89814f05b91707ad6f482e7a26914d5cef96 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 10 Nov 2025 22:14:25 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix=20:=20=EB=8F=99=EC=9D=BC=20=EB=A9=98?= =?UTF-8?q?=ED=86=A0=20=EB=A9=98=ED=8B=B0=20=EC=A4=91=EB=B3=B5=20=EC=8B=A0?= =?UTF-8?q?=EC=B2=AD=20=EB=B6=88=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20-=20UK=20=EC=A0=9C=EC=95=BD?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80=20-=20flyway=20script?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20-=20CustomException=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20Service=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20Test=20code=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solidconnection/common/exception/ErrorCode.java | 1 + .../solidconnection/mentor/domain/Mentoring.java | 8 ++++++++ .../mentor/service/MentoringCommandService.java | 8 +++++++- ...add_unique_constraint_to_mentor_id_mentee_id.sql | 3 +++ .../mentor/service/MentoringCommandServiceTest.java | 13 +++++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql diff --git a/src/main/java/com/example/solidconnection/common/exception/ErrorCode.java b/src/main/java/com/example/solidconnection/common/exception/ErrorCode.java index fae3c4980..17661fe2d 100644 --- a/src/main/java/com/example/solidconnection/common/exception/ErrorCode.java +++ b/src/main/java/com/example/solidconnection/common/exception/ErrorCode.java @@ -118,6 +118,7 @@ public enum ErrorCode { CHANNEL_SEQUENCE_NOT_UNIQUE(HttpStatus.BAD_REQUEST.value(), "채널의 순서가 중복되었습니다."), CHANNEL_REGISTRATION_LIMIT_EXCEEDED(HttpStatus.BAD_REQUEST.value(), "등록 가능한 채널 수를 초과하였습니다."), ALREADY_MENTOR(HttpStatus.BAD_REQUEST.value(), "이미 멘토로 등록된 사용자입니다."), + ALREADY_EXIST_MENTORING(HttpStatus.BAD_REQUEST.value(), "이미 신청된 멘티, 멘토입니다."), MENTORING_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "해당 멘토링 신청을 찾을 수 없습니다."), UNAUTHORIZED_MENTORING(HttpStatus.FORBIDDEN.value(), "멘토링 권한이 없습니다."), MENTORING_ALREADY_CONFIRMED(HttpStatus.BAD_REQUEST.value(), "이미 승인 또는 거절된 멘토링입니다."), diff --git a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java index a839d8122..6616b9814 100644 --- a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java +++ b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java @@ -13,6 +13,8 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import java.time.ZonedDateTime; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -27,6 +29,12 @@ @DynamicInsert @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "mentoring", uniqueConstraints = { + @UniqueConstraint( + name = "uk_mentoring_mentor_id_mentee_id", + columnNames = {"mentorId", "menteeId"} + ) +}) public class Mentoring extends BaseEntity { @Id diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java index 254323127..884526c1b 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java @@ -1,5 +1,6 @@ package com.example.solidconnection.mentor.service; +import static com.example.solidconnection.common.exception.ErrorCode.ALREADY_EXIST_MENTORING; import static com.example.solidconnection.common.exception.ErrorCode.MENTORING_ALREADY_CONFIRMED; import static com.example.solidconnection.common.exception.ErrorCode.MENTORING_NOT_FOUND; import static com.example.solidconnection.common.exception.ErrorCode.MENTOR_NOT_FOUND; @@ -30,8 +31,13 @@ public class MentoringCommandService { @Transactional public MentoringApplyResponse applyMentoring(long siteUserId, MentoringApplyRequest mentoringApplyRequest) { - Mentoring mentoring = new Mentoring(mentoringApplyRequest.mentorId(), siteUserId, VerifyStatus.PENDING); + long mentorId = mentoringApplyRequest.mentorId(); + + if (mentoringRepository.existsByMentorIdAndMenteeId(mentorId, siteUserId)) { + throw new CustomException(ALREADY_EXIST_MENTORING); + } + Mentoring mentoring = new Mentoring(mentoringApplyRequest.mentorId(), siteUserId, VerifyStatus.PENDING); return MentoringApplyResponse.from(mentoringRepository.save(mentoring)); } diff --git a/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql b/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql new file mode 100644 index 000000000..f71019b1d --- /dev/null +++ b/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql @@ -0,0 +1,3 @@ +ALTER TABLE mentoring +ADD CONSTRAINT uk_mentoring_mentor_id_mentee_id +UNIQUE (mentorId, menteeId); diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index 8c6a78468..002dfa6a5 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -1,5 +1,6 @@ package com.example.solidconnection.mentor.service; +import static com.example.solidconnection.common.exception.ErrorCode.ALREADY_EXIST_MENTORING; import static com.example.solidconnection.common.exception.ErrorCode.MENTORING_ALREADY_CONFIRMED; import static com.example.solidconnection.common.exception.ErrorCode.MENTORING_NOT_FOUND; import static com.example.solidconnection.common.exception.ErrorCode.UNAUTHORIZED_MENTORING; @@ -96,6 +97,18 @@ class 멘토링_신청_테스트 { () -> assertThat(mentoring.getVerifyStatus()).isEqualTo(VerifyStatus.PENDING) ); } + + @Test + void 동일_멘티_멘토끼리는_재신청되지않는다() { + // given + mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser.getId()); + MentoringApplyRequest request = new MentoringApplyRequest(mentor1.getId()); + + // when & then + assertThatThrownBy(() -> mentoringCommandService.applyMentoring(menteeUser.getId(), request)) + .isInstanceOf(CustomException.class) + .hasMessage(ALREADY_EXIST_MENTORING.getMessage()); + } } @Nested From f3ab378a090c27df8ef1a81246249c521b710b1b Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 10 Nov 2025 22:24:43 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix=20:=20column=EB=AA=85=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95=20-=20column=EB=AA=85=20camelCas?= =?UTF-8?q?e=20->=20snake=5Fcase=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 --- .../com/example/solidconnection/mentor/domain/Mentoring.java | 2 +- .../V37__add_unique_constraint_to_mentor_id_mentee_id.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java index 6616b9814..766d0dcb6 100644 --- a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java +++ b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java @@ -32,7 +32,7 @@ @Table(name = "mentoring", uniqueConstraints = { @UniqueConstraint( name = "uk_mentoring_mentor_id_mentee_id", - columnNames = {"mentorId", "menteeId"} + columnNames = {"mentor_id", "mentee_id"} ) }) public class Mentoring extends BaseEntity { diff --git a/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql b/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql index f71019b1d..98968fbb1 100644 --- a/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql +++ b/src/main/resources/db/migration/V37__add_unique_constraint_to_mentor_id_mentee_id.sql @@ -1,3 +1,3 @@ ALTER TABLE mentoring ADD CONSTRAINT uk_mentoring_mentor_id_mentee_id -UNIQUE (mentorId, menteeId); +UNIQUE (mentor_id, mentee_id); From 1dcdf6f6a4351a6aaccb23f2e26be43963c002b9 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Tue, 11 Nov 2025 01:20:04 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix=20:=20column=EB=AA=85=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95=20-=20column=EB=AA=85=20name?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solidconnection/mentor/domain/Mentoring.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java index 766d0dcb6..4dcae29bf 100644 --- a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java +++ b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java @@ -41,23 +41,23 @@ public class Mentoring extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column + @Column(name="confirmed_at") private ZonedDateTime confirmedAt; - @Column + @Column(name = "checked_at_by_mentor") private ZonedDateTime checkedAtByMentor; - @Column + @Column(name = "checked_at_by_mentee") private ZonedDateTime checkedAtByMentee; - @Column(nullable = false) + @Column(nullable = false, name="verify_status") @Enumerated(EnumType.STRING) private VerifyStatus verifyStatus = VerifyStatus.PENDING; - @Column + @Column(name = "mentor_id") private long mentorId; - @Column + @Column(name = "mentee_id") private long menteeId; public Mentoring(long mentorId, long menteeId, VerifyStatus verifyStatus) {