Skip to content

Commit 48041e3

Browse files
authored
Merge pull request #66 from Move-Log/develop
Merge develop to main
2 parents 7f6f240 + 0b3e28c commit 48041e3

File tree

4 files changed

+110
-12
lines changed

4 files changed

+110
-12
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.movelog.domain.record.dto.response;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
import java.time.LocalDateTime;
10+
11+
@Builder
12+
@AllArgsConstructor
13+
@NoArgsConstructor
14+
@Getter
15+
public class RecordCalendarRes {
16+
17+
@Schema( type = "int", example ="1", description="기록 ID")
18+
private Long recordId;
19+
20+
@Schema( type = "String", example ="https://movelog.s3.ap-northeast-2.amazonaws.com/record/2021-08-01/1.jpg", description="기록 이미지 URL")
21+
private String recordImageUrl;
22+
23+
@Schema( type = "String", example ="헬스", description="명사")
24+
private String noun;
25+
26+
@Schema( type = "String", example ="했어요", description="동사")
27+
private String verb;
28+
29+
@Schema( type = "LocalDateTime", example ="2025-08-01T00:00:00", description="기록 생성 시간")
30+
private LocalDateTime createdAt;
31+
32+
}

src/main/java/com/movelog/domain/record/presentation/RecordController.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.movelog.domain.record.presentation;
22

3+
import com.movelog.domain.news.dto.response.NewsCalendarRes;
34
import com.movelog.domain.record.dto.request.CreateRecordReq;
45
import com.movelog.domain.record.dto.request.SearchKeywordReq;
56
import com.movelog.domain.record.dto.response.RecentRecordImagesRes;
7+
import com.movelog.domain.record.dto.response.RecordCalendarRes;
68
import com.movelog.domain.record.dto.response.SearchKeywordRes;
79
import com.movelog.domain.record.dto.response.TodayRecordStatus;
810
import com.movelog.domain.record.service.RecordService;
@@ -16,6 +18,7 @@
1618
import io.swagger.v3.oas.annotations.responses.ApiResponse;
1719
import io.swagger.v3.oas.annotations.responses.ApiResponses;
1820
import lombok.RequiredArgsConstructor;
21+
import org.springframework.data.domain.Page;
1922
import org.springframework.http.ResponseEntity;
2023
import org.springframework.security.core.annotation.AuthenticationPrincipal;
2124
import org.springframework.web.ErrorResponse;
@@ -45,7 +48,7 @@ public ResponseEntity<?> createRecord(
4548
@Parameter(description = "Schemas의 CreateRecordReq를 참고해주세요.", required = true) @RequestPart CreateRecordReq createRecordReq,
4649
@RequestPart(value = "img", required = false) MultipartFile img
4750
) {
48-
recordService.createRecord(userPrincipal.getId(), createRecordReq, img);
51+
recordService.createRecord(userPrincipal, createRecordReq, img);
4952
return ResponseEntity.ok(ApiResponseUtil.success(Message.builder().message("기록이 생성되었습니다.").build()));
5053
}
5154

@@ -61,7 +64,7 @@ public ResponseEntity<?> createRecord(
6164
public ResponseEntity<?> retrieveTodayRecord(
6265
@Parameter(description = "User의 토큰을 입력해주세요.", required = false) @AuthenticationPrincipal UserPrincipal userPrincipal
6366
) {;
64-
TodayRecordStatus result = recordService.retrieveTodayRecord(5L);
67+
TodayRecordStatus result = recordService.retrieveTodayRecord(userPrincipal);
6568
return ResponseEntity.ok(ApiResponseUtil.success(result));
6669
}
6770

@@ -101,5 +104,25 @@ public ResponseEntity<?> searchKeyword(
101104
}
102105

103106

107+
@Operation(summary = "날짜별 기록 목록 조회 API", description = "특정 날짜에 생성된 기록 목록을 조회하는 API입니다.")
108+
@ApiResponses(value = {
109+
@ApiResponse(responseCode = "200", description = "날짜별 기록 목록 조회 성공",
110+
content = @Content(mediaType = "application/json",
111+
schema = @Schema(type = "array", implementation = RecordCalendarRes.class))),
112+
@ApiResponse(responseCode = "400", description = "날짜별 기록 목록 조회 실패",
113+
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)))
114+
115+
})
116+
@GetMapping("/calendar/{date}")
117+
public ResponseEntity<?> getRecordByDate(
118+
@Parameter(description = "Access Token을 입력해주세요.", required = true) @AuthenticationPrincipal UserPrincipal userPrincipal,
119+
@Parameter(description = "조회할 날짜를 입력해주세요. (yyyy-MM-dd 형식)", required = true) @PathVariable String date,
120+
@Parameter(description = "기록 목록의 페이지 번호를 입력해주세요. **Page는 0부터 시작됩니다!**", required = true)
121+
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page
122+
) {
123+
Page<RecordCalendarRes> response = recordService.getRecordByDate(userPrincipal, date, page);
124+
return ResponseEntity.ok(ApiResponseUtil.success(response));
125+
}
126+
104127

