diff --git a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java index e7964169fa..f20b666b28 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java @@ -350,6 +350,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple NotificationUpdate update = NotificationUpdate.builder() .updated(true) .notificationId(notificationId.getId()) + .notificationType(notification.getType()) .newStatus(NotificationStatus.READ) .build(); onNotificationUpdate(tenantId, recipientId, update); diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscription.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscription.java index d1822a6ffe..4324a3514a 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscription.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscription.java @@ -21,7 +21,6 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; @Data @@ -52,4 +51,5 @@ public abstract class TbSubscription { public int hashCode() { return Objects.hash(sessionId, subscriptionId, tenantId, entityId, type); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java index 6fa9111c3d..b8c83fe286 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; @@ -78,6 +79,7 @@ public class DefaultNotificationCommandsHandler implements NotificationCommandsH .entityId(securityCtx.getId()) .updateProcessor(this::handleNotificationsSubscriptionUpdate) .limit(cmd.getLimit()) + .notificationTypes(cmd.getTypes()) .build(); localSubscriptionService.addSubscription(subscription); @@ -105,8 +107,8 @@ public class DefaultNotificationCommandsHandler implements NotificationCommandsH private void fetchUnreadNotifications(NotificationsSubscription subscription) { log.trace("[{}, subId: {}] Fetching unread notifications from DB", subscription.getSessionId(), subscription.getSubscriptionId()); - PageData notifications = notificationService.findLatestUnreadNotificationsByRecipientId(subscription.getTenantId(), - WEB, (UserId) subscription.getEntityId(), subscription.getLimit()); + PageData notifications = notificationService.findLatestUnreadNotificationsByRecipientIdAndNotificationTypes(subscription.getTenantId(), + WEB, (UserId) subscription.getEntityId(), subscription.getNotificationTypes(), subscription.getLimit()); subscription.getLatestUnreadNotifications().clear(); notifications.getData().forEach(notification -> { subscription.getLatestUnreadNotifications().put(notification.getUuidId(), notification); @@ -139,6 +141,11 @@ public class DefaultNotificationCommandsHandler implements NotificationCommandsH log.trace("[{}, subId: {}] Handling notification update: {}", subscription.getSessionId(), subscription.getSubscriptionId(), update); Notification notification = update.getNotification(); UUID notificationId = notification != null ? notification.getUuidId() : update.getNotificationId(); + NotificationType notificationType = notification != null ? notification.getType() : update.getNotificationType(); + if (notificationType != null && !subscription.checkNotificationType(notificationType)) { + return; + } + if (update.isCreated()) { subscription.getLatestUnreadNotifications().put(notificationId, notification); subscription.getTotalUnreadCounter().incrementAndGet(); diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/NotificationsSubCmd.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/NotificationsSubCmd.java index 20f429b9f3..66a4a3dd30 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/NotificationsSubCmd.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/NotificationsSubCmd.java @@ -18,15 +18,19 @@ package org.thingsboard.server.service.ws.notification.cmd; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.service.ws.WsCmd; import org.thingsboard.server.service.ws.WsCmdType; +import java.util.Set; + @Data @NoArgsConstructor @AllArgsConstructor public class NotificationsSubCmd implements WsCmd { private int cmdId; private int limit; + private Set types; @Override public WsCmdType getType() { diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/UnreadNotificationsUpdate.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/UnreadNotificationsUpdate.java index 9349f2f8dd..eae88a0191 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/UnreadNotificationsUpdate.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/cmd/UnreadNotificationsUpdate.java @@ -24,13 +24,13 @@ import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.service.ws.telemetry.cmd.v2.CmdUpdate; import org.thingsboard.server.service.ws.telemetry.cmd.v2.CmdUpdateType; -import java.util.Collection; +import java.util.List; @Getter @ToString(exclude = "notifications") public class UnreadNotificationsUpdate extends CmdUpdate { - private final Collection notifications; + private final List notifications; private final Notification update; private final int totalUnreadCount; private final int sequenceNumber; @@ -39,7 +39,7 @@ public class UnreadNotificationsUpdate extends CmdUpdate { @JsonCreator public UnreadNotificationsUpdate(@JsonProperty("cmdId") int cmdId, @JsonProperty("errorCode") int errorCode, @JsonProperty("errorMsg") String errorMsg, - @JsonProperty("notifications") Collection notifications, + @JsonProperty("notifications") List notifications, @JsonProperty("update") Notification update, @JsonProperty("totalUnreadCount") int totalUnreadCount, @JsonProperty("sequenceNumber") int sequenceNumber) { diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationUpdate.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationUpdate.java index efbdd07c5b..b6835ca4ea 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationUpdate.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationUpdate.java @@ -21,6 +21,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import java.util.UUID; @@ -31,6 +32,7 @@ import java.util.UUID; public class NotificationUpdate { private UUID notificationId; + private NotificationType notificationType; private boolean created; private Notification notification; diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsCountSubscription.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsCountSubscription.java index 1e812c3b31..171416a63d 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsCountSubscription.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsCountSubscription.java @@ -23,7 +23,6 @@ import org.thingsboard.server.service.subscription.TbSubscription; import org.thingsboard.server.service.subscription.TbSubscriptionType; import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsCountUpdate; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; @Getter diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsSubscription.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsSubscription.java index 97dc15f6b0..58ced7c4bf 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsSubscription.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationsSubscription.java @@ -17,10 +17,12 @@ package org.thingsboard.server.service.ws.notification.sub; import lombok.Builder; import lombok.Getter; +import org.apache.commons.collections4.CollectionUtils; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.Notification; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.service.subscription.TbSubscription; import org.thingsboard.server.service.subscription.TbSubscriptionType; import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsUpdate; @@ -29,8 +31,8 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.stream.Collectors; @@ -39,13 +41,19 @@ public class NotificationsSubscription extends AbstractNotificationSubscription< private final Map latestUnreadNotifications = new HashMap<>(); private final int limit; + private final Set notificationTypes; @Builder public NotificationsSubscription(String serviceId, String sessionId, int subscriptionId, TenantId tenantId, EntityId entityId, BiConsumer, NotificationsSubscriptionUpdate> updateProcessor, - int limit) { + int limit, Set notificationTypes) { super(serviceId, sessionId, subscriptionId, tenantId, entityId, TbSubscriptionType.NOTIFICATIONS, updateProcessor); this.limit = limit; + this.notificationTypes = notificationTypes; + } + + public boolean checkNotificationType(NotificationType type) { + return CollectionUtils.isEmpty(notificationTypes) || notificationTypes.contains(type); } public UnreadNotificationsUpdate createFullUpdate() { diff --git a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java index 15650ff2e6..bbe31f3e94 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java @@ -143,6 +143,14 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest return submitNotificationRequest(targetId, text, 0, deliveryMethods); } + protected NotificationRequest submitNotificationRequest(NotificationType type, NotificationTargetId targetId, String text, NotificationDeliveryMethod... deliveryMethods) { + if (deliveryMethods.length == 0) { + deliveryMethods = new NotificationDeliveryMethod[]{NotificationDeliveryMethod.WEB}; + } + NotificationTemplate notificationTemplate = createNotificationTemplate(type, DEFAULT_NOTIFICATION_SUBJECT, text, deliveryMethods); + return submitNotificationRequest(List.of(targetId), notificationTemplate.getId(), 0); + } + protected NotificationRequest submitNotificationRequest(NotificationTargetId targetId, String text, int delayInSec, NotificationDeliveryMethod... deliveryMethods) { return submitNotificationRequest(List.of(targetId), text, delayInSec, deliveryMethods); } diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index 883a173edb..9981b7935d 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -210,6 +210,88 @@ public class NotificationApiTest extends AbstractNotificationApiTest { checkPartialNotificationsUpdate(otherWsClient.getLastDataUpdate(), notificationText, 1); } + @Test + public void testNotificationUpdates_typesFilter_multipleSubs() { + int generalSub = wsClient.subscribeForUnreadNotificationsAndWait(10, NotificationType.GENERAL); + int alarmSub = wsClient.subscribeForUnreadNotificationsAndWait(10, NotificationType.ALARM, NotificationType.GENERAL); + int entityActionSub = wsClient.subscribeForUnreadNotificationsAndWait(10, NotificationType.ENTITY_ACTION, NotificationType.GENERAL); + NotificationTarget notificationTarget = createNotificationTarget(customerUserId); + + String generalNotificationText1 = "General notification 1"; + submitNotificationRequest(NotificationType.GENERAL, notificationTarget.getId(), generalNotificationText1); + // expecting all 3 subs to received update + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKeys(generalSub, alarmSub, entityActionSub) + .allMatch(update -> update.getUpdate().getText().equals(generalNotificationText1) + && update.getTotalUnreadCount() == 1); + }); + Notification generalNotification1 = wsClient.getLastDataUpdate().getUpdate(); + + String generalNotificationText2 = "General notification 2"; + submitNotificationRequest(NotificationType.GENERAL, notificationTarget.getId(), generalNotificationText2); + // expecting all 3 subs to received update + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKeys(generalSub, alarmSub, entityActionSub) + .allMatch(update -> update.getUpdate().getText().equals(generalNotificationText2) + && update.getTotalUnreadCount() == 2); + }); + Notification generalNotification2 = wsClient.getLastDataUpdate().getUpdate(); + + // marking as read, expecting all 3 subs to received update + wsClient.markNotificationAsRead(generalNotification1.getUuidId()); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKeys(generalSub, alarmSub, entityActionSub) + .allMatch(update -> update.getTotalUnreadCount() == 1 && update.getNotifications().size() == 1 + && update.getNotifications().get(0).getText().equals(generalNotificationText2)); + }); + wsClient.getLastUpdates().clear(); + + String alarmNotificationText1 = "Alarm notification 1"; + submitNotificationRequest(NotificationType.ALARM, notificationTarget.getId(), alarmNotificationText1); + // expecting only 1 sub to received update + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKey(alarmSub) + .matches(update -> update.getUpdate().getText().equals(alarmNotificationText1) + && update.getTotalUnreadCount() == 2); + }); + Notification alarmNotification1 = wsClient.getLastDataUpdate().getUpdate(); + + String alarmNotificationText2 = "Alarm notification 2"; + submitNotificationRequest(NotificationType.ALARM, notificationTarget.getId(), alarmNotificationText2); + // expecting only 1 sub to received update + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKey(alarmSub) + .matches(update -> update.getUpdate().getText().equals(alarmNotificationText2) + && update.getTotalUnreadCount() == 3); + }); + await().during(3, TimeUnit.SECONDS) + .untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKeys(generalSub, entityActionSub) + .containsOnlyNulls(); + }); + + // marking as read, expecting only 1 sub to receive update + wsClient.markNotificationAsRead(alarmNotification1.getUuidId()); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKey(alarmSub) + .matches(update -> update.getTotalUnreadCount() == 2 && update.getNotifications().size() == 2); + }); + await().during(3, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKeys(generalSub, entityActionSub) + .containsOnlyNulls(); + }); + + // marking as read, expecting general and entity action subs with 0 unread, and alarm with 1 unread + wsClient.markNotificationAsRead(generalNotification2.getUuidId()); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThat(wsClient.getLastUpdates()).extractingByKeys(generalSub, entityActionSub) + .allMatch(update -> update.getTotalUnreadCount() == 0 && update.getNotifications().isEmpty()); + assertThat(wsClient.getLastUpdates()).extractingByKey(alarmSub) + .matches(update -> update.getTotalUnreadCount() == 1 && update.getNotifications().size() == 1 + && update.getNotifications().get(0).getText().equals(alarmNotificationText2)); + }); + } + @Test public void testMarkingAsRead_multipleSessions() throws Exception { connectOtherWsClient(); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java index 1ecae638a6..358e98bed1 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.notification.Notification; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.controller.TbTestWebSocketClient; import org.thingsboard.server.service.ws.notification.cmd.MarkAllNotificationsAsReadCmd; import org.thingsboard.server.service.ws.notification.cmd.MarkNotificationsAsReadCmd; @@ -35,7 +36,10 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; @Slf4j @Getter @@ -48,18 +52,28 @@ public class NotificationApiWsClient extends TbTestWebSocketClient { private int unreadCount; private List notifications; + private final Map lastUpdates = new ConcurrentHashMap<>(); + public NotificationApiWsClient(String wsUrl) throws URISyntaxException { super(new URI(wsUrl + "/api/ws")); } - public NotificationApiWsClient subscribeForUnreadNotifications(int limit) { - send(new NotificationsSubCmd(1, limit)); + public NotificationApiWsClient subscribeForUnreadNotifications(int limit, NotificationType... types) { + send(new NotificationsSubCmd(newCmdId(), limit, Arrays.stream(types).collect(Collectors.toSet()))); this.limit = limit; return this; } + public int subscribeForUnreadNotificationsAndWait(int limit, NotificationType... types) { + int subId = newCmdId(); + send(new NotificationsSubCmd(subId, limit, Arrays.stream(types).collect(Collectors.toSet()))); + waitForReply(); + this.limit = limit; + return subId; + } + public NotificationApiWsClient subscribeForUnreadNotificationsCount() { - send(new NotificationsCountSubCmd(2)); + send(new NotificationsCountSubCmd(newCmdId())); return this; } @@ -84,6 +98,7 @@ public class NotificationApiWsClient extends TbTestWebSocketClient { CmdUpdateType updateType = CmdUpdateType.valueOf(update.get("cmdUpdateType").asText()); if (updateType == CmdUpdateType.NOTIFICATIONS) { lastDataUpdate = JacksonUtil.treeToValue(update, UnreadNotificationsUpdate.class); + lastUpdates.put(lastDataUpdate.getCmdId(), lastDataUpdate); unreadCount = lastDataUpdate.getTotalUnreadCount(); if (lastDataUpdate.getNotifications() != null) { notifications = new ArrayList<>(lastDataUpdate.getNotifications()); @@ -115,7 +130,7 @@ public class NotificationApiWsClient extends TbTestWebSocketClient { super.onMessage(s); } - private static int newCmdId() { + private int newCmdId() { return RandomUtils.nextInt(1, 1000); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java index 91f6f7a379..86b12cfd86 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java @@ -19,10 +19,13 @@ import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import java.util.Set; + public interface NotificationService { Notification saveNotification(TenantId tenantId, Notification notification); @@ -35,7 +38,7 @@ public interface NotificationService { PageData findNotificationsByRecipientIdAndReadStatus(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, boolean unreadOnly, PageLink pageLink); - PageData findLatestUnreadNotificationsByRecipientId(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, int limit); + PageData findLatestUnreadNotificationsByRecipientIdAndNotificationTypes(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, Set types, int limit); int countUnreadNotificationsByRecipientId(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java index 5f91725b40..ec66a3d53a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java @@ -32,4 +32,5 @@ public enum NotificationType { EDGE_CONNECTION, EDGE_COMMUNICATION_FAILURE, TASK_PROCESSING_FAILURE + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java index 38a8cb4178..910055fc66 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; @@ -34,6 +35,7 @@ import org.thingsboard.server.dao.entity.EntityDaoService; import org.thingsboard.server.dao.sql.query.EntityKeyMapping; import java.util.Optional; +import java.util.Set; @Service @Slf4j @@ -72,10 +74,10 @@ public class DefaultNotificationService implements NotificationService, EntityDa } @Override - public PageData findLatestUnreadNotificationsByRecipientId(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, int limit) { + public PageData findLatestUnreadNotificationsByRecipientIdAndNotificationTypes(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, Set types, int limit) { SortOrder sortOrder = new SortOrder(EntityKeyMapping.CREATED_TIME, SortOrder.Direction.DESC); PageLink pageLink = new PageLink(limit, 0, null, sortOrder); - return findNotificationsByRecipientIdAndReadStatus(tenantId, deliveryMethod, recipientId, true, pageLink); + return notificationDao.findUnreadByDeliveryMethodAndRecipientIdAndNotificationTypesAndPageLink(tenantId, deliveryMethod, recipientId, types, pageLink); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationDao.java b/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationDao.java index 2233840058..060ea0e97f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationDao.java @@ -22,14 +22,19 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.Dao; +import java.util.Set; + public interface NotificationDao extends Dao { PageData findUnreadByDeliveryMethodAndRecipientIdAndPageLink(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, PageLink pageLink); + PageData findUnreadByDeliveryMethodAndRecipientIdAndNotificationTypesAndPageLink(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, Set types, PageLink pageLink); + PageData findByDeliveryMethodAndRecipientIdAndPageLink(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, PageLink pageLink); boolean updateStatusByIdAndRecipientId(TenantId tenantId, UserId recipientId, NotificationId notificationId, NotificationStatus status); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java index 64d663b397..22d2747e3b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.sql.notification; import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; @@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.DaoUtil; @@ -37,6 +39,7 @@ import org.thingsboard.server.dao.sql.JpaPartitionedAbstractDao; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; +import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -58,6 +61,14 @@ public class JpaNotificationDao extends JpaPartitionedAbstractDao findUnreadByDeliveryMethodAndRecipientIdAndNotificationTypesAndPageLink(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, Set types, PageLink pageLink) { + if (CollectionUtils.isEmpty(types)) { + return findUnreadByDeliveryMethodAndRecipientIdAndPageLink(tenantId, deliveryMethod, recipientId, pageLink); + } + return DaoUtil.toPageData(notificationRepository.findByDeliveryMethodAndRecipientIdAndTypeInAndStatusNot(deliveryMethod, + recipientId.getId(), types, NotificationStatus.READ, pageLink.getTextSearch(), DaoUtil.toPageable(pageLink))); + } + public PageData findByDeliveryMethodAndRecipientIdAndPageLink(TenantId tenantId, NotificationDeliveryMethod deliveryMethod, UserId recipientId, PageLink pageLink) { return DaoUtil.toPageData(notificationRepository.findByDeliveryMethodAndRecipientId(deliveryMethod, recipientId.getId(), pageLink.getTextSearch(), DaoUtil.toPageable(pageLink))); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java index dc432a566e..38bcff442c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java @@ -25,8 +25,10 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.dao.model.sql.NotificationEntity; +import java.util.Set; import java.util.UUID; @Repository @@ -42,7 +44,20 @@ public interface NotificationRepository extends JpaRepository :status " + + "AND (n.type IN :types) " + + "AND (:searchText is NULL OR ilike(n.subject, concat('%', :searchText, '%')) = true " + + "OR ilike(n.text, concat('%', :searchText, '%')) = true)") + Page findByDeliveryMethodAndRecipientIdAndTypeInAndStatusNot(@Param("deliveryMethod") NotificationDeliveryMethod deliveryMethod, + @Param("recipientId") UUID recipientId, + @Param("types") Set types, + @Param("status") NotificationStatus status, + @Param("searchText") String searchText, + Pageable pageable); + + @Query("SELECT n FROM NotificationEntity n WHERE n.deliveryMethod = :deliveryMethod " + + "AND n.recipientId = :recipientId " + "AND (:searchText is NULL OR ilike(n.subject, concat('%', :searchText, '%')) = true " + "OR ilike(n.text, concat('%', :searchText, '%')) = true)") Page findByDeliveryMethodAndRecipientId(@Param("deliveryMethod") NotificationDeliveryMethod deliveryMethod,