diff --git a/data-api/open-api-specification.yml b/data-api/open-api-specification.yml
index 4f79cc4..f55f45a 100644
--- a/data-api/open-api-specification.yml
+++ b/data-api/open-api-specification.yml
@@ -64,6 +64,36 @@ paths:
description: 'Not found'
'500':
description: 'Internal server error'
+ /users/{login-id}/notifications/summary:
+ get:
+ tags:
+ - notifications
+ summary: 'Get User Notification Summary'
+ operationId: 'getUserNotificationSummary'
+ parameters:
+ - name: 'login-id'
+ in: 'path'
+ required: true
+ schema:
+ type: 'string'
+ example: 'abc123'
+ responses:
+ '200':
+ description: 'Successful operation'
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/notificationSummary"
+ '400':
+ description: 'Bad request'
+ '401':
+ description: 'Unauthorized'
+ '403':
+ description: 'Forbidden'
+ '404':
+ description: 'Not found'
+ '500':
+ description: 'Internal server error'
/providers/{provider-id}:
get:
tags:
@@ -795,7 +825,7 @@ paths:
- name: 'type'
in: 'query'
schema:
- type: 'String'
+ type: 'string'
responses:
'200':
description: 'Successful operation'
@@ -1044,6 +1074,15 @@ components:
type: 'array'
items:
type: 'string'
+ notificationSummary:
+ type: 'object'
+ properties:
+ notifications:
+ type: 'integer'
+ standard_actions:
+ type: 'integer'
+ overdue_actions:
+ type: 'integer'
contactDetail:
type: 'object'
properties:
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/controller/NotificationsController.java b/data-service/src/main/java/uk/gov/laa/ccms/data/controller/NotificationsController.java
new file mode 100644
index 0000000..7d34b1a
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/controller/NotificationsController.java
@@ -0,0 +1,31 @@
+package uk.gov.laa.ccms.data.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RestController;
+import uk.gov.laa.ccms.data.api.NotificationsApi;
+import uk.gov.laa.ccms.data.model.NotificationSummary;
+import uk.gov.laa.ccms.data.service.NotificationService;
+
+/**
+ * Controller class responsible for handling notification-related requests.
+ *
+ *
This controller serves as an interface to return requested user notification
+ * information. It delegates the business logic to the {@link NotificationService}.
+ *
+ *
This class implements the {@link NotificationsApi} interface and provides
+ * endpoints for retrieving notification summaries for users.
+ */
+@RestController
+@RequiredArgsConstructor
+public class NotificationsController implements NotificationsApi {
+
+ private final NotificationService notificationService;
+
+ @Override
+ public ResponseEntity getUserNotificationSummary(String loginId) {
+ return notificationService.getUserNotificationSummary(loginId).map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+}
+
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationCount.java b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationCount.java
new file mode 100644
index 0000000..f41e102
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationCount.java
@@ -0,0 +1,53 @@
+package uk.gov.laa.ccms.data.entity;
+
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import jakarta.persistence.Column;
+import jakarta.persistence.EmbeddedId;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Immutable;
+
+/**
+ * Represents an immutable notification count entity corresponding to the
+ * "XXCCMS_NOTIFICATION_COUNT_V" database view.
+ *
+ * The entity tracks the total number of notifications for a specific user login
+ * and notification type.
+ */
+@Entity
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "XXCCMS_NOTIFICATION_COUNT_V")
+@Immutable
+@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+public class NotificationCount {
+
+ public static final String NOTIFICATION_TYPE_NOTIFICATIONS = "Notifications";
+ public static final String NOTIFICATION_TYPE_ACTIONS = "Actions";
+ public static final String NOTIFICATION_TYPE_OVERDUE = "Overdue";
+
+ /**
+ * The composite key for the NotificationCount entity.
+ * This key is used to uniquely identify a notification count entry
+ * based on the user login ID and notification type.
+ */
+ @EmbeddedId
+ private NotificationCountId id;
+
+ /**
+ * Represents the total number of notifications associated with a specific
+ * user login and notification type. This field is stored in the
+ * "NOTIFICATION_COUNT" column of the corresponding database view.
+ */
+ @Column(name = "NOTIFICATION_COUNT")
+ private Integer notificationCount;
+
+
+}
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationCountId.java b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationCountId.java
new file mode 100644
index 0000000..3cd1564
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationCountId.java
@@ -0,0 +1,36 @@
+package uk.gov.laa.ccms.data.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Convert;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Represents a composite primary key for the NotificationCount entity in the form of a
+ * NotificationCountId class. This key uniquely identifies a notification count record based on a
+ * combination of user login ID and notification type.
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class NotificationCountId implements Serializable {
+
+ /**
+ * A unique identifier representing a user's login session. This field is mapped to the
+ * "USER_LOGIN_ID" column in the database.
+ */
+ @Column(name = "USER_LOGIN_ID")
+ private String userLoginId;
+
+ /**
+ * Represents the type of notification associated with a user login session. This field is mapped
+ * to the "NOTIFICATION_TYPE" column in the database and uses the NotificationTypeConverter to
+ * translate between the NotificationType enumeration and its corresponding String representation
+ * for database storage.
+ */
+ @Column(name = "NOTIFICATION_TYPE")
+ @Convert(converter = NotificationTypeConverter.class)
+ private NotificationType notificationType;
+}
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationType.java b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationType.java
new file mode 100644
index 0000000..bfa8675
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationType.java
@@ -0,0 +1,35 @@
+package uk.gov.laa.ccms.data.entity;
+
+import lombok.Getter;
+
+/**
+ * Defines the type of notification. This enumeration is used to categorize
+ * different types of notifications within the system.
+ *
+ *
Each type has a corresponding database value which is a string representation
+ * of the notification type stored in the database.
+ *
+ *
The available types are:
+ *
+ * - NOTIFICATIONS: Represents general notifications. In
+ * the DB referred to as 'Notification'.
+ * - ACTION: Represents action-required notifications. In the DB referred to as 'Action'.
+ * - OVERDUE: Represents overdue notifications. In the DB referred to as 'Overdue'.
+ *
+ * The enum provides a mechanism to easily handle notification types
+ * programmatically by using the associated string value,
+ * allowing seamless conversion between the programmatic representation and
+ * the database representation.
+ */
+@Getter
+public enum NotificationType {
+ NOTIFICATIONS("Notification"),
+ ACTION("Action"),
+ OVERDUE("Overdue");
+
+ private final String dbValue;
+
+ NotificationType(String dbValue) {
+ this.dbValue = dbValue;
+ }
+}
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationTypeConverter.java b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationTypeConverter.java
new file mode 100644
index 0000000..ae47ae1
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/entity/NotificationTypeConverter.java
@@ -0,0 +1,62 @@
+package uk.gov.laa.ccms.data.entity;
+
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
+
+/**
+ * Converter implementation for mapping the NotificationType enumeration to a String
+ * representation in the database and vice versa.
+ *
+ * This converter is automatically applied to all entity attributes of type NotificationType
+ * across the JPA context due to the use of the @Converter annotation with autoApply set to true.
+ *
+ *
The convertToDatabaseColumn method translates a NotificationType enumeration value to its
+ * corresponding String representation for storage in the database. If the provided
+ * NotificationType is null, the database column is set to null.
+ *
+ *
The convertToEntityAttribute method takes a String from the database and converts it back
+ * to its corresponding NotificationType value. If the database value is null, it returns null
+ * as the entity attribute. If the database String does not match any known NotificationType,
+ * an IllegalArgumentException is thrown.
+ */
+@Converter(autoApply = true)
+public class NotificationTypeConverter implements AttributeConverter {
+
+ /**
+ * Converts a NotificationType enumeration value to its corresponding String representation
+ * for storage in the database.
+ *
+ * @param notificationType the NotificationType to be converted to a database column value;
+ * may be null, in which case the method returns null.
+ * @return the String representation of the given NotificationType for database storage,
+ * or null if the NotificationType is null.
+ */
+ @Override
+ public String convertToDatabaseColumn(NotificationType notificationType) {
+ return notificationType != null ? notificationType.getDbValue() : null;
+ }
+
+ /**
+ * Converts a database column value (String) to the corresponding
+ * NotificationType enumeration value.
+ *
+ * @param dbData the database column value that represents a
+ * NotificationType; may be null.
+ * @return the NotificationType corresponding to the given database value,
+ * or null if the input is null.
+ * @throws IllegalArgumentException if dbData does not match any known NotificationType values.
+ */
+ @Override
+ public NotificationType convertToEntityAttribute(String dbData) {
+ if (dbData == null) {
+ return null;
+ }
+
+ return switch (dbData) {
+ case "Notification" -> NotificationType.NOTIFICATIONS;
+ case "Action" -> NotificationType.ACTION;
+ case "Overdue" -> NotificationType.OVERDUE;
+ default -> throw new IllegalArgumentException("Unknown database value: " + dbData);
+ };
+ }
+}
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/mapper/NotificationSummaryMapper.java b/data-service/src/main/java/uk/gov/laa/ccms/data/mapper/NotificationSummaryMapper.java
new file mode 100644
index 0000000..678f99a
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/mapper/NotificationSummaryMapper.java
@@ -0,0 +1,68 @@
+package uk.gov.laa.ccms.data.mapper;
+
+import static java.util.Objects.isNull;
+
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
+import java.util.function.Predicate;
+import org.mapstruct.Mapper;
+import uk.gov.laa.ccms.data.entity.NotificationCount;
+import uk.gov.laa.ccms.data.entity.NotificationType;
+import uk.gov.laa.ccms.data.model.NotificationSummary;
+
+/**
+ * NotificationSummaryMapper is an interface for mapping notification count data
+ * to a notification summary. Utilizes Java streams to process lists of NotificationCount and
+ * derive a summary. This interface uses the MapStruct framework for object mapping and
+ * is defined as a Spring component.
+ *
+ * Note: It computes the sum of notifications, actions, and overdue actions from a
+ * list of NotificationCount.
+ *
+ * @see NotificationSummary
+ * @see NotificationCount
+ * @see NotificationType
+ */
+@Mapper(componentModel = "spring")
+public interface NotificationSummaryMapper {
+
+ Predicate IS_NOTIFICATION_TYPE =
+ x -> NotificationType.NOTIFICATIONS.equals(x.getId().getNotificationType());
+ Predicate IS_ACTION_TYPE =
+ x -> NotificationType.ACTION.equals(x.getId().getNotificationType());
+ Predicate IS_OVERDUE_TYPE =
+ x -> NotificationType.OVERDUE.equals(x.getId().getNotificationType());
+
+ /**
+ * Converts a list of NotificationCount objects into a NotificationSummary object
+ * by calculating the sum of different types of notifications.
+ *
+ * @param notificationCount a list containing instances of NotificationCount, each with a
+ * type and count of notifications
+ * @return a NotificationSummary object with the total count of notifications, standard actions,
+ * and overdue actions derived from the provided list
+ */
+ default NotificationSummary toNotificationSummary(
+ @NotNull List notificationCount) {
+
+ int notificationSum = 0;
+ int actionSum = 0;
+ int overdueSum = 0;
+ if (!isNull(notificationCount)) {
+ // There shouldn't really be an instance where there are multiple of the same notification
+ // type, however if there are due to inconsistencies in the DB, use Java streams to get
+ // the sum.
+ notificationSum = notificationCount.stream()
+ .filter(IS_NOTIFICATION_TYPE)
+ .mapToInt(NotificationCount::getNotificationCount).sum();
+ actionSum = notificationCount.stream()
+ .filter(IS_ACTION_TYPE)
+ .mapToInt(NotificationCount::getNotificationCount).sum();
+ overdueSum = notificationCount.stream()
+ .filter(IS_OVERDUE_TYPE)
+ .mapToInt(NotificationCount::getNotificationCount).sum();
+ }
+ return new NotificationSummary().notifications(notificationSum).standardActions(actionSum)
+ .overdueActions(overdueSum);
+ }
+}
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/repository/NotificationCountRepository.java b/data-service/src/main/java/uk/gov/laa/ccms/data/repository/NotificationCountRepository.java
new file mode 100644
index 0000000..307273e
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/repository/NotificationCountRepository.java
@@ -0,0 +1,24 @@
+package uk.gov.laa.ccms.data.repository;
+
+import java.util.List;
+import org.springframework.stereotype.Repository;
+import uk.gov.laa.ccms.data.entity.NotificationCount;
+import uk.gov.laa.ccms.data.entity.NotificationCountId;
+
+/**
+ * Repository interface for accessing {@link NotificationCount} entities.
+ *
+ * This repository extends the {@link ReadOnlyRepository} interface, it supports read-only
+ * operations for the {@code NotificationCount} entity, with the primary key of type
+ * {@code String}.
+ *
+ * @author Jamie Briggs
+ * @see NotificationCount
+ * @see ReadOnlyRepository
+ */
+@Repository
+public interface NotificationCountRepository
+ extends ReadOnlyRepository {
+
+ List findAllByIdUserLoginId(String userLoginId);
+}
diff --git a/data-service/src/main/java/uk/gov/laa/ccms/data/service/NotificationService.java b/data-service/src/main/java/uk/gov/laa/ccms/data/service/NotificationService.java
new file mode 100644
index 0000000..6c3b5ee
--- /dev/null
+++ b/data-service/src/main/java/uk/gov/laa/ccms/data/service/NotificationService.java
@@ -0,0 +1,50 @@
+package uk.gov.laa.ccms.data.service;
+
+import java.util.List;
+import java.util.Optional;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import uk.gov.laa.ccms.data.entity.NotificationCount;
+import uk.gov.laa.ccms.data.mapper.NotificationSummaryMapper;
+import uk.gov.laa.ccms.data.model.NotificationSummary;
+import uk.gov.laa.ccms.data.repository.NotificationCountRepository;
+
+/**
+ * Service class responsible for handling notification-related operations.
+ *
+ * This class serves to manage the retrieval of notification summaries
+ * for users, bridging the interactions between repositories, mappers,
+ * and other services required to obtain and synthesize notification data.
+ *
+ * @author Jamie Briggs
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class NotificationService {
+
+ private final NotificationCountRepository notificationCountRepository;
+ private final NotificationSummaryMapper notificationSummaryMapper;
+ private final UserService userService;
+
+ /**
+ * Retrieves the summary of notifications for a specific user.
+ *
+ * @param userId the unique identifier of the user for whom to retrieve the notification summary
+ * @return a NotificationSummary object representing the summary of notifications for the
+ * specified user
+ */
+ @Transactional
+ public Optional getUserNotificationSummary(String userId) {
+ // Check if user exists
+ if (userService.getUser(userId).isPresent()) {
+ List allByIdUserLoginId =
+ notificationCountRepository.findAllByIdUserLoginId(userId);
+ return Optional.ofNullable(
+ notificationSummaryMapper.toNotificationSummary(allByIdUserLoginId));
+ }
+ return Optional.empty();
+ }
+}
diff --git a/data-service/src/test/java/uk/gov/laa/ccms/data/controller/NotificationsControllerTest.java b/data-service/src/test/java/uk/gov/laa/ccms/data/controller/NotificationsControllerTest.java
new file mode 100644
index 0000000..1cd349d
--- /dev/null
+++ b/data-service/src/test/java/uk/gov/laa/ccms/data/controller/NotificationsControllerTest.java
@@ -0,0 +1,77 @@
+package uk.gov.laa.ccms.data.controller;
+
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
+
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.web.context.WebApplicationContext;
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
+import uk.gov.laa.ccms.data.model.NotificationSummary;
+import uk.gov.laa.ccms.data.service.NotificationService;
+
+@ExtendWith({SpringExtension.class})
+@ContextConfiguration
+@WebAppConfiguration
+class NotificationsControllerTest {
+
+ @Mock
+ private NotificationService notificationService;
+
+ @InjectMocks
+ private NotificationsController notificationsController;
+
+ private MockMvc mockMvc;
+
+ @Autowired
+ private WebApplicationContext webApplicationContext;
+
+ private ObjectMapper objectMapper;
+
+ @BeforeEach
+ public void setup() {
+ mockMvc = standaloneSetup(notificationsController).build();
+ objectMapper = new ObjectMapper();
+ }
+
+ @Test
+ @DisplayName("getUserNotificationSummary: Returns data")
+ void getUserNotificationSummary_returnsData() throws Exception {
+ //Given
+ String loginId = "123";
+ NotificationSummary expected = new NotificationSummary().notifications(1).standardActions(1)
+ .overdueActions(1);
+ when(notificationService.getUserNotificationSummary(loginId)).thenReturn(Optional.of(expected));
+ // Then
+ String jsonContent = objectMapper.writeValueAsString(expected);
+ this.mockMvc.perform(get("/users/{loginId}/notifications/summary", loginId))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andExpect(content().json(jsonContent));
+ }
+
+ @Test
+ @DisplayName("getUserNotificationSummary: Not found")
+ void getUserNotificationSummary_notFound() throws Exception {
+ // Given
+ String loginId = "123";
+ // Then
+ this.mockMvc.perform(get("/users/{loginId}/notifications/summary", loginId))
+ .andDo(print())
+ .andExpect(status().isNotFound());
+ }
+}
\ No newline at end of file
diff --git a/data-service/src/test/java/uk/gov/laa/ccms/data/entity/NotificationTypeConverterTest.java b/data-service/src/test/java/uk/gov/laa/ccms/data/entity/NotificationTypeConverterTest.java
new file mode 100644
index 0000000..6b911cd
--- /dev/null
+++ b/data-service/src/test/java/uk/gov/laa/ccms/data/entity/NotificationTypeConverterTest.java
@@ -0,0 +1,50 @@
+package uk.gov.laa.ccms.data.entity;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import uk.gov.laa.ccms.data.entity.NotificationType;
+
+public class NotificationTypeConverterTest {
+
+ NotificationTypeConverter converter = new NotificationTypeConverter();
+
+ @Test
+ @DisplayName("Should convert Notification DB Value to Entity value")
+ public void shouldConvertNotificationDbValuetoEntityValue() {
+ assertEquals(NotificationType.NOTIFICATIONS, converter.convertToEntityAttribute("Notification"));
+ }
+
+ @Test
+ @DisplayName("Should convert Action DB Value to Entity value")
+ public void shouldConvertActionDbValuetoEntityValue() {
+ assertEquals(NotificationType.ACTION, converter.convertToEntityAttribute("Action"));
+ }
+
+ @Test
+ @DisplayName("Should convert Overdue DB Value to Entity value")
+ public void shouldConvertOverdueDbValuetoEntityValue() {
+ assertEquals(NotificationType.OVERDUE, converter.convertToEntityAttribute("Overdue"));
+ }
+
+ @Test
+ @DisplayName("Should convert Notification Entity value to DB value")
+ public void shouldConvertNotificationEntityValuetoDBValue() {
+ assertEquals("Notification", converter.convertToDatabaseColumn(NotificationType.NOTIFICATIONS));
+ }
+
+ @Test
+ @DisplayName("Should convert Action Entity value to DB value")
+ public void shouldConvertActionEntityValuetoDBValue() {
+ assertEquals("Action", converter.convertToDatabaseColumn(NotificationType.ACTION));
+ }
+
+ @Test
+ @DisplayName("Should convert Overdue Entity value to DB value")
+ public void shouldConvertOverdueEntityValuetoDBValue() {
+ assertEquals("Overdue", converter.convertToDatabaseColumn(NotificationType.OVERDUE));
+ }
+
+}
diff --git a/data-service/src/test/java/uk/gov/laa/ccms/data/mapper/NotificationSummaryMapperImplTest.java b/data-service/src/test/java/uk/gov/laa/ccms/data/mapper/NotificationSummaryMapperImplTest.java
new file mode 100644
index 0000000..efd9986
--- /dev/null
+++ b/data-service/src/test/java/uk/gov/laa/ccms/data/mapper/NotificationSummaryMapperImplTest.java
@@ -0,0 +1,178 @@
+package uk.gov.laa.ccms.data.mapper;
+
+import static java.util.Collections.emptyList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import uk.gov.laa.ccms.data.entity.NotificationCount;
+import uk.gov.laa.ccms.data.entity.NotificationCountId;
+import uk.gov.laa.ccms.data.entity.NotificationType;
+import uk.gov.laa.ccms.data.model.NotificationSummary;
+
+@ExtendWith(MockitoExtension.class)
+class NotificationSummaryMapperImplTest {
+
+ NotificationSummaryMapperImpl mapper = new NotificationSummaryMapperImpl();
+
+ @Test
+ @DisplayName("Should return notification summary with zeros when empty list passed")
+ void shouldReturnNotificationSummaryWithZerosWhenEmptyListPassed() {
+ // Given
+ List counts = emptyList();
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(0).overdueActions(0),
+ result, "Should only contain zeros");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with zeros when null passed")
+ void shouldReturnNotificationSummaryWithZerosWhenNullPassed() {
+ // Given
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(null);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(0).overdueActions(0),
+ result, "Should only contain zeros");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with list of zeros passed")
+ void shouldReturnNotificationSummaryWithListOfZerosPassed() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(0).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(0).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(0).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(0).overdueActions(0),
+ result, "Should only contain zeros");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with 3 notifications")
+ void shouldReturnNotificationSummaryWith3Notifications() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(3).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(0).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(0).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(3).standardActions(0).overdueActions(0),
+ result, "Notification summary should only have 3 notifications");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with 5 notifications due to multiple NotificationCount objects")
+ void shouldReturnNotificationSummaryWith5NotificationsDueToMultipleNotificationCountObjects() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(2).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(3).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(5).standardActions(0).overdueActions(0),
+ result, "Notification summary should only have 5 notifications");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with 5 actions")
+ void shouldReturnNotificationSummaryWith5Actions() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(0).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(5).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(0).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(5).overdueActions(0),
+ result, "Notification summary should only have 5 actions");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with 6 actions due to multiple NotificationCount objects")
+ void shouldReturnNotificationSummaryWith6ActionsDueToMultipleNotificationCountObjects() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(2).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(4).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(6).overdueActions(0),
+ result, "Notification summary should only have 6 actions");
+ }
+
+
+ @Test
+ @DisplayName("Should return notification summary with 7 overdue")
+ void shouldReturnNotificationSummaryWith7Overdue() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(0).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(0).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(7).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(0).overdueActions(7),
+ result, "Notification summary should only have 7 actions");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with 9 overdue due to multiple NotificationCount objects")
+ void shouldReturnNotificationSummaryWith9OverdueDueToMultipleNotificationCountObjects() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(5).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(4).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(0).standardActions(0).overdueActions(9),
+ result, "Notification summary should only have 9 overdue");
+ }
+
+ @Test
+ @DisplayName("Should return notification summary with multiple notification types")
+ void shouldReturnNotificationSummaryWithMultipleNotificationTypes() {
+ // Given
+ List counts = Arrays.asList(
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.NOTIFICATIONS)).notificationCount(2).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.ACTION)).notificationCount(4).build(),
+ NotificationCount.builder().id(withNotificationCountId(NotificationType.OVERDUE)).notificationCount(6).build()
+ );
+ // When
+ NotificationSummary result = mapper.toNotificationSummary(counts);
+ // Then
+ assertEquals(new NotificationSummary().notifications(2).standardActions(4).overdueActions(6),
+ result, "Notification summary should only have 7 actions");
+ }
+
+
+
+ private static NotificationCountId withNotificationCountId(NotificationType notificationType) {
+ return new NotificationCountId("User", notificationType);
+ }
+
+
+}
\ No newline at end of file