Skip to content

Commit

Permalink
Merge pull request #204 from FEBFES/feature/201/notification-changes
Browse files Browse the repository at this point in the history
201 - notification changes
  • Loading branch information
IvanShish authored Jun 15, 2024
2 parents 8df1025 + 3de4106 commit 84c1200
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.febfes.fftmback.controller;

import com.febfes.fftmback.annotation.ApiDelete;
import com.febfes.fftmback.annotation.ApiGet;
import com.febfes.fftmback.annotation.ApiPatch;
import com.febfes.fftmback.annotation.ProtectedApi;
import com.febfes.fftmback.domain.dao.UserEntity;
import com.febfes.fftmback.dto.NotificationDto;
import com.febfes.fftmback.mapper.NotificationMapper;
import com.febfes.fftmback.service.NotificationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Optional;

@RestController
@RequiredArgsConstructor
Expand All @@ -27,16 +31,19 @@ public class NotificationController {

@Operation(summary = "Get notifications for the user they were sent to")
@ApiGet
public List<NotificationDto> getNotificationsForUser(
@RequestParam(value = "userId") long userId,
@RequestParam(value = "isRead") Optional<Boolean> isRead
) {
if (isRead.isPresent()) {
return notificationMapper.notificationsToDto(
notificationService.getNotificationsByUserIdAndIsRead(userId, isRead.get())
);
} else {
return notificationMapper.notificationsToDto(notificationService.getNotificationsByUserId(userId));
}
public List<NotificationDto> getNotificationsForUser(@AuthenticationPrincipal UserEntity user) {
return notificationMapper.notificationsToDto(notificationService.getNotificationsByUserId(user.getId()));
}

@Operation(summary = "Change notification isRead parameter")
@ApiPatch("/{notificationId}")
public void changeIsRead(@PathVariable Long notificationId, @RequestParam boolean isTrue) {
notificationService.changeIsRead(notificationId, isTrue);
}

@Operation(summary = "Delete notification by id")
@ApiDelete("/{notificationId}")
public void deleteNotification(@PathVariable Long notificationId) {
notificationService.deleteNotification(notificationId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
@EqualsAndHashCode(callSuper = true)
public class NotificationEntity extends BaseEntity {

public static final String ENTITY_NAME = "Notification";

@Column(name = "user_id_to")
private Long userIdTo;

Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/febfes/fftmback/dto/NotificationDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
public record NotificationDto(
Long id,
LocalDateTime createDate,
Long userIdTo,
String message,
boolean isRead
) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/febfes/fftmback/exception/Exceptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@ public Supplier<EntityNotFoundException> roleNotFoundByProjectId(Long projectId)
public Supplier<EntityNotFoundException> taskNotFound(Long id) {
return () -> new EntityNotFoundException(TaskEntity.ENTITY_NAME, id);
}

public Supplier<EntityNotFoundException> notificationNotFound(Long id) {
return () -> new EntityNotFoundException(NotificationEntity.ENTITY_NAME, id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
public interface NotificationRepository extends JpaRepository<NotificationEntity, Long> {

List<NotificationEntity> findByUserIdTo(Long userIdTo);

List<NotificationEntity> findByUserIdToAndIsRead(Long userIdTo, boolean isRead);
List<NotificationEntity> findByIsReadAndCreateDateBefore(boolean isRead, LocalDateTime createDateBefore);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.febfes.fftmback.schedule;

import com.febfes.fftmback.domain.dao.NotificationEntity;
import com.febfes.fftmback.repository.NotificationRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
@Transactional
@DisallowConcurrentExecution
public class DeleteNotificationJob implements Job {

private final NotificationRepository notificationRepository;

private static final Long NOTIFICATION_LIFE_DAYS = 30L;

@Override
public void execute(JobExecutionContext jobExecutionContext) {
LocalDateTime now = LocalDateTime.now();
List<NotificationEntity> notifications = notificationRepository.findByIsReadAndCreateDateBefore(
true, now.minusDays(NOTIFICATION_LIFE_DAYS));
if (!notifications.isEmpty()) {
notificationRepository.deleteAll(notifications);
log.info("Read notifications with a creation date of {} days ago have been deleted", NOTIFICATION_LIFE_DAYS);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ public interface NotificationService {

List<NotificationEntity> getNotificationsByUserId(Long userId);

List<NotificationEntity> getNotificationsByUserIdAndIsRead(Long userId, Boolean isRead);
NotificationEntity getNotificationById(Long id);

void createNotification(String message, Long userIdTo);

void changeIsRead(Long notificationId, boolean isRead);

void deleteNotification(Long id);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.febfes.fftmback.service;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.SchedulerException;

import java.util.Date;

public interface ScheduleService {

void startNewJobAt(Date triggerStartTime,
void startNewJobAt(Class<? extends Job> jobClass,
Date triggerStartTime,
JobDataMap jobDataMap,
String jobIdentity,
String triggerIdentity) throws SchedulerException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.febfes.fftmback.service.impl;

import com.febfes.fftmback.domain.dao.NotificationEntity;
import com.febfes.fftmback.exception.Exceptions;
import com.febfes.fftmback.repository.NotificationRepository;
import com.febfes.fftmback.service.NotificationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;

@Service
Expand All @@ -18,12 +20,14 @@ public class NotificationServiceImpl implements NotificationService {

@Override
public List<NotificationEntity> getNotificationsByUserId(Long userId) {
return notificationRepository.findByUserIdTo(userId);
return notificationRepository.findByUserIdTo(userId).stream()
.sorted(Comparator.comparing(NotificationEntity::getCreateDate).reversed())
.toList();
}

@Override
public List<NotificationEntity> getNotificationsByUserIdAndIsRead(Long userId, Boolean isRead) {
return notificationRepository.findByUserIdToAndIsRead(userId, isRead);
public NotificationEntity getNotificationById(Long id) {
return notificationRepository.findById(id).orElseThrow(Exceptions.notificationNotFound(id));
}

@Override
Expand All @@ -33,5 +37,20 @@ public void createNotification(String message, Long userIdTo) {
.userIdTo(userIdTo)
.build();
notificationRepository.save(notification);
log.info("Created notification with ID = {}", notification.getId());
}

@Override
public void changeIsRead(Long notificationId, boolean isRead) {
NotificationEntity notification = getNotificationById(notificationId);
notification.setRead(isRead);
notificationRepository.save(notification);
log.info("Change isRead to {} for notification with ID = {}", isRead, notification.getId());
}

@Override
public void deleteNotification(Long id) {
notificationRepository.deleteById(id);
log.info("Deleted notification with ID = {}", id);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.febfes.fftmback.service.impl;

import com.febfes.fftmback.schedule.TaskDeadlineJob;
import com.febfes.fftmback.schedule.DeleteNotificationJob;
import com.febfes.fftmback.service.ScheduleService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
Expand All @@ -16,14 +17,37 @@ public class ScheduleServiceImpl implements ScheduleService {

private final Scheduler scheduler;

public static final String JOB = "job";
public static final String TRIGGER = "trigger";
public static final String DELETE_NOTIFICATION = "delete_notification";

@PostConstruct
void postConstruct() throws SchedulerException {
JobKey jobKey = new JobKey(String.format("%s-%s", DELETE_NOTIFICATION, JOB));
if (scheduler.checkExists(jobKey)) {
log.info("{} already exists", jobKey.getName());
return;
}
String triggerIdentity = String.format("%s-%s", DELETE_NOTIFICATION, TRIGGER);
JobDetail job = JobBuilder.newJob(DeleteNotificationJob.class)
.withIdentity(jobKey)
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerIdentity)
.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(0, 0))
.build();
scheduler.scheduleJob(job, trigger);
}

@Override
public void startNewJobAt(
Class<? extends Job> jobClass,
Date triggerStartTime,
JobDataMap jobDataMap,
String jobIdentity,
String triggerIdentity
) throws SchedulerException {
JobDetail job = JobBuilder.newJob(TaskDeadlineJob.class)
JobDetail job = JobBuilder.newJob(jobClass)
.withIdentity(jobIdentity)
.usingJobData(jobDataMap)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.febfes.fftmback.domain.common.specification.TaskSpec;
import com.febfes.fftmback.domain.dao.TaskEntity;
import com.febfes.fftmback.domain.dao.TaskView;
import com.febfes.fftmback.schedule.TaskDeadlineJob;
import com.febfes.fftmback.service.ScheduleService;
import com.febfes.fftmback.service.TaskService;
import lombok.RequiredArgsConstructor;
Expand All @@ -16,6 +17,8 @@
import java.util.Set;
import java.util.UUID;

import static com.febfes.fftmback.service.impl.ScheduleServiceImpl.JOB;
import static com.febfes.fftmback.service.impl.ScheduleServiceImpl.TRIGGER;
import static com.febfes.fftmback.util.DateUtils.convertLocalDateTimeToDate;

@Service("taskServiceDecorator")
Expand All @@ -30,8 +33,6 @@ public class TaskServiceDecorator implements TaskService {
public static final String USER_ID = "userId";
public static final String TASK_ID = "taskId";
public static final String DEADLINE = "deadline";
public static final String JOB = "job";
public static final String TRIGGER = "trigger";

@Override
public List<TaskView> getTasks(int page, int limit, Long columnId, TaskSpec taskSpec) {
Expand Down Expand Up @@ -77,6 +78,7 @@ private void startDeadlineJob(LocalDateTime deadlineDate, Long userId, Long task
jobDataMap.put(TASK_ID, taskId);
String jobIdentity = String.format("%s-%s-%s", DEADLINE, JOB, UUID.randomUUID());
String triggerIdentity = String.format("%s-%s-%s", DEADLINE, TRIGGER, UUID.randomUUID());
scheduleService.startNewJobAt(convertLocalDateTimeToDate(deadlineDate), jobDataMap, jobIdentity, triggerIdentity);
scheduleService.startNewJobAt(TaskDeadlineJob.class, convertLocalDateTimeToDate(deadlineDate),
jobDataMap, jobIdentity, triggerIdentity);
}
}

0 comments on commit 84c1200

Please sign in to comment.