From 972134e151870318c08930c86655d66e74b830d3 Mon Sep 17 00:00:00 2001 From: hyeseon Date: Tue, 15 Aug 2023 02:27:54 +0900 Subject: [PATCH 1/3] =?UTF-8?q?#80=20refactor:=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EB=9D=BC=EB=B2=A8=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20dto=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8=ED=95=98=EA=B2=8C=20=EA=B5=AC=EC=A1=B0=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 --- .../issue/controller/IssueController.java | 4 +- .../issue/dto/IssueLabelResponseDto.java | 22 +++------- .../issue/service/IssueService.java | 43 ++++++++++--------- .../issueTracker/issue/vo/IssueLabelVo.java | 12 +++--- .../label/service/LabelService.java | 1 + 5 files changed, 38 insertions(+), 44 deletions(-) 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 28b266ee7..4e0efde3d 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 @@ -53,8 +53,8 @@ public ApiResponse postIssues(@Valid @RequestBody IssueWriteRequestDto r } @GetMapping("/issues/labels") - public ApiResponse> getIssueLabels() { - List labels = issueService.getIssueLabels(); + public ApiResponse getIssueLabels() { + IssueLabelResponseDto labels = issueService.getIssueLabels(); return ApiResponse.success(SUCCESS.getStatus(), labels); } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueLabelResponseDto.java b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueLabelResponseDto.java index dd7a0a145..d3175ff63 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueLabelResponseDto.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueLabelResponseDto.java @@ -1,30 +1,22 @@ package codesquad.issueTracker.issue.dto; -import codesquad.issueTracker.label.vo.LabelVo; +import codesquad.issueTracker.issue.vo.IssueLabelVo; +import java.util.List; import lombok.Builder; import lombok.Getter; @Getter public class IssueLabelResponseDto { - private Long id; - private String name; - private String backgroundColor; - private String textColor; + List labels; @Builder - public IssueLabelResponseDto(Long id, String name, String backgroundColor, String textColor) { - this.id = id; - this.name = name; - this.backgroundColor = backgroundColor; - this.textColor = textColor; + public IssueLabelResponseDto(List labels) { + this.labels = labels; } - public static IssueLabelResponseDto from(LabelVo label) { + public static IssueLabelResponseDto from(List labels) { return IssueLabelResponseDto.builder() - .id(label.getId()) - .name(label.getName()) - .backgroundColor(label.getBackgroundColor()) - .textColor(label.getTextColor()) + .labels(labels) .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 468f70a0a..b4c88c03e 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 @@ -73,18 +73,18 @@ public Long save(IssueWriteRequestDto request, Long id) { if (labels != null) { duplicatedId(labels); labels.stream() - .map(labelId -> labelService.validateLabelsId(labelId)) - .map(existLabel -> issueRepository.insertLabels(savedIssueId, existLabel.getId())) - .collect(Collectors.toList()); + .map(labelId -> labelService.validateLabelsId(labelId)) + .map(existLabel -> issueRepository.insertLabels(savedIssueId, existLabel.getId())) + .collect(Collectors.toList()); } // assignee 리스트가 null 이 아니면 assignees( 유저 id )가 존재하는지 검증 후 assignees 테이블에 insert if (assignees != null) { duplicatedId(assignees); assignees.stream() - .map(assigneesId -> userService.validateUserId(assigneesId)) - .map(existUser -> issueRepository.insertAssignees(savedIssueId, existUser.getId())) - .collect(Collectors.toList()); + .map(assigneesId -> userService.validateUserId(assigneesId)) + .map(existUser -> issueRepository.insertAssignees(savedIssueId, existUser.getId())) + .collect(Collectors.toList()); } return savedIssueId; } @@ -98,25 +98,26 @@ private void duplicatedId(List list) { } } - public List getIssueLabels() { + public IssueLabelResponseDto getIssueLabels() { LabelResponseDto allLabels = labelService.findAll(); - return allLabels.getLabels().stream() - .map(IssueLabelResponseDto::from) - .collect(Collectors.toList()); + List labels = allLabels.getLabels().stream() + .map(IssueLabelVo::from) + .collect(Collectors.toList()); + return IssueLabelResponseDto.from(labels); } public List getIssueMilestones() { List milestones = milestoneService.findMilestonesByStatus(Status.OPEN.getStatus()); return milestones.stream() - .map(IssueMilestoneResponseDto::from) - .collect(Collectors.toList()); + .map(IssueMilestoneResponseDto::from) + .collect(Collectors.toList()); } public List getIssueUsers() { List users = userService.getUsers(); return users.stream() - .map(IssueUserResponseDto::from) - .collect(Collectors.toList()); + .map(IssueUserResponseDto::from) + .collect(Collectors.toList()); } public IssueResponseDto getIssueById(Long issueId) { @@ -128,7 +129,7 @@ public IssueResponseDto getIssueById(Long issueId) { private Issue validateActiveIssueById(Long issueId) { return issueRepository.findActiveIssueById(issueId) - .orElseThrow(() -> new CustomException(ErrorCode.ALREADY_DELETED_ISSUE)); + .orElseThrow(() -> new CustomException(ErrorCode.ALREADY_DELETED_ISSUE)); } public IssueOptionResponseDto getIssueOptions(Long issueId) { @@ -155,9 +156,9 @@ public List modifyIssueStatus(ModifyIssueStatusRequestDto request) { if (issueIds != null) { duplicatedId(issueIds); issueIds.stream() - .map(issueId -> validateExistActiveIssue(issueId)) - .map(existIssue -> issueRepository.modifyStatus(existIssue.getId(), status)) - .collect(Collectors.toList()); + .map(issueId -> validateExistActiveIssue(issueId)) + .map(existIssue -> issueRepository.modifyStatus(existIssue.getId(), status)) + .collect(Collectors.toList()); } return issueIds; } @@ -171,12 +172,12 @@ public Long modifyIssueStatusInDetail(Long id, ModifyIssueStatusRequestDto reque private Issue validateExistActiveIssue(Long issuesIds) { return issueRepository.findActiveIssueById(issuesIds) - .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ISSUES)); + .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ISSUES)); } private void validateExistIssue(Long issueId) { issueRepository.findById(issueId) - .orElseThrow(() -> new CustomException(ErrorCode.NOT_EXIST_ISSUE)); + .orElseThrow(() -> new CustomException(ErrorCode.NOT_EXIST_ISSUE)); } @Transactional @@ -261,7 +262,7 @@ public IssueFileResponseDto uploadImg(MultipartFile multipartFile) { try (InputStream inputStream = multipartFile.getInputStream()) { amazonS3Client.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata) - .withCannedAcl(CannedAccessControlList.PublicRead)); + .withCannedAcl(CannedAccessControlList.PublicRead)); } catch (IOException e) { throw new CustomException(ErrorCode.FAILED_UPLOAD_FILE); } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueLabelVo.java b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueLabelVo.java index e9de06b55..8efb14933 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueLabelVo.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueLabelVo.java @@ -1,6 +1,6 @@ package codesquad.issueTracker.issue.vo; -import codesquad.issueTracker.label.domain.Label; +import codesquad.issueTracker.label.vo.LabelVo; import lombok.Builder; import lombok.Getter; @@ -20,12 +20,12 @@ public IssueLabelVo(Long id, String name, String backgroundColor, String textCol this.textColor = textColor; } - public static IssueLabelVo from(Label label) { + public static IssueLabelVo from(LabelVo labelVo) { return IssueLabelVo.builder() - .id(label.getId()) - .name(label.getName()) - .backgroundColor(label.getBackgroundColor()) - .textColor(label.getTextColor()) + .id(labelVo.getId()) + .name(labelVo.getName()) + .backgroundColor(labelVo.getBackgroundColor()) + .textColor(labelVo.getTextColor()) .build(); } } diff --git a/be/issue/src/main/java/codesquad/issueTracker/label/service/LabelService.java b/be/issue/src/main/java/codesquad/issueTracker/label/service/LabelService.java index 145255319..e3a825699 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/label/service/LabelService.java +++ b/be/issue/src/main/java/codesquad/issueTracker/label/service/LabelService.java @@ -59,6 +59,7 @@ public Long insertIssuesLabels(Long id, Long labelId) { public List findByIssueId(Long issueId) { return labelRepository.findLabelsById(issueId).stream() + .map(LabelVo::from) .map(IssueLabelVo::from) .collect(Collectors.toList()); } From 6b59bc45219efae2b69f98db48562699629e0bbe Mon Sep 17 00:00:00 2001 From: hyeseon Date: Tue, 15 Aug 2023 02:58:36 +0900 Subject: [PATCH 2/3] =?UTF-8?q?#80=20refactor:=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EB=A7=88=EC=9D=BC=EC=8A=A4=ED=86=A4=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20dto=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=8F=AC=ED=95=A8=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue/controller/IssueController.java | 4 +- .../issue/dto/IssueMilestoneResponseDto.java | 16 +- .../issue/dto/IssueOptionResponseDto.java | 2 +- .../issue/repository/IssueRepository.java | 2 +- .../issue/service/IssueService.java | 448 +++++++++--------- .../issue/vo/IssueMileStoneDetailVo.java | 24 + .../issue/vo/IssueMilestoneVo.java | 17 +- .../repository/MilestoneRepository.java | 9 +- .../milestone/service/MilestoneService.java | 5 +- 9 files changed, 274 insertions(+), 253 deletions(-) create mode 100644 be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMileStoneDetailVo.java 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 4e0efde3d..e8a30e7da 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 @@ -59,8 +59,8 @@ public ApiResponse getIssueLabels() { } @GetMapping("/issues/milestones") - public ApiResponse> getIssueMilestones() { - List milestones = issueService.getIssueMilestones(); + public ApiResponse getIssueMilestones() { + IssueMilestoneResponseDto milestones = issueService.getIssueMilestones(); return ApiResponse.success(SUCCESS.getStatus(), milestones); } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueMilestoneResponseDto.java b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueMilestoneResponseDto.java index 170800e99..5123fb466 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueMilestoneResponseDto.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueMilestoneResponseDto.java @@ -1,24 +1,22 @@ package codesquad.issueTracker.issue.dto; -import codesquad.issueTracker.milestone.vo.MilestoneVo; +import codesquad.issueTracker.issue.vo.IssueMileStoneDetailVo; +import java.util.List; import lombok.Builder; import lombok.Getter; @Getter public class IssueMilestoneResponseDto { - private Long id; - private String name; + private List milestones; @Builder - public IssueMilestoneResponseDto(Long id, String name) { - this.id = id; - this.name = name; + public IssueMilestoneResponseDto(List milestones) { + this.milestones = milestones; } - public static IssueMilestoneResponseDto from(MilestoneVo milestoneVo) { + public static IssueMilestoneResponseDto from(List milestones) { return builder() - .id(milestoneVo.getId()) - .name(milestoneVo.getName()) + .milestones(milestones) .build(); } } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java index a9e87f14a..1a9014acb 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java @@ -22,7 +22,7 @@ public IssueOptionResponseDto(List assignees, List lab } public static IssueOptionResponseDto of(List assignees, List labels, IssueMilestoneVo milestone) { - if (milestone.getId() == null) { + if (milestone.getIssueMileStoneDetailVo() == null) { return IssueOptionResponseDto.builder() .assignees(assignees) .labels(labels) 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 aad6bcbc9..0632b73f4 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 @@ -84,7 +84,7 @@ public int findCountByStatusAndMilestone(boolean status, IssueMilestoneVo milest + "and i.is_deleted = false " + "and i.is_closed = :status"; MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("milestoneId", milestone.getId()); + params.addValue("milestoneId", milestone.getIssueMileStoneDetailVo().getId()); params.addValue("status", status); return jdbcTemplate.queryForObject(sql, params, Integer.class); } 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 b4c88c03e..7896a0e4f 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 @@ -1,5 +1,6 @@ package codesquad.issueTracker.issue.service; +import codesquad.issueTracker.issue.vo.IssueMileStoneDetailVo; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; @@ -53,227 +54,228 @@ @Transactional(readOnly = true) public class IssueService { - @Value("${cloud.aws.s3.bucket}") - private String bucketName; - private final IssueRepository issueRepository; - private final LabelService labelService; - private final UserService userService; - private final MilestoneService milestoneService; - private final AmazonS3Client amazonS3Client; - - @Transactional - public Long save(IssueWriteRequestDto request, Long id) { - milestoneService.isExistMilestone(request.getMilestoneId()); - List labels = request.getLabels(); - List assignees = request.getAssignees(); - Issue issue = IssueWriteRequestDto.toEntity(request, id); - Long savedIssueId = issueRepository.insert(issue); - - // 라벨 리스트가 null 이 아니면 해당 라벨이 존재하는지 검증 후 라벨과 이슈 연결 테이블에 insert - if (labels != null) { - duplicatedId(labels); - labels.stream() - .map(labelId -> labelService.validateLabelsId(labelId)) - .map(existLabel -> issueRepository.insertLabels(savedIssueId, existLabel.getId())) - .collect(Collectors.toList()); - } - - // assignee 리스트가 null 이 아니면 assignees( 유저 id )가 존재하는지 검증 후 assignees 테이블에 insert - if (assignees != null) { - duplicatedId(assignees); - assignees.stream() - .map(assigneesId -> userService.validateUserId(assigneesId)) - .map(existUser -> issueRepository.insertAssignees(savedIssueId, existUser.getId())) - .collect(Collectors.toList()); - } - return savedIssueId; - } - - private void duplicatedId(List list) { - Set set = new HashSet<>(); - for (Long temp : list) { - if (!set.add(temp)) { - throw new CustomException(ErrorCode.DUPLICATE_OBJECT_FOUND); - } - } - } - - public IssueLabelResponseDto getIssueLabels() { - LabelResponseDto allLabels = labelService.findAll(); - List labels = allLabels.getLabels().stream() - .map(IssueLabelVo::from) - .collect(Collectors.toList()); - return IssueLabelResponseDto.from(labels); - } - - public List getIssueMilestones() { - List milestones = milestoneService.findMilestonesByStatus(Status.OPEN.getStatus()); - return milestones.stream() - .map(IssueMilestoneResponseDto::from) - .collect(Collectors.toList()); - } - - public List getIssueUsers() { - List users = userService.getUsers(); - return users.stream() - .map(IssueUserResponseDto::from) - .collect(Collectors.toList()); - } - - public IssueResponseDto getIssueById(Long issueId) { - validateExistIssue(issueId); - Issue issue = validateActiveIssueById(issueId); - - return IssueResponseDto.from(issue); - } - - private Issue validateActiveIssueById(Long issueId) { - return issueRepository.findActiveIssueById(issueId) - .orElseThrow(() -> new CustomException(ErrorCode.ALREADY_DELETED_ISSUE)); - } - - public IssueOptionResponseDto getIssueOptions(Long issueId) { - validateExistIssue(issueId); - validateActiveIssueById(issueId); - - List assignees = issueRepository.findAssigneesById(issueId); - List labels = labelService.findByIssueId(issueId); - IssueMilestoneVo milestone = milestoneService.findByIssueId(issueId); - - if (milestone.getId() != null) { - int closeCount = issueRepository.findCountByStatusAndMilestone(Status.CLOSED.getStatus(), milestone); - int openCount = issueRepository.findCountByStatusAndMilestone(Status.OPEN.getStatus(), milestone); - return IssueOptionResponseDto.of(assignees, labels, milestone.getMilestoneWithRatio(openCount, closeCount)); - } - - return IssueOptionResponseDto.of(assignees, labels, milestone); - } - - @Transactional - public List modifyIssueStatus(ModifyIssueStatusRequestDto request) { - List issueIds = request.getIssueIds(); - Boolean status = Status.from(request.getStatus()).getStatus(); - if (issueIds != null) { - duplicatedId(issueIds); - issueIds.stream() - .map(issueId -> validateExistActiveIssue(issueId)) - .map(existIssue -> issueRepository.modifyStatus(existIssue.getId(), status)) - .collect(Collectors.toList()); - } - return issueIds; - } - - @Transactional - public Long modifyIssueStatusInDetail(Long id, ModifyIssueStatusRequestDto request) { - Boolean status = Status.from(request.getStatus()).getStatus(); - validateExistActiveIssue(id); - return issueRepository.modifyStatus(id, status); - } - - private Issue validateExistActiveIssue(Long issuesIds) { - return issueRepository.findActiveIssueById(issuesIds) - .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ISSUES)); - } - - private void validateExistIssue(Long issueId) { - issueRepository.findById(issueId) - .orElseThrow(() -> new CustomException(ErrorCode.NOT_EXIST_ISSUE)); - } - - @Transactional - public ModifyIssueContentResponseDto modifyIssueContent(Long id, ModifyIssueContentRequestDto request) { - validateExistActiveIssue(id); - String modifiedContent = request.getContent(); - issueRepository.updateContent(id, modifiedContent); - return new ModifyIssueContentResponseDto(modifiedContent); - } - - @Transactional - public ModifyIssueTitleResponse modifyIssueTitle(Long id, ModifyIssueTitleRequest request) { - validateExistActiveIssue(id); - String modifiedTitle = request.getTitle(); - issueRepository.updateTitle(id, modifiedTitle); - return new ModifyIssueTitleResponse(modifiedTitle); - } - - @Transactional - public Long delete(Long id) { - validateExistActiveIssue(id); - Long deletedId = issueRepository.delete(id); - return deletedId; - - } - - @Transactional - public Long modifyAssignees(Long id, ModifyAssigneeRequestDto request) { - validateExistActiveIssue(id); - List assignees = request.getAssignees(); - - if (assignees != null) { - duplicatedId(assignees); - for (Long assigneeId : assignees) { - userService.validateUserId(assigneeId); - } - issueRepository.resetAssignees(id); - for (Long assigneeId : assignees) { - issueRepository.insertAssignees(id, assigneeId); - } - return id; - } - issueRepository.resetAssignees(id); - return id; - } - - @Transactional - public Long modifyLabels(Long id, ModifyLabelRequestDto request) { - validateExistActiveIssue(id); - List labels = request.getLabels(); - - if (labels != null) { - duplicatedId(labels); - for (Long labelId : labels) { - labelService.validateLabelsId(labelId); - } - labelService.resetLabels(id); - for (Long labelId : labels) { - labelService.insertIssuesLabels(id, labelId); - } - return id; - } - labelService.resetLabels(id); - return id; - } - - @Transactional - public Long modifyMilestone(Long id, ModifyIssueMilestoneDto request) { - validateExistActiveIssue(id); - Long milestoneId = request.getMilestone(); - if (milestoneId != null) { - milestoneService.isExistMilestone(milestoneId); - } - return issueRepository.updateMilestone(id, milestoneId); - } - - public IssueFileResponseDto uploadImg(MultipartFile multipartFile) { - validateFileExists(multipartFile); - String fileName = multipartFile.getOriginalFilename(); - ObjectMetadata objectMetadata = new ObjectMetadata(); - objectMetadata.setContentType(multipartFile.getContentType()); - - try (InputStream inputStream = multipartFile.getInputStream()) { - amazonS3Client.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata) - .withCannedAcl(CannedAccessControlList.PublicRead)); - } catch (IOException e) { - throw new CustomException(ErrorCode.FAILED_UPLOAD_FILE); - } - String url = amazonS3Client.getUrl(bucketName, fileName).toString(); - IssueFileResponseDto response = new IssueFileResponseDto(url); - return response; - } - - private void validateFileExists(MultipartFile multipartFile) { - if (multipartFile.isEmpty()) { - throw new CustomException(ErrorCode.EMPTY_FILE_EXCEPTION); - } - } + @Value("${cloud.aws.s3.bucket}") + private String bucketName; + private final IssueRepository issueRepository; + private final LabelService labelService; + private final UserService userService; + private final MilestoneService milestoneService; + private final AmazonS3Client amazonS3Client; + + @Transactional + public Long save(IssueWriteRequestDto request, Long id) { + milestoneService.isExistMilestone(request.getMilestoneId()); + List labels = request.getLabels(); + List assignees = request.getAssignees(); + Issue issue = IssueWriteRequestDto.toEntity(request, id); + Long savedIssueId = issueRepository.insert(issue); + + // 라벨 리스트가 null 이 아니면 해당 라벨이 존재하는지 검증 후 라벨과 이슈 연결 테이블에 insert + if (labels != null) { + duplicatedId(labels); + labels.stream() + .map(labelId -> labelService.validateLabelsId(labelId)) + .map(existLabel -> issueRepository.insertLabels(savedIssueId, existLabel.getId())) + .collect(Collectors.toList()); + } + + // assignee 리스트가 null 이 아니면 assignees( 유저 id )가 존재하는지 검증 후 assignees 테이블에 insert + if (assignees != null) { + duplicatedId(assignees); + assignees.stream() + .map(assigneesId -> userService.validateUserId(assigneesId)) + .map(existUser -> issueRepository.insertAssignees(savedIssueId, existUser.getId())) + .collect(Collectors.toList()); + } + return savedIssueId; + } + + private void duplicatedId(List list) { + Set set = new HashSet<>(); + for (Long temp : list) { + if (!set.add(temp)) { + throw new CustomException(ErrorCode.DUPLICATE_OBJECT_FOUND); + } + } + } + + public IssueLabelResponseDto getIssueLabels() { + LabelResponseDto allLabels = labelService.findAll(); + List labels = allLabels.getLabels().stream() + .map(IssueLabelVo::from) + .collect(Collectors.toList()); + return IssueLabelResponseDto.from(labels); + } + + public IssueMilestoneResponseDto getIssueMilestones() { + List milestones = milestoneService.findMilestonesByStatus(Status.OPEN.getStatus()); + List milestoneVos = milestones.stream() + .map(IssueMileStoneDetailVo::from) + .collect(Collectors.toList()); + return IssueMilestoneResponseDto.from(milestoneVos); + } + + public List getIssueUsers() { + List users = userService.getUsers(); + return users.stream() + .map(IssueUserResponseDto::from) + .collect(Collectors.toList()); + } + + public IssueResponseDto getIssueById(Long issueId) { + validateExistIssue(issueId); + Issue issue = validateActiveIssueById(issueId); + + return IssueResponseDto.from(issue); + } + + private Issue validateActiveIssueById(Long issueId) { + return issueRepository.findActiveIssueById(issueId) + .orElseThrow(() -> new CustomException(ErrorCode.ALREADY_DELETED_ISSUE)); + } + + public IssueOptionResponseDto getIssueOptions(Long issueId) { + validateExistIssue(issueId); + validateActiveIssueById(issueId); + + List assignees = issueRepository.findAssigneesById(issueId); + List labels = labelService.findByIssueId(issueId); + IssueMilestoneVo milestone = milestoneService.findByIssueId(issueId); + + if (milestone.getIssueMileStoneDetailVo() != null) { + int closeCount = issueRepository.findCountByStatusAndMilestone(Status.CLOSED.getStatus(), milestone); + int openCount = issueRepository.findCountByStatusAndMilestone(Status.OPEN.getStatus(), milestone); + return IssueOptionResponseDto.of(assignees, labels, milestone.getMilestoneWithRatio(openCount, closeCount)); + } + + return IssueOptionResponseDto.of(assignees, labels, milestone); + } + + @Transactional + public List modifyIssueStatus(ModifyIssueStatusRequestDto request) { + List issueIds = request.getIssueIds(); + Boolean status = Status.from(request.getStatus()).getStatus(); + if (issueIds != null) { + duplicatedId(issueIds); + issueIds.stream() + .map(issueId -> validateExistActiveIssue(issueId)) + .map(existIssue -> issueRepository.modifyStatus(existIssue.getId(), status)) + .collect(Collectors.toList()); + } + return issueIds; + } + + @Transactional + public Long modifyIssueStatusInDetail(Long id, ModifyIssueStatusRequestDto request) { + Boolean status = Status.from(request.getStatus()).getStatus(); + validateExistActiveIssue(id); + return issueRepository.modifyStatus(id, status); + } + + private Issue validateExistActiveIssue(Long issuesIds) { + return issueRepository.findActiveIssueById(issuesIds) + .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ISSUES)); + } + + private void validateExistIssue(Long issueId) { + issueRepository.findById(issueId) + .orElseThrow(() -> new CustomException(ErrorCode.NOT_EXIST_ISSUE)); + } + + @Transactional + public ModifyIssueContentResponseDto modifyIssueContent(Long id, ModifyIssueContentRequestDto request) { + validateExistActiveIssue(id); + String modifiedContent = request.getContent(); + issueRepository.updateContent(id, modifiedContent); + return new ModifyIssueContentResponseDto(modifiedContent); + } + + @Transactional + public ModifyIssueTitleResponse modifyIssueTitle(Long id, ModifyIssueTitleRequest request) { + validateExistActiveIssue(id); + String modifiedTitle = request.getTitle(); + issueRepository.updateTitle(id, modifiedTitle); + return new ModifyIssueTitleResponse(modifiedTitle); + } + + @Transactional + public Long delete(Long id) { + validateExistActiveIssue(id); + Long deletedId = issueRepository.delete(id); + return deletedId; + + } + + @Transactional + public Long modifyAssignees(Long id, ModifyAssigneeRequestDto request) { + validateExistActiveIssue(id); + List assignees = request.getAssignees(); + + if (assignees != null) { + duplicatedId(assignees); + for (Long assigneeId : assignees) { + userService.validateUserId(assigneeId); + } + issueRepository.resetAssignees(id); + for (Long assigneeId : assignees) { + issueRepository.insertAssignees(id, assigneeId); + } + return id; + } + issueRepository.resetAssignees(id); + return id; + } + + @Transactional + public Long modifyLabels(Long id, ModifyLabelRequestDto request) { + validateExistActiveIssue(id); + List labels = request.getLabels(); + + if (labels != null) { + duplicatedId(labels); + for (Long labelId : labels) { + labelService.validateLabelsId(labelId); + } + labelService.resetLabels(id); + for (Long labelId : labels) { + labelService.insertIssuesLabels(id, labelId); + } + return id; + } + labelService.resetLabels(id); + return id; + } + + @Transactional + public Long modifyMilestone(Long id, ModifyIssueMilestoneDto request) { + validateExistActiveIssue(id); + Long milestoneId = request.getMilestone(); + if (milestoneId != null) { + milestoneService.isExistMilestone(milestoneId); + } + return issueRepository.updateMilestone(id, milestoneId); + } + + public IssueFileResponseDto uploadImg(MultipartFile multipartFile) { + validateFileExists(multipartFile); + String fileName = multipartFile.getOriginalFilename(); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType(multipartFile.getContentType()); + + try (InputStream inputStream = multipartFile.getInputStream()) { + amazonS3Client.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + } catch (IOException e) { + throw new CustomException(ErrorCode.FAILED_UPLOAD_FILE); + } + String url = amazonS3Client.getUrl(bucketName, fileName).toString(); + IssueFileResponseDto response = new IssueFileResponseDto(url); + return response; + } + + private void validateFileExists(MultipartFile multipartFile) { + if (multipartFile.isEmpty()) { + throw new CustomException(ErrorCode.EMPTY_FILE_EXCEPTION); + } + } } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMileStoneDetailVo.java b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMileStoneDetailVo.java new file mode 100644 index 000000000..58717e585 --- /dev/null +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMileStoneDetailVo.java @@ -0,0 +1,24 @@ +package codesquad.issueTracker.issue.vo; + +import codesquad.issueTracker.milestone.vo.MilestoneVo; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class IssueMileStoneDetailVo { + private Long id; + private String name; + + @Builder + public IssueMileStoneDetailVo(Long id, String name) { + this.id = id; + this.name = name; + } + + public static IssueMileStoneDetailVo from(MilestoneVo milestoneVo) { + return IssueMileStoneDetailVo.builder() + .id(milestoneVo.getId()) + .name(milestoneVo.getName()) + .build(); + } +} diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMilestoneVo.java b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMilestoneVo.java index ae17b526e..2d771763d 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMilestoneVo.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueMilestoneVo.java @@ -1,32 +1,29 @@ package codesquad.issueTracker.issue.vo; +import codesquad.issueTracker.milestone.vo.MilestoneVo; import lombok.Builder; import lombok.Getter; @Getter public class IssueMilestoneVo { - private Long id; - private String name; + private IssueMileStoneDetailVo issueMileStoneDetailVo; private int completedRatio; @Builder - public IssueMilestoneVo(Long id, String name, int completedRatio) { - this.id = id; - this.name = name; + public IssueMilestoneVo(IssueMileStoneDetailVo issueMileStoneDetailVo, int completedRatio) { + this.issueMileStoneDetailVo = issueMileStoneDetailVo; this.completedRatio = completedRatio; } - public static IssueMilestoneVo from(IssueMilestoneVo issueMilestone) { + public static IssueMilestoneVo from(MilestoneVo milestoneVo) { return IssueMilestoneVo.builder() - .id(issueMilestone.getId()) - .name(issueMilestone.getName()) + .issueMileStoneDetailVo(IssueMileStoneDetailVo.from(milestoneVo)) .build(); } public IssueMilestoneVo getMilestoneWithRatio(int openCount, int closeCount) { return IssueMilestoneVo.builder() - .id(this.id) - .name(this.name) + .issueMileStoneDetailVo(this.issueMileStoneDetailVo) .completedRatio(calculateRatio(openCount, closeCount)) .build(); } diff --git a/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java b/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java index a5a75a89b..364fb3cbc 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java +++ b/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java @@ -1,6 +1,5 @@ package codesquad.issueTracker.milestone.repository; -import codesquad.issueTracker.issue.vo.IssueMilestoneVo; import java.time.LocalDate; import java.util.List; @@ -110,8 +109,8 @@ public int getLabelCount() { .issueClosedCount(rs.getInt("issueClosedCount")) .build(); - public Optional findByIssueId(Long issueId) { - String sql = "select m.id, m.name " + public Optional findByIssueId(Long issueId) { + String sql = "select m.id, m.name, m.description, m.don_date " + "from milestones m " + " join issues i on m.id = i.milestone_id " + "where i.id = :issueId " @@ -120,10 +119,10 @@ public Optional findByIssueId(Long issueId) { return Optional.ofNullable( DataAccessUtils.singleResult( - jdbcTemplate.query(sql, Map.of("issueId", issueId), issueMilestoneVoRowMapper))); + jdbcTemplate.query(sql, Map.of("issueId", issueId), milestoneVoRowMapper))); } - private final RowMapper issueMilestoneVoRowMapper = ((rs, rowNum) -> IssueMilestoneVo.builder() + private final RowMapper milestoneVoRowMapper = ((rs, rowNum) -> MilestoneVo.builder() .id(rs.getLong("id")) .name(rs.getString("name")) .build()); diff --git a/be/issue/src/main/java/codesquad/issueTracker/milestone/service/MilestoneService.java b/be/issue/src/main/java/codesquad/issueTracker/milestone/service/MilestoneService.java index 5e4176190..b89330fa5 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/milestone/service/MilestoneService.java +++ b/be/issue/src/main/java/codesquad/issueTracker/milestone/service/MilestoneService.java @@ -82,7 +82,8 @@ public List findMilestonesByStatus(Boolean status) { } public IssueMilestoneVo findByIssueId(Long issueId) { - return milestoneRepository.findByIssueId(issueId) - .orElseGet(() -> IssueMilestoneVo.builder().build()); + MilestoneVo milestoneVo = milestoneRepository.findByIssueId(issueId) + .orElseGet(() -> MilestoneVo.builder().build()); + return IssueMilestoneVo.from(milestoneVo); } } From bc7991ac803abf4533f7adf81420a9e3aac042cc Mon Sep 17 00:00:00 2001 From: hyeseon Date: Tue, 15 Aug 2023 03:11:17 +0900 Subject: [PATCH 3/3] =?UTF-8?q?#80=20refactor:=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EC=B0=B8=EC=97=AC=EC=9E=90=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20dto=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=8F=AC=ED=95=A8=ED=95=98=EA=B2=8C=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue/controller/IssueController.java | 4 +-- .../issue/dto/IssueOptionResponseDto.java | 2 +- .../issue/dto/IssueUserResponseDto.java | 20 ++++++-------- .../issue/service/IssueService.java | 10 ++++--- .../issueTracker/issue/vo/IssueUserVo.java | 27 +++++++++++++++++++ .../repository/MilestoneRepository.java | 2 +- 6 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueUserVo.java 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 e8a30e7da..4bb30965e 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 @@ -65,8 +65,8 @@ public ApiResponse getIssueMilestones() { } @GetMapping("/issues/participants") - public ApiResponse> getIssueUsers() { - List participants = issueService.getIssueUsers(); + public ApiResponse getIssueUsers() { + IssueUserResponseDto participants = issueService.getIssueUsers(); return ApiResponse.success(SUCCESS.getStatus(), participants); } diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java index 1a9014acb..a9186ab6b 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueOptionResponseDto.java @@ -22,7 +22,7 @@ public IssueOptionResponseDto(List assignees, List lab } public static IssueOptionResponseDto of(List assignees, List labels, IssueMilestoneVo milestone) { - if (milestone.getIssueMileStoneDetailVo() == null) { + if (milestone.getIssueMileStoneDetailVo().getId() == null) { return IssueOptionResponseDto.builder() .assignees(assignees) .labels(labels) diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueUserResponseDto.java b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueUserResponseDto.java index 7399bad3b..1a62170f9 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueUserResponseDto.java +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/dto/IssueUserResponseDto.java @@ -1,27 +1,23 @@ package codesquad.issueTracker.issue.dto; -import codesquad.issueTracker.user.domain.User; +import codesquad.issueTracker.issue.vo.IssueUserVo; +import java.util.List; import lombok.Builder; import lombok.Getter; @Getter public class IssueUserResponseDto { - private Long id; - private String name; - private String imageUrl; + private List participants; + @Builder - public IssueUserResponseDto(Long id, String name, String imageUrl) { - this.id = id; - this.name = name; - this.imageUrl = imageUrl; + public IssueUserResponseDto(List participants) { + this.participants = participants; } - public static IssueUserResponseDto from(User user) { + public static IssueUserResponseDto from(List participants) { return IssueUserResponseDto.builder() - .id(user.getId()) - .name(user.getName()) - .imageUrl(user.getProfileImg()) + .participants(participants) .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 7896a0e4f..501572f6b 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 @@ -1,6 +1,7 @@ package codesquad.issueTracker.issue.service; import codesquad.issueTracker.issue.vo.IssueMileStoneDetailVo; +import codesquad.issueTracker.issue.vo.IssueUserVo; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; @@ -115,11 +116,12 @@ public IssueMilestoneResponseDto getIssueMilestones() { return IssueMilestoneResponseDto.from(milestoneVos); } - public List getIssueUsers() { + public IssueUserResponseDto getIssueUsers() { List users = userService.getUsers(); - return users.stream() - .map(IssueUserResponseDto::from) + List participants = users.stream() + .map(IssueUserVo::from) .collect(Collectors.toList()); + return IssueUserResponseDto.from(participants); } public IssueResponseDto getIssueById(Long issueId) { @@ -142,7 +144,7 @@ public IssueOptionResponseDto getIssueOptions(Long issueId) { List labels = labelService.findByIssueId(issueId); IssueMilestoneVo milestone = milestoneService.findByIssueId(issueId); - if (milestone.getIssueMileStoneDetailVo() != null) { + if (milestone.getIssueMileStoneDetailVo().getId() != null) { int closeCount = issueRepository.findCountByStatusAndMilestone(Status.CLOSED.getStatus(), milestone); int openCount = issueRepository.findCountByStatusAndMilestone(Status.OPEN.getStatus(), milestone); return IssueOptionResponseDto.of(assignees, labels, milestone.getMilestoneWithRatio(openCount, closeCount)); diff --git a/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueUserVo.java b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueUserVo.java new file mode 100644 index 000000000..7c27adeda --- /dev/null +++ b/be/issue/src/main/java/codesquad/issueTracker/issue/vo/IssueUserVo.java @@ -0,0 +1,27 @@ +package codesquad.issueTracker.issue.vo; + +import codesquad.issueTracker.user.domain.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class IssueUserVo { + private Long id; + private String name; + private String imageUrl; + + @Builder + public IssueUserVo(Long id, String name, String imageUrl) { + this.id = id; + this.name = name; + this.imageUrl = imageUrl; + } + + public static IssueUserVo from(User user) { + return IssueUserVo.builder() + .id(user.getId()) + .name(user.getName()) + .imageUrl(user.getProfileImg()) + .build(); + } +} diff --git a/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java b/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java index 364fb3cbc..98de5350c 100644 --- a/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java +++ b/be/issue/src/main/java/codesquad/issueTracker/milestone/repository/MilestoneRepository.java @@ -110,7 +110,7 @@ public int getLabelCount() { .build(); public Optional findByIssueId(Long issueId) { - String sql = "select m.id, m.name, m.description, m.don_date " + String sql = "select m.id, m.name " + "from milestones m " + " join issues i on m.id = i.milestone_id " + "where i.id = :issueId "