diff --git a/src/main/java/org/sopt/lequuServer/domain/book/facade/BookFacade.java b/src/main/java/org/sopt/lequuServer/domain/book/facade/BookFacade.java index bf043dd..664faa4 100644 --- a/src/main/java/org/sopt/lequuServer/domain/book/facade/BookFacade.java +++ b/src/main/java/org/sopt/lequuServer/domain/book/facade/BookFacade.java @@ -9,7 +9,7 @@ import org.sopt.lequuServer.domain.book.model.Book; import org.sopt.lequuServer.domain.book.service.BookService; import org.sopt.lequuServer.domain.member.model.Member; -import org.sopt.lequuServer.domain.member.service.MemberService; +import org.sopt.lequuServer.domain.member.repository.MemberRepository; import org.sopt.lequuServer.global.s3.service.S3Service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,14 +20,14 @@ public class BookFacade { private final BookService bookService; - private final MemberService memberService; + private final MemberRepository memberRepository; private final S3Service s3Service; @Transactional public BookCreateResponseDto createBook(BookCreateRequest request, Long memberId) { // 유저 검증이 완료된 후에 새로운 Book 객체를 생성할 수 있는 것 - Member member = memberService.getMember(memberId); + Member member = memberRepository.findByIdOrThrow(memberId); /** * 요청을 한 유저를 가장 먼저 검증하고 diff --git a/src/main/java/org/sopt/lequuServer/domain/book/repository/BookRepository.java b/src/main/java/org/sopt/lequuServer/domain/book/repository/BookRepository.java index 54174a3..5880b3d 100644 --- a/src/main/java/org/sopt/lequuServer/domain/book/repository/BookRepository.java +++ b/src/main/java/org/sopt/lequuServer/domain/book/repository/BookRepository.java @@ -3,6 +3,8 @@ import java.util.List; import org.sopt.lequuServer.domain.book.model.Book; import org.springframework.data.domain.PageRequest; +import org.sopt.lequuServer.global.exception.enums.ErrorType; +import org.sopt.lequuServer.global.exception.model.CustomException; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -10,4 +12,9 @@ public interface BookRepository extends JpaRepository { @Query(value = "select b from Book b where b.isPopular = :isPopular") List getAllByPopular(@Param("isPopular") Boolean isPopular, PageRequest pageRequest); + + default Book findByIdOrThrow(Long id) { + return this.findById(id).orElseThrow( + () -> new CustomException(ErrorType.NOT_FOUND_BOOK_ERROR)); + } } \ No newline at end of file diff --git a/src/main/java/org/sopt/lequuServer/domain/book/service/BookService.java b/src/main/java/org/sopt/lequuServer/domain/book/service/BookService.java index 97d943c..03da50d 100644 --- a/src/main/java/org/sopt/lequuServer/domain/book/service/BookService.java +++ b/src/main/java/org/sopt/lequuServer/domain/book/service/BookService.java @@ -18,4 +18,4 @@ public class BookService { public BookCreateResponseDto createBook(Book book) { return BookCreateResponseDto.of(bookRepository.save(book)); } -} \ No newline at end of file +} diff --git a/src/main/java/org/sopt/lequuServer/domain/common/facade/CommonFacade.java b/src/main/java/org/sopt/lequuServer/domain/common/facade/CommonFacade.java index 483a635..96b7266 100644 --- a/src/main/java/org/sopt/lequuServer/domain/common/facade/CommonFacade.java +++ b/src/main/java/org/sopt/lequuServer/domain/common/facade/CommonFacade.java @@ -5,19 +5,18 @@ import org.sopt.lequuServer.domain.book.repository.BookRepository; import org.sopt.lequuServer.domain.common.dto.response.PopularBookResponseDto; import org.sopt.lequuServer.domain.common.dto.response.SplashDto; -import org.sopt.lequuServer.domain.note.service.NoteService; +import org.sopt.lequuServer.domain.note.repository.NoteRepository; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class CommonFacade { - - private final NoteService noteService; private final BookRepository bookRepository; + private final NoteRepository noteRepository; public SplashDto getSplash() { - return SplashDto.of(noteService.getAllNoteCount()); + return SplashDto.of(noteRepository.count()); } public List getHome() { diff --git a/src/main/java/org/sopt/lequuServer/domain/member/repository/MemberRepository.java b/src/main/java/org/sopt/lequuServer/domain/member/repository/MemberRepository.java index 6a68610..2dcda7e 100644 --- a/src/main/java/org/sopt/lequuServer/domain/member/repository/MemberRepository.java +++ b/src/main/java/org/sopt/lequuServer/domain/member/repository/MemberRepository.java @@ -1,14 +1,12 @@ package org.sopt.lequuServer.domain.member.repository; +import java.util.Optional; import org.sopt.lequuServer.domain.member.model.Member; import org.sopt.lequuServer.domain.member.model.SocialPlatform; +import org.sopt.lequuServer.global.exception.enums.ErrorType; import org.sopt.lequuServer.global.exception.model.CustomException; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.Optional; - -import static org.sopt.lequuServer.global.exception.enums.ErrorType.NOT_FOUND_MEMBER_ERROR; - public interface MemberRepository extends JpaRepository { boolean existsBySocialPlatformAndSocialId(SocialPlatform socialPlatform, String socialId); @@ -17,6 +15,6 @@ public interface MemberRepository extends JpaRepository { default Member findByIdOrThrow(Long id) { return this.findById(id) - .orElseThrow(() -> new CustomException(NOT_FOUND_MEMBER_ERROR)); + .orElseThrow(() -> new CustomException(ErrorType.NOT_FOUND_MEMBER_ERROR)); } -} \ No newline at end of file +} diff --git a/src/main/java/org/sopt/lequuServer/domain/member/service/MemberService.java b/src/main/java/org/sopt/lequuServer/domain/member/service/MemberService.java index 76d3b57..3ebda31 100644 --- a/src/main/java/org/sopt/lequuServer/domain/member/service/MemberService.java +++ b/src/main/java/org/sopt/lequuServer/domain/member/service/MemberService.java @@ -1,10 +1,14 @@ package org.sopt.lequuServer.domain.member.service; +import static org.sopt.lequuServer.global.exception.enums.ErrorType.INVALID_SOCIAL_ACCESS_TOKEN; +import static org.sopt.lequuServer.global.exception.enums.ErrorType.INVALID_TOKEN_HEADER_ERROR; +import static org.sopt.lequuServer.global.exception.enums.ErrorType.NOT_FOUND_MEMBER_ERROR; + import lombok.RequiredArgsConstructor; import org.sopt.lequuServer.domain.member.dto.request.SocialLoginRequestDto; import org.sopt.lequuServer.domain.member.dto.response.MemberLoginResponseDto; -import org.sopt.lequuServer.domain.member.model.SocialPlatform; import org.sopt.lequuServer.domain.member.model.Member; +import org.sopt.lequuServer.domain.member.model.SocialPlatform; import org.sopt.lequuServer.domain.member.repository.MemberRepository; import org.sopt.lequuServer.global.auth.fegin.kakao.KakaoLoginService; import org.sopt.lequuServer.global.auth.jwt.JwtProvider; @@ -14,8 +18,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import static org.sopt.lequuServer.global.exception.enums.ErrorType.*; - @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -101,7 +103,4 @@ private static String parseTokenString(String tokenString) { return strings[1]; } - public Member getMember(Long memberId) { - return memberRepository.findByIdOrThrow(memberId); - } } \ No newline at end of file diff --git a/src/main/java/org/sopt/lequuServer/domain/note/controller/NoteController.java b/src/main/java/org/sopt/lequuServer/domain/note/controller/NoteController.java new file mode 100644 index 0000000..59278b7 --- /dev/null +++ b/src/main/java/org/sopt/lequuServer/domain/note/controller/NoteController.java @@ -0,0 +1,31 @@ +package org.sopt.lequuServer.domain.note.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.security.Principal; +import lombok.RequiredArgsConstructor; +import org.sopt.lequuServer.domain.note.dto.request.NoteCreateDto; +import org.sopt.lequuServer.domain.note.facade.NoteFacade; +import org.sopt.lequuServer.global.auth.jwt.JwtProvider; +import org.sopt.lequuServer.global.common.dto.ApiResponse; +import org.sopt.lequuServer.global.exception.enums.SuccessType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/note") +@Tag(name = "Note", description = "레큐 노트 API") +@SecurityRequirement(name = "JWT Auth") +public class NoteController { + + private final NoteFacade noteFacade; + + @Operation(summary = "레큐 노트 생성") + @PostMapping + public ApiResponse createNote(Principal principal, NoteCreateDto noteCreateDto) { + return ApiResponse.success(SuccessType.CREATE_NOTE_SUCCESS, noteFacade.createNote(JwtProvider.getUserFromPrincial(principal), noteCreateDto)); + } +} diff --git a/src/main/java/org/sopt/lequuServer/domain/note/dto/request/NoteCreateDto.java b/src/main/java/org/sopt/lequuServer/domain/note/dto/request/NoteCreateDto.java new file mode 100644 index 0000000..903f6fb --- /dev/null +++ b/src/main/java/org/sopt/lequuServer/domain/note/dto/request/NoteCreateDto.java @@ -0,0 +1,23 @@ +package org.sopt.lequuServer.domain.note.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record NoteCreateDto( + @Schema(example = "1") + Long bookId, + //TODO DB상에서 관리하려면 그냥 Auditing으로 하는게 좋을지도? + @Schema(example = "2023.12.27 (수)") + String noteDate, + //TODO validation 추가 + @Schema(example = "test") + @NotBlank + @Size(min = 1, max = 1000, message = "레큐노트 내용은 1자 이상 1000자 이하여야합니다.") + String content, + @Schema(example = "0") + int textColor, + @Schema(example = "0") + String background +) { +} diff --git a/src/main/java/org/sopt/lequuServer/domain/note/dto/response/NoteResponseDto.java b/src/main/java/org/sopt/lequuServer/domain/note/dto/response/NoteResponseDto.java new file mode 100644 index 0000000..e66ca99 --- /dev/null +++ b/src/main/java/org/sopt/lequuServer/domain/note/dto/response/NoteResponseDto.java @@ -0,0 +1,12 @@ +package org.sopt.lequuServer.domain.note.dto.response; + +import org.sopt.lequuServer.domain.note.model.Note; + +public record NoteResponseDto( + Long noteId, + String bookUuid +) { + public static NoteResponseDto of(Note note) { + return new NoteResponseDto(note.getId(), note.getBook().getUuid()); + } +} diff --git a/src/main/java/org/sopt/lequuServer/domain/note/facade/NoteFacade.java b/src/main/java/org/sopt/lequuServer/domain/note/facade/NoteFacade.java new file mode 100644 index 0000000..acaac6c --- /dev/null +++ b/src/main/java/org/sopt/lequuServer/domain/note/facade/NoteFacade.java @@ -0,0 +1,28 @@ +package org.sopt.lequuServer.domain.note.facade; + +import lombok.RequiredArgsConstructor; +import org.sopt.lequuServer.domain.book.model.Book; +import org.sopt.lequuServer.domain.book.repository.BookRepository; +import org.sopt.lequuServer.domain.member.model.Member; +import org.sopt.lequuServer.domain.member.repository.MemberRepository; +import org.sopt.lequuServer.domain.note.dto.request.NoteCreateDto; +import org.sopt.lequuServer.domain.note.dto.response.NoteResponseDto; +import org.sopt.lequuServer.domain.note.model.Note; +import org.sopt.lequuServer.domain.note.service.NoteService; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class NoteFacade { + + private final MemberRepository memberRepository; + private final BookRepository bookRepository; + private final NoteService noteService; + + public NoteResponseDto createNote(Long userId, NoteCreateDto noteCreateDto) { + Member member = memberRepository.findByIdOrThrow(userId); + Book book = bookRepository.findByIdOrThrow(noteCreateDto.bookId()); + + return noteService.saveNote(Note.of(noteCreateDto.content(), noteCreateDto.background(), noteCreateDto.textColor(), member, book)); + } +} diff --git a/src/main/java/org/sopt/lequuServer/domain/note/service/NoteService.java b/src/main/java/org/sopt/lequuServer/domain/note/service/NoteService.java index bdda2e3..d530623 100644 --- a/src/main/java/org/sopt/lequuServer/domain/note/service/NoteService.java +++ b/src/main/java/org/sopt/lequuServer/domain/note/service/NoteService.java @@ -1,8 +1,11 @@ package org.sopt.lequuServer.domain.note.service; import lombok.RequiredArgsConstructor; +import org.sopt.lequuServer.domain.note.dto.response.NoteResponseDto; +import org.sopt.lequuServer.domain.note.model.Note; import org.sopt.lequuServer.domain.note.repository.NoteRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -10,10 +13,8 @@ public class NoteService { private final NoteRepository noteRepository; - //TODO 되는지 검증 필요 - public Long getAllNoteCount() { - return noteRepository.count(); + @Transactional + public NoteResponseDto saveNote(Note note) { + return NoteResponseDto.of(noteRepository.save(note)); } - - } diff --git a/src/main/java/org/sopt/lequuServer/global/exception/enums/SuccessType.java b/src/main/java/org/sopt/lequuServer/global/exception/enums/SuccessType.java index dccda13..0cc609e 100644 --- a/src/main/java/org/sopt/lequuServer/global/exception/enums/SuccessType.java +++ b/src/main/java/org/sopt/lequuServer/global/exception/enums/SuccessType.java @@ -27,6 +27,7 @@ public enum SuccessType { /** * 201 CREATED */ + CREATE_NOTE_SUCCESS(HttpStatus.CREATED, "레큐노트를 성공적으로 생성했습니다."), BOOK_CREATE_SUCCESS(HttpStatus.CREATED, "레큐북이 성공적으로 생성됐습니다.") ;