From 3f7f27c791614a9a53e08447ad5c23c773d85125 Mon Sep 17 00:00:00 2001 From: devplant Date: Tue, 19 Oct 2021 10:32:41 +0300 Subject: [PATCH] RED-2437 Notification Preferences Persistence -first implementation, including integration tests --- .../notification/EmailNotificationType.java | 5 ++ .../notification/NotificationPreferences.java | 25 ++++++ .../NotificationPreferencesResource.java | 25 ++++++ .../NotificationPreferencesEntity.java | 38 +++++++++ ...ficationPreferencesPersistenceService.java | 42 ++++++++++ .../NotificationPreferencesRepository.java | 7 ++ .../NotificationPreferencesController.java | 31 ++++++++ .../client/NotificationPreferencesClient.java | 8 ++ .../tests/NotificationPreferencesTest.java | 79 +++++++++++++++++++ .../AbstractPersistenceServerServiceTest.java | 3 + 10 files changed, 263 insertions(+) create mode 100644 persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/EmailNotificationType.java create mode 100644 persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/NotificationPreferences.java create mode 100644 persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationPreferencesResource.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/notification/NotificationPreferencesEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPreferencesPersistenceService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationPreferencesRepository.java create mode 100644 persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationPreferencesController.java create mode 100644 persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/NotificationPreferencesClient.java create mode 100644 persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/NotificationPreferencesTest.java diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/EmailNotificationType.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/EmailNotificationType.java new file mode 100644 index 000000000..7875f1b2e --- /dev/null +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/EmailNotificationType.java @@ -0,0 +1,5 @@ +package com.iqser.red.service.persistence.service.v1.api.model.notification; + +public enum EmailNotificationType { + DAILY, DAILY_SUMMARY, WEEKLY_SUMMARY +} diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/NotificationPreferences.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/NotificationPreferences.java new file mode 100644 index 000000000..8a98bac17 --- /dev/null +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/model/notification/NotificationPreferences.java @@ -0,0 +1,25 @@ +package com.iqser.red.service.persistence.service.v1.api.model.notification; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class NotificationPreferences { + + private String userId; + private boolean inAppNotificationsEnabled; + private boolean emailNotificationsEnabled; + private EmailNotificationType emailNotificationType; + @Builder.Default + private List emailNotifications = new ArrayList<>(); + @Builder.Default + private List inAppNotifications = new ArrayList<>(); +} diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationPreferencesResource.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationPreferencesResource.java new file mode 100644 index 000000000..44831c77f --- /dev/null +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationPreferencesResource.java @@ -0,0 +1,25 @@ +package com.iqser.red.service.persistence.service.v1.api.resources; + +import com.iqser.red.service.persistence.service.v1.api.model.notification.NotificationPreferences; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +public interface NotificationPreferencesResource { + + String REST_PATH = "/notification-preferences"; + + String USER_ID_PARAM = "userId"; + String USER_ID_PATH_PARAM = "/{" + USER_ID_PARAM + "}"; + + + @PostMapping(value = REST_PATH + USER_ID_PATH_PARAM, consumes = MediaType.APPLICATION_JSON_VALUE) + void setNotificationPreferences(@PathVariable(USER_ID_PARAM) String userId, @RequestBody NotificationPreferences notificationRequest); + + @ResponseStatus(value = HttpStatus.OK) + @GetMapping(value = REST_PATH + USER_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE) + NotificationPreferences getNotificationPreferences(@PathVariable(USER_ID_PARAM) String userId); + + @DeleteMapping(value = REST_PATH + USER_ID_PATH_PARAM, consumes = MediaType.APPLICATION_JSON_VALUE) + void deleteNotificationPreferences(@PathVariable(USER_ID_PARAM) String userId); +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/notification/NotificationPreferencesEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/notification/NotificationPreferencesEntity.java new file mode 100644 index 000000000..b0f48b6cd --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/notification/NotificationPreferencesEntity.java @@ -0,0 +1,38 @@ +package com.iqser.red.service.persistence.management.v1.processor.entity.notification; + +import com.iqser.red.service.persistence.service.v1.api.model.notification.EmailNotificationType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "notification_preference") +public class NotificationPreferencesEntity { + + @Id + private String userId; + + @Column + private boolean inAppNotificationsEnabled; + + @Column + private boolean emailNotificationsEnabled; + + @Column + private EmailNotificationType emailNotificationType; + + @ElementCollection + private List emailNotifications = new ArrayList<>(); + + @ElementCollection + private List inAppNotifications = new ArrayList<>(); +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPreferencesPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPreferencesPersistenceService.java new file mode 100644 index 000000000..bb2dfd1e8 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPreferencesPersistenceService.java @@ -0,0 +1,42 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.persistence; + +import com.iqser.red.service.persistence.management.v1.processor.entity.notification.NotificationPreferencesEntity; +import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.NotificationPreferencesRepository; +import com.iqser.red.service.persistence.service.v1.api.model.notification.NotificationPreferences; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +public class NotificationPreferencesPersistenceService { + + private final NotificationPreferencesRepository notificationPreferencesRepository; + + @Transactional + public void setNotificationPreference(String userId, NotificationPreferences notification) { + notificationPreferencesRepository.findById(userId) + .ifPresentOrElse(n -> { + BeanUtils.copyProperties(notification, n); + }, () -> { + NotificationPreferencesEntity notificationPreferencesEntity = new NotificationPreferencesEntity(); + BeanUtils.copyProperties(notification, notificationPreferencesEntity); + notificationPreferencesRepository.save(notificationPreferencesEntity); + }); + } + + @Transactional + public void deleteNotificationPreferences(String userId) { + notificationPreferencesRepository.deleteById(userId); + } + + @Transactional + public NotificationPreferencesEntity getNotificationPreferences(String userId) { + return notificationPreferencesRepository.findById(userId).orElseThrow(() -> { + throw new NotFoundException("Notification preferences not found for userId: " + userId); + }); + } +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationPreferencesRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationPreferencesRepository.java new file mode 100644 index 000000000..206736d0d --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationPreferencesRepository.java @@ -0,0 +1,7 @@ +package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository; + +import com.iqser.red.service.persistence.management.v1.processor.entity.notification.NotificationPreferencesEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface NotificationPreferencesRepository extends JpaRepository { +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationPreferencesController.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationPreferencesController.java new file mode 100644 index 000000000..567e7fdf2 --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationPreferencesController.java @@ -0,0 +1,31 @@ +package com.iqser.red.service.peristence.v1.server.controller; + +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.NotificationPreferencesPersistenceService; +import com.iqser.red.service.persistence.service.v1.api.model.notification.NotificationPreferences; +import com.iqser.red.service.persistence.service.v1.api.resources.NotificationPreferencesResource; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +import static com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter.convert; + +@RestController +@RequiredArgsConstructor +public class NotificationPreferencesController implements NotificationPreferencesResource { + + private final NotificationPreferencesPersistenceService notificationPreferencesPersistenceService; + + @Override + public void setNotificationPreferences(String userId, NotificationPreferences notificationRequest) { + notificationPreferencesPersistenceService.setNotificationPreference(userId, notificationRequest); + } + + @Override + public NotificationPreferences getNotificationPreferences(String userId) { + return convert(notificationPreferencesPersistenceService.getNotificationPreferences(userId), NotificationPreferences.class); + } + + @Override + public void deleteNotificationPreferences(String userId) { + notificationPreferencesPersistenceService.deleteNotificationPreferences(userId); + } +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/NotificationPreferencesClient.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/NotificationPreferencesClient.java new file mode 100644 index 000000000..c137e1a5c --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/NotificationPreferencesClient.java @@ -0,0 +1,8 @@ +package com.iqser.red.service.peristence.v1.server.integration.client; + +import com.iqser.red.service.persistence.service.v1.api.resources.NotificationPreferencesResource; +import org.springframework.cloud.openfeign.FeignClient; + +@FeignClient(name = "NotificationPreferencesClient", url = "http://localhost:${server.port}") +public interface NotificationPreferencesClient extends NotificationPreferencesResource { +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/NotificationPreferencesTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/NotificationPreferencesTest.java new file mode 100644 index 000000000..73b7b7314 --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/NotificationPreferencesTest.java @@ -0,0 +1,79 @@ +package com.iqser.red.service.peristence.v1.server.integration.tests; + +import com.iqser.red.service.peristence.v1.server.integration.client.NotificationPreferencesClient; +import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest; +import com.iqser.red.service.persistence.service.v1.api.model.notification.EmailNotificationType; +import com.iqser.red.service.persistence.service.v1.api.model.notification.NotificationPreferences; +import feign.FeignException; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NotificationPreferencesTest extends AbstractPersistenceServerServiceTest { + + private static final String USER_ID = "1234"; + private static final String DOSSIER_YOU_OWN_NOTIFICATION_1 = "Dossier status changes"; + private static final String DOSSIER_YOU_OWN_NOTIFICATION_2 = "Requests to join dossier"; + private static final String DOSSIER_YOU_OWN_NOTIFICATION_3 = "Document status changes"; + private static final String DOSSIER_YOU_OWN_NOTIFICATION_4 = "Document is sent for approval"; + + @Autowired + private NotificationPreferencesClient notificationPreferencesClient; + + private NotificationPreferences notificationPreferences; + List inAppNotifications = new ArrayList<>(); + List emailNotifications = new ArrayList<>(); + + @Before + public void setupData() { + inAppNotifications.add(DOSSIER_YOU_OWN_NOTIFICATION_1); + inAppNotifications.add(DOSSIER_YOU_OWN_NOTIFICATION_2); + inAppNotifications.add(DOSSIER_YOU_OWN_NOTIFICATION_3); + emailNotifications.add(DOSSIER_YOU_OWN_NOTIFICATION_1); + emailNotifications.add(DOSSIER_YOU_OWN_NOTIFICATION_2); + emailNotifications.add(DOSSIER_YOU_OWN_NOTIFICATION_4); + notificationPreferences = new NotificationPreferences(USER_ID, true, true, EmailNotificationType.DAILY, emailNotifications, inAppNotifications); + } + + @Test + public void testNotificationPreferences() { + // add notification + notificationPreferencesClient.setNotificationPreferences(USER_ID, notificationPreferences); + + NotificationPreferences notificationReceived = notificationPreferencesClient.getNotificationPreferences(USER_ID); + + assertThat(notificationReceived.getEmailNotificationType()).isEqualTo(EmailNotificationType.DAILY); + assertThat(notificationReceived.isEmailNotificationsEnabled()).isTrue(); + assertThat(notificationReceived.isInAppNotificationsEnabled()).isTrue(); + assertThat(notificationReceived.getInAppNotifications().size()).isEqualTo(notificationPreferences.getInAppNotifications().size()); + assertThat(notificationReceived.getEmailNotifications().size()).isEqualTo(notificationPreferences.getEmailNotifications().size()); + + // update notification + notificationPreferences.getInAppNotifications().add(DOSSIER_YOU_OWN_NOTIFICATION_4); + notificationPreferences.setEmailNotificationsEnabled(false); + + notificationPreferencesClient.setNotificationPreferences(USER_ID, notificationPreferences); + + notificationReceived = notificationPreferencesClient.getNotificationPreferences(USER_ID); + + assertThat(notificationReceived.getEmailNotificationType()).isEqualTo(EmailNotificationType.DAILY); + assertThat(notificationReceived.isEmailNotificationsEnabled()).isFalse(); + assertThat(notificationReceived.isInAppNotificationsEnabled()).isTrue(); + assertThat(notificationReceived.getInAppNotifications().size()).isEqualTo(notificationPreferences.getInAppNotifications().size()); + assertThat(notificationReceived.getEmailNotifications().size()).isEqualTo(notificationPreferences.getEmailNotifications().size()); + + + // delete notification + notificationPreferencesClient.deleteNotificationPreferences(USER_ID); + try { + notificationReceived = notificationPreferencesClient.getNotificationPreferences(USER_ID); + } catch (FeignException e) { + assertThat(e.status()).isEqualTo(404); + } + } +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java index 00a2d5597..8d148e7fa 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/utils/AbstractPersistenceServerServiceTest.java @@ -105,6 +105,8 @@ public abstract class AbstractPersistenceServerServiceTest { private DossierAttributeRepository dossierAttributeRepository; @Autowired private DossierAttributeConfigRepository dossierAttributeConfigRepository; + @Autowired + private NotificationPreferencesRepository notificationPreferencesRepository; @Before public void setupOptimize() { @@ -160,6 +162,7 @@ public abstract class AbstractPersistenceServerServiceTest { fileRepository.deleteAll(); dossierRepository.deleteAll(); dossierTemplateRepository.deleteAll(); + notificationPreferencesRepository.deleteAll(); } static class Initializer implements ApplicationContextInitializer {