Commit 3094fb72400687f2d67ec0efeb58917814d12ad0

Authored by Igor Kulikov
1 parent 96878b6d

Add customerId to alarm

@@ -90,6 +90,11 @@ ALTER TABLE device @@ -90,6 +90,11 @@ ALTER TABLE device
90 ADD COLUMN IF NOT EXISTS firmware_id uuid, 90 ADD COLUMN IF NOT EXISTS firmware_id uuid,
91 ADD COLUMN IF NOT EXISTS software_id uuid; 91 ADD COLUMN IF NOT EXISTS software_id uuid;
92 92
  93 +ALTER TABLE alarm
  94 + ADD COLUMN IF NOT EXISTS customer_id uuid;
  95 +
  96 +DELETE FROM relation WHERE from_type = 'TENANT' AND relation_type_group = 'RULE_CHAIN';
  97 +
93 DO $$ 98 DO $$
94 BEGIN 99 BEGIN
95 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device_profile') THEN 100 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device_profile') THEN
@@ -27,6 +27,9 @@ import org.thingsboard.rule.engine.profile.TbDeviceProfileNode; @@ -27,6 +27,9 @@ import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
27 import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration; 27 import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration;
28 import org.thingsboard.server.common.data.EntityView; 28 import org.thingsboard.server.common.data.EntityView;
29 import org.thingsboard.server.common.data.Tenant; 29 import org.thingsboard.server.common.data.Tenant;
  30 +import org.thingsboard.server.common.data.alarm.Alarm;
  31 +import org.thingsboard.server.common.data.alarm.AlarmInfo;
  32 +import org.thingsboard.server.common.data.alarm.AlarmQuery;
30 import org.thingsboard.server.common.data.id.EntityViewId; 33 import org.thingsboard.server.common.data.id.EntityViewId;
31 import org.thingsboard.server.common.data.id.TenantId; 34 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; 35 import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
@@ -34,9 +37,13 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; @@ -34,9 +37,13 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
34 import org.thingsboard.server.common.data.kv.TsKvEntry; 37 import org.thingsboard.server.common.data.kv.TsKvEntry;
35 import org.thingsboard.server.common.data.page.PageData; 38 import org.thingsboard.server.common.data.page.PageData;
36 import org.thingsboard.server.common.data.page.PageLink; 39 import org.thingsboard.server.common.data.page.PageLink;
  40 +import org.thingsboard.server.common.data.page.TimePageLink;
37 import org.thingsboard.server.common.data.rule.RuleChain; 41 import org.thingsboard.server.common.data.rule.RuleChain;
38 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 42 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
39 import org.thingsboard.server.common.data.rule.RuleNode; 43 import org.thingsboard.server.common.data.rule.RuleNode;
  44 +import org.thingsboard.server.dao.alarm.AlarmDao;
  45 +import org.thingsboard.server.dao.alarm.AlarmService;
  46 +import org.thingsboard.server.dao.entity.EntityService;
40 import org.thingsboard.server.dao.entityview.EntityViewService; 47 import org.thingsboard.server.dao.entityview.EntityViewService;
41 import org.thingsboard.server.dao.rule.RuleChainService; 48 import org.thingsboard.server.dao.rule.RuleChainService;
42 import org.thingsboard.server.dao.tenant.TenantService; 49 import org.thingsboard.server.dao.tenant.TenantService;
@@ -72,6 +79,15 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -72,6 +79,15 @@ public class DefaultDataUpdateService implements DataUpdateService {
72 @Autowired 79 @Autowired
73 private TimeseriesService tsService; 80 private TimeseriesService tsService;
74 81
  82 + @Autowired
  83 + private AlarmService alarmService;
  84 +
  85 + @Autowired
  86 + private EntityService entityService;
  87 +
  88 + @Autowired
  89 + private AlarmDao alarmDao;
  90 +
75 @Override 91 @Override
76 public void updateData(String fromVersion) throws Exception { 92 public void updateData(String fromVersion) throws Exception {
77 switch (fromVersion) { 93 switch (fromVersion) {
@@ -90,14 +106,25 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -90,14 +106,25 @@ public class DefaultDataUpdateService implements DataUpdateService {
90 case "3.2.2": 106 case "3.2.2":
91 log.info("Updating data from version 3.2.2 to 3.3.0 ..."); 107 log.info("Updating data from version 3.2.2 to 3.3.0 ...");
92 tenantsDefaultEdgeRuleChainUpdater.updateEntities(null); 108 tenantsDefaultEdgeRuleChainUpdater.updateEntities(null);
  109 + tenantsAlarmsCustomerUpdater.updateEntities(null);
93 break; 110 break;
94 default: 111 default:
95 throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); 112 throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion);
96 } 113 }
97 } 114 }
98 115
99 - private PaginatedUpdater<String, Tenant> tenantsDefaultRuleChainUpdater =  
100 - new PaginatedUpdater<String, Tenant>() { 116 + private final PaginatedUpdater<String, Tenant> tenantsDefaultRuleChainUpdater =
  117 + new PaginatedUpdater<>() {
  118 +
  119 + @Override
  120 + protected String getName() {
  121 + return "Tenants default rule chain updater";
  122 + }
  123 +
  124 + @Override
  125 + protected boolean forceReportTotal() {
  126 + return true;
  127 + }
101 128
102 @Override 129 @Override
103 protected PageData<Tenant> findEntities(String region, PageLink pageLink) { 130 protected PageData<Tenant> findEntities(String region, PageLink pageLink) {
@@ -117,8 +144,18 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -117,8 +144,18 @@ public class DefaultDataUpdateService implements DataUpdateService {
117 } 144 }
118 }; 145 };
119 146
120 - private PaginatedUpdater<String, Tenant> tenantsDefaultEdgeRuleChainUpdater =  
121 - new PaginatedUpdater<String, Tenant>() { 147 + private final PaginatedUpdater<String, Tenant> tenantsDefaultEdgeRuleChainUpdater =
  148 + new PaginatedUpdater<>() {
  149 +
  150 + @Override
  151 + protected String getName() {
  152 + return "Tenants default edge rule chain updater";
  153 + }
  154 +
  155 + @Override
  156 + protected boolean forceReportTotal() {
  157 + return true;
  158 + }
122 159
123 @Override 160 @Override
124 protected PageData<Tenant> findEntities(String region, PageLink pageLink) { 161 protected PageData<Tenant> findEntities(String region, PageLink pageLink) {
@@ -138,8 +175,18 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -138,8 +175,18 @@ public class DefaultDataUpdateService implements DataUpdateService {
138 } 175 }
139 }; 176 };
140 177
141 - private PaginatedUpdater<String, Tenant> tenantsRootRuleChainUpdater =  
142 - new PaginatedUpdater<String, Tenant>() { 178 + private final PaginatedUpdater<String, Tenant> tenantsRootRuleChainUpdater =
  179 + new PaginatedUpdater<>() {
  180 +
  181 + @Override
  182 + protected String getName() {
  183 + return "Tenants root rule chain updater";
  184 + }
  185 +
  186 + @Override
  187 + protected boolean forceReportTotal() {
  188 + return true;
  189 + }
143 190
144 @Override 191 @Override
145 protected PageData<Tenant> findEntities(String region, PageLink pageLink) { 192 protected PageData<Tenant> findEntities(String region, PageLink pageLink) {
@@ -192,8 +239,18 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -192,8 +239,18 @@ public class DefaultDataUpdateService implements DataUpdateService {
192 } 239 }
193 }; 240 };
194 241
195 - private PaginatedUpdater<String, Tenant> tenantsEntityViewsUpdater =  
196 - new PaginatedUpdater<String, Tenant>() { 242 + private final PaginatedUpdater<String, Tenant> tenantsEntityViewsUpdater =
  243 + new PaginatedUpdater<>() {
  244 +
  245 + @Override
  246 + protected String getName() {
  247 + return "Tenants entity views updater";
  248 + }
  249 +
  250 + @Override
  251 + protected boolean forceReportTotal() {
  252 + return true;
  253 + }
197 254
198 @Override 255 @Override
199 protected PageData<Tenant> findEntities(String region, PageLink pageLink) { 256 protected PageData<Tenant> findEntities(String region, PageLink pageLink) {
@@ -261,4 +318,48 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -261,4 +318,48 @@ public class DefaultDataUpdateService implements DataUpdateService {
261 }, MoreExecutors.directExecutor()); 318 }, MoreExecutors.directExecutor());
262 } 319 }
263 320
  321 + private final PaginatedUpdater<String, Tenant> tenantsAlarmsCustomerUpdater =
  322 + new PaginatedUpdater<>() {
  323 +
  324 + @Override
  325 + protected String getName() {
  326 + return "Tenants alarms customer updater";
  327 + }
  328 +
  329 + @Override
  330 + protected boolean forceReportTotal() {
  331 + return true;
  332 + }
  333 +
  334 + @Override
  335 + protected PageData<Tenant> findEntities(String region, PageLink pageLink) {
  336 + return tenantService.findTenants(pageLink);
  337 + }
  338 +
  339 + @Override
  340 + protected void updateEntity(Tenant tenant) {
  341 + updateTenantAlarmsCustomer(tenant.getId());
  342 + }
  343 + };
  344 +
  345 + private void updateTenantAlarmsCustomer(TenantId tenantId) {
  346 + AlarmQuery alarmQuery = new AlarmQuery(null, new TimePageLink(100), null, null, false);
  347 + PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, alarmQuery);
  348 + boolean hasNext = true;
  349 + while (hasNext) {
  350 + for (Alarm alarm : alarms.getData()) {
  351 + if (alarm.getCustomerId() == null && alarm.getOriginator() != null) {
  352 + alarm.setCustomerId(entityService.fetchEntityCustomerId(tenantId, alarm.getOriginator()));
  353 + alarmDao.save(tenantId, alarm);
  354 + }
  355 + }
  356 + if (alarms.hasNext()) {
  357 + alarmQuery.setPageLink(alarmQuery.getPageLink().nextPageLink());
  358 + alarms = alarmDao.findAlarms(tenantId, alarmQuery);
  359 + } else {
  360 + hasNext = false;
  361 + }
  362 + }
  363 + }
  364 +
264 } 365 }
@@ -15,16 +15,20 @@ @@ -15,16 +15,20 @@
15 */ 15 */
16 package org.thingsboard.server.service.install.update; 16 package org.thingsboard.server.service.install.update;
17 17
  18 +import lombok.extern.slf4j.Slf4j;
18 import org.thingsboard.server.common.data.SearchTextBased; 19 import org.thingsboard.server.common.data.SearchTextBased;
19 import org.thingsboard.server.common.data.id.UUIDBased; 20 import org.thingsboard.server.common.data.id.UUIDBased;
20 import org.thingsboard.server.common.data.page.PageData; 21 import org.thingsboard.server.common.data.page.PageData;
21 import org.thingsboard.server.common.data.page.PageLink; 22 import org.thingsboard.server.common.data.page.PageLink;
22 23
  24 +@Slf4j
23 public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UUIDBased>> { 25 public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UUIDBased>> {
24 26
25 private static final int DEFAULT_LIMIT = 100; 27 private static final int DEFAULT_LIMIT = 100;
  28 + private int updated = 0;
26 29
27 public void updateEntities(I id) { 30 public void updateEntities(I id) {
  31 + updated = 0;
28 PageLink pageLink = new PageLink(DEFAULT_LIMIT); 32 PageLink pageLink = new PageLink(DEFAULT_LIMIT);
29 boolean hasNext = true; 33 boolean hasNext = true;
30 while (hasNext) { 34 while (hasNext) {
@@ -32,13 +36,25 @@ public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UU @@ -32,13 +36,25 @@ public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UU
32 for (D entity : entities.getData()) { 36 for (D entity : entities.getData()) {
33 updateEntity(entity); 37 updateEntity(entity);
34 } 38 }
  39 + updated += entities.getData().size();
35 hasNext = entities.hasNext(); 40 hasNext = entities.hasNext();
36 if (hasNext) { 41 if (hasNext) {
  42 + log.info("{}: {} entities updated so far...", getName(), updated);
37 pageLink = pageLink.nextPageLink(); 43 pageLink = pageLink.nextPageLink();
  44 + } else {
  45 + if (updated > DEFAULT_LIMIT || forceReportTotal()) {
  46 + log.info("{}: {} total entities updated.", getName(), updated);
  47 + }
38 } 48 }
39 } 49 }
40 } 50 }
41 51
  52 + protected boolean forceReportTotal() {
  53 + return false;
  54 + }
  55 +
  56 + protected abstract String getName();
  57 +
42 protected abstract PageData<D> findEntities(I id, PageLink pageLink); 58 protected abstract PageData<D> findEntities(I id, PageLink pageLink);
43 59
44 protected abstract void updateEntity(D entity); 60 protected abstract void updateEntity(D entity);
@@ -28,6 +28,8 @@ public interface EntityService { @@ -28,6 +28,8 @@ public interface EntityService {
28 28
29 ListenableFuture<String> fetchEntityNameAsync(TenantId tenantId, EntityId entityId); 29 ListenableFuture<String> fetchEntityNameAsync(TenantId tenantId, EntityId entityId);
30 30
  31 + CustomerId fetchEntityCustomerId(TenantId tenantId, EntityId entityId);
  32 +
31 void deleteEntityRelations(TenantId tenantId, EntityId entityId); 33 void deleteEntityRelations(TenantId tenantId, EntityId entityId);
32 34
33 long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query); 35 long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query);
@@ -21,9 +21,11 @@ import lombok.AllArgsConstructor; @@ -21,9 +21,11 @@ import lombok.AllArgsConstructor;
21 import lombok.Builder; 21 import lombok.Builder;
22 import lombok.Data; 22 import lombok.Data;
23 import org.thingsboard.server.common.data.BaseData; 23 import org.thingsboard.server.common.data.BaseData;
  24 +import org.thingsboard.server.common.data.HasCustomerId;
24 import org.thingsboard.server.common.data.HasName; 25 import org.thingsboard.server.common.data.HasName;
25 import org.thingsboard.server.common.data.HasTenantId; 26 import org.thingsboard.server.common.data.HasTenantId;
26 import org.thingsboard.server.common.data.id.AlarmId; 27 import org.thingsboard.server.common.data.id.AlarmId;
  28 +import org.thingsboard.server.common.data.id.CustomerId;
27 import org.thingsboard.server.common.data.id.EntityId; 29 import org.thingsboard.server.common.data.id.EntityId;
28 import org.thingsboard.server.common.data.id.TenantId; 30 import org.thingsboard.server.common.data.id.TenantId;
29 31
@@ -35,9 +37,10 @@ import java.util.List; @@ -35,9 +37,10 @@ import java.util.List;
35 @Data 37 @Data
36 @Builder 38 @Builder
37 @AllArgsConstructor 39 @AllArgsConstructor
38 -public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId { 40 +public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, HasCustomerId {
39 41
40 private TenantId tenantId; 42 private TenantId tenantId;
  43 + private CustomerId customerId;
41 private String type; 44 private String type;
42 private EntityId originator; 45 private EntityId originator;
43 private AlarmSeverity severity; 46 private AlarmSeverity severity;
@@ -62,6 +65,7 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId { @@ -62,6 +65,7 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId {
62 super(alarm.getId()); 65 super(alarm.getId());
63 this.createdTime = alarm.getCreatedTime(); 66 this.createdTime = alarm.getCreatedTime();
64 this.tenantId = alarm.getTenantId(); 67 this.tenantId = alarm.getTenantId();
  68 + this.customerId = alarm.getCustomerId();
65 this.type = alarm.getType(); 69 this.type = alarm.getType();
66 this.originator = alarm.getOriginator(); 70 this.originator = alarm.getOriginator();
67 this.severity = alarm.getSeverity(); 71 this.severity = alarm.getSeverity();
@@ -110,6 +110,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -110,6 +110,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
110 if (alarm.getEndTs() == 0L) { 110 if (alarm.getEndTs() == 0L) {
111 alarm.setEndTs(alarm.getStartTs()); 111 alarm.setEndTs(alarm.getStartTs());
112 } 112 }
  113 + alarm.setCustomerId(entityService.fetchEntityCustomerId(alarm.getTenantId(), alarm.getOriginator()));
113 if (alarm.getId() == null) { 114 if (alarm.getId() == null) {
114 Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get(); 115 Alarm existing = alarmDao.findLatestByOriginatorAndType(alarm.getTenantId(), alarm.getOriginator(), alarm.getType()).get();
115 if (existing == null || existing.getStatus().isCleared()) { 116 if (existing == null || existing.getStatus().isCleared()) {
@@ -355,6 +356,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -355,6 +356,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
355 existing.setStatus(alarm.getStatus()); 356 existing.setStatus(alarm.getStatus());
356 existing.setSeverity(alarm.getSeverity()); 357 existing.setSeverity(alarm.getSeverity());
357 existing.setDetails(alarm.getDetails()); 358 existing.setDetails(alarm.getDetails());
  359 + existing.setCustomerId(alarm.getCustomerId());
358 existing.setPropagate(existing.isPropagate() || alarm.isPropagate()); 360 existing.setPropagate(existing.isPropagate() || alarm.isPropagate());
359 List<String> existingPropagateRelationTypes = existing.getPropagateRelationTypes(); 361 List<String> existingPropagateRelationTypes = existing.getPropagateRelationTypes();
360 List<String> newRelationTypes = alarm.getPropagateRelationTypes(); 362 List<String> newRelationTypes = alarm.getPropagateRelationTypes();
@@ -22,6 +22,7 @@ import com.google.common.util.concurrent.MoreExecutors; @@ -22,6 +22,7 @@ import com.google.common.util.concurrent.MoreExecutors;
22 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
23 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
  25 +import org.thingsboard.server.common.data.HasCustomerId;
25 import org.thingsboard.server.common.data.HasName; 26 import org.thingsboard.server.common.data.HasName;
26 import org.thingsboard.server.common.data.id.AlarmId; 27 import org.thingsboard.server.common.data.id.AlarmId;
27 import org.thingsboard.server.common.data.id.AssetId; 28 import org.thingsboard.server.common.data.id.AssetId;
@@ -54,6 +55,7 @@ import org.thingsboard.server.dao.rule.RuleChainService; @@ -54,6 +55,7 @@ import org.thingsboard.server.dao.rule.RuleChainService;
54 import org.thingsboard.server.dao.tenant.TenantService; 55 import org.thingsboard.server.dao.tenant.TenantService;
55 import org.thingsboard.server.dao.user.UserService; 56 import org.thingsboard.server.dao.user.UserService;
56 57
  58 +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
57 import static org.thingsboard.server.dao.service.Validator.validateId; 59 import static org.thingsboard.server.dao.service.Validator.validateId;
58 60
59 /** 61 /**
@@ -175,6 +177,50 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe @@ -175,6 +177,50 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
175 return entityName; 177 return entityName;
176 } 178 }
177 179
  180 + @Override
  181 + public CustomerId fetchEntityCustomerId(TenantId tenantId, EntityId entityId) {
  182 + log.trace("Executing fetchEntityCustomerId [{}]", entityId);
  183 + HasCustomerId hasCustomerId = null;
  184 + switch (entityId.getEntityType()) {
  185 + case TENANT:
  186 + case RULE_CHAIN:
  187 + case RULE_NODE:
  188 + case DASHBOARD:
  189 + case WIDGETS_BUNDLE:
  190 + case WIDGET_TYPE:
  191 + case TENANT_PROFILE:
  192 + case DEVICE_PROFILE:
  193 + case API_USAGE_STATE:
  194 + case TB_RESOURCE:
  195 + case FIRMWARE:
  196 + break;
  197 + case CUSTOMER:
  198 + hasCustomerId = () -> new CustomerId(entityId.getId());
  199 + break;
  200 + case USER:
  201 + hasCustomerId = userService.findUserById(tenantId, new UserId(entityId.getId()));
  202 + break;
  203 + case ASSET:
  204 + hasCustomerId = assetService.findAssetById(tenantId, new AssetId(entityId.getId()));
  205 + break;
  206 + case DEVICE:
  207 + hasCustomerId = deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId()));
  208 + break;
  209 + case ALARM:
  210 + try {
  211 + hasCustomerId = alarmService.findAlarmByIdAsync(tenantId, new AlarmId(entityId.getId())).get();
  212 + } catch (Exception e) {}
  213 + break;
  214 + case ENTITY_VIEW:
  215 + hasCustomerId = entityViewService.findEntityViewById(tenantId, new EntityViewId(entityId.getId()));
  216 + break;
  217 + case EDGE:
  218 + hasCustomerId = edgeService.findEdgeById(tenantId, new EdgeId(entityId.getId()));
  219 + break;
  220 + }
  221 + return hasCustomerId != null ? hasCustomerId.getCustomerId() : new CustomerId(NULL_UUID);
  222 + }
  223 +
178 private static void validateEntityCountQuery(EntityCountQuery query) { 224 private static void validateEntityCountQuery(EntityCountQuery query) {
179 if (query == null) { 225 if (query == null) {
180 throw new IncorrectParameterException("Query must be specified."); 226 throw new IncorrectParameterException("Query must be specified.");
@@ -258,6 +258,7 @@ public class ModelConstants { @@ -258,6 +258,7 @@ public class ModelConstants {
258 */ 258 */
259 public static final String ALARM_COLUMN_FAMILY_NAME = "alarm"; 259 public static final String ALARM_COLUMN_FAMILY_NAME = "alarm";
260 public static final String ALARM_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; 260 public static final String ALARM_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
  261 + public static final String ALARM_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
261 public static final String ALARM_TYPE_PROPERTY = "type"; 262 public static final String ALARM_TYPE_PROPERTY = "type";
262 public static final String ALARM_DETAILS_PROPERTY = "details"; 263 public static final String ALARM_DETAILS_PROPERTY = "details";
263 public static final String ALARM_ORIGINATOR_ID_PROPERTY = "originator_id"; 264 public static final String ALARM_ORIGINATOR_ID_PROPERTY = "originator_id";
@@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.alarm.Alarm; @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.alarm.Alarm;
27 import org.thingsboard.server.common.data.alarm.AlarmSeverity; 27 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
28 import org.thingsboard.server.common.data.alarm.AlarmStatus; 28 import org.thingsboard.server.common.data.alarm.AlarmStatus;
29 import org.thingsboard.server.common.data.id.AlarmId; 29 import org.thingsboard.server.common.data.id.AlarmId;
  30 +import org.thingsboard.server.common.data.id.CustomerId;
30 import org.thingsboard.server.common.data.id.EntityIdFactory; 31 import org.thingsboard.server.common.data.id.EntityIdFactory;
31 import org.thingsboard.server.common.data.id.TenantId; 32 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.dao.model.BaseEntity; 33 import org.thingsboard.server.dao.model.BaseEntity;
@@ -44,6 +45,7 @@ import java.util.UUID; @@ -44,6 +45,7 @@ import java.util.UUID;
44 45
45 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ACK_TS_PROPERTY; 46 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ACK_TS_PROPERTY;
46 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_CLEAR_TS_PROPERTY; 47 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_CLEAR_TS_PROPERTY;
  48 +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_CUSTOMER_ID_PROPERTY;
47 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_END_TS_PROPERTY; 49 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_END_TS_PROPERTY;
48 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ORIGINATOR_ID_PROPERTY; 50 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ORIGINATOR_ID_PROPERTY;
49 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ORIGINATOR_TYPE_PROPERTY; 51 import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ORIGINATOR_TYPE_PROPERTY;
@@ -64,6 +66,9 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity @@ -64,6 +66,9 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity
64 @Column(name = ALARM_TENANT_ID_PROPERTY) 66 @Column(name = ALARM_TENANT_ID_PROPERTY)
65 private UUID tenantId; 67 private UUID tenantId;
66 68
  69 + @Column(name = ALARM_CUSTOMER_ID_PROPERTY)
  70 + private UUID customerId;
  71 +
67 @Column(name = ALARM_ORIGINATOR_ID_PROPERTY) 72 @Column(name = ALARM_ORIGINATOR_ID_PROPERTY)
68 private UUID originatorId; 73 private UUID originatorId;
69 74
@@ -115,6 +120,9 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity @@ -115,6 +120,9 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity
115 if (alarm.getTenantId() != null) { 120 if (alarm.getTenantId() != null) {
116 this.tenantId = alarm.getTenantId().getId(); 121 this.tenantId = alarm.getTenantId().getId();
117 } 122 }
  123 + if (alarm.getCustomerId() != null) {
  124 + this.customerId = alarm.getCustomerId().getId();
  125 + }
118 this.type = alarm.getType(); 126 this.type = alarm.getType();
119 this.originatorId = alarm.getOriginator().getId(); 127 this.originatorId = alarm.getOriginator().getId();
120 this.originatorType = alarm.getOriginator().getEntityType(); 128 this.originatorType = alarm.getOriginator().getEntityType();
@@ -138,6 +146,7 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity @@ -138,6 +146,7 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity
138 this.setId(alarmEntity.getId()); 146 this.setId(alarmEntity.getId());
139 this.setCreatedTime(alarmEntity.getCreatedTime()); 147 this.setCreatedTime(alarmEntity.getCreatedTime());
140 this.tenantId = alarmEntity.getTenantId(); 148 this.tenantId = alarmEntity.getTenantId();
  149 + this.customerId = alarmEntity.getCustomerId();
141 this.type = alarmEntity.getType(); 150 this.type = alarmEntity.getType();
142 this.originatorId = alarmEntity.getOriginatorId(); 151 this.originatorId = alarmEntity.getOriginatorId();
143 this.originatorType = alarmEntity.getOriginatorType(); 152 this.originatorType = alarmEntity.getOriginatorType();
@@ -159,6 +168,9 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity @@ -159,6 +168,9 @@ public abstract class AbstractAlarmEntity<T extends Alarm> extends BaseSqlEntity
159 if (tenantId != null) { 168 if (tenantId != null) {
160 alarm.setTenantId(new TenantId(tenantId)); 169 alarm.setTenantId(new TenantId(tenantId));
161 } 170 }
  171 + if (customerId != null) {
  172 + alarm.setCustomerId(new CustomerId(customerId));
  173 + }
162 alarm.setOriginator(EntityIdFactory.getByTypeAndUuid(originatorType, originatorId)); 174 alarm.setOriginator(EntityIdFactory.getByTypeAndUuid(originatorType, originatorId));
163 alarm.setType(type); 175 alarm.setType(type);
164 alarm.setSeverity(severity); 176 alarm.setSeverity(severity);
@@ -19,6 +19,7 @@ import lombok.Data; @@ -19,6 +19,7 @@ import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
20 import org.hibernate.annotations.TypeDef; 20 import org.hibernate.annotations.TypeDef;
21 import org.thingsboard.server.common.data.alarm.Alarm; 21 import org.thingsboard.server.common.data.alarm.Alarm;
  22 +import org.thingsboard.server.common.data.alarm.AlarmInfo;
22 import org.thingsboard.server.dao.util.mapping.JsonStringType; 23 import org.thingsboard.server.dao.util.mapping.JsonStringType;
23 24
24 import javax.persistence.Entity; 25 import javax.persistence.Entity;
@@ -37,6 +38,10 @@ public final class AlarmEntity extends AbstractAlarmEntity<Alarm> { @@ -37,6 +38,10 @@ public final class AlarmEntity extends AbstractAlarmEntity<Alarm> {
37 super(); 38 super();
38 } 39 }
39 40
  41 + public AlarmEntity(AlarmInfo alarmInfo) {
  42 + super(alarmInfo);
  43 + }
  44 +
40 public AlarmEntity(Alarm alarm) { 45 public AlarmEntity(Alarm alarm) {
41 super(alarm); 46 super(alarm);
42 } 47 }
@@ -100,12 +100,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -100,12 +100,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
100 @Transactional 100 @Transactional
101 public RuleChain saveRuleChain(RuleChain ruleChain) { 101 public RuleChain saveRuleChain(RuleChain ruleChain) {
102 ruleChainValidator.validate(ruleChain, RuleChain::getTenantId); 102 ruleChainValidator.validate(ruleChain, RuleChain::getTenantId);
103 - RuleChain savedRuleChain = ruleChainDao.save(ruleChain.getTenantId(), ruleChain);  
104 - if (ruleChain.isRoot() && ruleChain.getId() == null) {  
105 - createRelation(ruleChain.getTenantId(), new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),  
106 - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));  
107 - }  
108 - return savedRuleChain; 103 + return ruleChainDao.save(ruleChain.getTenantId(), ruleChain);
109 } 104 }
110 105
111 @Override 106 @Override
@@ -114,29 +109,20 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -114,29 +109,20 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
114 RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId()); 109 RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId());
115 if (!ruleChain.isRoot()) { 110 if (!ruleChain.isRoot()) {
116 RuleChain previousRootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId()); 111 RuleChain previousRootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
117 - try {  
118 - if (previousRootRuleChain == null) {  
119 - setRootAndSave(tenantId, ruleChain);  
120 - return true;  
121 - } else if (!previousRootRuleChain.getId().equals(ruleChain.getId())) {  
122 - deleteRelation(tenantId, new EntityRelation(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(),  
123 - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));  
124 - previousRootRuleChain.setRoot(false);  
125 - ruleChainDao.save(tenantId, previousRootRuleChain);  
126 - setRootAndSave(tenantId, ruleChain);  
127 - return true;  
128 - }  
129 - } catch (ExecutionException | InterruptedException e) {  
130 - log.warn("[{}] Failed to set root rule chain, ruleChainId: [{}]", ruleChainId);  
131 - throw new RuntimeException(e); 112 + if (previousRootRuleChain == null) {
  113 + setRootAndSave(tenantId, ruleChain);
  114 + return true;
  115 + } else if (!previousRootRuleChain.getId().equals(ruleChain.getId())) {
  116 + previousRootRuleChain.setRoot(false);
  117 + ruleChainDao.save(tenantId, previousRootRuleChain);
  118 + setRootAndSave(tenantId, ruleChain);
  119 + return true;
132 } 120 }
133 } 121 }
134 return false; 122 return false;
135 } 123 }
136 124
137 - private void setRootAndSave(TenantId tenantId, RuleChain ruleChain) throws ExecutionException, InterruptedException {  
138 - createRelation(tenantId, new EntityRelation(ruleChain.getTenantId(), ruleChain.getId(),  
139 - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN)); 125 + private void setRootAndSave(TenantId tenantId, RuleChain ruleChain) {
140 ruleChain.setRoot(true); 126 ruleChain.setRoot(true);
141 ruleChainDao.save(tenantId, ruleChain); 127 ruleChainDao.save(tenantId, ruleChain);
142 } 128 }
@@ -179,41 +165,45 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -179,41 +165,45 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
179 toDelete.add(existingNode); 165 toDelete.add(existingNode);
180 } 166 }
181 } 167 }
182 - for (RuleNode node : toAddOrUpdate) {  
183 - node.setRuleChainId(ruleChain.getId());  
184 - RuleNode savedNode = ruleNodeDao.save(tenantId, node);  
185 - createRelation(tenantId, new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),  
186 - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));  
187 - int index = nodes.indexOf(node);  
188 - nodes.set(index, savedNode);  
189 - ruleNodeIndexMap.put(savedNode.getId(), index); 168 + if (nodes != null) {
  169 + for (RuleNode node : toAddOrUpdate) {
  170 + node.setRuleChainId(ruleChain.getId());
  171 + RuleNode savedNode = ruleNodeDao.save(tenantId, node);
  172 + createRelation(tenantId, new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
  173 + EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
  174 + int index = nodes.indexOf(node);
  175 + nodes.set(index, savedNode);
  176 + ruleNodeIndexMap.put(savedNode.getId(), index);
  177 + }
190 } 178 }
191 for (RuleNode node : toDelete) { 179 for (RuleNode node : toDelete) {
192 deleteRuleNode(tenantId, node.getId()); 180 deleteRuleNode(tenantId, node.getId());
193 } 181 }
194 RuleNodeId firstRuleNodeId = null; 182 RuleNodeId firstRuleNodeId = null;
195 - if (ruleChainMetaData.getFirstNodeIndex() != null) {  
196 - firstRuleNodeId = nodes.get(ruleChainMetaData.getFirstNodeIndex()).getId();  
197 - }  
198 - if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId))  
199 - || (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) {  
200 - ruleChain.setFirstRuleNodeId(firstRuleNodeId);  
201 - ruleChainDao.save(tenantId, ruleChain);  
202 - }  
203 - if (ruleChainMetaData.getConnections() != null) {  
204 - for (NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) {  
205 - EntityId from = nodes.get(nodeConnection.getFromIndex()).getId();  
206 - EntityId to = nodes.get(nodeConnection.getToIndex()).getId();  
207 - String type = nodeConnection.getType();  
208 - createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE)); 183 + if (nodes != null) {
  184 + if (ruleChainMetaData.getFirstNodeIndex() != null) {
  185 + firstRuleNodeId = nodes.get(ruleChainMetaData.getFirstNodeIndex()).getId();
209 } 186 }
210 - }  
211 - if (ruleChainMetaData.getRuleChainConnections() != null) {  
212 - for (RuleChainConnectionInfo nodeToRuleChainConnection : ruleChainMetaData.getRuleChainConnections()) {  
213 - EntityId from = nodes.get(nodeToRuleChainConnection.getFromIndex()).getId();  
214 - EntityId to = nodeToRuleChainConnection.getTargetRuleChainId();  
215 - String type = nodeToRuleChainConnection.getType();  
216 - createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE, nodeToRuleChainConnection.getAdditionalInfo())); 187 + if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId))
  188 + || (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) {
  189 + ruleChain.setFirstRuleNodeId(firstRuleNodeId);
  190 + ruleChainDao.save(tenantId, ruleChain);
  191 + }
  192 + if (ruleChainMetaData.getConnections() != null) {
  193 + for (NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) {
  194 + EntityId from = nodes.get(nodeConnection.getFromIndex()).getId();
  195 + EntityId to = nodes.get(nodeConnection.getToIndex()).getId();
  196 + String type = nodeConnection.getType();
  197 + createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
  198 + }
  199 + }
  200 + if (ruleChainMetaData.getRuleChainConnections() != null) {
  201 + for (RuleChainConnectionInfo nodeToRuleChainConnection : ruleChainMetaData.getRuleChainConnections()) {
  202 + EntityId from = nodes.get(nodeToRuleChainConnection.getFromIndex()).getId();
  203 + EntityId to = nodeToRuleChainConnection.getTargetRuleChainId();
  204 + String type = nodeToRuleChainConnection.getType();
  205 + createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE, nodeToRuleChainConnection.getAdditionalInfo()));
  206 + }
217 } 207 }
218 } 208 }
219 209
@@ -307,24 +297,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -307,24 +297,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
307 297
308 @Override 298 @Override
309 public RuleChain getRootTenantRuleChain(TenantId tenantId) { 299 public RuleChain getRootTenantRuleChain(TenantId tenantId) {
310 - return getRootRuleChainByType(tenantId, RuleChainType.CORE);  
311 - }  
312 -  
313 - private RuleChain getRootRuleChainByType(TenantId tenantId, RuleChainType type) {  
314 Validator.validateId(tenantId, "Incorrect tenant id for search request."); 300 Validator.validateId(tenantId, "Incorrect tenant id for search request.");
315 - List<EntityRelation> relations = relationService.findByFrom(tenantId, tenantId, RelationTypeGroup.RULE_CHAIN);  
316 - if (relations != null && !relations.isEmpty()) {  
317 - for (EntityRelation relation : relations) {  
318 - RuleChainId ruleChainId = new RuleChainId(relation.getTo().getId());  
319 - RuleChain ruleChainById = findRuleChainById(tenantId, ruleChainId);  
320 - if (type.equals(ruleChainById.getType())) {  
321 - return ruleChainById;  
322 - }  
323 - }  
324 - return null;  
325 - } else {  
326 - return null;  
327 - } 301 + return ruleChainDao.findRootRuleChainByTenantIdAndType(tenantId.getId(), RuleChainType.CORE);
328 } 302 }
329 303
330 @Override 304 @Override
@@ -366,7 +340,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -366,7 +340,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
366 boolean valid = true; 340 boolean valid = true;
367 EntityType toType = relation.getTo().getEntityType(); 341 EntityType toType = relation.getTo().getEntityType();
368 if (toType == EntityType.RULE_NODE || toType == EntityType.RULE_CHAIN) { 342 if (toType == EntityType.RULE_NODE || toType == EntityType.RULE_CHAIN) {
369 - BaseData entity; 343 + BaseData<?> entity;
370 if (relation.getTo().getEntityType() == EntityType.RULE_NODE) { 344 if (relation.getTo().getEntityType() == EntityType.RULE_NODE) {
371 entity = ruleNodeDao.findById(tenantId, relation.getTo().getId()); 345 entity = ruleNodeDao.findById(tenantId, relation.getTo().getId());
372 } else { 346 } else {
@@ -501,9 +475,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -501,9 +475,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
501 ObjectNode objNode = (ObjectNode) node; 475 ObjectNode objNode = (ObjectNode) node;
502 objNode.put("id", tenantId.getId().toString()); 476 objNode.put("id", tenantId.getId().toString());
503 } else { 477 } else {
504 - Iterator<JsonNode> childIter = node.iterator();  
505 - while (childIter.hasNext()) {  
506 - searchTenantIdRecursive(tenantId, childIter.next()); 478 + for (JsonNode jsonNode : node) {
  479 + searchTenantIdRecursive(tenantId, jsonNode);
507 } 480 }
508 } 481 }
509 } 482 }
@@ -608,7 +581,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -608,7 +581,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
608 581
609 @Override 582 @Override
610 public RuleChain getEdgeTemplateRootRuleChain(TenantId tenantId) { 583 public RuleChain getEdgeTemplateRootRuleChain(TenantId tenantId) {
611 - return getRootRuleChainByType(tenantId, RuleChainType.EDGE); 584 + Validator.validateId(tenantId, "Incorrect tenant id for search request.");
  585 + return ruleChainDao.findRootRuleChainByTenantIdAndType(tenantId.getId(), RuleChainType.EDGE);
612 } 586 }
613 587
614 @Override 588 @Override
@@ -618,13 +592,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -618,13 +592,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
618 if (previousEdgeTemplateRootRuleChain == null || !previousEdgeTemplateRootRuleChain.getId().equals(ruleChain.getId())) { 592 if (previousEdgeTemplateRootRuleChain == null || !previousEdgeTemplateRootRuleChain.getId().equals(ruleChain.getId())) {
619 try { 593 try {
620 if (previousEdgeTemplateRootRuleChain != null) { 594 if (previousEdgeTemplateRootRuleChain != null) {
621 - deleteRelation(tenantId, new EntityRelation(previousEdgeTemplateRootRuleChain.getTenantId(), previousEdgeTemplateRootRuleChain.getId(),  
622 - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));  
623 previousEdgeTemplateRootRuleChain.setRoot(false); 595 previousEdgeTemplateRootRuleChain.setRoot(false);
624 ruleChainDao.save(tenantId, previousEdgeTemplateRootRuleChain); 596 ruleChainDao.save(tenantId, previousEdgeTemplateRootRuleChain);
625 } 597 }
626 - createRelation(tenantId, new EntityRelation(ruleChain.getTenantId(), ruleChain.getId(),  
627 - EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));  
628 ruleChain.setRoot(true); 598 ruleChain.setRoot(true);
629 ruleChainDao.save(tenantId, ruleChain); 599 ruleChainDao.save(tenantId, ruleChain);
630 return true; 600 return true;
@@ -699,8 +669,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -699,8 +669,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
699 ruleNodeDao.removeById(tenantId, entityId.getId()); 669 ruleNodeDao.removeById(tenantId, entityId.getId());
700 } 670 }
701 671
702 - private DataValidator<RuleChain> ruleChainValidator =  
703 - new DataValidator<RuleChain>() { 672 + private final DataValidator<RuleChain> ruleChainValidator =
  673 + new DataValidator<>() {
704 @Override 674 @Override
705 protected void validateCreate(TenantId tenantId, RuleChain data) { 675 protected void validateCreate(TenantId tenantId, RuleChain data) {
706 DefaultTenantProfileConfiguration profileConfiguration = 676 DefaultTenantProfileConfiguration profileConfiguration =
@@ -739,8 +709,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @@ -739,8 +709,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
739 } 709 }
740 }; 710 };
741 711
742 - private PaginatedRemover<TenantId, RuleChain> tenantRuleChainsRemover =  
743 - new PaginatedRemover<TenantId, RuleChain>() { 712 + private final PaginatedRemover<TenantId, RuleChain> tenantRuleChainsRemover =
  713 + new PaginatedRemover<>() {
744 714
745 @Override 715 @Override
746 protected PageData<RuleChain> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { 716 protected PageData<RuleChain> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
@@ -51,6 +51,15 @@ public interface RuleChainDao extends Dao<RuleChain>, TenantEntityDao { @@ -51,6 +51,15 @@ public interface RuleChainDao extends Dao<RuleChain>, TenantEntityDao {
51 PageData<RuleChain> findRuleChainsByTenantIdAndType(UUID tenantId, RuleChainType type, PageLink pageLink); 51 PageData<RuleChain> findRuleChainsByTenantIdAndType(UUID tenantId, RuleChainType type, PageLink pageLink);
52 52
53 /** 53 /**
  54 + * Find root rule chain by tenantId and type
  55 + *
  56 + * @param tenantId the tenantId
  57 + * @param type the type
  58 + * @return the rule chain object
  59 + */
  60 + RuleChain findRootRuleChainByTenantIdAndType(UUID tenantId, RuleChainType type);
  61 +
  62 + /**
54 * Find rule chains by tenantId, edgeId and page link. 63 * Find rule chains by tenantId, edgeId and page link.
55 * 64 *
56 * @param tenantId the tenantId 65 * @param tenantId the tenantId
@@ -120,13 +120,7 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> { @@ -120,13 +120,7 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> {
120 Pageable pageable); 120 Pageable pageable);
121 121
122 @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmInfoEntity(a) FROM AlarmEntity a " + 122 @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmInfoEntity(a) FROM AlarmEntity a " +
123 - "WHERE a.tenantId = :tenantId " +  
124 - "AND (" +  
125 - "a.originatorId IN (SELECT d.id from DeviceEntity d WHERE d.customerId = :customerId) " +  
126 - "OR a.originatorId IN (SELECT asset.id from AssetEntity asset WHERE asset.customerId = :customerId) " +  
127 - "OR a.originatorId IN (SELECT u.id from UserEntity u WHERE u.customerId = :customerId) " +  
128 - "OR a.originatorId = :customerId" +  
129 - ") " + 123 + "WHERE a.tenantId = :tenantId AND a.customerId = :customerId " +
130 "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + 124 "AND (:startTime IS NULL OR a.createdTime >= :startTime) " +
131 "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + 125 "AND (:endTime IS NULL OR a.createdTime <= :endTime) " +
132 "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " + 126 "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " +
@@ -137,13 +131,7 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> { @@ -137,13 +131,7 @@ public interface AlarmRepository extends CrudRepository<AlarmEntity, UUID> {
137 countQuery = "" + 131 countQuery = "" +
138 "SELECT count(a) " + 132 "SELECT count(a) " +
139 "FROM AlarmEntity a " + 133 "FROM AlarmEntity a " +
140 - "WHERE a.tenantId = :tenantId " +  
141 - "AND (" +  
142 - "a.originatorId IN (SELECT d.id from DeviceEntity d WHERE d.customerId = :customerId) " +  
143 - "OR a.originatorId IN (SELECT asset.id from AssetEntity asset WHERE asset.customerId = :customerId) " +  
144 - "OR a.originatorId IN (SELECT u.id from UserEntity u WHERE u.customerId = :customerId) " +  
145 - "OR a.originatorId = :customerId" +  
146 - ") " + 134 + "WHERE a.tenantId = :tenantId AND a.customerId = :customerId " +
147 "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + 135 "AND (:startTime IS NULL OR a.createdTime >= :startTime) " +
148 "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + 136 "AND (:endTime IS NULL OR a.createdTime <= :endTime) " +
149 "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " + 137 "AND ((:alarmStatuses) IS NULL OR a.status in (:alarmStatuses)) " +
@@ -83,6 +83,12 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R @@ -83,6 +83,12 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R
83 } 83 }
84 84
85 @Override 85 @Override
  86 + public RuleChain findRootRuleChainByTenantIdAndType(UUID tenantId, RuleChainType type) {
  87 + log.debug("Try to find root rule chain by tenantId [{}] and type [{}]", tenantId, type);
  88 + return DaoUtil.getData(ruleChainRepository.findByTenantIdAndTypeAndRootIsTrue(tenantId, type));
  89 + }
  90 +
  91 + @Override
86 public PageData<RuleChain> findRuleChainsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) { 92 public PageData<RuleChain> findRuleChainsByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, PageLink pageLink) {
87 log.debug("Try to find rule chains by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink); 93 log.debug("Try to find rule chains by tenantId [{}], edgeId [{}] and pageLink [{}]", tenantId, edgeId, pageLink);
88 94
@@ -50,5 +50,8 @@ public interface RuleChainRepository extends PagingAndSortingRepository<RuleChai @@ -50,5 +50,8 @@ public interface RuleChainRepository extends PagingAndSortingRepository<RuleChai
50 @Param("edgeId") UUID edgeId, 50 @Param("edgeId") UUID edgeId,
51 @Param("searchText") String searchText, 51 @Param("searchText") String searchText,
52 Pageable pageable); 52 Pageable pageable);
  53 +
  54 + RuleChainEntity findByTenantIdAndTypeAndRootIsTrue(UUID tenantId, RuleChainType ruleChainType);
  55 +
53 Long countByTenantId(UUID tenantId); 56 Long countByTenantId(UUID tenantId);
54 } 57 }
@@ -35,6 +35,7 @@ CREATE TABLE IF NOT EXISTS alarm ( @@ -35,6 +35,7 @@ CREATE TABLE IF NOT EXISTS alarm (
35 start_ts bigint, 35 start_ts bigint,
36 status varchar(255), 36 status varchar(255),
37 tenant_id uuid, 37 tenant_id uuid,
  38 + customer_id uuid,
38 propagate_relation_types varchar, 39 propagate_relation_types varchar,
39 type varchar(255) 40 type varchar(255)
40 ); 41 );
@@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS alarm ( @@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS alarm (
53 start_ts bigint, 53 start_ts bigint,
54 status varchar(255), 54 status varchar(255),
55 tenant_id uuid, 55 tenant_id uuid,
  56 + customer_id uuid,
56 propagate_relation_types varchar, 57 propagate_relation_types varchar,
57 type varchar(255) 58 type varchar(255)
58 ); 59 );
@@ -188,12 +188,12 @@ @@ -188,12 +188,12 @@
188 </mat-drawer-content> 188 </mat-drawer-content>
189 </mat-drawer-container> 189 </mat-drawer-container>
190 <section fxLayout="row" class="layout-wrap tb-footer-buttons" fxLayoutAlign="start end"> 190 <section fxLayout="row" class="layout-wrap tb-footer-buttons" fxLayoutAlign="start end">
191 - <tb-footer-fab-buttons *ngIf="!embedded" 191 + <tb-footer-fab-buttons *ngIf="!embedded && !isMobileApp"
192 [fxShow]="!isAddingWidget && isEdit && !widgetEditMode" 192 [fxShow]="!isAddingWidget && isEdit && !widgetEditMode"
193 relative 193 relative
194 [footerFabButtons]="addWidgetFabButtons"> 194 [footerFabButtons]="addWidgetFabButtons">
195 </tb-footer-fab-buttons> 195 </tb-footer-fab-buttons>
196 - <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen && !embedded" 196 + <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen && !embedded && !isMobileApp"
197 mat-fab color="accent" class="tb-btn-footer" 197 mat-fab color="accent" class="tb-btn-footer"
198 [ngClass]="{'tb-hide': !isEdit || isAddingWidget}" 198 [ngClass]="{'tb-hide': !isEdit || isAddingWidget}"
199 [disabled]="isLoading$ | async" 199 [disabled]="isLoading$ | async"
@@ -202,7 +202,7 @@ @@ -202,7 +202,7 @@
202 matTooltipPosition="above"> 202 matTooltipPosition="above">
203 <mat-icon>done</mat-icon> 203 <mat-icon>done</mat-icon>
204 </button> 204 </button>
205 - <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen && !embedded" 205 + <button *ngIf="(isTenantAdmin() || isSystemAdmin()) && !forceFullscreen && !embedded && !isMobileApp"
206 mat-fab color="accent" class="tb-btn-footer" 206 mat-fab color="accent" class="tb-btn-footer"
207 [ngClass]="{'tb-hide': isAddingWidget || (isLoading$ | async)}" 207 [ngClass]="{'tb-hide': isAddingWidget || (isLoading$ | async)}"
208 [disabled]="isLoading$ | async" 208 [disabled]="isLoading$ | async"