Skip to content

Commit

Permalink
๐Ÿš€ :: v0.1.5
Browse files Browse the repository at this point in the history
๐Ÿš€ :: v0.1.5
  • Loading branch information
ImNM authored Dec 27, 2022
2 parents 5eea10e + 5451f04 commit c8f4bf1
Show file tree
Hide file tree
Showing 19 changed files with 360 additions and 196 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,6 @@ public class GroupBriefInfoDto {

private GroupType groupType;

public GroupBriefInfoDto(GroupBaseInfoVo groupBaseInfoVo) {
groupId = groupBaseInfoVo.getGroupId();
title = groupBaseInfoVo.getTitle();
description = groupBaseInfoVo.getDescription();
publicAccess = groupBaseInfoVo.getPublicAccess();
thumbnailPath = groupBaseInfoVo.getThumbnailPath();
groupType = groupBaseInfoVo.getGroupType();
category = new CategoryDto(groupBaseInfoVo.getCategory());
}

public GroupBriefInfoDto(GroupBaseInfoVo groupBaseInfoVo, Integer memberCount) {
groupId = groupBaseInfoVo.getGroupId();
title = groupBaseInfoVo.getTitle();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.depromeet.knockknockbackend.domain.group.presentation.dto.response;


import io.github.depromeet.knockknockbackend.domain.group.domain.GroupType;
import io.github.depromeet.knockknockbackend.domain.group.domain.vo.GroupBaseInfoVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class GroupInfoForNotificationDto {
private Long groupId;

private String title;

private String description;

private String thumbnailPath;

@Schema(description = "๊ณต๊ฐœ ๊ทธ๋ฃน ์—ฌ๋ถ€ ture ๋ฉด ๊ณต๊ฐœ์ž„")
private Boolean publicAccess;

private GroupType groupType;

public GroupInfoForNotificationDto(GroupBaseInfoVo groupBaseInfoVo) {
groupId = groupBaseInfoVo.getGroupId();
title = groupBaseInfoVo.getTitle();
description = groupBaseInfoVo.getDescription();
publicAccess = groupBaseInfoVo.getPublicAccess();
thumbnailPath = groupBaseInfoVo.getThumbnailPath();
groupType = groupBaseInfoVo.getGroupType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import io.github.depromeet.knockknockbackend.domain.reaction.domain.NotificationReaction;
import io.github.depromeet.knockknockbackend.domain.user.domain.User;
import io.github.depromeet.knockknockbackend.global.database.BaseTimeEntity;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
Expand Down Expand Up @@ -61,10 +63,20 @@ public class Notification extends BaseTimeEntity {
@OneToMany(mappedBy = "notification", fetch = FetchType.LAZY)
private Set<NotificationReaction> notificationReactions = new HashSet<>();

private LocalDateTime reservedAt;

private boolean deleted;

public void addReceivers(List<NotificationReceiver> receivers) {
this.receivers.addAll(receivers);
private void addReceivers(List<DeviceToken> deviceTokens) {
this.receivers.addAll(
deviceTokens.stream()
.map(
deviceToken ->
new NotificationReceiver(
this,
User.of(deviceToken.getUserId()),
deviceToken.getToken()))
.collect(Collectors.toList()));
}

public void deleteNotification() {
Expand All @@ -75,15 +87,25 @@ public static Notification of(Long notificationId) {
return Notification.builder().id(notificationId).build();
}

public static Notification of(
String title, String content, String imageUrl, Group group, User sendUser) {
return Notification.builder()
.title(title)
.content(content)
.imageUrl(imageUrl)
.group(group)
.sendUser(sendUser)
.build();
public static Notification makeNotificationWithReceivers(
List<DeviceToken> deviceTokens,
String title,
String content,
String imageUrl,
Group group,
User sendUser,
LocalDateTime reservedAt) {
Notification notification =
Notification.builder()
.title(title)
.content(content)
.imageUrl(imageUrl)
.group(group)
.sendUser(sendUser)
.reservedAt(reservedAt)
.build();
notification.addReceivers(deviceTokens);
return notification;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.depromeet.knockknockbackend.domain.notification.domain.repository;


import io.github.depromeet.knockknockbackend.domain.group.domain.Group;
import io.github.depromeet.knockknockbackend.domain.notification.domain.DeviceToken;
import io.github.depromeet.knockknockbackend.domain.notification.domain.Notification;
import java.util.List;
Expand All @@ -10,10 +11,13 @@
public interface CustomNotificationRepository {

Slice<Notification> findSliceFromStorage(
Long userId, Long groupId, Integer periodOfMonth, Pageable pageable);
Long userId, List<Group> groups, Integer periodOfMonth, Pageable pageable);

List<DeviceToken> findTokenByGroupAndOptionAndNonBlock(
Long userId, Long groupId, Boolean nightOption);

List<Notification> findSliceLatestByReceiver(Long receiveUserId);

Slice<Notification> findSliceByGroupId(
Long userId, Long groupId, boolean deleted, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.depromeet.knockknockbackend.domain.notification.domain.repository;

import static io.github.depromeet.knockknockbackend.domain.group.domain.QGroup.group;
import static io.github.depromeet.knockknockbackend.domain.group.domain.QGroupUser.groupUser;
import static io.github.depromeet.knockknockbackend.domain.notification.domain.QDeviceToken.deviceToken;
import static io.github.depromeet.knockknockbackend.domain.notification.domain.QNotification.notification;
Expand All @@ -12,6 +13,7 @@
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import io.github.depromeet.knockknockbackend.domain.group.domain.Group;
import io.github.depromeet.knockknockbackend.domain.notification.domain.DeviceToken;
import io.github.depromeet.knockknockbackend.domain.notification.domain.Notification;
import java.time.LocalDate;
Expand All @@ -32,26 +34,50 @@ public class CustomNotificationRepositoryImpl implements CustomNotificationRepos
private static final int NUMBER_OF_LATEST_NOTIFICATIONS = 10;
private final JPAQueryFactory queryFactory;

private boolean hasNext(List<Notification> notifications, Pageable pageable) {
private <T> boolean hasNext(List<T> list, Pageable pageable) {
boolean hasNext = false;
if (notifications.size() > pageable.getPageSize()) {
notifications.remove(pageable.getPageSize());
if (list.size() > pageable.getPageSize()) {
list.remove(pageable.getPageSize());
hasNext = true;
}
return hasNext;
}

@Override
public Slice<Notification> findSliceByGroupId(
Long userId, Long groupId, boolean deleted, Pageable pageable) {
List<Notification> notifications =
queryFactory
.selectFrom(notification)
.join(notification.group, group)
.fetchJoin()
.where(
group.id.eq(groupId),
notification.deleted.eq(deleted),
JPAExpressions.selectFrom(blockUser)
.where(
blockUser.blockedUser.eq(notification.sendUser),
blockUser.user.id.eq(userId))
.notExists())
.orderBy(sort("notification", pageable))
.offset(pageable.getOffset())
.limit(pageable.getPageSize() + NEXT_SLICE_CHECK)
.fetch();

return new SliceImpl<>(notifications, pageable, hasNext(notifications, pageable));
}

@Override
public Slice<Notification> findSliceFromStorage(
Long userId, Long groupId, Integer periodOfMonth, Pageable pageable) {
Long userId, List<Group> groups, Integer periodOfMonth, Pageable pageable) {
List<Notification> notifications =
queryFactory
.select(notification)
.from(storage)
.innerJoin(storage.notification, notification)
.where(
storage.user.id.eq(userId),
eqGroupId(groupId),
eqGroupIdIn(groups),
greaterEqualPeriodOfMonth(periodOfMonth))
.orderBy(sort("storage", pageable))
.offset(pageable.getOffset())
Expand All @@ -73,6 +99,7 @@ public List<DeviceToken> findTokenByGroupAndOptionAndNonBlock(
.on(groupUser.user.id.eq(option.userId))
.where(
groupUser.group.id.eq(groupId),
deviceToken.user.id.ne(userId),
option.newOption.eq(true),
eqNightOption(nightOption),
JPAExpressions.selectFrom(blockUser)
Expand All @@ -87,6 +114,8 @@ public List<DeviceToken> findTokenByGroupAndOptionAndNonBlock(
public List<Notification> findSliceLatestByReceiver(Long receiveUserId) {
return queryFactory
.selectFrom(notification)
.join(notification.group, group)
.fetchJoin()
.where(
notification.deleted.eq(false),
JPAExpressions.selectFrom(notificationReceiver)
Expand All @@ -106,11 +135,11 @@ private BooleanExpression eqNightOption(Boolean nightOption) {
return option.nightOption.eq(nightOption);
}

private BooleanExpression eqGroupId(Long groupId) {
if (groupId == null) {
private BooleanExpression eqGroupIdIn(List<Group> groups) {
if (groups.isEmpty()) {
return null;
}
return notification.group.id.eq(groupId);
return notification.group.in(groups);
}

private BooleanExpression greaterEqualPeriodOfMonth(Integer periodOfMonth) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@

import io.github.depromeet.knockknockbackend.domain.notification.domain.Notification;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;

public interface NotificationRepository
extends JpaRepository<Notification, Long>, CustomNotificationRepository {

@EntityGraph(attributePaths = {"group"})
Slice<Notification> findAllByGroupIdAndDeleted(
Long groupId, boolean deleted, Pageable pageable);

@EntityGraph(attributePaths = {"group"})
Optional<Notification> findById(Long notificationId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@
import io.github.depromeet.knockknockbackend.domain.group.domain.Group;
import io.github.depromeet.knockknockbackend.domain.notification.domain.Reservation;
import io.github.depromeet.knockknockbackend.domain.user.domain.User;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

public interface ReservationRepository extends CrudRepository<Reservation, Long> {
List<Reservation> findByGroupAndSendUserOrderBySendAtAsc(Group group, User sendUser);

List<Reservation> findBySendAtLessThan(LocalDateTime sendAt);

@Modifying
@Query("delete from Reservation r where r.id in :reservationIds")
void deleteByIdIn(@Param("reservationIds") List<Long> reservationIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.github.depromeet.knockknockbackend.domain.notification.presentation.dto.response.QueryNotificationListLatestResponse;
import io.github.depromeet.knockknockbackend.domain.notification.presentation.dto.response.QueryNotificationListResponse;
import io.github.depromeet.knockknockbackend.domain.notification.service.NotificationService;
import io.github.depromeet.knockknockbackend.domain.notification.service.ReservationService;
import io.github.depromeet.knockknockbackend.global.annotation.DisableSecurity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
Expand All @@ -24,6 +25,7 @@
public class NotificationController {

private final NotificationService notificationService;
private final ReservationService reservationService;

@Operation(summary = "์ตœ์‹  ํ‘ธ์‰ฌ์•Œ๋ฆผ ๋ฆฌ์ŠคํŠธ")
@GetMapping
Expand All @@ -45,13 +47,6 @@ public void sendInstance(@RequestBody SendInstanceRequest request) {
notificationService.sendInstance(request);
}

@Operation(summary = "์˜ˆ์•ฝ ํ‘ธ์‰ฌ์•Œ๋ฆผ ๋ฐœ์†ก")
@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/reservation")
public void sendReservation(@RequestBody SendReservationRequest request) {
notificationService.sendReservation(request);
}

@Operation(summary = "์•Œ๋ฆผ๋ฐฉ ํ‘ธ์‰ฌ์•Œ๋ฆผ ๋ฆฌ์ŠคํŠธ")
@GetMapping("/{group_id}")
public QueryNotificationListResponse queryListByGroupId(
Expand All @@ -78,17 +73,24 @@ public void sendInstanceToMeBeforeSignUp(
notificationService.sendInstanceToMeBeforeSignUp(request);
}

@Operation(summary = "์˜ˆ์•ฝ ํ‘ธ์‰ฌ์•Œ๋ฆผ ๋ฐœ์†ก")
@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/reservation")
public void sendReservation(@RequestBody SendReservationRequest request) {
reservationService.sendReservation(request);
}

@Operation(summary = "์˜ˆ์•ฝ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์‹œ๊ฐ„์ˆ˜์ •")
@ResponseStatus(HttpStatus.OK)
@PatchMapping("/reservation")
public void changeSendAtReservation(@RequestBody ChangeSendAtReservationRequest request) {
notificationService.changeSendAtReservation(request);
reservationService.changeSendAtReservation(request);
}

@Operation(summary = "์˜ˆ์•ฝ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์‚ญ์ œ")
@ResponseStatus(HttpStatus.OK)
@DeleteMapping("/reservation/{reservation_id}")
public void deleteReservation(@PathVariable("reservation_id") Long reservationId) {
notificationService.deleteReservation(reservationId);
reservationService.deleteReservation(reservationId);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.depromeet.knockknockbackend.domain.notification.presentation.dto.response;


import io.github.depromeet.knockknockbackend.domain.group.presentation.dto.response.GroupBriefInfoDto;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -11,7 +10,6 @@
@AllArgsConstructor
public class QueryNotificationListResponse {

private final GroupBriefInfoDto groups;
private final List<QueryReservationListResponseElement> reservations;
private final Slice<QueryNotificationListResponseElement> notifications;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.depromeet.knockknockbackend.domain.notification.presentation.dto.response;


import io.github.depromeet.knockknockbackend.domain.group.presentation.dto.response.GroupInfoForNotificationDto;
import java.time.LocalDateTime;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -14,5 +15,6 @@ public class QueryNotificationListResponseElement {
private String imageUrl;
private LocalDateTime createdDate;
private Long sendUserId;
private GroupInfoForNotificationDto groups;
private QueryNotificationReactionResponseElement reactions;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.github.depromeet.knockknockbackend.domain.notification.service;


import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class NotificationReservationScheduler {

private final ReservationService reservationService;

@Scheduled(cron = "0 0/1 * * * *")
public void reservationNotification() {
reservationService.processScheduledReservation();
}
}
Loading

0 comments on commit c8f4bf1

Please sign in to comment.