Skip to content

Commit 3329361

Browse files
authored
Merge pull request #78 from project-lyrics/dev
Dev to Main
2 parents 84952eb + cc22bcc commit 3329361

30 files changed

Lines changed: 334 additions & 33 deletions

src/main/java/com/projectlyrics/server/domain/common/message/ErrorCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public enum ErrorCode {
5959
INVALID_NOTE_DELETION(HttpStatus.BAD_REQUEST, "05003", "해당 노트를 삭제할 수 없습니다."),
6060
INVALID_NOTE_UPDATE(HttpStatus.BAD_REQUEST, "05004", "해당 노트를 수정할 수 없습니다."),
6161
TOO_MANY_DRAFT_NOTE(HttpStatus.BAD_REQUEST, "05005", "임시저장 노트의 개수가 초과되었습니다."),
62+
NO_LYRICS_FOR_NOTE(HttpStatus.BAD_REQUEST, "05006", "해당 노트에 대한 가사가 필요합니다."),
6263

6364
// Song
6465
SONG_NOT_FOUND(HttpStatus.NOT_FOUND, "06000", "해당 노래를 조회할 수 없습니다."),

src/main/java/com/projectlyrics/server/domain/note/api/NoteController.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@
2929
import org.springframework.web.bind.annotation.RestController;
3030

3131
@RestController
32-
@RequestMapping("/api/v1/notes")
32+
@RequestMapping("/api/v1")
3333
@RequiredArgsConstructor
3434
public class NoteController {
3535

3636
private final NoteCommandService noteCommandService;
3737
private final NoteQueryService noteQueryService;
3838
private final ViewCommandService viewCommandService;
3939

40-
@PostMapping
40+
@PostMapping("/notes")
4141
public ResponseEntity<NoteCreateResponse> create(
4242
@Authenticated AuthContext authContext,
4343
@RequestBody @Valid NoteCreateRequest request
@@ -49,7 +49,7 @@ public ResponseEntity<NoteCreateResponse> create(
4949
.body(new NoteCreateResponse(true));
5050
}
5151

52-
@PatchMapping("/{noteId}")
52+
@PatchMapping("/notes/{noteId}")
5353
public ResponseEntity<NoteUpdateResponse> update(
5454
@Authenticated AuthContext authContext,
5555
@PathVariable(name = "noteId") Long noteId,
@@ -62,7 +62,7 @@ public ResponseEntity<NoteUpdateResponse> update(
6262
.body(new NoteUpdateResponse(true));
6363
}
6464

65-
@DeleteMapping("/{noteId}")
65+
@DeleteMapping("/notes/{noteId}")
6666
public ResponseEntity<NoteDeleteResponse> delete(
6767
@Authenticated AuthContext authContext,
6868
@PathVariable(name = "noteId") Long noteId
@@ -74,7 +74,7 @@ public ResponseEntity<NoteDeleteResponse> delete(
7474
.body(new NoteDeleteResponse(true));
7575
}
7676

77-
@GetMapping("/{noteId}")
77+
@GetMapping("/notes/{noteId}")
7878
public ResponseEntity<NoteDetailResponse> getNote(
7979
@Authenticated AuthContext authContext,
8080
@RequestHeader("Device-Id") String deviceId,
@@ -91,7 +91,7 @@ public ResponseEntity<NoteDetailResponse> getNote(
9191
.body(noteQueryService.getNoteById(noteId, authContext.getId()));
9292
}
9393

94-
@GetMapping
94+
@GetMapping("/users/notes")
9595
public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfUser(
9696
@Authenticated AuthContext authContext,
9797
@RequestParam(name = "hasLyrics") boolean hasLyrics,
@@ -106,21 +106,22 @@ public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfUs
106106
.body(response);
107107
}
108108

109-
@GetMapping("/favorite-artists")
110-
public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfFavoriteArtists(
109+
@GetMapping("/notes")
110+
public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotes(
111111
@Authenticated AuthContext authContext,
112112
@RequestParam(name = "hasLyrics") boolean hasLyrics,
113+
@RequestParam(name = "isFavoriteArtistsOnly", defaultValue = "false") boolean isFavoriteArtistsOnly,
113114
@RequestParam(name = "cursor", required = false) Long cursor,
114115
@RequestParam(name = "size", defaultValue = "10") int size
115116
) {
116-
CursorBasePaginatedResponse<NoteGetResponse> response = noteQueryService.getNotesOfFavoriteArtists(hasLyrics, authContext.getId(), cursor, size);
117+
CursorBasePaginatedResponse<NoteGetResponse> response = noteQueryService.getNotes(hasLyrics, isFavoriteArtistsOnly, authContext.getId(), cursor, size);
117118

118119
return ResponseEntity
119120
.status(HttpStatus.OK)
120121
.body(response);
121122
}
122123

123-
@GetMapping("/artists")
124+
@GetMapping("/notes/artists")
124125
public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfArtist(
125126
@Authenticated AuthContext authContext,
126127
@RequestParam(name = "hasLyrics") boolean hasLyrics,
@@ -135,7 +136,7 @@ public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfAr
135136
.body(response);
136137
}
137138

138-
@GetMapping("/songs")
139+
@GetMapping("/notes/songs")
139140
public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfSong(
140141
@Authenticated AuthContext authContext,
141142
@RequestParam(name = "hasLyrics") boolean hasLyrics,
@@ -150,7 +151,7 @@ public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesOfSo
150151
.body(response);
151152
}
152153

153-
@GetMapping("/bookmarked")
154+
@GetMapping("/notes/bookmarked")
154155
public ResponseEntity<CursorBasePaginatedResponse<NoteGetResponse>> getNotesBookmarked(
155156
@Authenticated AuthContext authContext,
156157
@RequestParam(name = "hasLyrics") boolean hasLyrics,

src/main/java/com/projectlyrics/server/domain/note/dto/request/NoteCreateRequest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.projectlyrics.server.domain.note.entity.NoteBackground;
44
import com.projectlyrics.server.domain.note.entity.NoteStatus;
5+
import com.projectlyrics.server.domain.note.entity.NoteType;
56
import jakarta.validation.constraints.NotBlank;
67
import jakarta.validation.constraints.NotNull;
78

@@ -12,6 +13,8 @@ public record NoteCreateRequest(
1213
NoteBackground background,
1314
@NotNull
1415
NoteStatus status,
16+
@NotNull(message = "노트 유형이 입력되지 않았습니다.")
17+
NoteType noteType,
1518
Long songId
1619
) {
1720
}

src/main/java/com/projectlyrics/server/domain/note/dto/response/NoteDetailResponse.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public record NoteDetailResponse(
1414
Long id,
1515
String content,
1616
String status,
17+
String noteType,
1718
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
1819
LocalDateTime createdAt,
1920
LyricsGetResponse lyrics,
@@ -31,6 +32,7 @@ public static NoteDetailResponse of(Note note, List<Comment> comments, Long user
3132
note.getId(),
3233
note.getContent(),
3334
note.getNoteStatus().name(),
35+
note.getNoteType().name(),
3436
note.getCreatedAt(),
3537
LyricsGetResponse.from(note.getLyrics()),
3638
UserGetResponse.from(note.getPublisher()),
@@ -50,6 +52,7 @@ public static NoteDetailResponse of(Note note, List<Comment> comments, Long user
5052
note.getId(),
5153
note.getContent(),
5254
note.getNoteStatus().name(),
55+
note.getNoteType().name(),
5356
createdAt,
5457
LyricsGetResponse.from(note.getLyrics()),
5558
UserGetResponse.from(note.getPublisher()),

src/main/java/com/projectlyrics/server/domain/note/dto/response/NoteGetResponse.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public record NoteGetResponse(
1212
Long id,
1313
String content,
1414
String status,
15+
String noteType,
1516
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
1617
LocalDateTime createdAt,
1718
LyricsGetResponse lyrics,
@@ -28,6 +29,7 @@ public static NoteGetResponse of(Note note, Long userId) {
2829
note.getId(),
2930
note.getContent(),
3031
note.getNoteStatus().name(),
32+
note.getNoteType().name(),
3133
note.getCreatedAt(),
3234
LyricsGetResponse.from(note.getLyrics()),
3335
UserGetResponse.from(note.getPublisher()),
@@ -44,6 +46,7 @@ public static NoteGetResponse of(Note note, Long userId, LocalDateTime createdAt
4446
note.getId(),
4547
note.getContent(),
4648
note.getNoteStatus().name(),
49+
note.getNoteType().name(),
4750
createdAt,
4851
LyricsGetResponse.from(note.getLyrics()),
4952
UserGetResponse.from(note.getPublisher()),

src/main/java/com/projectlyrics/server/domain/note/entity/Note.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ public class Note extends BaseEntity {
3434
@Enumerated(EnumType.STRING)
3535
private NoteStatus noteStatus;
3636

37+
@Enumerated(EnumType.STRING)
38+
@Column(nullable = false, columnDefinition = "VARCHAR(50) DEFAULT 'FREE'")
39+
private NoteType noteType;
40+
3741
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
3842
@JoinColumn(name="lyrics_id")
3943
private Lyrics lyrics;
@@ -58,12 +62,14 @@ private Note(
5862
String content,
5963
Lyrics lyrics,
6064
NoteStatus noteStatus,
65+
NoteType noteType,
6166
User publisher,
6267
Song song
6368
) {
6469
this.id = id;
6570
this.content = content;
6671
this.noteStatus = noteStatus;
72+
this.noteType = noteType;
6773
this.publisher = publisher;
6874
this.song = song;
6975
addLyrics(lyrics);
@@ -73,17 +79,19 @@ private Note(
7379
String content,
7480
Lyrics lyrics,
7581
NoteStatus noteStatus,
82+
NoteType noteType,
7683
User publisher,
7784
Song song
7885
) {
79-
this(null, content, lyrics, noteStatus, publisher, song);
86+
this(null, content, lyrics, noteStatus, noteType, publisher, song);
8087
}
8188

8289
public static Note create(NoteCreate noteCreate) {
8390
return new Note(
8491
noteCreate.content(),
8592
Lyrics.of(noteCreate.lyrics(), noteCreate.background()),
8693
noteCreate.status(),
94+
noteCreate.noteType(),
8795
noteCreate.publisher(),
8896
noteCreate.song()
8997
);
@@ -95,6 +103,7 @@ public static Note createWithId(Long id, NoteCreate noteCreate) {
95103
noteCreate.content(),
96104
Lyrics.of(noteCreate.lyrics(), noteCreate.background()),
97105
noteCreate.status(),
106+
noteCreate.noteType(),
98107
noteCreate.publisher(),
99108
noteCreate.song()
100109
);

src/main/java/com/projectlyrics/server/domain/note/entity/NoteCreate.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.projectlyrics.server.domain.note.entity;
22

33
import com.projectlyrics.server.domain.note.dto.request.NoteCreateRequest;
4+
import com.projectlyrics.server.domain.note.exception.NoLyricsForNoteException;
45
import com.projectlyrics.server.domain.song.entity.Song;
56
import com.projectlyrics.server.domain.user.entity.User;
67

@@ -11,22 +12,32 @@ public record NoteCreate(
1112
String lyrics,
1213
NoteBackground background,
1314
NoteStatus status,
15+
NoteType noteType,
1416
User publisher,
1517
Song song
1618
) {
1719

1820
public static NoteCreate from(NoteCreateRequest request, User publisher, Song song) {
1921
checkNull(request.status());
22+
checkNull(request.noteType());
2023
checkNull(publisher);
2124
checkNull(song);
25+
validateLyricsForType(request.noteType(), request.lyrics());
2226

2327
return new NoteCreate(
2428
request.content(),
2529
request.lyrics(),
2630
request.background(),
2731
request.status(),
32+
request.noteType(),
2833
publisher,
2934
song
3035
);
3136
}
37+
38+
private static void validateLyricsForType(NoteType noteType, String lyrics) {
39+
if (noteType == NoteType.LYRICS_ANALYSIS && (lyrics == null || lyrics.isBlank())) {
40+
throw new NoLyricsForNoteException();
41+
}
42+
}
3243
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.projectlyrics.server.domain.note.entity;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonValue;
5+
import lombok.RequiredArgsConstructor;
6+
7+
import java.util.Arrays;
8+
9+
@RequiredArgsConstructor
10+
public enum NoteType {
11+
12+
FREE("FREE"),
13+
QUESTION("QUESTION"),
14+
LYRICS_ANALYSIS("LYRICS_ANALYSIS"),
15+
;
16+
17+
private final String type;
18+
19+
@JsonValue
20+
public String getType() {
21+
return type;
22+
}
23+
24+
@JsonCreator
25+
public static NoteType of(String type) {
26+
return Arrays.stream(NoteType.values())
27+
.filter(noteType -> noteType.type.equals(type))
28+
.findFirst()
29+
.orElseThrow(() -> new IllegalArgumentException("Invalid NoteType: " + type));
30+
}
31+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.projectlyrics.server.domain.note.exception;
2+
3+
import com.projectlyrics.server.domain.common.message.ErrorCode;
4+
import com.projectlyrics.server.global.exception.FeelinException;
5+
6+
public class NoLyricsForNoteException extends FeelinException {
7+
8+
public NoLyricsForNoteException() {
9+
super(ErrorCode.NO_LYRICS_FOR_NOTE);
10+
}
11+
}

src/main/java/com/projectlyrics/server/domain/note/repository/NoteQueryRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public interface NoteQueryRepository {
1212

1313
Slice<Note> findAllByUserId(boolean hasLyrics, Long artistId, Long userId, Long cursorId, Pageable pageable);
1414
Slice<Note> findAllByArtistIds(boolean hasLyrics, List<Long> artistsIds, Long userId, Long cursorId, Pageable pageable);
15+
Slice<Note> findAll(boolean hasLyrics, List<Long> artistsIds, Long userId, Long cursorId, Pageable pageable);
1516
Slice<Note> findAllByArtistId(boolean hasLyrics, Long artistId, Long userId, Long cursorId, Pageable pageable);
1617
Slice<Note> findAllBookmarkedAndByArtistId(boolean hasLyrics, Long artistId, Long userId, Long cursorId, Pageable pageable);
1718
Slice<Note> findAllBySongId(boolean hasLyrics, Long songId, Long userId, Long cursorId, Pageable pageable);

0 commit comments

Comments
 (0)