Browse Source

Merge remote-tracking branch 'klimov/feature/notification-system' into feature/notification-system

pull/7980/head
Vladyslav_Prykhodko 4 years ago
parent
commit
0e3d98afbc
  1. 45
      application/src/main/java/org/thingsboard/server/controller/NotificationController.java
  2. 9
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
  3. 4
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java
  4. 2
      application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java
  5. 5
      application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java
  6. 131
      application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java
  7. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestService.java
  8. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTargetService.java
  9. 5
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java
  10. 31
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestPreview.java
  11. 1
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStatus.java
  12. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java
  13. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/PushDeliveryMethodNotificationTemplate.java
  14. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SlackDeliveryMethodNotificationTemplate.java
  15. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SmsDeliveryMethodNotificationTemplate.java
  16. 2
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java
  17. 4
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRequestService.java
  18. 11
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java
  19. 2
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationRequestDao.java
  20. 4
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java
  21. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRequestRepository.java
  22. 3
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java

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

@ -33,22 +33,32 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestPreview;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.notification.NotificationRequestService;
import org.thingsboard.server.dao.notification.NotificationService;
import org.thingsboard.server.dao.notification.NotificationSettingsService;
import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.dao.notification.NotificationTemplateService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.notification.NotificationProcessingContext;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import javax.validation.Valid;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@RestController
@TbCoreComponent
@ -59,6 +69,8 @@ public class NotificationController extends BaseController {
private final NotificationService notificationService;
private final NotificationRequestService notificationRequestService;
private final NotificationTemplateService notificationTemplateService;
private final NotificationTargetService notificationTargetService;
private final NotificationCenter notificationCenter;
private final NotificationSettingsService notificationSettingsService;
@ -112,6 +124,39 @@ public class NotificationController extends BaseController {
return doSaveAndLog(EntityType.NOTIFICATION_REQUEST, notificationRequest, notificationCenter::processNotificationRequest);
}
@PostMapping("/notification/request/preview")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest notificationRequest,
@AuthenticationPrincipal SecurityUser user) {
NotificationRequestPreview preview = new NotificationRequestPreview();
notificationRequest.setOriginatorEntityId(user.getId());
NotificationTemplate notificationTemplate = notificationTemplateService.findNotificationTemplateById(user.getTenantId(), notificationRequest.getTemplateId());
NotificationProcessingContext mockProcessingCtx = NotificationProcessingContext.builder()
.tenantId(user.getTenantId())
.request(notificationRequest)
.settings(null)
.template(notificationTemplate)
.build();
mockProcessingCtx.init();
Map<String, String> templateContext = mockProcessingCtx.createTemplateContext(user);
Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates = mockProcessingCtx.getDeliveryMethods().stream()
.collect(Collectors.toMap(m -> m, deliveryMethod -> {
return mockProcessingCtx.getProcessedTemplate(deliveryMethod, templateContext);
}));
preview.setProcessedTemplates(processedTemplates);
Map<UUID, Integer> recipientsCountByTarget = notificationRequest.getTargets().stream()
.collect(Collectors.toMap(id -> id, targetId -> {
return notificationTargetService.countRecipientsForNotificationTarget(user.getTenantId(), new NotificationTargetId(targetId));
}));
preview.setRecipientsCountByTarget(recipientsCountByTarget);
preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum());
return preview;
}
@GetMapping("/notification/request/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequest getNotificationRequestById(@PathVariable UUID id) throws ThingsboardException {

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

@ -120,7 +120,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
}
}
notificationRequest.setStatus(NotificationRequestStatus.SENT);
notificationRequest.setStatus(NotificationRequestStatus.PROCESSING);
NotificationRequest savedNotificationRequest = notificationRequestService.saveNotificationRequest(tenantId, notificationRequest);
NotificationProcessingContext ctx = NotificationProcessingContext.builder()
@ -134,9 +134,9 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
Set<NotificationDeliveryMethod> deliveryMethods = ctx.getDeliveryMethods();
List<ListenableFuture<Void>> results = new ArrayList<>();
for (NotificationTargetId targetId : notificationRequest.getTargets()) {
for (UUID targetId : notificationRequest.getTargets()) {
DaoUtil.processBatches(pageLink -> {
return notificationTargetService.findRecipientsForNotificationTarget(tenantId, ctx.getCustomerId(), targetId, pageLink);
return notificationTargetService.findRecipientsForNotificationTarget(tenantId, ctx.getCustomerId(), new NotificationTargetId(targetId), pageLink);
}, 200, recipientsBatch -> {
for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) {
if (deliveryMethod.isIndependent()) continue;
@ -172,7 +172,8 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
Futures.whenAllComplete(results).run(() -> {
NotificationRequestStats stats = ctx.getStats();
try {
notificationRequestService.updateNotificationRequestStats(tenantId, savedNotificationRequest.getId(), stats);
notificationRequestService.updateNotificationRequest(tenantId, savedNotificationRequest.getId(),
NotificationRequestStatus.SENT, stats);
} catch (Exception e) {
log.error("Failed to update stats for notification request {}", savedNotificationRequest.getId(), e);
}

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

@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.notification.info.AlarmOriginatedNotificationInfo;
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationRequest;
@ -46,6 +47,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.executors.NotificationExecutorService;
import java.util.List;
import java.util.stream.Collectors;
@Service
@TbCoreComponent
@ -131,7 +133,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
NotificationInfo notificationInfo = constructNotificationInfo(alarm);
NotificationRequest notificationRequest = NotificationRequest.builder()
.tenantId(tenantId)
.targets(List.of(targetId))
.targets(List.of(targetId).stream().map(UUIDBased::getId).collect(Collectors.toList()))
.templateId(notificationRule.getTemplateId())
.additionalConfig(config)
.info(notificationInfo)

2
application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java

@ -90,7 +90,7 @@ public class NotificationProcessingContext {
return (C) settings.getDeliveryMethodsConfigs().get(deliveryMethod);
}
protected <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, Map<String, String> templateContext) {
public <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, Map<String, String> templateContext) {
if (request.getInfo() != null) {
templateContext = new HashMap<>(templateContext);
templateContext.putAll(request.getInfo().getTemplateData());

5
application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java

@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@ -53,6 +54,7 @@ import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -107,8 +109,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
UserOriginatedNotificationInfo notificationInfo = new UserOriginatedNotificationInfo();
notificationInfo.setDescription("My description");
NotificationRequest notificationRequest = NotificationRequest.builder()
.tenantId(tenantId)
.targets(targets)
.targets(targets.stream().map(UUIDBased::getId).collect(Collectors.toList()))
.templateId(notificationTemplateId)
.info(notificationInfo)
.additionalConfig(config)

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

@ -28,6 +28,8 @@ import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
import org.thingsboard.server.common.data.notification.NotificationRequestPreview;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.NotificationType;
@ -35,14 +37,21 @@ import org.thingsboard.server.common.data.notification.info.UserOriginatedNotifi
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.targets.AllUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.CustomerUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.UserListNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import org.thingsboard.server.common.data.notification.template.PushDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.SlackConversation;
import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.SmsDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.notification.NotificationDao;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
@ -59,6 +68,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.type;
import static org.awaitility.Awaitility.await;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@ -271,7 +281,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
@Test
public void testNotificationUpdatesForALotOfUsers() throws Exception {
int usersCount = 200; // FIXME: sometimes if set e.g. to 150, up to 5 WS sessions don't receive update
int usersCount = 100;
Map<User, NotificationApiWsClient> sessions = new HashMap<>();
List<NotificationTargetId> targets = new ArrayList<>();
@ -321,7 +331,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
});
await().atMost(2, TimeUnit.SECONDS)
.until(() -> getStats(notificationRequest.getId()) != null);
.until(() -> findNotificationRequest(notificationRequest.getId()).isSent());
NotificationRequestStats stats = getStats(notificationRequest.getId());
assertThat(stats.getSent().get(NotificationDeliveryMethod.PUSH)).hasValue(usersCount);
assertThat(stats.getSent().get(NotificationDeliveryMethod.EMAIL)).hasValue(usersCount);
@ -338,6 +348,117 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
sessions.values().forEach(WebSocketClient::close);
}
@Test
public void testNotificationRequestPreview() throws Exception {
NotificationTarget target1 = new NotificationTarget();
target1.setName("Me");
UserListNotificationTargetConfig target1Config = new UserListNotificationTargetConfig();
target1Config.setUsersIds(DaoUtil.toUUIDs(List.of(tenantAdminUserId)));
target1.setConfiguration(target1Config);
target1 = saveNotificationTarget(target1);
createDifferentCustomer();
loginTenantAdmin();
int customerUsersCount = 10;
for (int i = 0; i < customerUsersCount; i++) {
User customerUser = new User();
customerUser.setAuthority(Authority.CUSTOMER_USER);
customerUser.setTenantId(tenantId);
customerUser.setCustomerId(differentCustomerId);
customerUser.setEmail("other-customer-" + i + "@thingsboard.org");
customerUser = createUser(customerUser, "12345678");
}
NotificationTarget target2 = new NotificationTarget();
target2.setName("Other customer users");
CustomerUsersNotificationTargetConfig target2Config = new CustomerUsersNotificationTargetConfig();
target2Config.setCustomerId(differentCustomerId.getId());
target2Config.setGetCustomerIdFromOriginatorEntity(false);
target2.setConfiguration(target2Config);
target2 = saveNotificationTarget(target2);
NotificationTemplate notificationTemplate = new NotificationTemplate();
notificationTemplate.setNotificationType(NotificationType.GENERAL);
notificationTemplate.setName("Test template");
String requestorEmail = TENANT_ADMIN_EMAIL;
NotificationTemplateConfig templateConfig = new NotificationTemplateConfig();
templateConfig.setDefaultTextTemplate("Default message for SMS and PUSH: ${email}");
templateConfig.setNotificationSubject("Default subject for EMAIL: ${email}");
HashMap<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates = new HashMap<>();
templateConfig.setDeliveryMethodsTemplates(templates);
notificationTemplate.setConfiguration(templateConfig);
PushDeliveryMethodNotificationTemplate pushNotificationTemplate = new PushDeliveryMethodNotificationTemplate();
pushNotificationTemplate.setEnabled(true);
// using default message for push
pushNotificationTemplate.setSubject("Subject for PUSH: ${email}");
templates.put(NotificationDeliveryMethod.PUSH, pushNotificationTemplate);
SmsDeliveryMethodNotificationTemplate smsNotificationTemplate = new SmsDeliveryMethodNotificationTemplate();
smsNotificationTemplate.setEnabled(true);
// using default message for sms
templates.put(NotificationDeliveryMethod.SMS, smsNotificationTemplate);
EmailDeliveryMethodNotificationTemplate emailNotificationTemplate = new EmailDeliveryMethodNotificationTemplate();
emailNotificationTemplate.setEnabled(true);
emailNotificationTemplate.setBody("Message for EMAIL: ${email}");
// using default subject for email
templates.put(NotificationDeliveryMethod.EMAIL, emailNotificationTemplate);
SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate();
slackNotificationTemplate.setEnabled(true);
slackNotificationTemplate.setConversationType(SlackConversation.Type.PUBLIC_CHANNEL);
slackNotificationTemplate.setConversationId("U1234567");
slackNotificationTemplate.setBody("Message for SLACK: ${email}");
templates.put(NotificationDeliveryMethod.SLACK, slackNotificationTemplate);
notificationTemplate = saveNotificationTemplate(notificationTemplate);
NotificationRequest notificationRequest = new NotificationRequest();
notificationRequest.setTargets(List.of(target1.getUuidId(), target2.getUuidId()));
notificationRequest.setTemplateId(notificationTemplate.getId());
notificationRequest.setAdditionalConfig(new NotificationRequestConfig());
NotificationRequestPreview preview = doPost("/api/notification/request/preview", notificationRequest, NotificationRequestPreview.class);
assertThat(preview.getRecipientsCountByTarget().get(target1.getUuidId())).isEqualTo(1);
assertThat(preview.getRecipientsCountByTarget().get(target2.getUuidId())).isEqualTo(customerUsersCount);
assertThat(preview.getTotalRecipientsCount()).isEqualTo(1 + customerUsersCount);
Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates = preview.getProcessedTemplates();
assertThat(processedTemplates.get(NotificationDeliveryMethod.PUSH)).asInstanceOf(type(PushDeliveryMethodNotificationTemplate.class))
.satisfies(template -> {
assertThat(template.getBody())
.startsWith("Default message for SMS and PUSH")
.endsWith(requestorEmail);
assertThat(template.getSubject())
.startsWith("Subject for PUSH")
.endsWith(requestorEmail);
});
assertThat(processedTemplates.get(NotificationDeliveryMethod.SMS)).asInstanceOf(type(SmsDeliveryMethodNotificationTemplate.class))
.satisfies(template -> {
assertThat(template.getBody())
.startsWith("Default message for SMS and PUSH")
.endsWith(requestorEmail);
});
assertThat(processedTemplates.get(NotificationDeliveryMethod.EMAIL)).asInstanceOf(type(EmailDeliveryMethodNotificationTemplate.class))
.satisfies(template -> {
assertThat(template.getBody())
.startsWith("Message for EMAIL")
.endsWith(requestorEmail);
assertThat(template.getSubject())
.startsWith("Default subject for EMAIL")
.endsWith(requestorEmail);
});
assertThat(processedTemplates.get(NotificationDeliveryMethod.SLACK)).asInstanceOf(type(SlackDeliveryMethodNotificationTemplate.class))
.satisfies(template -> {
assertThat(template.getBody())
.startsWith("Message for SLACK")
.endsWith(requestorEmail);
});
}
@Test
public void testNotificationRequestStats() throws Exception {
wsClient.subscribeForUnreadNotifications(10);
@ -350,7 +471,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
wsClient.waitForUpdate();
await().atMost(2, TimeUnit.SECONDS)
.until(() -> getStats(notificationRequest.getId()) != null);
.until(() -> findNotificationRequest(notificationRequest.getId()).isSent());
NotificationRequestStats stats = getStats(notificationRequest.getId());
assertThat(stats.getSent().get(NotificationDeliveryMethod.PUSH)).hasValue(1);
@ -434,7 +555,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
NotificationRequest successfulNotificationRequest = submitNotificationRequest(Collections.emptyList(), notificationTemplate.getId(), 0);
await().atMost(2, TimeUnit.SECONDS)
.until(() -> getStats(successfulNotificationRequest.getId()) != null);
.until(() -> findNotificationRequest(successfulNotificationRequest.getId()).isSent());
verify(slackService).sendMessage(eq(tenantId), eq(slackToken), eq(conversationId), eq(config.getDefaultTextTemplate()));
NotificationRequestStats stats = getStats(successfulNotificationRequest.getId());
assertThat(stats.getSent().get(NotificationDeliveryMethod.SLACK)).hasValue(1);
@ -443,7 +564,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
doThrow(new RuntimeException(errorMessage)).when(slackService).sendMessage(any(), any(), any(), any());
NotificationRequest failedNotificationRequest = submitNotificationRequest(Collections.emptyList(), notificationTemplate.getId(), 0);
await().atMost(2, TimeUnit.SECONDS)
.until(() -> getStats(failedNotificationRequest.getId()) != null);
.until(() -> findNotificationRequest(failedNotificationRequest.getId()).isSent());
stats = getStats(failedNotificationRequest.getId());
assertThat(stats.getErrors().get(NotificationDeliveryMethod.SLACK).values()).containsExactly(errorMessage);
}

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

@ -44,6 +44,6 @@ public interface NotificationRequestService {
PageData<NotificationRequest> findScheduledNotificationRequests(PageLink pageLink);
void updateNotificationRequestStats(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationRequestStats stats);
void updateNotificationRequest(TenantId tenantId, NotificationRequestId requestId, NotificationRequestStatus requestStatus, NotificationRequestStats stats);
}

4
common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTargetService.java

@ -32,7 +32,9 @@ public interface NotificationTargetService {
PageData<NotificationTarget> findNotificationTargetsByTenantId(TenantId tenantId, PageLink pageLink);
PageData<User> findRecipientsForNotificationTarget(TenantId tenantId, CustomerId customerId, NotificationTargetId notificationTargetId, PageLink pageLink);
PageData<User> findRecipientsForNotificationTarget(TenantId tenantId, CustomerId customerId, NotificationTargetId targetId, PageLink pageLink);
int countRecipientsForNotificationTarget(TenantId tenantId, NotificationTargetId targetId);
PageData<User> findRecipientsForNotificationTargetConfig(TenantId tenantId, CustomerId customerId, NotificationTargetConfig targetConfig, PageLink pageLink);

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

@ -27,16 +27,15 @@ import org.thingsboard.server.common.data.HasTenantId;
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.NotificationTargetId;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.UUID;
@Data
@EqualsAndHashCode(callSuper = true)
@ -47,7 +46,7 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
private TenantId tenantId;
@NotNull
private List<NotificationTargetId> targets;
private List<UUID> targets;
@NotNull
private NotificationTemplateId templateId;

31
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestPreview.java

@ -0,0 +1,31 @@
/**
* 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 org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
import java.util.Map;
import java.util.UUID;
@Data
public class NotificationRequestPreview {
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates;
private int totalRecipientsCount;
private Map<UUID, Integer> recipientsCountByTarget;
}

1
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStatus.java

@ -16,6 +16,7 @@
package org.thingsboard.server.common.data.notification;
public enum NotificationRequestStatus {
PROCESSING,
SENT,
SCHEDULED
}

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java

@ -18,11 +18,13 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class EmailDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate implements HasSubject {
private String subject;

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/PushDeliveryMethodNotificationTemplate.java

@ -18,11 +18,13 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PushDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate implements HasSubject {
private String subject;

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SlackDeliveryMethodNotificationTemplate.java

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import javax.validation.constraints.NotEmpty;
@ -25,6 +26,7 @@ import javax.validation.constraints.NotEmpty;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
private SlackConversation.Type conversationType;

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SmsDeliveryMethodNotificationTemplate.java

@ -18,11 +18,13 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SmsDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
public SmsDeliveryMethodNotificationTemplate(SmsDeliveryMethodNotificationTemplate other) {

2
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java

@ -109,7 +109,7 @@ public class NotificationRequestEntity extends BaseSqlEntity<NotificationRequest
notificationRequest.setId(new NotificationRequestId(id));
notificationRequest.setCreatedTime(createdTime);
notificationRequest.setTenantId(getTenantId(tenantId));
notificationRequest.setTargets(listFromString(targets, uuid -> new NotificationTargetId(UUID.fromString(uuid))));
notificationRequest.setTargets(listFromString(targets, UUID::fromString));
notificationRequest.setTemplateId(getEntityId(templateId, NotificationTemplateId::new));
notificationRequest.setInfo(fromJson(info, NotificationInfo.class));
notificationRequest.setAdditionalConfig(fromJson(additionalConfig, NotificationRequestConfig.class));

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

@ -79,8 +79,8 @@ public class DefaultNotificationRequestService implements NotificationRequestSer
}
@Override
public void updateNotificationRequestStats(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationRequestStats stats) {
notificationRequestDao.updateStatsById(tenantId, notificationRequestId, stats);
public void updateNotificationRequest(TenantId tenantId, NotificationRequestId requestId, NotificationRequestStatus requestStatus, NotificationRequestStats stats) {
notificationRequestDao.updateById(tenantId, requestId, requestStatus, stats);
}

11
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java

@ -62,13 +62,18 @@ public class DefaultNotificationTargetService implements NotificationTargetServi
}
@Override
public PageData<User> findRecipientsForNotificationTarget(TenantId tenantId, CustomerId customerId, NotificationTargetId notificationTargetId, PageLink pageLink) {
NotificationTarget notificationTarget = findNotificationTargetById(tenantId, notificationTargetId);
Objects.requireNonNull(notificationTarget, "Notification target [" + notificationTargetId + "] not found");
public PageData<User> findRecipientsForNotificationTarget(TenantId tenantId, CustomerId customerId, NotificationTargetId targetId, PageLink pageLink) {
NotificationTarget notificationTarget = findNotificationTargetById(tenantId, targetId);
Objects.requireNonNull(notificationTarget, "Notification target [" + targetId + "] not found");
NotificationTargetConfig configuration = notificationTarget.getConfiguration();
return findRecipientsForNotificationTargetConfig(tenantId, customerId, configuration, pageLink);
}
@Override
public int countRecipientsForNotificationTarget(TenantId tenantId, NotificationTargetId targetId) {
return (int) findRecipientsForNotificationTarget(tenantId, null, targetId, new PageLink(1)).getTotalElements();
}
@Override
public PageData<User> findRecipientsForNotificationTargetConfig(TenantId tenantId, CustomerId customerId, NotificationTargetConfig targetConfig, PageLink pageLink) {
switch (targetConfig.getType()) {

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

@ -41,7 +41,7 @@ public interface NotificationRequestDao extends Dao<NotificationRequest> {
PageData<NotificationRequest> findAllByStatus(NotificationRequestStatus status, PageLink pageLink);
void updateStatsById(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationRequestStats stats);
void updateById(TenantId tenantId, NotificationRequestId requestId, NotificationRequestStatus requestStatus, NotificationRequestStats stats);
boolean existsByStatusAndTargetId(TenantId tenantId, NotificationRequestStatus status, NotificationTargetId targetId);

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

@ -72,8 +72,8 @@ public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationReques
}
@Override
public void updateStatsById(TenantId tenantId, NotificationRequestId notificationRequestId, NotificationRequestStats stats) {
notificationRequestRepository.updateStatsById(notificationRequestId.getId(), JacksonUtil.valueToTree(stats));
public void updateById(TenantId tenantId, NotificationRequestId requestId, NotificationRequestStatus requestStatus, NotificationRequestStats stats) {
notificationRequestRepository.updateStatusAndStatsById(requestId.getId(), requestStatus, JacksonUtil.valueToTree(stats));
}
@Override

6
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRequestRepository.java

@ -46,8 +46,10 @@ public interface NotificationRequestRepository extends JpaRepository<Notificatio
@Modifying
@Transactional
@Query("UPDATE NotificationRequestEntity r SET r.stats = :stats WHERE r.id = :id")
void updateStatsById(@Param("id") UUID id, @Param("stats") JsonNode stats);
@Query("UPDATE NotificationRequestEntity r SET r.status = :status, r.stats = :stats WHERE r.id = :id")
void updateStatusAndStatsById(@Param("id") UUID id,
@Param("status") NotificationRequestStatus status,
@Param("stats") JsonNode stats);
boolean existsByStatusAndTargetsContaining(NotificationRequestStatus status, String targetIdStr);

3
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java

@ -24,12 +24,13 @@ import org.thingsboard.server.common.data.notification.NotificationRequestConfig
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.UUID;
@Data
public class TbNotificationNodeConfiguration implements NodeConfiguration<TbNotificationNodeConfiguration> {
@NotEmpty
private List<NotificationTargetId> targets;
private List<UUID> targets;
@NotNull
private NotificationTemplateId templateId;
private NotificationRequestConfig additionalConfig;

Loading…
Cancel
Save