diff --git a/server/src/docs/asciidoc/index.adoc b/server/src/docs/asciidoc/index.adoc index 30989af..92fbac1 100644 --- a/server/src/docs/asciidoc/index.adoc +++ b/server/src/docs/asciidoc/index.adoc @@ -1057,3 +1057,23 @@ include::{snippets}/api/plants/info/1/response-fields.adoc[] ==== 실패 Response 실패 1. include::{snippets}/api/plants/info/2/http-response.adoc[] + + +=== **14. 달력에서 그린룸 활동 정보 조회** + +특정 날짜의 모든 그린룸 활동 내역들을 조회함. + +==== Request +include::{snippets}/api/greenroom/calendar/1/http-request.adoc[] + +==== Request Headers +include::{snippets}/api/greenroom/calendar/1/request-headers.adoc[] + +==== Request Query Parameter Fields +include::{snippets}/api/greenroom/calendar/1/query-parameters.adoc[] + +==== 성공 Response +include::{snippets}/api/greenroom/calendar/1/http-response.adoc[] + +==== Response Body Fields +include::{snippets}/api/greenroom/calendar/1/response-fields.adoc[] diff --git a/server/src/main/java/com/greenroom/server/api/domain/common/entity/BaseTime.java b/server/src/main/java/com/greenroom/server/api/domain/common/entity/BaseTime.java index b7b5ac7..be42b59 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/common/entity/BaseTime.java +++ b/server/src/main/java/com/greenroom/server/api/domain/common/entity/BaseTime.java @@ -26,6 +26,7 @@ public class BaseTime { @Column(updatable = false,insertable = false) protected LocalDateTime createDate; + @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) @Column(insertable = false,updatable = false) diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/controller/GreenroomController.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/controller/GreenroomController.java index 0c283da..5ee4d8b 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/controller/GreenroomController.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/controller/GreenroomController.java @@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.time.LocalDate; import java.util.List; @RestController @@ -100,6 +101,10 @@ public ResponseEntity updateActivity(@PathVariable(value = "greenro return ResponseEntity.ok(ApiResponse.success(ResponseCodeEnum.SUCCESS,greenroomService.updateActivity(activityInfoUpdateRequestDto,greenroomId))); } + @GetMapping("/calendar") + public ResponseEntity getCalender(@AuthenticationPrincipal User user, @RequestParam(value = "date") LocalDate date, @RequestParam (value = "type",required = false) Long activityId){ + return ResponseEntity.ok(ApiResponse.success(ResponseCodeEnum.SUCCESS,greenroomService.getGreenroomInfoFromCalendar(user.getUsername(),date,activityId))); + } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java new file mode 100644 index 0000000..d6dfd00 --- /dev/null +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java @@ -0,0 +1,49 @@ +package com.greenroom.server.api.domain.greenroom.dto.out; + +import com.greenroom.server.api.domain.greenroom.entity.*; +import com.greenroom.server.api.global.config.PropertiesHolder; + +import java.time.LocalDate; +import java.time.format.TextStyle; +import java.util.List; +import java.util.Locale; + +public record GreenroomCalendarResponseDto(DateInfo dateInfo, List mainInfo) { + public static GreenroomCalendarResponseDto from(LocalDate date, List mainInfo){ + return new GreenroomCalendarResponseDto(DateInfo.from(date),mainInfo); + } + + public record CalendarInfo(GreenroomInfo greenroomInfo, List activity , List diary){ + public static CalendarInfo of(GreenroomInfo greenroomInfo,List activity, List diary){ + return new CalendarInfo(greenroomInfo,activity,diary); + } + } + + public record GreenroomInfo(Long greenroomId, String greenroomName){ + public static GreenroomInfo from(GreenRoom greenRoom){ + return new GreenroomInfo(greenRoom.getGreenroomId(),greenRoom.getName()); + } + } + public record DateInfo(Integer year, Integer month, Integer date,String day){ + public static DateInfo from(LocalDate date){ + return new DateInfo(date.getYear(),date.getMonthValue(),date.getDayOfMonth(),date.getDayOfWeek() + .getDisplayName(TextStyle.SHORT, Locale.KOREAN)); + } + } + public record TodoInfo(Long activityId, String activityName, Integer remainingDays, Boolean isCompleted){ + public static TodoInfo from(Todo todo){ + Integer remainingDays = todo.getNextTodoDate().getDayOfYear() - LocalDate.now().getDayOfYear(); + return new TodoInfo(todo.getActivity().getActivityId(),todo.getActivity().getActivityName(),remainingDays,false); + } + public static TodoInfo from(TodoLog todoLog){ + Activity activity = todoLog.getActivity(); + return new TodoInfo(activity.getActivityId(),activity.getActivityName(),null,true); + } + } + public record DiaryInfo(Long diaryId, String title, String body, String imageUrl){ + public static DiaryInfo from(Diary diary){ + String imageUrl = diary.getDiaryPictureUrl()==null?null:PropertiesHolder.CDN_PATH+"/"+diary.getDiaryPictureUrl(); + return new DiaryInfo(diary.getDiaryId(),diary.getTitle(),diary.getContent(),imageUrl); + } + } +} diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/enums/GreenRoomStatus.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/enums/GreenRoomStatus.java index ad763cc..719821d 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/enums/GreenRoomStatus.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/enums/GreenRoomStatus.java @@ -6,9 +6,7 @@ public enum GreenRoomStatus { ENABLED("활성화됨"), - DISABLED("비활성화됨"), - DELETED("삭제됨"), - OTHER("기타"); + DISABLED("비활성화됨"); private final String description; diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/DiaryRepository.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/DiaryRepository.java index 14b4673..a0575d7 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/DiaryRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/DiaryRepository.java @@ -3,12 +3,14 @@ import com.greenroom.server.api.domain.greenroom.dto.in.DiaryImageSimpleDto; import com.greenroom.server.api.domain.greenroom.entity.Diary; import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; +import com.greenroom.server.api.domain.greenroom.entity.TodoLog; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.time.LocalDate; import java.util.Collection; import java.util.List; @@ -26,4 +28,7 @@ public interface DiaryRepository extends JpaRepository { void deleteAllByGreenRoom(GreenRoom greenRoom); + @Query("select d from Diary d where FUNCTION('DATE', d.createDate)=:date And d.greenRoom.greenroomId in :greenRooms ") + List findByCreateDateAndGreenRoomIn(@Param("date")LocalDate date, @Param("greenRooms") List greenRoom); + } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/GreenRoomRepository.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/GreenRoomRepository.java index 7477d64..c903162 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/GreenRoomRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/GreenRoomRepository.java @@ -30,10 +30,12 @@ public interface GreenRoomRepository extends JpaRepository { void deleteAllByGreenroomId(@Param("ids")Collection greenroomId); - @EntityGraph(attributePaths = {"plant"}) List findGreenRoomByUserAndGreenroomStatus(User user, GreenRoomStatus greenRoomStatus); + @EntityGraph(attributePaths = {"plant"}) + List findGreenRoomByUser(User user); + @EntityGraph(attributePaths = {"plant"}) Optional findByGreenroomIdAndGreenroomStatus(Long greenroomId, GreenRoomStatus greenRoomStatus); } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoLogRepository.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoLogRepository.java index d4c996c..8e4d659 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoLogRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoLogRepository.java @@ -1,13 +1,18 @@ package com.greenroom.server.api.domain.greenroom.repository; +import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; import com.greenroom.server.api.domain.greenroom.entity.TodoLog; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.List; @Repository public interface TodoLogRepository extends JpaRepository { @@ -18,4 +23,8 @@ public interface TodoLogRepository extends JpaRepository { @Query("delete from TodoLog tl where tl.greenRoom.greenroomId =(:id)") @Modifying void deleteAllByGreenRoomGreenroomId(@Param("id")Long greenroomId); + + @EntityGraph(attributePaths ={"activity"}) + @Query("select tl from TodoLog tl where FUNCTION('DATE', tl.createDate) =:date And tl.greenRoom.greenroomId in (:greenRooms) ") + List findByCreateDateAndGreenRoomIn( @Param("date") LocalDate date, @Param("greenRooms") List greenRooms); } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoRepository.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoRepository.java index b376cd7..913d976 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/repository/TodoRepository.java @@ -2,6 +2,7 @@ import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; import com.greenroom.server.api.domain.greenroom.entity.Todo; +import com.greenroom.server.api.domain.greenroom.entity.TodoLog; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -9,6 +10,7 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.time.LocalDate; import java.util.Collection; import java.util.List; @@ -26,4 +28,11 @@ public interface TodoRepository extends JpaRepository { List findAllByGreenRoomAndActivity(@Param("greenroomId")Long greenroomId,@Param("activityIds") List activityIds ); List findAllByGreenRoom(GreenRoom greenRoom); + + @EntityGraph(attributePaths ={"activity"}) + @Query("select t from Todo t where FUNCTION('DATE', t.nextTodoDate)<=:date And t.greenRoom.greenroomId in :greenRooms ") + List findByNextTodoDateAndGreenRoomIn(@Param("date") LocalDate nextTodoDate,@Param("greenRooms")List greenRoomList); + @EntityGraph(attributePaths ={"activity"}) + @Query("select t from Todo t where FUNCTION('DATE', t.nextTodoDate) =:date And t.greenRoom.greenroomId in :greenRooms ") + List findByNextTodoDateAndGreenRoomInFuture(@Param("date") LocalDate date,@Param("greenRooms")List greenRoomList); } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/DiaryService.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/DiaryService.java index d48707d..030f6d8 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/DiaryService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/DiaryService.java @@ -1,12 +1,15 @@ package com.greenroom.server.api.domain.greenroom.service; import com.amazonaws.util.StringUtils; +import com.greenroom.server.api.domain.greenroom.entity.Diary; import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; import com.greenroom.server.api.domain.greenroom.repository.DiaryRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -29,4 +32,8 @@ public List deleteAllByGreenRoom(List greenroomIdList){ diaryRepository.deleteAllByIdInBatch(deletedDiaryIdList); return imageDeleteList; } + + public List getAllDiariesByGreenroomAndDate(ListgreenRoomList, LocalDate date){ + return diaryRepository.findByCreateDateAndGreenRoomIn(date,greenRoomList.stream().map(GreenRoom::getGreenroomId).toList()); + } } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/GreenroomService.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/GreenroomService.java index 89a38ed..c10cfd2 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/GreenroomService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/GreenroomService.java @@ -1,12 +1,8 @@ package com.greenroom.server.api.domain.greenroom.service; -import com.amazonaws.util.StringUtils; import com.greenroom.server.api.domain.greenroom.dto.in.*; import com.greenroom.server.api.domain.greenroom.dto.out.*; -import com.greenroom.server.api.domain.greenroom.entity.Activity; -import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; -import com.greenroom.server.api.domain.greenroom.entity.Plant; -import com.greenroom.server.api.domain.greenroom.entity.Todo; +import com.greenroom.server.api.domain.greenroom.entity.*; import com.greenroom.server.api.domain.greenroom.enums.GreenRoomStatus; import com.greenroom.server.api.domain.greenroom.repository.GreenRoomRepository; import com.greenroom.server.api.domain.user.entity.User; @@ -18,7 +14,6 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -27,6 +22,7 @@ import java.time.LocalDate; import java.time.format.DateTimeParseException; import java.util.*; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -338,5 +334,104 @@ public void updateTodo(Todo todo, ActivityInfoUpdateRequestDto.ActivityInfoUpdat todo.updateNextTodoDate(baseDate.plusDays(term)); } + + public GreenroomCalendarResponseDto getGreenroomInfoFromCalendar(String email, LocalDate date, Long activityId){ + + User user = customUserDetailService.findUserByEmail(email); + + if(date.isBefore(LocalDate.now())){ + return GreenroomCalendarResponseDto.from(date,getGreenroomInfoPast(user,date,activityId)); + } + else if(date.isEqual(LocalDate.now())){ + return GreenroomCalendarResponseDto.from(date,getGreenroomInfoPresent(user,date,activityId)); + } + else{ + return GreenroomCalendarResponseDto.from(date,getGreenroomInfoFuture(user,date,activityId)); + } + } + + private List getEnabledGreenRooms(User user) { + return greenRoomRepository.findGreenRoomByUserAndGreenroomStatus(user, GreenRoomStatus.ENABLED); + } + + private List getAllGreenRooms(User user) { + return greenRoomRepository.findGreenRoomByUser(user); + } + + private Map> getTodoLogs(List rooms, LocalDate date, Long activityId) { + return todoLogService.getAllTodoLogByGreenroomAndDate(rooms, date).stream() + .filter(log -> activityId == null || Objects.equals(log.getActivity().getActivityId(), activityId)) + .collect(Collectors.groupingBy(TodoLog::getGreenRoom)); + } + + private Map> getTodos(List rooms, LocalDate date, Long activityId) { + return todoService.getAllTodoByGreenroomAndDate(rooms, date).stream() + .filter(todo -> activityId == null || Objects.equals(todo.getActivity().getActivityId(), activityId)) + .collect(Collectors.groupingBy(Todo::getGreenRoom)); + } + + private Map> getDiaries(List rooms, LocalDate date) { + return diaryService.getAllDiariesByGreenroomAndDate(rooms, date).stream() + .collect(Collectors.groupingBy(Diary::getGreenRoom)); + } + + private GreenroomCalendarResponseDto.CalendarInfo buildCalendarInfo(GreenRoom greenRoom, List todoLogs, List todos, List diaries) { + + List todoInfos = new ArrayList<>(); + if (todoLogs != null) todoInfos.addAll(todoLogs.stream().map(GreenroomCalendarResponseDto.TodoInfo::from).toList()); + if (todos != null) todoInfos.addAll(todos.stream().map(GreenroomCalendarResponseDto.TodoInfo::from).toList()); + + List diaryInfos = diaries != null ? diaries.stream().map(GreenroomCalendarResponseDto.DiaryInfo::from).toList() : new ArrayList<>(); + + GreenroomCalendarResponseDto.GreenroomInfo greenroomInfo = GreenroomCalendarResponseDto.GreenroomInfo.from(greenRoom); + return GreenroomCalendarResponseDto.CalendarInfo.of(greenroomInfo, todoInfos, diaryInfos); + } + + public List getGreenroomInfoPast(User user, LocalDate date, Long activityId){ + List greenRoomListForTodoLogAndDiary = getAllGreenRooms(user); + if(greenRoomListForTodoLogAndDiary.isEmpty()){return List.of();} + + Map> todoLogList = getTodoLogs(greenRoomListForTodoLogAndDiary,date,activityId); + Map> diaryList = getDiaries(greenRoomListForTodoLogAndDiary,date); + + Set resultGreenroomList = new HashSet<>(); + resultGreenroomList.addAll(todoLogList.keySet());resultGreenroomList.addAll(diaryList.keySet()); + + + return resultGreenroomList.isEmpty()?List.of():resultGreenroomList.stream() + .map(greenroom -> buildCalendarInfo(greenroom, todoLogList.getOrDefault(greenroom, null), null, diaryList.getOrDefault(greenroom, null))) + .toList(); + + } + public List getGreenroomInfoPresent(User user, LocalDate date, Long activityId){ + List greenRoomListForTodoLogAndDiary = getAllGreenRooms(user); + List greenRoomListForTodo = getEnabledGreenRooms(user); + + if(greenRoomListForTodoLogAndDiary.isEmpty()||greenRoomListForTodo.isEmpty()){return List.of();} + + Map> todoLogList = getTodoLogs(greenRoomListForTodoLogAndDiary,date,activityId); + Map> todoList = getTodos(greenRoomListForTodo,date,activityId); + Map> diaryList = getDiaries(greenRoomListForTodoLogAndDiary,date); + + Set resultGreenroomList = new HashSet<>(); + resultGreenroomList.addAll(todoList.keySet()); resultGreenroomList.addAll(todoLogList.keySet());resultGreenroomList.addAll(diaryList.keySet()); + + + return resultGreenroomList.isEmpty()?List.of():resultGreenroomList.stream() + .map(greenroom -> buildCalendarInfo(greenroom, todoLogList.getOrDefault(greenroom, null), todoList.getOrDefault(greenroom, null) ,diaryList.getOrDefault(greenroom, null))) + .toList(); + } + + public List getGreenroomInfoFuture(User user, LocalDate date, Long activityId){ + List greenRoomListForTodo = getEnabledGreenRooms(user); + if(greenRoomListForTodo.isEmpty()){return List.of();} + + Map> todoList = getTodos(greenRoomListForTodo,date,activityId); + + + return todoList.isEmpty()?List.of():todoList.keySet().stream() + .map(greenroom -> buildCalendarInfo(greenroom, null, todoList.getOrDefault(greenroom, null), null)) + .toList(); + } } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoLogService.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoLogService.java index 12eacce..011c180 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoLogService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoLogService.java @@ -1,11 +1,13 @@ package com.greenroom.server.api.domain.greenroom.service; +import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; import com.greenroom.server.api.domain.greenroom.entity.TodoLog; import com.greenroom.server.api.domain.greenroom.repository.TodoLogRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.time.LocalDate; +import java.time.LocalTime; import java.util.List; @Service @@ -24,5 +26,7 @@ public void deleteAllByGreenroom(List greenroomIdList){ todoLogRepository.deleteAllByGreenRoom(greenroomIdList); } - + public List getAllTodoLogByGreenroomAndDate(List greenRooms, LocalDate date){ + return todoLogRepository.findByCreateDateAndGreenRoomIn(date, greenRooms.stream().map(GreenRoom::getGreenroomId).toList()); + } } diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoService.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoService.java index 53f0965..98bbcad 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/TodoService.java @@ -107,5 +107,11 @@ public List findAllByGreenroom(GreenRoom greenRoom){ return todoRepository.findAllByGreenRoom(greenRoom); } + public List getAllTodoByGreenroomAndDate(List greenRoomList, LocalDate date){ + if(date.isAfter(LocalDate.now())){ + return todoRepository.findByNextTodoDateAndGreenRoomInFuture(date, greenRoomList.stream().map(GreenRoom::getGreenroomId).toList()); + } + return todoRepository.findByNextTodoDateAndGreenRoomIn(date, greenRoomList.stream().map(GreenRoom::getGreenroomId).toList()); + } } diff --git a/server/src/main/java/com/greenroom/server/api/domain/notification/repository/NotificationRepository.java b/server/src/main/java/com/greenroom/server/api/domain/notification/repository/NotificationRepository.java index f7f27f9..6af14e7 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/notification/repository/NotificationRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/notification/repository/NotificationRepository.java @@ -4,6 +4,9 @@ import com.greenroom.server.api.domain.user.entity.User; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.Optional; @@ -13,6 +16,8 @@ public interface NotificationRepository extends JpaRepository Optional findByUser(User user); - void deleteByUser(User user); + @Query("delete from Notification n where n.user =:user") + @Modifying + void deleteByUser(@Param("user")User user); } diff --git a/server/src/main/java/com/greenroom/server/api/domain/user/repository/CheckInRepository.java b/server/src/main/java/com/greenroom/server/api/domain/user/repository/CheckInRepository.java index b316a93..e5f1856 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/user/repository/CheckInRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/user/repository/CheckInRepository.java @@ -3,10 +3,17 @@ import com.greenroom.server.api.domain.user.entity.CheckIn; import com.greenroom.server.api.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.Optional; public interface CheckInRepository extends JpaRepository { Optional findByUser(User user); + + @Query("delete from CheckIn c where c.user =:user") + @Modifying + void deleteByUser(@Param("user")User user); } diff --git a/server/src/main/java/com/greenroom/server/api/domain/user/repository/UserRepository.java b/server/src/main/java/com/greenroom/server/api/domain/user/repository/UserRepository.java index 87578c9..33c7cff 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/user/repository/UserRepository.java +++ b/server/src/main/java/com/greenroom/server/api/domain/user/repository/UserRepository.java @@ -4,6 +4,9 @@ import com.greenroom.server.api.domain.user.enums.UserStatus; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; @@ -20,4 +23,8 @@ public interface UserRepository extends JpaRepository { List findAllByUserStatusAndDeleteDateBefore(UserStatus userStatus, LocalDateTime updateDate); + @Query("delete from User u where u.userId =:userId") + @Modifying + void deleteByUserId(@Param("userId")Long userId); + } diff --git a/server/src/main/java/com/greenroom/server/api/domain/user/service/UserService.java b/server/src/main/java/com/greenroom/server/api/domain/user/service/UserService.java index f3702a6..e24fde1 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/user/service/UserService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/user/service/UserService.java @@ -8,6 +8,7 @@ import com.greenroom.server.api.domain.user.dto.*; import com.greenroom.server.api.domain.user.entity.User; import com.greenroom.server.api.domain.user.enums.UserStatus; +import com.greenroom.server.api.domain.user.repository.CheckInRepository; import com.greenroom.server.api.domain.user.repository.GradeRepository; import com.greenroom.server.api.domain.user.repository.UserRepository; import com.greenroom.server.api.security.repository.EmailVerificationLogsRepository; @@ -40,6 +41,7 @@ public class UserService { private final GreenRoomRepository greenRoomRepository; private final NotificationRepository notificationRepository; private final GradeRepository gradeRepository; + private final CheckInRepository checkInRepository; private final CustomUserDetailService customUserDetailService; @@ -95,8 +97,15 @@ public List deleteAllWithUser(User user){ public List deleteUserData(User user){ //alarm 삭제 notificationRepository.deleteByUser(user); + + //check in 삭제 + checkInRepository.deleteByUser(user); + + //refresh token 삭제 + refreshTokenRepository.deleteByUser(user); + //user 객체 삭제 - userRepository.delete(user); + userRepository.deleteByUserId(user.getUserId()); if(StringUtils.hasValue(user.getProfileUrl())) return List.of(user.getProfileUrl()); else return List.of(); @@ -135,7 +144,7 @@ public UserInfoResponseDto getUserInformation(String email){ User user = customUserDetailService.findUserByEmail(email); //없으면 not found error반환 LocalDateTime userJoinedDate = user.getCreateDate(); - Long userDurationWithGreenroom = ChronoUnit.DAYS.between(userJoinedDate.toLocalDate(), LocalDate.now()); + Long userDurationWithGreenroom = ChronoUnit.DAYS.between(userJoinedDate.toLocalDate(), LocalDate.now())+1; int nextGradeRequiredSeed = gradeRepository.findById(user.getGrade().getGradeId()+1).get().getRequiredSeed(); int seedsToNextGrade = nextGradeRequiredSeed - user.getGrade().getRequiredSeed() ; diff --git a/server/src/main/java/com/greenroom/server/api/security/repository/RefreshTokenRepository.java b/server/src/main/java/com/greenroom/server/api/security/repository/RefreshTokenRepository.java index a4300c1..324288a 100644 --- a/server/src/main/java/com/greenroom/server/api/security/repository/RefreshTokenRepository.java +++ b/server/src/main/java/com/greenroom/server/api/security/repository/RefreshTokenRepository.java @@ -3,6 +3,9 @@ import com.greenroom.server.api.domain.user.entity.User; import com.greenroom.server.api.security.entity.RefreshToken; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.Optional; @@ -15,5 +18,8 @@ public interface RefreshTokenRepository extends JpaRepository findRefreshTokenByUser(User user); + @Query("delete from RefreshToken r where r.user =:user") + @Modifying + void deleteByUser(@Param("user")User user); } diff --git a/server/src/test/java/com/greenroom/server/api/GreenroomIntegrationTest.java b/server/src/test/java/com/greenroom/server/api/GreenroomIntegrationTest.java index 8e2e51e..bf90a6c 100644 --- a/server/src/test/java/com/greenroom/server/api/GreenroomIntegrationTest.java +++ b/server/src/test/java/com/greenroom/server/api/GreenroomIntegrationTest.java @@ -5,10 +5,8 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.greenroom.server.api.config.TestExecutionListener; import com.greenroom.server.api.domain.greenroom.dto.in.*; -import com.greenroom.server.api.domain.greenroom.entity.Adornment; -import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; -import com.greenroom.server.api.domain.greenroom.entity.Plant; -import com.greenroom.server.api.domain.greenroom.entity.Todo; +import com.greenroom.server.api.domain.greenroom.entity.*; +import com.greenroom.server.api.domain.greenroom.enums.GreenRoomStatus; import com.greenroom.server.api.domain.greenroom.repository.*; import com.greenroom.server.api.domain.greenroom.service.GreenroomService; import com.greenroom.server.api.domain.user.entity.User; @@ -120,6 +118,12 @@ public class GreenroomIntegrationTest { @Autowired private ActivityRepository activityRepository; + @Autowired + private TodoLogRepository todoLogRepository; + + @Autowired + private DiaryRepository diaryRepository; + @MockitoSpyBean private GreenroomService mockitoGreenroomService; @@ -171,7 +175,7 @@ public User signupForTest(){ public GreenRoom createGreenRoom(User user){ Plant plant = plantRepository.findById(20L).get(); - //plantRepository.save(plant); + GreenRoom greenRoom = GreenRoom.of("test 그린룸",null,user,plant); @@ -186,6 +190,40 @@ public GreenRoom createGreenRoom(User user){ return greenRoom; } + public GreenRoom createGreenRoomForCalender(User user){ + + Plant plant = plantRepository.findById(20L).get(); + + GreenRoom greenRoom = GreenRoom.of("초롱이",null,user,plant); + greenRoomRepository.save(greenRoom); + + Todo todo1 = Todo.builder().greenRoom(greenRoom).activity(activityRepository.findAll().get(0)).nextTodoDate(LocalDate.now().minusDays(2)).term(5).baseDate(LocalDate.now().minusDays(7)).build(); + Todo todo2 = Todo.builder().greenRoom(greenRoom).activity(activityRepository.findAll().get(2)).nextTodoDate(LocalDate.now().plusDays(2)).term(5).baseDate(LocalDate.now().minusDays(3)).build(); + TodoLog todoLog = TodoLog.builder().greenRoom(greenRoom).activity(activityRepository.findAll().get(0)).build(); + todoLogRepository.save(todoLog); + + todoRepository.save(todo1);todoRepository.save(todo2); + + Diary diary = Diary.builder().greenRoom(greenRoom).title("제목입니다~").content("본문입니다 ~ ").diaryPictureUrl(null).build(); + diaryRepository.save(diary); + + GreenRoom greenRoom2 = GreenRoom.of("아롱이",null,user,plant); + greenRoom2.updateStatus(GreenRoomStatus.DISABLED); + greenRoomRepository.save(greenRoom2); + + Todo todo3 = Todo.builder().greenRoom(greenRoom2).activity(activityRepository.findAll().get(0)).nextTodoDate(LocalDate.now().minusDays(2)).term(5).baseDate(LocalDate.now().minusDays(7)).build(); + Todo todo4 = Todo.builder().greenRoom(greenRoom2).activity(activityRepository.findAll().get(2)).nextTodoDate(LocalDate.now().plusDays(2)).term(5).baseDate(LocalDate.now().minusDays(3)).build(); + TodoLog todoLog2 = TodoLog.builder().greenRoom(greenRoom2).activity(activityRepository.findAll().get(0)).build(); + todoLogRepository.save(todoLog2); + + todoRepository.save(todo3);todoRepository.save(todo4); + + adornmentRepository.save(Adornment.createAdornment(itemRepository.findAll().get(0),greenRoom)); + + + return greenRoom; + } + private MockMultipartFile getTestMultiPartFile (){ String filePath = "src/test/resources/test.jpg"; //test 이미지 파일경로 @@ -438,6 +476,45 @@ private MockMultipartFile getInvalidTestMultiPartFile (){ fieldWithPath("data.inactiveCycle[].activityId").type(JsonFieldType.NUMBER).description("activity id : activity id 문서 부분 참조"), fieldWithPath("data.inactiveCycle[].activityName").type(JsonFieldType.STRING).description("activity 이름")); + List resultDescriptorsForCalenderInfo= List.of( + fieldWithPath("status").type(JsonFieldType.STRING).description("응답 상태"), + fieldWithPath("code").type(JsonFieldType.STRING).description("상태 코드"), + fieldWithPath("data").type(JsonFieldType.OBJECT).optional().description("data").optional(), + fieldWithPath("data.dateInfo").type(JsonFieldType.OBJECT).description("조회 날짜 정보"), + fieldWithPath("data.dateInfo.year").type(JsonFieldType.NUMBER).description("조회 날짜 연도"), + fieldWithPath("data.dateInfo.month").type(JsonFieldType.NUMBER).description("조회 날짜 월"), + fieldWithPath("data.dateInfo.date").type(JsonFieldType.NUMBER).description("조회 날짜 일자"), + fieldWithPath("data.dateInfo.day").type(JsonFieldType.STRING).description("조회 날짜 요일"), + fieldWithPath("data.mainInfo").type(JsonFieldType.ARRAY).description("활동 정보 및 일기 내역").optional().attributes(new Attributes.Attribute("constraint","정보를 조회할 그린룸이 없거나 활동 내역이 없는 경우 빈 배열")), + fieldWithPath("data.mainInfo[].greenroomInfo").type(JsonFieldType.OBJECT).description("그린룸 정보"), + fieldWithPath("data.mainInfo[].greenroomInfo.greenroomId").type(JsonFieldType.NUMBER).description("그린룸 id"), + fieldWithPath("data.mainInfo[].greenroomInfo.greenroomName").type(JsonFieldType.STRING).description("그린룸 닉네임"), + + fieldWithPath("data.mainInfo[].activity").type(JsonFieldType.ARRAY).description("활동 정보 내역").optional().attributes(new Attributes.Attribute("constraint","활동 내역 정보가 없는 경우 빈 배열")), + fieldWithPath("data.mainInfo[].activity[].activityId").type(JsonFieldType.NUMBER).description("activity id"), + fieldWithPath("data.mainInfo[].activity[].activityName").type(JsonFieldType.STRING).description("activity 이름"), + fieldWithPath("data.mainInfo[].activity[].isCompleted").type(JsonFieldType.BOOLEAN).description(""" + 활동 완료 여부: + + 1. 과거 날짜 조회시(이미 완료함) : true + + 2. 현재 날짜 조회시 : 오늘 해야할 일을 완료 했을 경우 true, 미완료시 false + + 3. 미래 날짜 조회시(아직 미완료) : false """), + fieldWithPath("data.mainInfo[].activity[].remainingDays").type(JsonFieldType.NUMBER).optional().description( + """ + 현재 날짜를 기준으로 활동 수행 날짜까지 남은 일수 + + 1. 이미 완료한 경우 : null + + 2. 수행해야 하는 날짜가 현재 날짜보다 과거인 경우 : -값 + + 3. 수행해야 하는 날짜가 오늘인 경우 : 0 + + 4. 수행해야 하는 날짜가 현재 날짜보다 미래인 경우 : +값 + + """ + ).attributes(new Attributes.Attribute("constraint","과거 날짜 조회시 이미 완료된 활동 내역이므로 null")), + fieldWithPath("data.mainInfo[].diary").type(JsonFieldType.ARRAY).description("활동 정보 및 일기 내역").optional().attributes(new Attributes.Attribute("constraint","일기 내역이 없는 경우 빈 배열")), + fieldWithPath("data.mainInfo[].diary[].diaryId").type(JsonFieldType.NUMBER).description("일기 id"), + fieldWithPath("data.mainInfo[].diary[].title").type(JsonFieldType.STRING).description("일기 제목"), + fieldWithPath("data.mainInfo[].diary[].body").type(JsonFieldType.STRING).description("일기 본문"), + fieldWithPath("data.mainInfo[].diary[].imageUrl").type(JsonFieldType.STRING).description("일기에 등록한 이미지 url").optional().attributes(new Attributes.Attribute("constraint","등록한 이미지가 없을 경우 null"))); + + @Transactional @Test public void 그린룸_정보_조회_성공1() throws Exception { @@ -1430,5 +1507,49 @@ private RestDocumentationResultHandler getDocumentForUpdateActivityInfo(Integer } + private ResultActions getResultActionsForCalenderInfo(String date) throws Exception { + String token = getTokenForTest((long) (10*1000)); + return mockMvc.perform( // api 실행 + RestDocumentationRequestBuilders + .get("/api/greenroom/calendar") + .param("date",date) + .header(HttpHeaders.AUTHORIZATION, "Bearer "+token)); + } + + private RestDocumentationResultHandler getDocumentForCalenderInfo(Integer identifier){ + return document("api/greenroom/calendar/"+identifier, + preprocessRequest(prettyPrint(),modifyUris().scheme("https").host("greenroom-server.site").removePort()), + preprocessResponse(prettyPrint(), getModifiedHeader()), + queryParameters(parameterDescriptorsForCalenderInfo), + responseFields(resultDescriptorsForCalenderInfo), // responseBody 설명 + requestHeaders(headerWithName("Authorization").description("Bearer : 사용자 access Token")), + resource(ResourceSnippetParameters.builder() + .tag("그린룸") // 문서에서 api들이 태그로 분류됨 + .summary("그린룸 날짜별 정보 api") // api 이름 + .description("그린룸 달력 정보 api 조회") // api 설명 + .build())); + } + private final List parameterDescriptorsForCalenderInfo = List.of( + parameterWithName("date").description("조회 날짜").attributes(new Attributes.Attribute("constraint","yyyy-mm-dd")), + parameterWithName("type").description("특정 type의 주기를 조회하는 경우 activity id 전달").optional().attributes(new Attributes.Attribute("constraint","상단 표에 작성된 activity id"),new Attributes.Attribute("default","모든 activity의 활동 내역을 조회")) + ); + + @Test + @Transactional + public void 그린룸_달력정보_조회_성공() throws Exception { + //given + User user = signupForTest(); + createGreenRoomForCalender(user); + + //when + ResultActions resultActions = getResultActionsForCalenderInfo(LocalDate.now().toString()); + + //then + resultActions.andExpect(status().isOk()); + + //문서화 + resultActions.andDo(getDocumentForCalenderInfo(1)); + } + }