Browse Source

Add ability to update notification request

pull/7511/head
ViacheslavKlimov 4 years ago
parent
commit
684ef4a658
  1. 69
      application/src/main/java/org/thingsboard/server/controller/NotificationController.java
  2. 9
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationManager.java
  3. 25
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java
  4. 19
      application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java
  5. 1
      application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationRequestUpdate.java
  6. 6
      application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java
  7. 3
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestService.java
  8. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java
  9. 15
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java
  10. 35
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestInfo.java
  11. 6
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRequestService.java
  12. 13
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java
  13. 2
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationDao.java
  14. 4
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestDao.java
  15. 4
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java
  16. 19
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java
  17. 17
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java
  18. 2
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NotificationManager.java
  19. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java

69
application/src/main/java/org/thingsboard/server/controller/NotificationController.java

@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationOriginatorType; import org.thingsboard.server.common.data.notification.NotificationOriginatorType;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationSeverity; import org.thingsboard.server.common.data.notification.NotificationSeverity;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -88,34 +89,43 @@ public class NotificationController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequest createNotificationRequest(@RequestBody NotificationRequest notificationRequest, public NotificationRequest createNotificationRequest(@RequestBody NotificationRequest notificationRequest,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
accessControlService.checkPermission(user, Resource.NOTIFICATION_REQUEST, Operation.CREATE, null, notificationRequest);
// todo: check permission for notification target // todo: check permission for notification target
if (notificationRequest.getId() != null) {
// TODO: think about notification request update
throw new IllegalArgumentException("Notification request cannot be changed. You can delete it and create a new one");
}
notificationRequest.setOriginatorType(NotificationOriginatorType.USER);
notificationRequest.setOriginatorEntityId(user.getId());
if (StringUtils.isBlank(notificationRequest.getNotificationReason())) {
notificationRequest.setNotificationReason(NotificationRequest.GENERAL_NOTIFICATION_REASON);
}
if (notificationRequest.getNotificationSeverity() == null) {
notificationRequest.setNotificationSeverity(NotificationSeverity.NORMAL);
}
if (notificationRequest.getNotificationInfo() != null && notificationRequest.getNotificationInfo().getOriginatorType() != null) {
throw new IllegalArgumentException("Unsupported notification info type");
}
notificationRequest.setRuleId(null);
notificationRequest.setStatus(null);
try { if (notificationRequest.getId() == null) {
NotificationRequest savedNotificationRequest = notificationManager.processNotificationRequest(user.getTenantId(), notificationRequest); accessControlService.checkPermission(user, Resource.NOTIFICATION_REQUEST, Operation.CREATE, null, notificationRequest);
logEntityAction(user, EntityType.NOTIFICATION_REQUEST, savedNotificationRequest, ActionType.ADDED); notificationRequest.setOriginatorType(NotificationOriginatorType.USER);
return savedNotificationRequest; notificationRequest.setOriginatorEntityId(user.getId());
} catch (Exception e) { if (StringUtils.isBlank(notificationRequest.getNotificationReason())) {
logEntityAction(user, EntityType.NOTIFICATION_REQUEST, notificationRequest, null, ActionType.ADDED, e); notificationRequest.setNotificationReason("General");
throw e; }
if (notificationRequest.getNotificationSeverity() == null) {
notificationRequest.setNotificationSeverity(NotificationSeverity.NORMAL);
}
if (notificationRequest.getNotificationInfo() != null && notificationRequest.getNotificationInfo().getOriginatorType() != null) {
throw new IllegalArgumentException("Unsupported notification info type");
}
notificationRequest.setRuleId(null);
notificationRequest.setStatus(null);
return notificationManager.processNotificationRequest(user.getTenantId(), notificationRequest);
} else {
NotificationRequest existingNotificationRequest = notificationRequestService.findNotificationRequestById(user.getTenantId(), notificationRequest.getId());
checkNotNull(existingNotificationRequest);
accessControlService.checkPermission(user, Resource.NOTIFICATION_REQUEST, Operation.WRITE, notificationRequest.getId(), notificationRequest);
existingNotificationRequest.setNotificationReason(notificationRequest.getNotificationReason());
existingNotificationRequest.setTextTemplate(notificationRequest.getTextTemplate());
existingNotificationRequest.setNotificationSeverity(notificationRequest.getNotificationSeverity());
return notificationManager.updateNotificationRequest(user.getTenantId(), existingNotificationRequest);
} }
//
// try {
// NotificationRequest savedNotificationRequest = ;
// logEntityAction(user, EntityType.NOTIFICATION_REQUEST, savedNotificationRequest, ActionType.ADDED);
// return savedNotificationRequest;
// } catch (Exception e) {
// logEntityAction(user, EntityType.NOTIFICATION_REQUEST, notificationRequest, null, ActionType.ADDED, e);
// throw e;
// }
} }
@GetMapping("/notification/request/{id}") @GetMapping("/notification/request/{id}")
@ -126,6 +136,15 @@ public class NotificationController extends BaseController {
return notificationRequestService.findNotificationRequestById(user.getTenantId(), notificationRequestId); return notificationRequestService.findNotificationRequestById(user.getTenantId(), notificationRequestId);
} }
@GetMapping("/notification/request/info/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequestInfo getNotificationRequestInfoById(@PathVariable UUID id,
@AuthenticationPrincipal SecurityUser user) {
// fixme: permission checks
NotificationRequestId notificationRequestId = new NotificationRequestId(id);
return notificationRequestService.getNotificationRequestInfoById(user.getTenantId(), notificationRequestId);
}
@GetMapping("/notification/requests") @GetMapping("/notification/requests")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public PageData<NotificationRequest> getNotificationRequests(@RequestParam int pageSize, public PageData<NotificationRequest> getNotificationRequests(@RequestParam int pageSize,

9
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationManager.java

@ -153,15 +153,18 @@ public class DefaultNotificationManager extends AbstractSubscriptionService impl
} }
@Override @Override
public void updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest) { public NotificationRequest updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest) {
log.debug("Updating notification request {}", notificationRequest.getId()); log.debug("Updating notification request {}", notificationRequest.getId());
notificationRequestService.saveNotificationRequest(tenantId, notificationRequest); notificationRequest = notificationRequestService.saveNotificationRequest(tenantId, notificationRequest);
notificationService.updateNotificationsInfosByRequestId(tenantId, notificationRequest.getId(), notificationRequest.getNotificationInfo()); notificationService.updateNotificationsByRequestId(tenantId, notificationRequest.getId(),
notificationRequest.getNotificationReason(), notificationRequest.getNotificationInfo());
onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder() onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder()
.notificationRequestId(notificationRequest.getId()) .notificationRequestId(notificationRequest.getId())
.notificationReason(notificationRequest.getNotificationReason())
.notificationInfo(notificationRequest.getNotificationInfo()) .notificationInfo(notificationRequest.getNotificationInfo())
.deleted(false) .deleted(false)
.build()); .build());
return notificationRequest;
} }
private Notification createNotification(User recipient, NotificationRequest notificationRequest) { private Notification createNotification(User recipient, NotificationRequest notificationRequest) {

25
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java

@ -18,8 +18,10 @@ package org.thingsboard.server.service.notification;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.rule.engine.api.NotificationManager; import org.thingsboard.rule.engine.api.NotificationManager;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.id.NotificationTargetId;
@ -38,10 +40,12 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import java.util.List; import java.util.List;
import java.util.Map;
@Service @Service
@TbCoreComponent @TbCoreComponent
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j
public class DefaultNotificationRuleProcessingService implements NotificationRuleProcessingService { public class DefaultNotificationRuleProcessingService implements NotificationRuleProcessingService {
private final NotificationRuleService notificationRuleService; private final NotificationRuleService notificationRuleService;
@ -78,6 +82,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
// todo: think about: what if notification rule was updated? // todo: think about: what if notification rule was updated?
private void onAlarmUpdate(TenantId tenantId, NotificationRuleId notificationRuleId, Alarm alarm, boolean deleted) { private void onAlarmUpdate(TenantId tenantId, NotificationRuleId notificationRuleId, Alarm alarm, boolean deleted) {
log.debug("Processing alarm update ({}) with notification rule {}", alarm.getId(), notificationRuleId);
List<NotificationRequest> notificationRequests = notificationRequestService.findNotificationRequestsByRuleIdAndOriginatorEntityId(tenantId, notificationRuleId, alarm.getId()); List<NotificationRequest> notificationRequests = notificationRequestService.findNotificationRequestsByRuleIdAndOriginatorEntityId(tenantId, notificationRuleId, alarm.getId());
NotificationRule notificationRule = notificationRuleService.findNotificationRuleById(tenantId, notificationRuleId); NotificationRule notificationRule = notificationRuleService.findNotificationRuleById(tenantId, notificationRuleId);
if (notificationRule == null) return; if (notificationRule == null) return;
@ -101,7 +106,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
} }
} }
} else { } else {
NotificationInfo newNotificationInfo = constructNotificationInfo(alarm, notificationRule); NotificationInfo newNotificationInfo = constructNotificationInfo(alarm);
for (NotificationRequest notificationRequest : notificationRequests) { for (NotificationRequest notificationRequest : notificationRequests) {
NotificationInfo previousNotificationInfo = notificationRequest.getNotificationInfo(); NotificationInfo previousNotificationInfo = notificationRequest.getNotificationInfo();
if (!previousNotificationInfo.equals(newNotificationInfo)) { if (!previousNotificationInfo.equals(newNotificationInfo)) {
@ -121,13 +126,13 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
if (delayInSec > 0) { if (delayInSec > 0) {
config.setSendingDelayInSec(delayInSec); config.setSendingDelayInSec(delayInSec);
} }
NotificationInfo notificationInfo = constructNotificationInfo(alarm, notificationRule); NotificationInfo notificationInfo = constructNotificationInfo(alarm);
NotificationRequest notificationRequest = NotificationRequest.builder() NotificationRequest notificationRequest = NotificationRequest.builder()
.tenantId(tenantId) .tenantId(tenantId)
.targetId(targetId) .targetId(targetId)
.notificationReason("Alarm") .notificationReason("Alarm")
.textTemplate(notificationRule.getNotificationTextTemplate()) // todo: format with alarm vars .textTemplate(formatNotificationTextTemplate(notificationRule.getNotificationTextTemplate(), alarm))
.notificationInfo(notificationInfo) .notificationInfo(notificationInfo)
.notificationSeverity(NotificationSeverity.NORMAL) // todo: from alarm severity .notificationSeverity(NotificationSeverity.NORMAL) // todo: from alarm severity
.originatorType(NotificationOriginatorType.ALARM) .originatorType(NotificationOriginatorType.ALARM)
@ -138,7 +143,19 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
notificationManager.processNotificationRequest(tenantId, notificationRequest); notificationManager.processNotificationRequest(tenantId, notificationRequest);
} }
private NotificationInfo constructNotificationInfo(Alarm alarm, NotificationRule notificationRule) { private String formatNotificationTextTemplate(String textTemplate, Alarm alarm) {
Map<String, String> context = Map.of( // fixme: notification text is not updatable
"alarmType", alarm.getType(),
"alarmId", alarm.getId().toString(),
"alarmOriginatorEntityType", alarm.getOriginator().getEntityType().toString(),
"alarmOriginatorId", alarm.getOriginator().getId().toString(),
"alarmSeverity", alarm.getSeverity().toString(),
"alarmStatus", alarm.getStatus().toString()
);
return TbNodeUtils.processTemplate(textTemplate, context);
}
private NotificationInfo constructNotificationInfo(Alarm alarm) {
return AlarmOriginatedNotificationInfo.builder() return AlarmOriginatedNotificationInfo.builder()
.alarmId(alarm.getId()) .alarmId(alarm.getId())
.alarmType(alarm.getType()) .alarmType(alarm.getType())

19
application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java

@ -20,30 +20,29 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.rule.engine.api.NotificationManager;
import org.thingsboard.server.common.data.id.IdBased; import org.thingsboard.server.common.data.id.IdBased;
import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationStatus; import org.thingsboard.server.common.data.notification.NotificationStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.dao.notification.NotificationService;
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.rule.engine.api.NotificationManager;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.ws.notification.cmd.NotificationsCountSubCmd;
import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpdate;
import org.thingsboard.server.service.ws.notification.sub.NotificationUpdate;
import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscription;
import org.thingsboard.server.service.subscription.TbLocalSubscriptionService; import org.thingsboard.server.service.subscription.TbLocalSubscriptionService;
import org.thingsboard.server.service.ws.WebSocketService;
import org.thingsboard.server.service.ws.WebSocketSessionRef; import org.thingsboard.server.service.ws.WebSocketSessionRef;
import org.thingsboard.server.service.ws.notification.cmd.MarkNotificationsAsReadCmd; import org.thingsboard.server.service.ws.notification.cmd.MarkNotificationsAsReadCmd;
import org.thingsboard.server.service.ws.notification.cmd.NotificationsCountSubCmd;
import org.thingsboard.server.service.ws.notification.cmd.NotificationsSubCmd; import org.thingsboard.server.service.ws.notification.cmd.NotificationsSubCmd;
import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscriptionUpdate; import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpdate;
import org.thingsboard.server.service.ws.notification.sub.NotificationUpdate;
import org.thingsboard.server.service.ws.notification.sub.NotificationsCountSubscription; import org.thingsboard.server.service.ws.notification.sub.NotificationsCountSubscription;
import org.thingsboard.server.service.ws.WebSocketService; import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscription;
import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscriptionUpdate;
import org.thingsboard.server.service.ws.telemetry.cmd.v2.CmdUpdate; import org.thingsboard.server.service.ws.telemetry.cmd.v2.CmdUpdate;
import org.thingsboard.server.service.ws.telemetry.cmd.v2.UnsubscribeCmd; import org.thingsboard.server.service.ws.telemetry.cmd.v2.UnsubscribeCmd;
@ -168,11 +167,11 @@ public class DefaultNotificationCommandsHandler implements NotificationCommandsH
sendUpdate(subscription.getSessionId(), subscription.createFullUpdate()); sendUpdate(subscription.getSessionId(), subscription.createFullUpdate());
} }
} else { } else {
NotificationInfo notificationInfo = update.getNotificationInfo();
subscription.getLatestUnreadNotifications().values().stream() subscription.getLatestUnreadNotifications().values().stream()
.filter(notification -> notification.getRequestId().equals(notificationRequestId)) .filter(notification -> notification.getRequestId().equals(notificationRequestId))
.forEach(notification -> { .forEach(notification -> {
notification.setInfo(notificationInfo); notification.setReason(update.getNotificationReason());
notification.setInfo(update.getNotificationInfo());
sendUpdate(subscription.getSessionId(), subscription.createPartialUpdate(notification)); sendUpdate(subscription.getSessionId(), subscription.createPartialUpdate(notification));
}); });
} }

1
application/src/main/java/org/thingsboard/server/service/ws/notification/sub/NotificationRequestUpdate.java

@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.notification.NotificationInfo;
@Builder @Builder
public class NotificationRequestUpdate { public class NotificationRequestUpdate {
private NotificationRequestId notificationRequestId; private NotificationRequestId notificationRequestId;
private String notificationReason;
private NotificationInfo notificationInfo; private NotificationInfo notificationInfo;
private boolean deleted; private boolean deleted;
} }

6
application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java

@ -247,7 +247,7 @@ public class NotificationApiTest extends AbstractControllerTest {
@Test @Test
public void testNotificationUpdatesForUsersInTarget() throws Exception { public void testNotificationUpdatesForUsersInTarget() throws Exception {
Map<User, NotificationApiWsClient> wsSessions = createUsersAndSetUpWsSessions(150); Map<User, NotificationApiWsClient> wsSessions = createUsersAndSetUpWsSessions(100);
wsSessions.forEach((user, wsClient) -> { wsSessions.forEach((user, wsClient) -> {
wsClient.subscribeForUnreadNotifications(10); wsClient.subscribeForUnreadNotifications(10);
wsClient.waitForReply(true); wsClient.waitForReply(true);
@ -258,14 +258,14 @@ public class NotificationApiTest extends AbstractControllerTest {
NotificationTarget notificationTarget = new NotificationTarget(); NotificationTarget notificationTarget = new NotificationTarget();
UserListNotificationTargetConfig config = new UserListNotificationTargetConfig(); UserListNotificationTargetConfig config = new UserListNotificationTargetConfig();
config.setUsersIds(wsSessions.keySet().stream().map(User::getUuidId).collect(Collectors.toList())); config.setUsersIds(wsSessions.keySet().stream().map(User::getUuidId).collect(Collectors.toList()));
notificationTarget.setName("150 users"); notificationTarget.setName("100 users");
notificationTarget.setTenantId(tenantId); notificationTarget.setTenantId(tenantId);
notificationTarget.setConfiguration(config); notificationTarget.setConfiguration(config);
notificationTarget = saveNotificationTarget(notificationTarget); notificationTarget = saveNotificationTarget(notificationTarget);
wsSessions.forEach((user, wsClient) -> wsClient.registerWaitForUpdate(2)); wsSessions.forEach((user, wsClient) -> wsClient.registerWaitForUpdate(2));
NotificationRequest notificationRequest = submitNotificationRequest(notificationTarget.getId(), "Hello, ${recipientEmail}"); NotificationRequest notificationRequest = submitNotificationRequest(notificationTarget.getId(), "Hello, ${recipientEmail}");
await().atMost(3, TimeUnit.SECONDS) await().atMost(5, TimeUnit.SECONDS)
.pollDelay(1, TimeUnit.SECONDS).pollInterval(500, TimeUnit.MILLISECONDS) .pollDelay(1, TimeUnit.SECONDS).pollInterval(500, TimeUnit.MILLISECONDS)
.until(() -> wsSessions.values().stream() .until(() -> wsSessions.values().stream()
.allMatch(wsClient -> wsClient.getLastDataUpdate() != null .allMatch(wsClient -> wsClient.getLastDataUpdate() != null

3
common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestService.java

@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -39,4 +40,6 @@ public interface NotificationRequestService {
PageData<NotificationRequest> findScheduledNotificationRequests(PageLink pageLink); PageData<NotificationRequest> findScheduledNotificationRequests(PageLink pageLink);
NotificationRequestInfo getNotificationRequestInfoById(TenantId tenantId, NotificationRequestId id);
} }

2
common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java

@ -38,6 +38,6 @@ public interface NotificationService {
int countUnreadNotificationsByUserId(TenantId tenantId, UserId userId); int countUnreadNotificationsByUserId(TenantId tenantId, UserId userId);
int updateNotificationsInfosByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationInfo notificationInfo); int updateNotificationsByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, String notificationReason, NotificationInfo notificationInfo);
} }

15
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java

@ -61,7 +61,20 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
private NotificationRequestConfig additionalConfig; private NotificationRequestConfig additionalConfig;
private NotificationRequestStatus status; private NotificationRequestStatus status;
public static final String GENERAL_NOTIFICATION_REASON = "General"; public NotificationRequest(NotificationRequest other) {
super(other);
this.tenantId = other.tenantId;
this.targetId = other.targetId;
this.notificationReason = other.notificationReason;
this.textTemplate = other.textTemplate;
this.notificationInfo = other.notificationInfo;
this.notificationSeverity = other.notificationSeverity;
this.originatorType = other.originatorType;
this.originatorEntityId = other.originatorEntityId;
this.ruleId = other.ruleId;
this.additionalConfig = other.additionalConfig;
this.status = other.status;
}
@JsonIgnore @JsonIgnore
@Override @Override

35
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestInfo.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.notification;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Map;
@Data
@EqualsAndHashCode(callSuper = true)
public class NotificationRequestInfo extends NotificationRequest {
private int sent;
private int read;
private Map<String, NotificationStatus> statusesByRecipient;
public NotificationRequestInfo(NotificationRequest notificationRequest) {
super(notificationRequest);
}
}

6
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRequestService.java

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus; import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -71,6 +72,11 @@ public class DefaultNotificationRequestService implements NotificationRequestSer
return notificationRequestDao.findAllByStatus(NotificationRequestStatus.SCHEDULED, pageLink); return notificationRequestDao.findAllByStatus(NotificationRequestStatus.SCHEDULED, pageLink);
} }
@Override
public NotificationRequestInfo getNotificationRequestInfoById(TenantId tenantId, NotificationRequestId id) {
return notificationRequestDao.getNotificationRequestInfoById(tenantId, id);
}
private static class NotificationRequestValidator extends DataValidator<NotificationRequest> { private static class NotificationRequestValidator extends DataValidator<NotificationRequest> {

13
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationService.java

@ -17,28 +17,19 @@ package org.thingsboard.server.dao.notification;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationInfo; import org.thingsboard.server.common.data.notification.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.NotificationSeverity;
import org.thingsboard.server.common.data.notification.NotificationStatus; import org.thingsboard.server.common.data.notification.NotificationStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.sql.query.EntityKeyMapping; import org.thingsboard.server.dao.sql.query.EntityKeyMapping;
import java.util.List;
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@ -83,8 +74,8 @@ public class DefaultNotificationService implements NotificationService {
} }
@Override @Override
public int updateNotificationsInfosByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationInfo notificationInfo) { public int updateNotificationsByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, String notificationReason, NotificationInfo notificationInfo) {
return notificationDao.updateInfosByRequestId(tenantId, notificationRequestId, notificationInfo); return notificationDao.updateByRequestId(tenantId, notificationRequestId, notificationReason, notificationInfo);
} }
} }

2
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationDao.java

@ -38,6 +38,6 @@ public interface NotificationDao extends Dao<Notification> {
PageData<Notification> findByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, PageLink pageLink); PageData<Notification> findByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, PageLink pageLink);
int updateInfosByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationInfo notificationInfo); int updateByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, String notificationReason, NotificationInfo notificationInfo);
} }

