Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
feat: ✨ 북마크 추가/삭제 기능 구현, 일기/홈화면 조회 쿼리문 수정 (#66)
Browse files Browse the repository at this point in the history
* Initial commit

* Feat/#1 oauth2login (#3)

* feat: User 엔터티 생성

* feat: jwt 버전 11->12, JWTUtil 생성

* feat: JWTFilter(JwtAuthenticationFilter) 등록

* feat: kakao 로그인 구현

* docs: swagger 태그(Authorization) 추가 (#5)

* feat: User 엔터티 생성

* feat: jwt 버전 11->12, JWTUtil 생성

* feat: JWTFilter(JwtAuthenticationFilter) 등록

* feat: kakao 로그인 구현

* docs: swagger 태그(Authorization) 추가

* feat: accesstoken 테스트를 위한 test login 생성 (#9)

* feat: User 엔티티에 상속 (#12)

* feat: BaseEntity 생성

* feat: User 엔티티에 상속

* feat: 일기 생성 기능 구현 (#14)

* feat: accesstoken 테스트를 위한 test login 생성

* feat: 일기 생성 기능 구현

* hotfix: ci 에러 수정 (#16)

* feat: accesstoken 테스트를 위한 test login 생성

* feat: 일기 생성 기능 구현

* hotfix: ci 에러 수정

* fix: OIDC 카카오 로그인 nullPointerException 해결

* feat: 닉네임 설정 기능 구현 (#21)

* feat: 일기 수정 기능 구현 (#25)

* feat: 일기에 감정 컬럼 추가

* feat: 일기 수정 기능 구현

* feat: 일기 삭제 기능 구현 (#27)

* feat: 일기에 감정 컬럼 추가

* feat: 일기 수정 기능 구현

* feat: 일기 삭제 기능 구현

* feat: 일기 감정 분석 기능 구현 (#31)

* feat: 감정 저장 기능 구현 (#33)

* feat: 일기 감정 분석 기능 구현

* feat: 감정 저장 기능 구현

* fix: 🐛 감정 저장 안되던 오류 수정 (#35)

* feat: 일기 감정 분석 기능 구현

* feat: 감정 저장 기능 구현

* fix: 🐛 감정 저장 안되던 오류 수정

* hotfix: 🚑 서버 꺼짐 현상 해결 (#37)

* feat: 일기 감정 분석 기능 구현

* feat: 감정 저장 기능 구현

* fix: 🐛 감정 저장 안되던 오류 수정

* hotfix: 🚑 서버 꺼짐 현상 해결

* feat: ✨ 홈 화면 조회 기능 구현 (#41)

* feat: ✨ 회원가입 완료 여부 필드 추가 (#44)

* feat: ✨ 일기 상세 조회 구현 (#47)

* feat: ✨ 기간 별 감정 통계 조회 기능 구현 (#50)

* feat: ✨ 일기 내용 검색 기능 구현 (#52)

* feat: ✨ 감정 별 일기 조회 (#54)

* feat: ✨ 월 별 일기 조회 기능 구현 (#59)

* ci: ⚡ workflow 수정 (#61)

* ci: ⚡ workflow 수정

* ci: ⚡ workflow 수정

* feat: ✨ user 엔터티 fcmToken 컬럼 추가, 로그인 시 토큰 최신화 구현 (#63)

* ci: ⚡ workflow 수정

* ci: ⚡ workflow 수정

* feat: ✨ fcm 토큰 알림 기능 구현

* feat: ✨ user 엔터티 fcmToken 컬럼 추가, 로그인 시 토큰 최신화 구현

* feat: ✨ 북마크 추가/삭제 기능 구현, 일기/홈화면 조회 쿼리문 수정 (#65)

* feat: ✨ 북마크 추가 기능 구현

* feat: ✨ 북마크 추가/삭제 기능 구현, 일기/홈화면 조회 쿼리문 수정
  • Loading branch information
LEEJaeHyeok97 authored Jul 31, 2024
1 parent 56b016e commit b10ee6a
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/aidiary/domain/auth/dto/IdTokenReq.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ public record IdTokenReq(
String provider,
String fcmToken
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.aidiary.domain.bookmark.application;

import com.aidiary.domain.bookmark.domain.Bookmark;
import com.aidiary.domain.bookmark.domain.repository.BookmarkRepository;
import com.aidiary.domain.diary.domain.Diary;
import com.aidiary.domain.diary.domain.repository.DiaryRepository;
import com.aidiary.domain.user.domain.User;
import com.aidiary.domain.user.domain.repository.UserRepository;
import com.aidiary.global.config.security.token.UserPrincipal;
import com.aidiary.global.payload.Message;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BookmarkService {

private final UserRepository userRepository;
private final DiaryRepository diaryRepository;
private final BookmarkRepository bookmarkRepository;

@Transactional
public Message diaryBookmark(UserPrincipal userPrincipal, Long diaryId) {
User user = userRepository.findById(userPrincipal.getId())
.orElseThrow(EntityNotFoundException::new);
Diary diary = diaryRepository.findById(diaryId)
.orElseThrow(EntityNotFoundException::new);

if (!diary.getUser().equals(user)) {
return Message
.builder()
.message("해당하는 일기를 찾지 못했습니다.")
.build();
}

if (bookmarkRepository.findByDiaryId(diaryId).isPresent()) {
return Message
.builder()
.message("이미 존재하는 북마크에 북마크 추가를 시도하였습니다.")
.build();
}

Bookmark bookmark = Bookmark.builder()
.user(user)
.diary(diary)
.build();

bookmarkRepository.save(bookmark);

return Message
.builder()
.message("해당 일기에 북마크를 추가했습니다.")
.build();
}

@Transactional
public Message deleteDiaryBookmark(UserPrincipal userPrincipal, Long diaryId) {
User user = userRepository.findById(userPrincipal.getId())
.orElseThrow(EntityNotFoundException::new);
Diary diary = diaryRepository.findById(diaryId)
.orElseThrow(EntityNotFoundException::new);

if (bookmarkRepository.findByUserAndDiary(user, diary).isEmpty()) {
return Message.builder()
.message("북마크 데이터를 찾을 수 없습니다.")
.build();
}

Bookmark bookmark = bookmarkRepository.findByUserIdAndDiaryId(userPrincipal.getId(), diaryId)
.orElseThrow(EntityNotFoundException::new);

bookmarkRepository.delete(bookmark);

return Message.builder()
.message("해당 일기의 북마크를 삭제했습니다.")
.build();
}
}
35 changes: 35 additions & 0 deletions src/main/java/com/aidiary/domain/bookmark/domain/Bookmark.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.aidiary.domain.bookmark.domain;

import com.aidiary.domain.common.BaseEntity;
import com.aidiary.domain.diary.domain.Diary;
import com.aidiary.domain.user.domain.User;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Bookmark extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "diary_id")
private Diary diary;


@Builder
public Bookmark(User user, Diary diary) {
this.user = user;
this.diary = diary;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.aidiary.domain.bookmark.domain.repository;

public interface BookmarkQueryDslRepository {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.aidiary.domain.bookmark.domain.repository;

import com.aidiary.domain.bookmark.domain.Bookmark;
import com.aidiary.domain.diary.domain.Diary;
import com.aidiary.domain.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface BookmarkRepository extends JpaRepository<Bookmark, Long>, BookmarkQueryDslRepository {
Optional<Bookmark> findByDiaryId(Long id);

Optional<Bookmark> findByUserAndDiary(User user, Diary diary);

Optional<Bookmark> findByUserIdAndDiaryId(Long id, Long diaryId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.aidiary.domain.bookmark.presentation;

import com.aidiary.domain.bookmark.application.BookmarkService;
import com.aidiary.global.config.security.token.CurrentUser;
import com.aidiary.global.config.security.token.UserPrincipal;
import com.aidiary.global.payload.ErrorResponse;
import com.aidiary.global.payload.Message;
import com.aidiary.global.payload.ResponseCustom;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@Tag(name = "Bookmark", description = "Bookmark API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/bookmark")
public class BookmarkController {

private final BookmarkService bookmarkService;


@Operation(summary = "북마크 추가", description = "입력된 diary의 id값에 북마크를 생성합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "일기 북마크 성공", content = {@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = Message.class)))}),
@ApiResponse(responseCode = "400", description = "일기 북마크 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}),
})
@PostMapping("/{diaryId}")
public ResponseCustom<Message> addBookmark(
@Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal,
@Parameter(description = "diary의 id를 입력해주세요.", required = true) @PathVariable Long diaryId
) {
return ResponseCustom.OK(bookmarkService.diaryBookmark(userPrincipal, diaryId));
}

@Operation(summary = "북마크 삭제", description = "입력된 diary의 id값에 북마크를 삭제합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "일기 북마크 삭제 성공", content = {@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = Message.class)))}),
@ApiResponse(responseCode = "400", description = "일기 북마크 삭제 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}),
})
@DeleteMapping("/{diaryId}")
public ResponseCustom<Message> deleteBookmark(
@Parameter(description = "Accesstoken을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal,
@Parameter(description = "diary의 id를 입력해주세요.", required = true) @PathVariable Long diaryId
) {
return ResponseCustom.OK(bookmarkService.deleteDiaryBookmark(userPrincipal, diaryId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,9 @@ public DiaryDetailsRes viewDiary(UserPrincipal userPrincipal, Long diaryId) thro
}


DiaryDetailsRes diaryDetailsRes = DiaryDetailsRes.builder()
.diaryId(diary.getId())
.nickname(user.getNickname())
.content(diary.getContent())
.diaryEntryDate(diary.getDiaryEntryDate())
.emotion(diary.getEmotion())
.build();
DiaryDetailsRes oneByUserIdAndDiaryId = diaryRepository.findOneByUserIdAndDiaryId(userPrincipal.getId(), diaryId);

return diaryDetailsRes;
return oneByUserIdAndDiaryId;

}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/aidiary/domain/diary/domain/Diary.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ public void updateDiaryEntryDate(LocalDate diaryEntryDate) {
public void updateEmotion(String emotion) {
this.emotion = emotion;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.aidiary.domain.diary.domain.repository;

import com.aidiary.domain.diary.domain.Diary;
import com.aidiary.domain.diary.dto.DiaryDetailsRes;
import com.aidiary.domain.diary.dto.SearchDiariesRes;
import com.aidiary.domain.diary.dto.condition.DiariesSearchCondition;
Expand Down Expand Up @@ -28,4 +29,6 @@ public interface DiaryQueryDslRepository {
Slice<DiarysByEmotionRes> findAllByEmotionAndUserId(String emotion, Long id, Pageable pageable);

List<DiaryDetailsRes> findByUserIdWithYearAndMonth(Long id, int year, int month);

DiaryDetailsRes findOneByUserIdAndDiaryId(Long id, Long diaryId);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.aidiary.domain.diary.domain.repository;

import com.aidiary.domain.bookmark.domain.QBookmark;
import com.aidiary.domain.diary.domain.Diary;
import com.aidiary.domain.diary.dto.DiaryDetailsRes;
import com.aidiary.domain.diary.dto.QDiaryDetailsRes;
import com.aidiary.domain.diary.dto.QSearchDiariesRes;
Expand All @@ -26,6 +28,7 @@
import java.time.LocalDate;
import java.util.List;

import static com.aidiary.domain.bookmark.domain.QBookmark.bookmark;
import static com.aidiary.domain.diary.domain.QDiary.*;

@RequiredArgsConstructor
Expand All @@ -40,9 +43,11 @@ public List<HomeViewRes> findRecentFiveDiaryWithAuthorization(Long userId) {
.select(new QHomeViewRes(
diary.content,
diary.diaryEntryDate,
diary.emotion
diary.emotion,
bookmark.id.isNotNull()
))
.from(diary)
.leftJoin(bookmark).on(diary.id.eq(bookmark.diary.id))
.orderBy(diary.diaryEntryDate.desc())
.limit(5)
.fetch();
Expand Down Expand Up @@ -175,9 +180,11 @@ public List<DiaryDetailsRes> findByUserIdWithYearAndMonth(Long id, int year, int
diary.user.nickname,
diary.content,
diary.diaryEntryDate,
diary.emotion
diary.emotion,
bookmark.id.isNotNull()
))
.from(diary)
.leftJoin(bookmark).on(diary.id.eq(bookmark.diary.id))
.where(diary.user.id.eq(id),
diary.diaryEntryDate.year().eq(year),
diary.diaryEntryDate.month().eq(month))
Expand All @@ -187,6 +194,28 @@ public List<DiaryDetailsRes> findByUserIdWithYearAndMonth(Long id, int year, int
return results;
}

@Override
public DiaryDetailsRes findOneByUserIdAndDiaryId(Long userId, Long diaryId) {

DiaryDetailsRes diaryDetailsRes = queryFactory
.select(new QDiaryDetailsRes(
diary.id,
diary.user.nickname,
diary.content,
diary.diaryEntryDate,
diary.emotion,
bookmark.id.isNotNull()
))
.from(diary)
.leftJoin(bookmark).on(diary.id.eq(bookmark.diary.id))
.where(diary.user.id.eq(userId),
diary.id.eq(diaryId)
)
.fetchOne();

return diaryDetailsRes;
}

private Slice<DiarysByEmotionRes> toSlice(List<DiarysByEmotionRes> results, Pageable pageable) {
int pageSize = pageable.getPageSize();
boolean hasNext = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ public record DiaryDetailsRes(
String nickname,
String content,
LocalDate diaryEntryDate,
String emotion
String emotion,
Boolean isBookmarked
) {
@QueryProjection
public DiaryDetailsRes(Long diaryId, String nickname, String content, LocalDate diaryEntryDate, String emotion) {
public DiaryDetailsRes(Long diaryId, String nickname, String content, LocalDate diaryEntryDate, String emotion, Boolean isBookmarked) {
this.diaryId = diaryId;
this.nickname = nickname;
this.content = content;
this.diaryEntryDate = diaryEntryDate;
this.emotion = emotion;
this.isBookmarked = isBookmarked;
}
}
6 changes: 4 additions & 2 deletions src/main/java/com/aidiary/domain/home/dto/HomeViewRes.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
public record HomeViewRes(
String content,
LocalDate diaryEntryDate,
String emotion
String emotion,
Boolean isBookmarked
) {

@QueryProjection
public HomeViewRes(String content, LocalDate diaryEntryDate, String emotion) {
public HomeViewRes(String content, LocalDate diaryEntryDate, String emotion, Boolean isBookmarked) {
this.content = content;
this.diaryEntryDate = diaryEntryDate;
this.emotion = emotion;
this.isBookmarked = isBookmarked;
}
}

0 comments on commit b10ee6a

Please sign in to comment.