diff --git a/build.gradle b/build.gradle index c0649cd..b5e78e7 100644 --- a/build.gradle +++ b/build.gradle @@ -47,6 +47,10 @@ dependencies { // okhttp implementation 'com.squareup.okhttp3:okhttp:4.12.0' + // mapper (ModelMapper) + implementation 'org.modelmapper:modelmapper:3.0.0' + + // dotenv (환경변수 관리) implementation 'io.github.cdimascio:java-dotenv:5.2.2' } diff --git a/src/main/java/com/bamboo/log/diary/api/DiaryController.java b/src/main/java/com/bamboo/log/diary/api/DiaryController.java index bdde0d2..6268ae9 100644 --- a/src/main/java/com/bamboo/log/diary/api/DiaryController.java +++ b/src/main/java/com/bamboo/log/diary/api/DiaryController.java @@ -31,6 +31,12 @@ public ResponseEntity createDiary(@RequestBody CreateDiaryRequest createDiaryReq } } + @Operation(summary = "월별 일기 조회") + @GetMapping("/month") + public ResponseEntity getDiariesByMonth(@RequestParam String date) { + return diaryService.getDiariesByMonth(date); + } + @Operation(summary = "날짜별 일기 조회") @GetMapping("/date") public ResponseEntity getDiaryByDate(@RequestParam LocalDateTime date) { diff --git a/src/main/java/com/bamboo/log/diary/dto/ParseYearMonth.java b/src/main/java/com/bamboo/log/diary/dto/ParseYearMonth.java new file mode 100644 index 0000000..3811fea --- /dev/null +++ b/src/main/java/com/bamboo/log/diary/dto/ParseYearMonth.java @@ -0,0 +1,17 @@ +package com.bamboo.log.diary.dto; + +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.time.YearMonth; + +@Getter +@Builder +public class ParseYearMonth { + + private YearMonth parsedYearMonth; + private LocalDateTime startOfMonth; + private LocalDateTime endOfMonth; + +} diff --git a/src/main/java/com/bamboo/log/diary/dto/response/CheckDiaryResponse.java b/src/main/java/com/bamboo/log/diary/dto/response/CheckDiaryResponse.java index b15ff89..ad365f7 100644 --- a/src/main/java/com/bamboo/log/diary/dto/response/CheckDiaryResponse.java +++ b/src/main/java/com/bamboo/log/diary/dto/response/CheckDiaryResponse.java @@ -9,5 +9,5 @@ public record CheckDiaryResponse(@NotEmpty(message = "Date shouldn't be empty") LocalDateTime date, @NotEmpty(message = "Diary Description shouldn't be empty") String diaryDescription, @NotEmpty(message = "Summary Image shouldn't be empty") byte[] summaryImage - ) { -} +) { +} \ No newline at end of file diff --git a/src/main/java/com/bamboo/log/diary/dto/response/GetDiariesOfMonthResponse.java b/src/main/java/com/bamboo/log/diary/dto/response/GetDiariesOfMonthResponse.java new file mode 100644 index 0000000..96285a3 --- /dev/null +++ b/src/main/java/com/bamboo/log/diary/dto/response/GetDiariesOfMonthResponse.java @@ -0,0 +1,22 @@ +package com.bamboo.log.diary.dto.response; + +import lombok.Builder; + +import java.time.LocalDateTime; +import java.util.List; + +@Builder +public record GetDiariesOfMonthResponse( + int diariesCount, + String date, + List diaries +) { + + @Builder + public record DiaryOfMonth( + LocalDateTime createdAt, + String context, + byte[] summaryImage + ) {} + +} diff --git a/src/main/java/com/bamboo/log/diary/repository/TodaySummaryRepository.java b/src/main/java/com/bamboo/log/diary/repository/TodaySummaryRepository.java index 2442924..195266f 100644 --- a/src/main/java/com/bamboo/log/diary/repository/TodaySummaryRepository.java +++ b/src/main/java/com/bamboo/log/diary/repository/TodaySummaryRepository.java @@ -3,10 +3,13 @@ import com.bamboo.log.diary.domain.TodaySummary; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface TodaySummaryRepository extends JpaRepository { Optional findByDiaryId(Long diaryId); + List findByDiaryIdIn(List diaryIds); + } diff --git a/src/main/java/com/bamboo/log/diary/service/diary/DiaryService.java b/src/main/java/com/bamboo/log/diary/service/diary/DiaryService.java index 57d08fc..85392f0 100644 --- a/src/main/java/com/bamboo/log/diary/service/diary/DiaryService.java +++ b/src/main/java/com/bamboo/log/diary/service/diary/DiaryService.java @@ -9,6 +9,7 @@ public interface DiaryService { ResponseEntity createDiary(CreateDiaryRequest createDiaryRequest); - ResponseEntity getDiaryByDate(LocalDateTime date); + ResponseEntity getDiariesByMonth(String date); + ResponseEntity getDiaryByDate(LocalDateTime date); } diff --git a/src/main/java/com/bamboo/log/diary/service/diary/DiaryServiceImpl.java b/src/main/java/com/bamboo/log/diary/service/diary/DiaryServiceImpl.java index 66a2fe6..b00bb68 100644 --- a/src/main/java/com/bamboo/log/diary/service/diary/DiaryServiceImpl.java +++ b/src/main/java/com/bamboo/log/diary/service/diary/DiaryServiceImpl.java @@ -2,11 +2,15 @@ import com.bamboo.log.diary.domain.Diary; import com.bamboo.log.diary.domain.TodaySummary; +import com.bamboo.log.diary.dto.ParseYearMonth; import com.bamboo.log.diary.dto.request.CreateDiaryRequest; import com.bamboo.log.diary.dto.response.CheckDiaryResponse; import com.bamboo.log.diary.dto.response.CreateDiaryResponse; +import com.bamboo.log.diary.dto.response.GetDiariesOfMonthResponse; +import com.bamboo.log.diary.dto.response.GetDiariesOfMonthResponse.DiaryOfMonth; import com.bamboo.log.diary.repository.DiaryRepository; import com.bamboo.log.diary.repository.TodaySummaryRepository; + import com.bamboo.log.domain.user.oauth.dto.CustomOAuth2User; import com.bamboo.log.domain.user.oauth.repository.UserRepository; import com.bamboo.log.domain.user.oauth.service.CustomOAuth2UserService; @@ -14,8 +18,8 @@ import com.bamboo.log.diary.service.summary.TodaySummaryService; import com.bamboo.log.domain.user.jwt.service.UserContextUtil; -import com.bamboo.log.domain.user.oauth.dto.KakaoResponse; import com.bamboo.log.domain.user.oauth.entity.UserEntity; +import com.bamboo.log.domain.user.oauth.repository.UserRepository; import com.bamboo.log.utils.ResponseHandler; import com.bamboo.log.utils.dto.ResponseForm; import lombok.RequiredArgsConstructor; @@ -25,9 +29,14 @@ import java.io.IOException; import java.time.LocalDateTime; +import java.time.YearMonth; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; import java.util.List; import java.util.Optional; - @Service @Transactional @RequiredArgsConstructor @@ -41,31 +50,67 @@ public class DiaryServiceImpl implements DiaryService { @Override public ResponseEntity createDiary(CreateDiaryRequest createDiaryRequest) { - // 해당 시점의 localDateTime 저장 LocalDateTime localDateTime = LocalDateTime.now(); - - // 데이터베이스에 저장 Diary diary = saveDiary(createDiaryRequest, localDateTime); - byte[] todayImage = todaySummaryService.createTodaySummaryImage(createDiaryRequest.diaryDetail()); - // todaySummaryImage 데이터베이스에 저장 try { todaySummaryService.saveTodaySummaryImage(todayImage, diary.getId()); + } catch (RuntimeException e) { + return ResponseHandler.create404Error(new ResponseForm(), e); } catch (IOException e) { return ResponseHandler.create500Error(new ResponseForm(), e); } - // 201 code 반환 return ResponseHandler.create201Response(new ResponseForm(), new CreateDiaryResponse(localDateTime)); } + @Override + public ResponseEntity getDiariesByMonth(String date) { + ParseYearMonth parseYearMonth = getParsedDate(date); + UserEntity user = userRepository.findByUsername(userContextUtil.getUsername()); + + try { + List diaries = diaryRepository.findByUserAAndCreatedAtBetween(user, + parseYearMonth.getStartOfMonth(), parseYearMonth.getEndOfMonth()); + + List diaryIds = diaries.stream().map(Diary::getId).toList(); + Map summaryImageMap = todaySummaryRepository.findByDiaryIdIn(diaryIds) + .stream() + .collect(Collectors.toMap(TodaySummary::getDiaryId, TodaySummary::getImageData)); + + List diaryOfMonthList = diaries.stream() + .map(diary -> new DiaryOfMonth( + diary.getCreatedAt(), + diary.getContext(), + summaryImageMap.getOrDefault(diary.getId(), null) + )) + .toList(); + + return ResponseHandler.create200Response(new ResponseForm(), + GetDiariesOfMonthResponse.builder() + .diariesCount(diaryOfMonthList.size()) + .date(date) + .diaries(diaryOfMonthList) + .build()); + } catch (RuntimeException e) { + return ResponseHandler.create404Error(new ResponseForm(), e); + } catch (Exception e) { + return ResponseHandler.create500Error(new ResponseForm(), e); + } + } + @Override public ResponseEntity getDiaryByDate(LocalDateTime date) { UserEntity user = userRepository.findByUsername(userContextUtil.getUsername()); try { List diaries = diaryRepository.findByUserAAndCreatedAtBetween(user, date, date); + + if (diaries.isEmpty()) { + throw new RuntimeException("해당 날짜에 작성된 일기가 없습니다."); + } + Diary diaryByDate = diaries.get(0); Optional summaryImage = todaySummaryRepository.findByDiaryId(diaryByDate.getId()); @@ -73,12 +118,13 @@ public ResponseEntity getDiaryByDate(LocalDateTime date) { CheckDiaryResponse.builder() .date(diaryByDate.getCreatedAt()) .diaryDescription(diaryByDate.getContext()) - .summaryImage(summaryImage.get().getImageData())); + + .summaryImage(summaryImage.map(TodaySummary::getImageData).orElse(null)) + .build()); } catch (RuntimeException e) { return ResponseHandler.create404Error(new ResponseForm(), new IllegalArgumentException("해당 날짜에 작성된 일기가 없습니다.")); - } - catch (Exception e) { + } catch (Exception e) { return ResponseHandler.create500Error(new ResponseForm(), e); } } @@ -95,4 +141,15 @@ private Diary saveDiary(CreateDiaryRequest createDiaryRequest, LocalDateTime loc return diaryRepository.save(diary); } + private ParseYearMonth getParsedDate(String date) { + YearMonth parsedYearMonth = YearMonth.parse(date, DateTimeFormatter.ofPattern("yyyy-MM")); + LocalDateTime startOfMonth = parsedYearMonth.atDay(1).atStartOfDay(); + LocalDateTime endOfMonth = parsedYearMonth.atEndOfMonth().atTime(23, 59, 59); + + return ParseYearMonth.builder() + .parsedYearMonth(parsedYearMonth) + .startOfMonth(startOfMonth) + .endOfMonth(endOfMonth) + .build(); + } }