4
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestDao.java

@ -16,9 +16,11 @@
package org.thingsboard.server.dao.notification; package org.thingsboard.server.dao.notification;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus; import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -34,4 +36,6 @@ public interface NotificationRequestDao extends Dao<NotificationRequest> {
PageData<NotificationRequest> findAllByStatus(NotificationRequestStatus status, PageLink pageLink); PageData<NotificationRequest> findAllByStatus(NotificationRequestStatus status, PageLink pageLink);
NotificationRequestInfo getNotificationRequestInfoById(TenantId tenantId, NotificationRequestId id);
} }

4
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java

@ -91,8 +91,8 @@ public class JpaNotificationDao extends JpaAbstractDao<NotificationEntity, Notif
} }
@Override @Override
public int updateInfosByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationInfo notificationInfo) { public int updateByRequestId(TenantId tenantId, NotificationRequestId notificationRequestId, String notificationReason, NotificationInfo notificationInfo) {
return notificationRepository.updateInfosByRequestId(notificationRequestId.getId(), JacksonUtil.valueToTree(notificationInfo)); return notificationRepository.updateReasonAndInfoByRequestId(notificationRequestId.getId(), notificationReason, JacksonUtil.valueToTree(notificationInfo));
} }
@Override @Override

19
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java

@ -19,11 +19,15 @@ import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus; import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.NotificationStatus;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
@ -33,7 +37,9 @@ import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
@Component @Component
@SqlDao @SqlDao
@ -41,6 +47,7 @@ import java.util.UUID;
public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationRequestEntity, NotificationRequest> implements NotificationRequestDao { public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationRequestEntity, NotificationRequest> implements NotificationRequestDao {
private final NotificationRequestRepository notificationRequestRepository; private final NotificationRequestRepository notificationRequestRepository;
private final NotificationRepository notificationRepository;
@Override @Override
public PageData<NotificationRequest> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) { public PageData<NotificationRequest> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) {
@ -58,6 +65,18 @@ public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationReques
return DaoUtil.toPageData(notificationRequestRepository.findAllByStatus(status, DaoUtil.toPageable(pageLink))); return DaoUtil.toPageData(notificationRequestRepository.findAllByStatus(status, DaoUtil.toPageable(pageLink)));
} }
@Transactional(readOnly = true)
@Override
public NotificationRequestInfo getNotificationRequestInfoById(TenantId tenantId, NotificationRequestId id) {
NotificationRequestInfo notificationRequestInfo = new NotificationRequestInfo(findById(tenantId, id.getId()));
notificationRequestInfo.setSent(notificationRepository.countByRequestId(id.getId()));
notificationRequestInfo.setRead(notificationRepository.countByRequestIdAndStatus(id.getId(), NotificationStatus.READ));
Map<String, NotificationStatus> statusesByRecipient = notificationRepository.getStatusesByRecipientForRequestId(id.getId()).stream()
.collect(Collectors.toMap(r -> (String) r[0], r -> (NotificationStatus) r[1]));
notificationRequestInfo.setStatusesByRecipient(statusesByRecipient);
return notificationRequestInfo;
}
@Override @Override
protected Class<NotificationRequestEntity> getEntityClass() { protected Class<NotificationRequestEntity> getEntityClass() {
return NotificationRequestEntity.class; return NotificationRequestEntity.class;

17
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java

@ -27,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.notification.NotificationStatus; import org.thingsboard.server.common.data.notification.NotificationStatus;
import org.thingsboard.server.dao.model.sql.NotificationEntity; import org.thingsboard.server.dao.model.sql.NotificationEntity;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Repository @Repository
@ -50,7 +51,19 @@ public interface NotificationRepository extends JpaRepository<NotificationEntity
@Modifying @Modifying
@Transactional @Transactional
@Query("UPDATE NotificationEntity n SET n.info = :info WHERE n.requestId = :requestId") @Query("UPDATE NotificationEntity n " +
int updateInfosByRequestId(@Param("requestId") UUID requestId, @Param("info") JsonNode info); "SET n.info = :info, n.reason = :reason " +
"WHERE n.requestId = :requestId")
int updateReasonAndInfoByRequestId(@Param("requestId") UUID requestId,
@Param("reason") String reason,
@Param("info") JsonNode info);
int countByRequestId(UUID requestId);
int countByRequestIdAndStatus(UUID requestId, NotificationStatus status);
@Query("SELECT u.email, n.status FROM NotificationEntity n INNER JOIN UserEntity u ON n.recipientId = u.id " +
"WHERE n.requestId = :requestId")
List<Object[]> getStatusesByRecipientForRequestId(@Param("requestId") UUID requestId);
} }

2
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NotificationManager.java

@ -29,6 +29,6 @@ public interface NotificationManager {
void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId); void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId);
void updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest); NotificationRequest updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest);
} }

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java

@ -191,7 +191,6 @@ class DeviceState {
AlarmState alarmState = alarmStates.computeIfAbsent(alarm.getId(), AlarmState alarmState = alarmStates.computeIfAbsent(alarm.getId(),
a -> new AlarmState(this.deviceProfile, deviceId, alarm, getOrInitPersistedAlarmState(alarm), dynamicPredicateValueCtx)); a -> new AlarmState(this.deviceProfile, deviceId, alarm, getOrInitPersistedAlarmState(alarm), dynamicPredicateValueCtx));
alarmState.processAckAlarm(alarmNf); alarmState.processAckAlarm(alarmNf);
// todo: process notification rule
} }
ctx.tellSuccess(msg); ctx.tellSuccess(msg);
} }

Loading…
Cancel
Save