105128
}

src/main/java/com/movelog/domain/record/repository/RecordRepository.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import com.movelog.domain.record.domain.Keyword;
44
import com.movelog.domain.record.domain.Record;
55
import com.movelog.domain.user.domain.User;
6+
import org.springframework.data.domain.Page;
7+
import org.springframework.data.domain.Pageable;
68
import org.springframework.data.jpa.repository.JpaRepository;
9+
import org.springframework.data.jpa.repository.Query;
710
import org.springframework.stereotype.Repository;
811

912
import java.time.LocalDateTime;
@@ -15,4 +18,11 @@ public interface RecordRepository extends JpaRepository<Record,Long> {
1518
List<Record> findByKeywordInAndActionTimeBetween(List<Keyword> keywords, LocalDateTime startTime, LocalDateTime endTime);
1619

1720
List<Record> findTop5ByKeywordOrderByActionTimeDesc(Keyword keyword);
21+
22+
@Query("SELECT r FROM Record r " +
23+
"JOIN r.keyword k " +
24+
"WHERE k.user = :user " +
25+
"AND r.actionTime BETWEEN :start AND :end " +
26+
"ORDER BY r.actionTime ASC")
27+
Page<Record> findRecordByUserAndCreatedAtBetween(User user, LocalDateTime start, LocalDateTime end, Pageable pageable);
1828
}

src/main/java/com/movelog/domain/record/service/RecordService.java

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
package com.movelog.domain.record.service;
22

3+
import com.movelog.domain.news.domain.News;
4+
import com.movelog.domain.news.dto.response.NewsCalendarRes;
35
import com.movelog.domain.record.domain.Keyword;
46
import com.movelog.domain.record.domain.Record;
57
import com.movelog.domain.record.domain.VerbType;
68
import com.movelog.domain.record.dto.request.CreateRecordReq;
79
import com.movelog.domain.record.dto.request.SearchKeywordReq;
810
import com.movelog.domain.record.dto.response.RecentRecordImagesRes;
11+
import com.movelog.domain.record.dto.response.RecordCalendarRes;
912
import com.movelog.domain.record.dto.response.SearchKeywordRes;
1013
import com.movelog.domain.record.dto.response.TodayRecordStatus;
1114
import com.movelog.domain.record.repository.KeywordRepository;
1215
import com.movelog.domain.record.repository.RecordRepository;
16+
import com.movelog.domain.user.application.UserService;
1317
import com.movelog.domain.user.domain.User;
1418
import com.movelog.domain.user.domain.repository.UserRepository;
19+
import com.movelog.domain.user.exception.UserNotFoundException;
1520
import com.movelog.global.config.security.token.UserPrincipal;
1621
import com.movelog.global.util.S3Util;
1722
import jakarta.validation.ConstraintViolation;
1823
import lombok.RequiredArgsConstructor;
1924
import lombok.extern.slf4j.Slf4j;
25+
import org.springframework.data.domain.Page;
26+
import org.springframework.data.domain.PageRequest;
27+
import org.springframework.data.domain.Pageable;
2028
import org.springframework.stereotype.Service;
2129
import org.springframework.transaction.annotation.Transactional;
2230
import org.springframework.web.multipart.MultipartFile;
@@ -34,14 +42,16 @@
3442
@Slf4j
3543
public class RecordService {
3644
private final RecordRepository recordRepository;
37-
private final UserRepository userRepository;
45+
private final UserService userService;
46+
3847
private final KeywordRepository keywordRepository;
3948
private final S3Util s3Util;
49+
private final UserRepository userRepository;
4050

4151
@Transactional
42-
public void createRecord(Long userId, CreateRecordReq createRecordReq, MultipartFile img) {
43-
User user = validUserById(userId);
44-
// User user = validUserById(5L);
52+
public void createRecord(UserPrincipal userPrincipal, CreateRecordReq createRecordReq, MultipartFile img) {
53+
User user = validUserById(userPrincipal);
54+
// User user = userRepository.findById(5L).orElseThrow(UserNotFoundException::new);
4555
validateCreateRecordReq(createRecordReq);
4656

4757
String recordImgUrl = s3Util.uploadToRecordFolder(img);
@@ -83,9 +93,9 @@ public void createRecord(Long userId, CreateRecordReq createRecordReq, Multipart
8393
}
8494

8595

86-
public TodayRecordStatus retrieveTodayRecord(Long userId) {
96+
public TodayRecordStatus retrieveTodayRecord(UserPrincipal userPrincipal) {
8797
// 유저 유효성 검사 및 조회
88-
User user = validUserById(userId);
98+
User user = validUserById(userPrincipal);
8999

90100
// 오늘의 시작 시간과 끝 시간 계산
91101
LocalDate today = LocalDate.now();
@@ -120,7 +130,7 @@ public TodayRecordStatus retrieveTodayRecord(Long userId) {
120130
}
121131

122132
public List<RecentRecordImagesRes> retrieveRecentRecordImages(UserPrincipal userPrincipal, Long keywordId) {
123-
User user = validUserById(userPrincipal.getId());
133+
User user = validUserById(userPrincipal);
124134
// User user = validUserById(5L);
125135
Keyword keyword = validKeywordById(keywordId);
126136
List<Record> records = recordRepository.findTop5ByKeywordOrderByActionTimeDesc(keyword);
@@ -136,7 +146,7 @@ public List<RecentRecordImagesRes> retrieveRecentRecordImages(UserPrincipal user
136146

137147

138148
public List<SearchKeywordRes> searchKeyword(UserPrincipal userPrincipal, SearchKeywordReq searchKeywordReq) {
139-
User user = validUserById(userPrincipal.getId());
149+
User user = validUserById(userPrincipal);
140150
// User user = validUserById(5L);
141151
String keyword = searchKeywordReq.getSearchKeyword();
142152
List<Keyword> keywords = keywordRepository.findAllByUserAndKeywordContaining(user, keyword);
@@ -161,8 +171,29 @@ public List<SearchKeywordRes> searchKeyword(UserPrincipal userPrincipal, SearchK
161171
return sortedResults;
162172
}
163173

164-
private User validUserById(Long userId) {
165-
Optional<User> userOptional = userRepository.findById(userId);
174+
public Page<RecordCalendarRes> getRecordByDate(UserPrincipal userPrincipal, String date, Integer page) {
175+
User user = validUserById(userPrincipal);
176+
// User user = userRepository.findById(5L).orElseThrow(UserNotFoundException::new);
177+
LocalDateTime start = LocalDateTime.parse(date + "T00:00:00");
178+
LocalDateTime end = LocalDateTime.parse(date + "T23:59:59");
179+
180+
Pageable pageable = PageRequest.of(0, 15); // 원하는 페이지와 크기를 지정
181+
Page<Record> recordList = recordRepository.findRecordByUserAndCreatedAtBetween(user, start, end, pageable);
182+
183+
return recordList.map(record -> RecordCalendarRes.builder()
184+
.recordId(record.getRecordId())
185+
.recordImageUrl(record.getRecordImage())
186+
.noun(record.getKeyword().getKeyword())
187+
.verb(VerbType.getStringVerbType(record.getKeyword().getVerbType()))
188+
.createdAt(record.getCreatedAt())
189+
.build());
190+
191+
}
192+
193+
194+
private User validUserById(UserPrincipal userPrincipal) {
195+
Optional<User> userOptional = userService.findById(userPrincipal.getId());
196+
if (userOptional.isEmpty()) { throw new UserNotFoundException(); }
166197
return userOptional.get();
167198
}
168199

@@ -183,4 +214,6 @@ private void validateCreateRecordReq(CreateRecordReq createRecordReq) {
183214
throw new IllegalArgumentException("noun is required.");
184215
}
185216
}
217+
218+
186219
}

0 commit comments

Comments
 (0)