From ae7e7f0c71b563059339321f38071902bcf5bac2 Mon Sep 17 00:00:00 2001 From: eeddiinn Date: Sun, 14 Jul 2024 02:43:34 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[FIX]=20=EB=8C=80=EC=83=81,=20=EC=9D=BC?= =?UTF-8?q?=EC=8B=9C,=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20null=20=ED=97=88?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A2=8B=EC=95=84=EC=9A=94=EC=88=98,=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=88=98,=20=EC=A0=80=EC=9E=A5=20=EC=88=98=200?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=B4=88=EA=B8=B0=ED=99=94=20=20#25?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../notice/dto/NoticeCreateRequest.java | 3 +- .../univoice/domain/notice/entity/Notice.java | 5 ++ .../domain/notice/service/NoticeService.java | 61 +++++++++++-------- .../exception/ValidationExceptionHandler.java | 24 ++++++++ .../univoice/infra/external/S3Service.java | 34 +++++------ 6 files changed, 84 insertions(+), 45 deletions(-) create mode 100644 src/main/java/sopt/univoice/infra/common/exception/ValidationExceptionHandler.java diff --git a/build.gradle b/build.gradle index 04b66f4..52848d1 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + implementation 'org.springframework.boot:spring-boot-starter-validation' // 유효성 검사 위해 } tasks.named('test') { diff --git a/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java b/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java index 64023d9..172b649 100644 --- a/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java +++ b/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java @@ -27,6 +27,5 @@ public class NoticeCreateRequest { @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) private LocalDateTime endTime; - private List studentCardImages; - + private List imageList; } diff --git a/src/main/java/sopt/univoice/domain/notice/entity/Notice.java b/src/main/java/sopt/univoice/domain/notice/entity/Notice.java index 52d250c..0246c25 100644 --- a/src/main/java/sopt/univoice/domain/notice/entity/Notice.java +++ b/src/main/java/sopt/univoice/domain/notice/entity/Notice.java @@ -30,8 +30,12 @@ public class Notice extends BaseTimeEntity { private Long noticeLike = 0L; private Long viewCount = 0L; + + private Long noticeSave = 0L; + private String target; + private LocalDateTime startTime; private LocalDateTime endTime; @@ -71,6 +75,7 @@ public Notice(String title, String content, String target, LocalDateTime startTi this.member = member; this.noticeLike = 0L; this.viewCount = 0L; + this.noticeSave = 0L; this.contentSummary = contentSummary; this.category = category; } diff --git a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java index a5af6e2..930ff47 100644 --- a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java +++ b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java @@ -31,16 +31,16 @@ public class NoticeService { private final PrincipalHandler principalHandler; private final S3Service s3Service; private final OpenAiService openAiService; + private final NoticeViewRepository noticeViewRepository; private final NoticeLikeRepository noticeLikeRepository; private final SaveNoticeRepository saveNoticeRepository; - private final NoticeViewRepository noticeViewRepository; @Transactional public void createPost(NoticeCreateRequest noticeCreateRequest) { Long memberId = principalHandler.getUserIdFromPrincipal(); System.out.println("Authenticated Member ID: " + memberId); Member member = authRepository.findById(memberId) - .orElseThrow(() -> new RuntimeException("회원이 존재하지 않습니다.")); + .orElseThrow(() -> new RuntimeException("회원이 존재하지 않습니다.")); System.out.println("Member Role: " + member.getAffiliation().getRole()); String summarizedContent = null; @@ -60,27 +60,36 @@ public void createPost(NoticeCreateRequest noticeCreateRequest) { // Notice 엔티티 생성 및 저장 Notice notice = Notice.builder() - .title(noticeCreateRequest.getTitle()) - .content(noticeCreateRequest.getContent()) - .target(noticeCreateRequest.getTarget()) - .startTime(noticeCreateRequest.getStartTime()) - .endTime(noticeCreateRequest.getEndTime()) - .member(member) - .contentSummary(summarizedContent) - .category("공지사항") // category 값을 '공지사항'으로 설정 - .build(); + .title(noticeCreateRequest.getTitle()) + .content(noticeCreateRequest.getContent()) + .target(noticeCreateRequest.getTarget() != null ? noticeCreateRequest.getTarget() : "") + .startTime(noticeCreateRequest.getStartTime() != null ? noticeCreateRequest.getStartTime() : null) + .endTime(noticeCreateRequest.getEndTime() != null ? noticeCreateRequest.getEndTime() : null) + .member(member) + .contentSummary(summarizedContent) + .category("공지사항") // category 값을 '공지사항'으로 설정 + .build(); noticeRepository.save(notice); System.out.println("Notice saved successfully with ID: " + notice.getId()); // NoticeImage 엔티티 생성 및 저장 - for (MultipartFile file : noticeCreateRequest.getStudentCardImages()) { - String fileName = storeFile(file); // 파일 저장 로직 필요 - NoticeImage noticeImage = NoticeImage.builder() - .notice(notice) - .noticeImage(fileName) - .build(); - noticeImageRepository.save(noticeImage); - System.out.println("NoticeImage saved successfully with file name: " + fileName); + List files = noticeCreateRequest.getImageList(); + + if (files != null && !files.isEmpty()) { + for (MultipartFile file : files) { + try { + String fileUrl = storeFile(file); // 파일 저장 로직 필요 + NoticeImage noticeImage = NoticeImage.builder() + .notice(notice) + .noticeImage(fileUrl) + .build(); + noticeImageRepository.save(noticeImage); + System.out.println("NoticeImage saved successfully with file URL: " + fileUrl); + } catch (Exception e) { + System.err.println("Error saving NoticeImage: " + e.getMessage()); + e.printStackTrace(); + } + } } // NoticeView 엔티티 생성 및 저장 @@ -89,24 +98,24 @@ public void createPost(NoticeCreateRequest noticeCreateRequest) { for (Member universityMember : universityMembers) { NoticeView noticeView = NoticeView.builder() - .notice(notice) - .member(universityMember) - .readAt(false) - .build(); + .notice(notice) + .member(universityMember) + .readAt(false) + .build(); noticeViewRepository.save(noticeView); } - } private String storeFile(MultipartFile file) { try { - return s3Service.uploadImage("notice-images/", file); + String fileUrl = s3Service.uploadImage("notice-images/", file); + return fileUrl; } catch (IOException e) { + System.err.println("File upload failed: " + e.getMessage()); throw new RuntimeException("파일 업로드에 실패했습니다.", e); } } - @Transactional public void likeNotice(Long noticeId) { Long memberId = principalHandler.getUserIdFromPrincipal(); diff --git a/src/main/java/sopt/univoice/infra/common/exception/ValidationExceptionHandler.java b/src/main/java/sopt/univoice/infra/common/exception/ValidationExceptionHandler.java new file mode 100644 index 0000000..f8c1c2a --- /dev/null +++ b/src/main/java/sopt/univoice/infra/common/exception/ValidationExceptionHandler.java @@ -0,0 +1,24 @@ +package sopt.univoice.infra.common.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class ValidationExceptionHandler { + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidationExceptions(MethodArgumentNotValidException ex) { + Map errors = new HashMap<>(); + ex.getBindingResult().getFieldErrors().forEach(error -> + errors.put(error.getField(), error.getDefaultMessage()) + ); + return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); + } +} + diff --git a/src/main/java/sopt/univoice/infra/external/S3Service.java b/src/main/java/sopt/univoice/infra/external/S3Service.java index 6852aea..4741d45 100644 --- a/src/main/java/sopt/univoice/infra/external/S3Service.java +++ b/src/main/java/sopt/univoice/infra/external/S3Service.java @@ -20,15 +20,17 @@ public class S3Service { private final String bucketName; private final AwsConfig awsConfig; + private final String region; private static final List IMAGE_EXTENSIONS = Arrays.asList("image/jpeg", "image/png", "image/jpg", "image/webp"); - - public S3Service(@Value("${aws-property.s3-bucket-name}") final String bucketName, AwsConfig awsConfig) { + public S3Service(@Value("${aws-property.s3-bucket-name}") final String bucketName, + AwsConfig awsConfig, + @Value("${aws-property.aws-region}") final String region) { this.bucketName = bucketName; this.awsConfig = awsConfig; + this.region = region; } - public String uploadImage(String directoryPath, MultipartFile image) throws IOException { final String key = directoryPath + generateImageFileName(); final S3Client s3Client = awsConfig.getS3Client(); @@ -37,33 +39,33 @@ public String uploadImage(String directoryPath, MultipartFile image) throws IOEx validateFileSize(image); PutObjectRequest request = PutObjectRequest.builder() - .bucket(bucketName) - .key(key) - .contentType(image.getContentType()) - .contentDisposition("inline") - .build(); + .bucket(bucketName) + .key(key) + .contentType(image.getContentType()) + .contentDisposition("inline") + .build(); RequestBody requestBody = RequestBody.fromBytes(image.getBytes()); s3Client.putObject(request, requestBody); - return key; + + // Return the URL of the uploaded image + return String.format("https://%s.s3.%s.amazonaws.com/%s", bucketName, region, key); } public void deleteImage(String key) throws IOException { final S3Client s3Client = awsConfig.getS3Client(); s3Client.deleteObject((DeleteObjectRequest.Builder builder) -> - builder.bucket(bucketName) - .key(key) - .build() + builder.bucket(bucketName) + .key(key) + .build() ); } - private String generateImageFileName() { return UUID.randomUUID() + ".jpg"; } - private void validateExtension(MultipartFile image) { String contentType = image.getContentType(); if (!IMAGE_EXTENSIONS.contains(contentType)) { @@ -78,6 +80,4 @@ private void validateFileSize(MultipartFile image) { throw new RuntimeException("이미지 사이즈는 5MB를 넘을 수 없습니다."); } } - -} - +} \ No newline at end of file From f18d2662bc9de6911bd5419fd8787cadd32421f2 Mon Sep 17 00:00:00 2001 From: eeddiinn Date: Sun, 14 Jul 2024 04:02:39 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[FIX]=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=93=B1=EB=A1=9D=EC=8B=9C=20=EC=A0=9C=EB=AA=A9=20?= =?UTF-8?q?100=EC=9E=90=20=EC=A0=9C=ED=95=9C=20=EB=B0=8F=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=B5=9C=EB=8C=80=205=EA=B0=9C=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C=20#27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univoice/domain/notice/controller/NoticeController.java | 3 ++- .../sopt/univoice/domain/notice/dto/NoticeCreateRequest.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/sopt/univoice/domain/notice/controller/NoticeController.java b/src/main/java/sopt/univoice/domain/notice/controller/NoticeController.java index 27100d1..4cf771a 100644 --- a/src/main/java/sopt/univoice/domain/notice/controller/NoticeController.java +++ b/src/main/java/sopt/univoice/domain/notice/controller/NoticeController.java @@ -1,6 +1,7 @@ package sopt.univoice.domain.notice.controller; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -19,7 +20,7 @@ public class NoticeController { private final NoticeService noticeService; @PostMapping("/create") - public ResponseEntity> createPost(@ModelAttribute NoticeCreateRequest noticeCreateRequest) { + public ResponseEntity> createPost(@Valid @ModelAttribute NoticeCreateRequest noticeCreateRequest) { System.out.println("createPost method called with request: " + noticeCreateRequest); noticeService.createPost(noticeCreateRequest); return ResponseEntity.status(HttpStatus.CREATED) diff --git a/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java b/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java index 172b649..56e74aa 100644 --- a/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java +++ b/src/main/java/sopt/univoice/domain/notice/dto/NoticeCreateRequest.java @@ -1,5 +1,6 @@ package sopt.univoice.domain.notice.dto; +import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; import lombok.*; import org.springframework.format.annotation.DateTimeFormat; @@ -15,7 +16,7 @@ //@AllArgsConstructor public class NoticeCreateRequest { - + @Size(max = 100) private String title; private String content; @@ -27,5 +28,6 @@ public class NoticeCreateRequest { @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) private LocalDateTime endTime; + @Size(max = 5) private List imageList; } From 8052be9b512fc5bc76fa69285b363e403394b018 Mon Sep 17 00:00:00 2001 From: eeddiinn Date: Sun, 14 Jul 2024 05:15:01 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[FIX]=20notice=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=20=EB=93=B1=EB=A1=9D=ED=95=9C=20=EB=82=A0=EC=A7=9C,?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80,=20?= =?UTF-8?q?=EC=9D=BC=EC=8B=9C=EB=8A=94=20=EC=82=AD=EC=A0=9C=20&=20?= =?UTF-8?q?=EC=B5=9C=EA=B7=BC=20=EC=A0=80=EC=9E=A5=20=EC=88=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20&=20=EC=A0=80=EC=9E=A5=20=EC=88=98=20=EC=A6=9D?= =?UTF-8?q?=EA=B0=80,=20=EA=B0=90=EC=86=8C=20=EC=B6=94=EA=B0=80=20#27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notice/dto/NoticeSaveDTO.java | 4 +- .../univoice/domain/notice/entity/Notice.java | 3 ++ .../domain/notice/entity/SaveNotice.java | 3 +- .../repository/SaveNoticeRepository.java | 2 + .../domain/notice/service/NoticeService.java | 47 +++++++++++++------ .../exception/message/ErrorMessage.java | 1 + 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/main/java/sopt/univoice/domain/notice/dto/NoticeSaveDTO.java b/src/main/java/sopt/univoice/domain/notice/dto/NoticeSaveDTO.java index 9a1f0fd..baaf94f 100644 --- a/src/main/java/sopt/univoice/domain/notice/dto/NoticeSaveDTO.java +++ b/src/main/java/sopt/univoice/domain/notice/dto/NoticeSaveDTO.java @@ -13,6 +13,6 @@ public class NoticeSaveDTO { private Long viewCount; private Long noticeLike; private String category; - private LocalDateTime startTime; - private LocalDateTime endTime; + private LocalDateTime createdAt; + private String image; } diff --git a/src/main/java/sopt/univoice/domain/notice/entity/Notice.java b/src/main/java/sopt/univoice/domain/notice/entity/Notice.java index 0246c25..6dbd535 100644 --- a/src/main/java/sopt/univoice/domain/notice/entity/Notice.java +++ b/src/main/java/sopt/univoice/domain/notice/entity/Notice.java @@ -94,6 +94,9 @@ public Long getViewCount() { return viewCount; } + public void setNoticeSave(Long noticeSave) { + this.noticeSave = noticeSave; + } } diff --git a/src/main/java/sopt/univoice/domain/notice/entity/SaveNotice.java b/src/main/java/sopt/univoice/domain/notice/entity/SaveNotice.java index b57b163..eb8e6f4 100644 --- a/src/main/java/sopt/univoice/domain/notice/entity/SaveNotice.java +++ b/src/main/java/sopt/univoice/domain/notice/entity/SaveNotice.java @@ -5,12 +5,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; import sopt.univoice.domain.user.entity.Member; +import sopt.univoice.infra.persistence.BaseTimeEntity; @Entity @Getter @NoArgsConstructor -public class SaveNotice { +public class SaveNotice extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/sopt/univoice/domain/notice/repository/SaveNoticeRepository.java b/src/main/java/sopt/univoice/domain/notice/repository/SaveNoticeRepository.java index df912fa..21f635b 100644 --- a/src/main/java/sopt/univoice/domain/notice/repository/SaveNoticeRepository.java +++ b/src/main/java/sopt/univoice/domain/notice/repository/SaveNoticeRepository.java @@ -12,6 +12,8 @@ public interface SaveNoticeRepository extends JpaRepository{ Optional findByNoticeAndMember(Notice notice, Member member); List findByMember(Member member); + + boolean existsByNoticeAndMember(Notice notice, Member member); } diff --git a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java index 930ff47..b3ddcc6 100644 --- a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java +++ b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java @@ -13,12 +13,15 @@ import sopt.univoice.domain.user.entity.Member; import sopt.univoice.domain.affiliation.entity.Role; import sopt.univoice.infra.common.exception.UnauthorizedException; +import sopt.univoice.infra.common.exception.message.BusinessException; import sopt.univoice.infra.common.exception.message.ErrorMessage; import sopt.univoice.infra.external.OpenAiService; import sopt.univoice.infra.external.S3Service; import java.io.IOException; +import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Service @@ -169,6 +172,16 @@ public void saveNotice(Long noticeId) { Notice notice = noticeRepository.findById(noticeId) .orElseThrow(() -> new RuntimeException("공지사항이 존재하지 않습니다.")); + // 이미 저장한 공지인지 확인하는 부분 추가 + boolean alreadySaved = saveNoticeRepository.existsByNoticeAndMember(notice, member); + if (alreadySaved) { + throw new BusinessException(ErrorMessage.ALREADY_SAVED); + } + + // noticeSave를 1 증가시킵니다. + notice.setNoticeSave(notice.getNoticeSave() + 1); + noticeRepository.save(notice); + // SaveNotice 엔티티 생성 및 저장 SaveNotice saveNotice = SaveNotice.builder() .notice(notice) @@ -187,9 +200,13 @@ public void saveCancleNotice(Long noticeId) { Notice notice = noticeRepository.findById(noticeId) .orElseThrow(() -> new RuntimeException("공지사항이 존재하지 않습니다.")); + // noticeSave를 1 감소시킵니다. + notice.setNoticeSave(notice.getNoticeSave() - 1); + noticeRepository.save(notice); + // SaveNotice 엔티티 삭제 SaveNotice saveNotice = saveNoticeRepository.findByNoticeAndMember(notice, member) - .orElseThrow(() -> new RuntimeException("저장된 공지사항이 존재하지 않습니다.")); + .orElseThrow(() -> new RuntimeException("저장된 공지사항이 존재하지 않습니다.")); saveNoticeRepository.delete(saveNotice); } @@ -203,19 +220,21 @@ public List getSaveNoticeByUser() { List saveNotices = saveNoticeRepository.findByMember(member); return saveNotices.stream() - .map(saveNotice -> { - Notice notice = saveNotice.getNotice(); - return new NoticeSaveDTO( - notice.getId(), - notice.getTitle(), - notice.getViewCount(), - notice.getNoticeLike(), - notice.getCategory(), - notice.getStartTime(), - notice.getEndTime() - ); - }) - .collect(Collectors.toList()); + .map(saveNotice -> { + Notice notice = saveNotice.getNotice(); + String image = notice.getNoticeImages().isEmpty() ? null : notice.getNoticeImages().get(0).getNoticeImage(); + return new NoticeSaveDTO( + notice.getId(), + notice.getTitle(), + notice.getViewCount(), + notice.getNoticeLike(), + notice.getCategory(), + notice.getCreatedAt(), + image + ); + }) + .sorted(Comparator.comparing(NoticeSaveDTO::getCreatedAt)) + .collect(Collectors.toList()); } @Transactional diff --git a/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java b/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java index c3bea00..f719d16 100644 --- a/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java +++ b/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java @@ -12,6 +12,7 @@ public enum ErrorMessage { EMAIL_DUPLICATE(HttpStatus.NO_CONTENT.value(), "이미 사용중인 이메일 입니다."), JWT_UNAUTHORIZED_EXCEPTION(HttpStatus.UNAUTHORIZED.value(), "사용자의 로그인 검증을 실패했습니다."), APPROVEADMIN_UNAUTHORIZED_EXCEPTION(HttpStatus.UNAUTHORIZED.value(), "승인된 관리자의 로그인 검증을 실패했습니다."), + ALREADY_SAVED(HttpStatus.CONFLICT.value(), "이미 저장한 공지입니다."), ; private final int status; private final String message; From 63c7a2278e21112f31fa3e529c88e6b42a1411fd Mon Sep 17 00:00:00 2001 From: eeddiinn Date: Sun, 14 Jul 2024 05:40:54 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[FIX]=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=20=EB=88=8C=EB=A0=80=EB=8A=94=EC=A7=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=20#27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notice/repository/NoticeLikeRepository.java | 2 ++ .../sopt/univoice/domain/notice/service/NoticeService.java | 6 ++++++ .../infra/common/exception/message/ErrorMessage.java | 1 + 3 files changed, 9 insertions(+) diff --git a/src/main/java/sopt/univoice/domain/notice/repository/NoticeLikeRepository.java b/src/main/java/sopt/univoice/domain/notice/repository/NoticeLikeRepository.java index 56e9160..38d9f56 100644 --- a/src/main/java/sopt/univoice/domain/notice/repository/NoticeLikeRepository.java +++ b/src/main/java/sopt/univoice/domain/notice/repository/NoticeLikeRepository.java @@ -9,4 +9,6 @@ public interface NoticeLikeRepository extends JpaRepository { Optional findByNoticeAndMember(Notice notice, Member member); + + boolean existsByNoticeAndMember(Notice notice, Member member); } diff --git a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java index b3ddcc6..f7d34df 100644 --- a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java +++ b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java @@ -129,6 +129,12 @@ public void likeNotice(Long noticeId) { Notice notice = noticeRepository.findById(noticeId) .orElseThrow(() -> new RuntimeException("공지사항이 존재하지 않습니다.")); + // 이미 좋아요를 누른 것인지 확인 + boolean alreadyLiked = noticeLikeRepository.existsByNoticeAndMember(notice, member); + if (alreadyLiked) { + throw new BusinessException(ErrorMessage.ALREADY_LIKED); + } + // noticeLike를 1 증가시킵니다. notice.setNoticeLike(notice.getNoticeLike() + 1); noticeRepository.save(notice); diff --git a/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java b/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java index f719d16..d9581d2 100644 --- a/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java +++ b/src/main/java/sopt/univoice/infra/common/exception/message/ErrorMessage.java @@ -13,6 +13,7 @@ public enum ErrorMessage { JWT_UNAUTHORIZED_EXCEPTION(HttpStatus.UNAUTHORIZED.value(), "사용자의 로그인 검증을 실패했습니다."), APPROVEADMIN_UNAUTHORIZED_EXCEPTION(HttpStatus.UNAUTHORIZED.value(), "승인된 관리자의 로그인 검증을 실패했습니다."), ALREADY_SAVED(HttpStatus.CONFLICT.value(), "이미 저장한 공지입니다."), + ALREADY_LIKED(HttpStatus.CONFLICT.value(), "이미 좋아요한 공지입니다."), ; private final int status; private final String message; From c330013264482c16941adc1ae0a065ace2ad961c Mon Sep 17 00:00:00 2001 From: eeddiinn Date: Sun, 14 Jul 2024 07:14:15 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[FIX]=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=84=B8=EB=B6=80=EC=82=AC=ED=95=AD=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=97=90=EC=84=9C=20category,=20contentSummary,=20mem?= =?UTF-8?q?berId,=20noticeLike=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20createdA?= =?UTF-8?q?t=20=EC=B6=94=EA=B0=80=20=20#27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notice/dto/NoticeDetailResponseDTO.java | 11 ++++------- .../univoice/domain/notice/service/NoticeService.java | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/main/java/sopt/univoice/domain/notice/dto/NoticeDetailResponseDTO.java b/src/main/java/sopt/univoice/domain/notice/dto/NoticeDetailResponseDTO.java index 9a2efd5..2ef938f 100644 --- a/src/main/java/sopt/univoice/domain/notice/dto/NoticeDetailResponseDTO.java +++ b/src/main/java/sopt/univoice/domain/notice/dto/NoticeDetailResponseDTO.java @@ -10,16 +10,13 @@ @AllArgsConstructor public class NoticeDetailResponseDTO { private Long id; + private String writeAffiliation; private String title; - private String content; - private Long noticeLike; - private Long viewCount; private String target; private LocalDateTime startTime; private LocalDateTime endTime; - private String category; - private String contentSummary; - private Long memberId; - private String writeAffiliation; + private String content; + private LocalDateTime createdAt; + private Long viewCount; private List noticeImages; } diff --git a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java index f7d34df..7d0ef2f 100644 --- a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java +++ b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java @@ -487,17 +487,14 @@ public NoticeDetailResponseDTO getNoticeById(Long noticeId) { return new NoticeDetailResponseDTO( notice.getId(), + writeAffiliation, notice.getTitle(), - notice.getContent(), - notice.getNoticeLike(), - notice.getViewCount(), notice.getTarget(), notice.getStartTime(), notice.getEndTime(), - notice.getCategory(), - notice.getContentSummary(), - notice.getMember().getId(), - writeAffiliation, // 추가된 부분 + notice.getContent(), + notice.getCreatedAt(), + notice.getViewCount(), notice.getNoticeImages().stream().map(NoticeImage::getNoticeImage).collect(Collectors.toList()) ); } From da2e3779b59f1c6355cafed158b63b7346c5d5d0 Mon Sep 17 00:00:00 2001 From: eeddiinn Date: Sun, 14 Jul 2024 07:18:05 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[FIX]=20=ED=91=B8=EC=8B=9C=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0=20#27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/sopt/univoice/domain/notice/service/NoticeService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java index 67168fe..a379c7e 100644 --- a/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java +++ b/src/main/java/sopt/univoice/domain/notice/service/NoticeService.java @@ -19,6 +19,7 @@ import sopt.univoice.infra.external.S3Service; import java.io.IOException; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors;