Notification request info

This commit is contained in:
ViacheslavKlimov 2023-01-17 19:29:27 +02:00
parent b7f3aef044
commit 89aa75718d
15 changed files with 219 additions and 23 deletions

View File

@ -39,8 +39,10 @@ import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationProcessingContext;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestPreview;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
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;
@ -56,6 +58,7 @@ import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@ -147,10 +150,16 @@ public class NotificationController extends BaseController {
}));
preview.setProcessedTemplates(processedTemplates);
Map<UUID, Integer> recipientsCountByTarget = notificationRequest.getTargets().stream()
.collect(Collectors.toMap(id -> id, targetId -> {
return notificationTargetService.countRecipientsForNotificationTarget(user.getTenantId(), new NotificationTargetId(targetId));
}));
Map<String, Integer> recipientsCountByTarget = new HashMap<>();
notificationRequest.getTargets().forEach(targetId -> {
NotificationTarget notificationTarget = notificationTargetService.findNotificationTargetById(user.getTenantId(), new NotificationTargetId(targetId));
if (notificationTarget == null) {
throw new IllegalArgumentException("Notification target with id " + targetId + " not found");
}
int recipientsCount = notificationTargetService.countRecipientsForNotificationTargetConfig(user.getTenantId(), notificationTarget.getConfiguration());
recipientsCountByTarget.put(notificationTarget.getName(), recipientsCount);
});
preview.setRecipientsCountByTarget(recipientsCountByTarget);
preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum());
@ -159,21 +168,21 @@ public class NotificationController extends BaseController {
@GetMapping("/notification/request/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequest getNotificationRequestById(@PathVariable UUID id) throws ThingsboardException {
public NotificationRequestInfo getNotificationRequestById(@PathVariable UUID id) throws ThingsboardException {
NotificationRequestId notificationRequestId = new NotificationRequestId(id);
return checkEntityId(notificationRequestId, notificationRequestService::findNotificationRequestById, Operation.READ);
return checkEntityId(notificationRequestId, notificationRequestService::findNotificationRequestInfoById, Operation.READ);
}
@GetMapping("/notification/requests")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public PageData<NotificationRequest> getNotificationRequests(@RequestParam int pageSize,
public PageData<NotificationRequestInfo> getNotificationRequests(@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationRequestService.findNotificationRequestsByTenantIdAndOriginatorType(user.getTenantId(), EntityType.USER, pageLink);
return notificationRequestService.findNotificationRequestsInfosByTenantIdAndOriginatorType(user.getTenantId(), EntityType.USER, pageLink);
}
@DeleteMapping("/notification/request/{id}")

View File

@ -32,6 +32,7 @@ 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.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.info.UserOriginatedNotificationInfo;
@ -177,8 +178,13 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
return Pair.of(user, wsClient);
}
protected NotificationRequest findNotificationRequest(NotificationRequestId id) throws Exception {
return doGet("/api/notification/request/" + id, NotificationRequest.class);
protected NotificationRequestInfo findNotificationRequest(NotificationRequestId id) throws Exception {
return doGet("/api/notification/request/" + id, NotificationRequestInfo.class);
}
protected PageData<NotificationRequestInfo> findNotificationRequests() throws Exception {
PageLink pageLink = new PageLink(10);
return doGetTypedWithPageLink("/api/notification/requests?", new TypeReference<PageData<NotificationRequestInfo>>() {}, pageLink);
}
protected void deleteNotificationRequest(NotificationRequestId id) throws Exception {

View File

@ -29,6 +29,7 @@ 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.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestPreview;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
@ -63,6 +64,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@ -424,8 +426,8 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
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.getRecipientsCountByTarget().get(target1.getName())).isEqualTo(1);
assertThat(preview.getRecipientsCountByTarget().get(target2.getName())).isEqualTo(customerUsersCount);
assertThat(preview.getTotalRecipientsCount()).isEqualTo(1 + customerUsersCount);
Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates = preview.getProcessedTemplates();
@ -461,6 +463,21 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
});
}
@Test
public void testNotificationRequestInfo() throws Exception {
NotificationDeliveryMethod[] deliveryMethods = new NotificationDeliveryMethod[]{
NotificationDeliveryMethod.PUSH, NotificationDeliveryMethod.EMAIL
};
NotificationTemplate template = createNotificationTemplate(NotificationType.GENERAL, "Test subject", "Test text", deliveryMethods);
NotificationTarget target = createNotificationTarget(tenantAdminUserId);
NotificationRequest request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0);
NotificationRequestInfo requestInfo = findNotificationRequests().getData().get(0);
assertThat(requestInfo.getId()).isEqualTo(request.getId());
assertThat(requestInfo.getTemplateName()).isEqualTo(template.getName());
assertThat(requestInfo.getDeliveryMethods()).containsOnly(deliveryMethods);
}
@Test
public void testNotificationRequestStats() throws Exception {
wsClient.subscribeForUnreadNotifications(10);

View File

@ -21,6 +21,7 @@ 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.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData;
@ -34,8 +35,12 @@ public interface NotificationRequestService {
NotificationRequest findNotificationRequestById(TenantId tenantId, NotificationRequestId id);
NotificationRequestInfo findNotificationRequestInfoById(TenantId tenantId, NotificationRequestId id);
PageData<NotificationRequest> findNotificationRequestsByTenantIdAndOriginatorType(TenantId tenantId, EntityType originatorType, PageLink pageLink);
PageData<NotificationRequestInfo> findNotificationRequestsInfosByTenantIdAndOriginatorType(TenantId tenantId, EntityType originatorType, PageLink pageLink);
List<NotificationRequestId> findNotificationRequestsIdsByStatusAndRuleId(TenantId tenantId, NotificationRequestStatus requestStatus, NotificationRuleId ruleId);
List<NotificationRequest> findNotificationRequestsByRuleIdAndOriginatorEntityId(TenantId tenantId, NotificationRuleId ruleId, EntityId originatorEntityId);

View File

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

View File

@ -63,6 +63,19 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
private NotificationRequestStats stats;
public NotificationRequest(NotificationRequest other) {
super(other);
this.tenantId = other.tenantId;
this.targets = other.targets;
this.templateId = other.templateId;
this.info = other.info;
this.additionalConfig = other.additionalConfig;
this.originatorEntityId = other.originatorEntityId;
this.ruleId = other.ruleId;
this.status = other.status;
this.stats = other.stats;
}
@JsonIgnore
@Override
public String getName() {

View File

@ -0,0 +1,38 @@
/**
* 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 lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class NotificationRequestInfo extends NotificationRequest {
private String templateName;
private List<NotificationDeliveryMethod> deliveryMethods;
public NotificationRequestInfo(NotificationRequest request, String templateName, List<NotificationDeliveryMethod> deliveryMethods) {
super(request);
this.templateName = templateName;
this.deliveryMethods = deliveryMethods;
}
}

View File

@ -19,13 +19,12 @@ 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;
private Map<String, Integer> recipientsCountByTarget;
}

View File

@ -103,6 +103,21 @@ public class NotificationRequestEntity extends BaseSqlEntity<NotificationRequest
setStats(toJson(notificationRequest.getStats()));
}
public NotificationRequestEntity(NotificationRequestEntity other) {
this.id = other.id;
this.createdTime = other.createdTime;
this.tenantId = other.tenantId;
this.targets = other.targets;
this.templateId = other.templateId;
this.info = other.info;
this.additionalConfig = other.additionalConfig;
this.originatorEntityId = other.originatorEntityId;
this.originatorEntityType = other.originatorEntityType;
this.ruleId = other.ruleId;
this.status = other.status;
this.stats = other.stats;
}
@Override
public NotificationRequest toData() {
NotificationRequest notificationRequest = new NotificationRequest();

View File

@ -0,0 +1,51 @@
/**
* 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.dao.model.sql;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Data
@EqualsAndHashCode(callSuper = true)
public class NotificationRequestInfoEntity extends NotificationRequestEntity {
private String templateName;
private JsonNode templateConfig;
public NotificationRequestInfoEntity(NotificationRequestEntity requestEntity, String templateName, Object templateConfig) {
super(requestEntity);
this.templateName = templateName;
this.templateConfig = (JsonNode) templateConfig;
}
@Override
public NotificationRequestInfo toData() {
List<NotificationDeliveryMethod> deliveryMethods = fromJson(templateConfig, NotificationTemplateConfig.class)
.getDeliveryMethodsTemplates().entrySet().stream()
.filter(entry -> entry.getValue().isEnabled())
.map(Map.Entry::getKey).collect(Collectors.toList());
return new NotificationRequestInfo(super.toData(), templateName, deliveryMethods);
}
}

View File

@ -24,6 +24,7 @@ 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.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData;
@ -52,11 +53,21 @@ public class DefaultNotificationRequestService implements NotificationRequestSer
return notificationRequestDao.findById(tenantId, id.getId());
}
@Override
public NotificationRequestInfo findNotificationRequestInfoById(TenantId tenantId, NotificationRequestId id) {
return notificationRequestDao.findInfoById(tenantId, id);
}
@Override
public PageData<NotificationRequest> findNotificationRequestsByTenantIdAndOriginatorType(TenantId tenantId, EntityType originatorType, PageLink pageLink) {
return notificationRequestDao.findByTenantIdAndOriginatorTypeAndPageLink(tenantId, originatorType, pageLink);
}
@Override
public PageData<NotificationRequestInfo> findNotificationRequestsInfosByTenantIdAndOriginatorType(TenantId tenantId, EntityType originatorType, PageLink pageLink) {
return notificationRequestDao.findInfosByTenantIdAndOriginatorTypeAndPageLink(tenantId, originatorType, pageLink);
}
@Override
public List<NotificationRequestId> findNotificationRequestsIdsByStatusAndRuleId(TenantId tenantId, NotificationRequestStatus requestStatus, NotificationRuleId ruleId) {
return notificationRequestDao.findIdsByRuleId(tenantId, requestStatus, ruleId);

View File

@ -70,8 +70,8 @@ public class DefaultNotificationTargetService implements NotificationTargetServi
}
@Override
public int countRecipientsForNotificationTarget(TenantId tenantId, NotificationTargetId targetId) {
return (int) findRecipientsForNotificationTarget(tenantId, null, targetId, new PageLink(1)).getTotalElements();
public int countRecipientsForNotificationTargetConfig(TenantId tenantId, NotificationTargetConfig targetConfig) {
return (int) findRecipientsForNotificationTargetConfig(tenantId, null, targetConfig, new PageLink(1)).getTotalElements();
}
@Override

View File

@ -23,6 +23,7 @@ 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.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData;
@ -35,6 +36,8 @@ public interface NotificationRequestDao extends Dao<NotificationRequest> {
PageData<NotificationRequest> findByTenantIdAndOriginatorTypeAndPageLink(TenantId tenantId, EntityType originatorType, PageLink pageLink);
PageData<NotificationRequestInfo> findInfosByTenantIdAndOriginatorTypeAndPageLink(TenantId tenantId, EntityType originatorType, PageLink pageLink);
List<NotificationRequestId> findIdsByRuleId(TenantId tenantId, NotificationRequestStatus requestStatus, NotificationRuleId ruleId);
List<NotificationRequest> findByRuleIdAndOriginatorEntityId(TenantId tenantId, NotificationRuleId ruleId, EntityId originatorEntityId);
@ -49,4 +52,6 @@ public interface NotificationRequestDao extends Dao<NotificationRequest> {
int removeAllByCreatedTimeBefore(long ts);
NotificationRequestInfo findInfoById(TenantId tenantId, NotificationRequestId id);
}

View File

@ -27,12 +27,14 @@ 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.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.NotificationRequestEntity;
import org.thingsboard.server.dao.model.sql.NotificationRequestInfoEntity;
import org.thingsboard.server.dao.notification.NotificationRequestDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao;
@ -52,7 +54,14 @@ public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationReques
@Override
public PageData<NotificationRequest> findByTenantIdAndOriginatorTypeAndPageLink(TenantId tenantId, EntityType originatorType, PageLink pageLink) {
return DaoUtil.toPageData(notificationRequestRepository.findByTenantIdAndOriginatorEntityType(getId(tenantId, true), originatorType, DaoUtil.toPageable(pageLink)));
return DaoUtil.toPageData(notificationRequestRepository.findByTenantIdAndOriginatorEntityType(getId(tenantId, true),
originatorType, DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<NotificationRequestInfo> findInfosByTenantIdAndOriginatorTypeAndPageLink(TenantId tenantId, EntityType originatorType, PageLink pageLink) {
return DaoUtil.pageToPageData(notificationRequestRepository.findInfosByTenantIdAndOriginatorEntityType(getId(tenantId, true),
originatorType, DaoUtil.toPageable(pageLink))).mapData(NotificationRequestInfoEntity::toData);
}
@Override
@ -91,6 +100,12 @@ public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationReques
return notificationRequestRepository.deleteAllByCreatedTimeBefore(ts);
}
@Override
public NotificationRequestInfo findInfoById(TenantId tenantId, NotificationRequestId id) {
NotificationRequestInfoEntity info = notificationRequestRepository.findInfoById(id.getId());
return info != null ? info.toData() : null;
}
@Override
protected Class<NotificationRequestEntity> getEntityClass() {
return NotificationRequestEntity.class;

View File

@ -27,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.dao.model.sql.NotificationRequestEntity;
import org.thingsboard.server.dao.model.sql.NotificationRequestInfoEntity;
import java.util.List;
import java.util.UUID;
@ -34,8 +35,19 @@ import java.util.UUID;
@Repository
public interface NotificationRequestRepository extends JpaRepository<NotificationRequestEntity, UUID> {
String REQUEST_INFO_QUERY = "SELECT new org.thingsboard.server.dao.model.sql.NotificationRequestInfoEntity(r, t.name, t.configuration) " +
"FROM NotificationRequestEntity r INNER JOIN NotificationTemplateEntity t ON r.templateId = t.id";
Page<NotificationRequestEntity> findByTenantIdAndOriginatorEntityType(UUID tenantId, EntityType originatorType, Pageable pageable);
@Query(REQUEST_INFO_QUERY + " WHERE r.tenantId = :tenantId AND r.originatorEntityType = :originatorType")
Page<NotificationRequestInfoEntity> findInfosByTenantIdAndOriginatorEntityType(@Param("tenantId") UUID tenantId,
@Param("originatorType") EntityType originatorType,
Pageable pageable);
@Query(REQUEST_INFO_QUERY + " WHERE r.id = :id")
NotificationRequestInfoEntity findInfoById(@Param("id") UUID id);
@Query("SELECT r.id FROM NotificationRequestEntity r WHERE r.status = :status AND r.ruleId = :ruleId")
List<UUID> findAllIdsByStatusAndRuleId(@Param("status") NotificationRequestStatus status,
@Param("ruleId") UUID ruleId);