From db405cce680378620303530b7eb3f4e980d78a89 Mon Sep 17 00:00:00 2001 From: DOEKYONG Date: Mon, 14 Aug 2023 15:21:37 +0900 Subject: [PATCH] =?UTF-8?q?#80=20feat=20:=20issue=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EC=97=90=EC=84=9C=20=EC=9D=B4=EC=8A=88?= =?UTF-8?q?=EB=93=A4=20=EC=83=81=ED=83=9C=EB=B3=80=EA=B2=BD=20api=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/exception/ErrorCode.java | 7 ++-- .../issue/controller/IssueController.java | 9 +++++ .../issue/repository/IssueRepository.java | 33 +++++++++++++++++++ .../issue/service/IssueService.java | 18 ++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/be/issue/src/main/java/codesquad/issueTracker/global/exception/ErrorCode.java b/be/issue/src/main/java/codesquad/issueTracker/global/exception/ErrorCode.java index 2a516eb34..ad90994f4 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/global/exception/ErrorCode.java +++ b/be/issue/src/main/java/codesquad/issueTracker/global/exception/ErrorCode.java @@ -37,7 +37,7 @@ public enum ErrorCode implements StatusCode { ALREADY_DELETED_COMMENT(HttpStatus.BAD_REQUEST, "이미 삭제된 댓글입니다."), FAILED_CREATE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류로 인해 댓글 생성에 실패했습니다."), FAILED_UPDATE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류로 인해 댓글 수정에 실패했습니다."), - FAILED_DELETE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE,"DB 서버 오류로 인해 댓글 삭제에 실패했습니다."), + FAILED_DELETE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류로 인해 댓글 삭제에 실패했습니다."), // -- [Milestone] -- // INVALIDATE_DATE(HttpStatus.BAD_REQUEST, "현재 날짜보다 이전 날짜 입니다."), @@ -51,10 +51,9 @@ public enum ErrorCode implements StatusCode { LABEL_DELETE_FAILED(HttpStatus.BAD_REQUEST, "DB에서 라벨 삭제에 실패했습니다"), LABEL_FIND_FAILED(HttpStatus.BAD_REQUEST, "서버 오류로 라벨을 조회할 수 없습니다"), - // -- [Issue] -- // - DUPLICATE_OBJECT_FOUND(HttpStatus.BAD_REQUEST, "중복된 항목 선택입니다."); - + DUPLICATE_OBJECT_FOUND(HttpStatus.BAD_REQUEST, "중복된 항목 선택입니다."), + NOT_FOUND_ISSUES(HttpStatus.BAD_REQUEST, "이슈를 찾을 수 없습니다."); private HttpStatus status; private String message; diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/controller/IssueController.java b/be/issue/src/main/java/codesquad/issueTracker/issue/controller/IssueController.java index 4cf9203c8..29b8b67cb 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/controller/IssueController.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/controller/IssueController.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +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; @@ -12,6 +13,7 @@ import codesquad.issueTracker.global.common.ApiResponse; import codesquad.issueTracker.issue.dto.IssueWriteRequestDto; +import codesquad.issueTracker.issue.dto.ModifyIssueStatusRequestDto; import codesquad.issueTracker.issue.service.IssueService; import lombok.RequiredArgsConstructor; @@ -29,4 +31,11 @@ public ApiResponse postIssues(@Valid @RequestBody IssueWriteRequestDto r issueService.save(request, id); return ApiResponse.success(SUCCESS.getStatus(), SUCCESS.getMessage()); } + + @PatchMapping("/issues/status") + public ApiResponse patchStatus(@RequestBody ModifyIssueStatusRequestDto request) { + issueService.modifyIssueStatus(request); + return ApiResponse.success(SUCCESS.getStatus(), SUCCESS.getMessage()); + } + } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/repository/IssueRepository.java b/be/issue/src/main/java/codesquad/issueTracker/issue/repository/IssueRepository.java index 13a9c25fd..f93feec47 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/repository/IssueRepository.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/repository/IssueRepository.java @@ -1,6 +1,12 @@ package codesquad.issueTracker.issue.repository; +import java.time.LocalDateTime; +import java.util.Map; +import java.util.Optional; + +import org.springframework.dao.support.DataAccessUtils; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; @@ -49,4 +55,31 @@ public Long insertAssignees(Long issueId, Long userId) { jdbcTemplate.update(sql, parameters, keyHolder); return keyHolder.getKey().longValue(); } + + public Optional findById(Long id) { + String sql = "SELECT id, milestone_id, user_id, title, content, created_at, is_closed FROM issues WHERE id = :id AND is_deleted = 0"; + return Optional.ofNullable( + DataAccessUtils.singleResult( + jdbcTemplate.query(sql, Map.of("id", id), issueRowMapper))); + } + + public Long modifyStatus(Long issueId, Boolean status) { + String sql = "UPDATE issues SET is_closed = :status where id = :id AND is_deleted = 0"; + SqlParameterSource parameterSource = new MapSqlParameterSource() + .addValue("id", issueId) + .addValue("status", status); + jdbcTemplate.update(sql, parameterSource); + return issueId; + } + + private final RowMapper issueRowMapper = (rs, rowNum) -> Issue.builder() + .id(rs.getLong("id")) + .milestoneId(rs.getLong("milestone_id")) + .userId(rs.getLong("user_id")) + .title(rs.getString("title")) + .content(rs.getString("content")) + .createdAt(rs.getObject("created_at", LocalDateTime.class)) + .isClosed(rs.getBoolean("is_closed")) + .build(); + } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/service/IssueService.java b/be/issue/src/main/java/codesquad/issueTracker/issue/service/IssueService.java index 8a6dd0bfb..bf574c214 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/service/IssueService.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/service/IssueService.java @@ -9,10 +9,12 @@ import org.springframework.transaction.annotation.Transactional; import codesquad.issueTracker.comment.service.CommentService; +import codesquad.issueTracker.global.common.Status; import codesquad.issueTracker.global.exception.CustomException; import codesquad.issueTracker.global.exception.ErrorCode; import codesquad.issueTracker.issue.domain.Issue; import codesquad.issueTracker.issue.dto.IssueWriteRequestDto; +import codesquad.issueTracker.issue.dto.ModifyIssueStatusRequestDto; import codesquad.issueTracker.issue.repository.IssueRepository; import codesquad.issueTracker.label.service.LabelService; import codesquad.issueTracker.milestone.service.MilestoneService; @@ -66,4 +68,20 @@ private void duplicatedId(List list) { } } } + + @Transactional + public List modifyIssueStatus(ModifyIssueStatusRequestDto request) { + List issueIds = request.getIssueIds(); + Boolean status = Status.from(request.getStatus()).getStatus(); + duplicatedId(issueIds); + validateExistIssue(issueIds); + return issueIds.stream() + .map(issueId -> issueRepository.modifyStatus(issueId, status)).collect(Collectors.toList()); + } + + private void validateExistIssue(List issuesIds) { + for (Long issueId : issuesIds) { + issueRepository.findById(issueId).orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ISSUES)); + } + } }