diff --git a/nect-api/src/main/java/com/nect/api/domain/matching/controller/MatchingController.java b/nect-api/src/main/java/com/nect/api/domain/matching/controller/MatchingController.java index 68294091..d2d7bece 100644 --- a/nect-api/src/main/java/com/nect/api/domain/matching/controller/MatchingController.java +++ b/nect-api/src/main/java/com/nect/api/domain/matching/controller/MatchingController.java @@ -18,6 +18,8 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/matchings") @@ -136,4 +138,9 @@ public ApiResponse getProjectInfo( ){ return ApiResponse.ok(mainHomeFacade.getRecruitingProjectsDetails(projectId)); } + + @GetMapping("/notices") + public ApiResponse> getMatchingNotices(){ + return ApiResponse.ok(matchingService.getMatchingNotice()); + } } diff --git a/nect-api/src/main/java/com/nect/api/domain/matching/dto/MatchingResDto.java b/nect-api/src/main/java/com/nect/api/domain/matching/dto/MatchingResDto.java index 52ffe30c..87d4872d 100644 --- a/nect-api/src/main/java/com/nect/api/domain/matching/dto/MatchingResDto.java +++ b/nect-api/src/main/java/com/nect/api/domain/matching/dto/MatchingResDto.java @@ -69,4 +69,12 @@ public record ProjectSummary( LocalDateTime expiresAt, MatchingStatus status ){} + + @Builder + public record MatchingNoticeResDto( + Long noticeId, + String title, + String description, + Integer sortOrder + ){} } diff --git a/nect-api/src/main/java/com/nect/api/domain/matching/service/MatchingService.java b/nect-api/src/main/java/com/nect/api/domain/matching/service/MatchingService.java index 9849d1df..b2fbf2bc 100644 --- a/nect-api/src/main/java/com/nect/api/domain/matching/service/MatchingService.java +++ b/nect-api/src/main/java/com/nect/api/domain/matching/service/MatchingService.java @@ -10,12 +10,14 @@ import com.nect.api.domain.user.service.UserService; import com.nect.api.global.infra.S3Service; import com.nect.core.entity.matching.Matching; +import com.nect.core.entity.matching.MatchingNotice; import com.nect.core.entity.matching.enums.MatchingRejectReason; import com.nect.core.entity.matching.enums.MatchingRequestType; import com.nect.core.entity.matching.enums.MatchingStatus; import com.nect.core.entity.team.Project; import com.nect.core.entity.user.User; import com.nect.core.entity.user.enums.RoleField; +import com.nect.core.repository.matching.MatchingNoticeRepository; import com.nect.core.repository.matching.MatchingRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -34,6 +36,7 @@ public class MatchingService { private final ProjectService projectService; private final S3Service s3Service; private final ProjectTeamCommandService projectTeamCommandService; + private final MatchingNoticeRepository matchingNoticeRepository; public Matching createUserToProjectMatching( User requestUser, @@ -377,4 +380,18 @@ public MatchingResDto.MatchingListRes getReceivedTotalMatchingsByTarget(Long use .projectMatchings(projectSummaries) .build(); } + + public List getMatchingNotice() { + List notices = matchingNoticeRepository.findAllOrderBySortOrder(); + + return notices.stream() + .map(matchingNotice -> MatchingResDto.MatchingNoticeResDto.builder() + .noticeId(matchingNotice.getId()) + .title(matchingNotice.getTitle()) + .description(matchingNotice.getDescription()) + .sortOrder(matchingNotice.getSortOrder()) + .build() + ) + .toList(); + } } diff --git a/nect-api/src/test/java/com/nect/api/domain/matching/MatchingControllerTest.java b/nect-api/src/test/java/com/nect/api/domain/matching/MatchingControllerTest.java index 6657e417..20da2ab8 100644 --- a/nect-api/src/test/java/com/nect/api/domain/matching/MatchingControllerTest.java +++ b/nect-api/src/test/java/com/nect/api/domain/matching/MatchingControllerTest.java @@ -1372,4 +1372,62 @@ void getReceivedTotalMatchings() throws Exception { ) )); } + + @Test + void getMatchingNotices() throws Exception { + MatchingResDto.MatchingNoticeResDto notice1 = MatchingResDto.MatchingNoticeResDto.builder() + .noticeId(1L) + .title("대기 만료 시, 매칭이 자동 거절 처리") + .description(null) + .sortOrder(1) + .build(); + + MatchingResDto.MatchingNoticeResDto notice2 = MatchingResDto.MatchingNoticeResDto.builder() + .noticeId(2L) + .title("24시간 동안의 매칭 취소 / 거절 / 수락은 번복 불가") + .description(null) + .sortOrder(2) + .build(); + + MatchingResDto.MatchingNoticeResDto notice3 = MatchingResDto.MatchingNoticeResDto.builder() + .noticeId(3L) + .title("리더가 직접 보내는 요청은 파트당 최대 3명까지 가능 (24시간 동안)") + .description("리더는 24시간 동안 한 프로젝트의 파트당 최대 3명에게 매칭 요청을 직접 보낼 수 있습니다.\n" + + "이때, 유저가 보내오는 프로젝트 매칭 요청은 포함되지 않습니다.\n") + .sortOrder(3) + .build(); + + List notices = List.of(notice1, notice2, notice3); + + given(matchingService.getMatchingNotice()).willReturn(notices); + + mockMvc.perform(get("/api/v1/matchings/notices") + .header("Authorization", "Bearer AccessToken") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document("matching-get-notices", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + resource(ResourceSnippetParameters.builder() + .tag("Matching") + .summary("매칭 유의 사항 조회") + .description("매칭 관련 유의 사항을 조회합니다.") + .requestHeaders( + headerWithName("Authorization").description("액세스 토큰 (Bearer 스키마)") + ) + .responseFields( + fieldWithPath("status.statusCode").description("상태 코드"), + fieldWithPath("status.message").description("상태 메시지"), + fieldWithPath("status.description").optional().description("상태 설명"), + + fieldWithPath("body[]").description("공지 목록"), + fieldWithPath("body[].noticeId").description("공지 ID"), + fieldWithPath("body[].title").description("공지 제목"), + fieldWithPath("body[].description").optional().description("공지 내용"), + fieldWithPath("body[].sortOrder").description("정렬 순서") + ) + .build() + ) + )); + } } diff --git a/nect-core/src/main/java/com/nect/core/entity/matching/MatchingNotice.java b/nect-core/src/main/java/com/nect/core/entity/matching/MatchingNotice.java new file mode 100644 index 00000000..e60c7ae5 --- /dev/null +++ b/nect-core/src/main/java/com/nect/core/entity/matching/MatchingNotice.java @@ -0,0 +1,26 @@ +package com.nect.core.entity.matching; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "matching_notice") +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MatchingNotice { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String title; + + @Column(columnDefinition = "text") + private String description; + + @Column(name = "sort_order") + private Integer sortOrder; +} diff --git a/nect-core/src/main/java/com/nect/core/repository/matching/MatchingNoticeRepository.java b/nect-core/src/main/java/com/nect/core/repository/matching/MatchingNoticeRepository.java new file mode 100644 index 00000000..d09a616f --- /dev/null +++ b/nect-core/src/main/java/com/nect/core/repository/matching/MatchingNoticeRepository.java @@ -0,0 +1,19 @@ +package com.nect.core.repository.matching; + +import com.nect.core.entity.matching.MatchingNotice; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface MatchingNoticeRepository extends JpaRepository { + + @Query(""" + select mn + from MatchingNotice mn + order by mn.sortOrder asc + """) + List findAllOrderBySortOrder(); +}