Browse Source

Add API to find calculated fields by filter

pull/14328/head
Viacheslav Klimov 10 months ago
parent
commit
c75e9d96e5
  1. 97
      application/src/main/java/org/thingsboard/server/controller/CalculatedFieldController.java
  2. 2
      application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
  3. 51
      application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java
  4. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/cf/CalculatedFieldService.java
  5. 41
      common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedFieldFilter.java
  6. 34
      common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedFieldInfo.java
  7. 20
      dao/src/main/java/org/thingsboard/server/dao/cf/BaseCalculatedFieldService.java
  8. 3
      dao/src/main/java/org/thingsboard/server/dao/cf/CalculatedFieldDao.java
  9. 9
      dao/src/main/java/org/thingsboard/server/dao/sql/cf/CalculatedFieldRepository.java
  10. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/cf/JpaCalculatedFieldDao.java

97
application/src/main/java/org/thingsboard/server/controller/CalculatedFieldController.java

@ -44,6 +44,8 @@ import org.thingsboard.script.api.tbel.TbelInvokeService;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EventInfo;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldFilter;
import org.thingsboard.server.common.data.cf.CalculatedFieldInfo;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.CalculatedFieldConfiguration;
import org.thingsboard.server.common.data.event.EventType;
@ -59,14 +61,18 @@ import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.cf.ctx.state.CalculatedFieldTbelScriptEngine;
import org.thingsboard.server.service.entitiy.cf.TbCalculatedFieldService;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static org.thingsboard.server.controller.ControllerConstants.CF_TEXT_SEARCH_DESCRIPTION;
@ -99,30 +105,30 @@ public class CalculatedFieldController extends BaseController {
private static final String TEST_SCRIPT_EXPRESSION =
"Execute the Script expression and return the result. The format of request: \n\n"
+ MARKDOWN_CODE_BLOCK_START
+ "{\n" +
" \"expression\": \"var temp = 0; foreach(element: temperature.values) {temp += element.value;} var avgTemperature = temp / temperature.values.size(); var adjustedTemperature = avgTemperature + 0.1 * humidity.value; return {\\\"adjustedTemperature\\\": adjustedTemperature};\",\n" +
" \"arguments\": {\n" +
" \"temperature\": {\n" +
" \"type\": \"TS_ROLLING\",\n" +
" \"timeWindow\": {\n" +
" \"startTs\": 1739775630002,\n" +
" \"endTs\": 65432211,\n" +
" \"limit\": 5\n" +
" },\n" +
" \"values\": [\n" +
" { \"ts\": 1739775639851, \"value\": 23 },\n" +
" { \"ts\": 1739775664561, \"value\": 43 },\n" +
" { \"ts\": 1739775713079, \"value\": 15 },\n" +
" { \"ts\": 1739775999522, \"value\": 34 },\n" +
" { \"ts\": 1739776228452, \"value\": 22 }\n" +
" ]\n" +
" },\n" +
" \"humidity\": { \"type\": \"SINGLE_VALUE\", \"ts\": 1739776478057, \"value\": 23 }\n" +
" }\n" +
"}"
+ MARKDOWN_CODE_BLOCK_END
+ "\n\n Expected result JSON contains \"output\" and \"error\".";
+ MARKDOWN_CODE_BLOCK_START
+ "{\n" +
" \"expression\": \"var temp = 0; foreach(element: temperature.values) {temp += element.value;} var avgTemperature = temp / temperature.values.size(); var adjustedTemperature = avgTemperature + 0.1 * humidity.value; return {\\\"adjustedTemperature\\\": adjustedTemperature};\",\n" +
" \"arguments\": {\n" +
" \"temperature\": {\n" +
" \"type\": \"TS_ROLLING\",\n" +
" \"timeWindow\": {\n" +
" \"startTs\": 1739775630002,\n" +
" \"endTs\": 65432211,\n" +
" \"limit\": 5\n" +
" },\n" +
" \"values\": [\n" +
" { \"ts\": 1739775639851, \"value\": 23 },\n" +
" { \"ts\": 1739775664561, \"value\": 43 },\n" +
" { \"ts\": 1739775713079, \"value\": 15 },\n" +
" { \"ts\": 1739775999522, \"value\": 34 },\n" +
" { \"ts\": 1739776228452, \"value\": 22 }\n" +
" ]\n" +
" },\n" +
" \"humidity\": { \"type\": \"SINGLE_VALUE\", \"ts\": 1739776478057, \"value\": 23 }\n" +
" }\n" +
"}"
+ MARKDOWN_CODE_BLOCK_END
+ "\n\n Expected result JSON contains \"output\" and \"error\".";
@ApiOperation(value = "Create Or Update Calculated Field (saveCalculatedField)",
notes = "Creates or Updates the Calculated Field. When creating calculated field, platform generates Calculated Field Id as " + UUID_WIKI_LINK +
@ -183,6 +189,46 @@ public class CalculatedFieldController extends BaseController {
return checkNotNull(tbCalculatedFieldService.findByTenantIdAndEntityId(getTenantId(), entityId, type, pageLink));
}
@ApiOperation(value = "Get calculated fields (getCalculatedFields)",
notes = "Fetch tenant calculated fields based on the filter.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@GetMapping(value = "/calculatedFields")
public PageData<CalculatedFieldInfo> getCalculatedFields(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@Parameter(description = "Calculated field type filter.")
@RequestParam CalculatedFieldType type,
@Parameter(description = "Entity type filter. If not specified, calculated fields for all supported entity types will be returned.")
@RequestParam(required = false) EntityType entityType,
@Parameter(description = "Entities filter. If not specified, calculated fields for entity type filter will be returned.")
@RequestParam(required = false) List<UUID> entities,
@Parameter(description = "Name filter.")
@RequestParam(required = false) String name,
@Parameter(description = CF_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name"}))
@RequestParam(required = false) String sortProperty,
@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"}))
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
SecurityUser user = getCurrentUser();
Set<EntityType> entityTypes;
if (entityType == null) {
entityTypes = CalculatedField.SUPPORTED_ENTITIES.keySet();
} else {
entityTypes = EnumSet.of(entityType);
}
CalculatedFieldFilter filter = CalculatedFieldFilter.builder()
.type(type)
.entityTypes(entityTypes)
.entityIds(entities)
.name(name)
.build();
return calculatedFieldService.findCalculatedFieldsByTenantIdAndFilter(user.getTenantId(), filter, pageLink);
}
@ApiOperation(value = "Delete Calculated Field (deleteCalculatedField)",
notes = "Deletes the calculated field. Referencing non-existing Calculated Field Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@ -295,7 +341,8 @@ public class CalculatedFieldController extends BaseController {
return;
}
case CUSTOMER, ASSET, DEVICE -> checkEntityId(referencedEntityId, Operation.READ);
default -> throw new IllegalArgumentException("Calculated fields do not support '" + entityType + "' for referenced entities.");
default ->
throw new IllegalArgumentException("Calculated fields do not support '" + entityType + "' for referenced entities.");
}
}
}

2
application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java

@ -1370,7 +1370,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
return doPost("/api/calculatedField", calculatedField, CalculatedField.class);
}
protected PageData<CalculatedField> getCalculatedFields(EntityId entityId, CalculatedFieldType type, PageLink pageLink) throws Exception {
protected PageData<CalculatedField> getEntityCalculatedFields(EntityId entityId, CalculatedFieldType type, PageLink pageLink) throws Exception {
return doGetTypedWithPageLink("/api/" + entityId.getEntityType() + "/" + entityId.getId() + "/calculatedFields" +
(type != null ? "?type=" + type.name() + "&" : "?"), new TypeReference<>() {}, pageLink);
}

51
application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java

@ -15,13 +15,17 @@
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.type.TypeReference;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldInfo;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.Argument;
import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
@ -36,6 +40,7 @@ import org.thingsboard.server.common.data.cf.configuration.geofencing.EntityCoor
import org.thingsboard.server.common.data.cf.configuration.geofencing.GeofencingCalculatedFieldConfiguration;
import org.thingsboard.server.common.data.cf.configuration.geofencing.ZoneGroupConfiguration;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
@ -45,6 +50,7 @@ import org.thingsboard.server.dao.service.DaoSqlTest;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
@ -192,17 +198,56 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest {
}
@Test
public void testGetCalculatedFields() throws Exception {
public void testGetEntityCalculatedFields() throws Exception {
Device testDevice = createDevice("Test device", "1234567890");
CalculatedField calculatedField = getSimpleCalculatedField(testDevice.getId());
calculatedField = doPost("/api/calculatedField", calculatedField, CalculatedField.class);
assertThat(getCalculatedFields(testDevice.getId(), null, new PageLink(10)).getData())
assertThat(getEntityCalculatedFields(testDevice.getId(), null, new PageLink(10)).getData())
.singleElement().isEqualTo(calculatedField);
assertThat(getCalculatedFields(testDevice.getId(), CalculatedFieldType.SIMPLE, new PageLink(10)).getData())
assertThat(getEntityCalculatedFields(testDevice.getId(), CalculatedFieldType.SIMPLE, new PageLink(10)).getData())
.singleElement().isEqualTo(calculatedField);
}
@Test
public void testGetCalculatedFieldsByFilter() throws Exception {
Device device = createDevice("Device A", "1234567890");
CalculatedFieldInfo deviceCalculatedField = new CalculatedFieldInfo(
doPost("/api/calculatedField", getSimpleCalculatedField(device.getId()), CalculatedField.class),
"Device A"
);
DeviceProfile deviceProfile = doPost("/api/deviceProfile", createDeviceProfile("Profile A"), DeviceProfile.class);
CalculatedFieldInfo profileCalculatedField = new CalculatedFieldInfo(
doPost("/api/calculatedField", getSimpleCalculatedField(deviceProfile.getId()), CalculatedField.class),
"Profile A"
);
List<CalculatedFieldInfo> allCalculatedFields = getCalculatedFields(CalculatedFieldType.SIMPLE, null, null, null);
assertThat(allCalculatedFields).contains(deviceCalculatedField, profileCalculatedField);
List<CalculatedFieldInfo> profileLevelCalculatedFields = getCalculatedFields(CalculatedFieldType.SIMPLE, EntityType.DEVICE_PROFILE, null, null);
assertThat(profileLevelCalculatedFields).containsOnly(profileCalculatedField);
List<CalculatedFieldInfo> specificDeviceCalculatedFields = getCalculatedFields(CalculatedFieldType.SIMPLE, EntityType.DEVICE, List.of(device.getUuidId()), null);
assertThat(specificDeviceCalculatedFields).containsOnly(deviceCalculatedField);
List<CalculatedFieldInfo> byNameCalculatedFields = getCalculatedFields(CalculatedFieldType.SIMPLE, null, null, deviceCalculatedField.getName());
assertThat(byNameCalculatedFields).containsOnly(deviceCalculatedField);
}
private List<CalculatedFieldInfo> getCalculatedFields(CalculatedFieldType type,
EntityType entityType,
List<UUID> entities,
String name) throws Exception {
return doGetTypedWithPageLink("/api/calculatedFields?type=" + type + "&" +
(entityType != null ? "entityType=" + entityType + "&" : "") +
(entities != null ? "entities=" + String.join(",",
entities.stream().map(UUID::toString).toList()) + "&" : "") +
(name != null ? "name=" + name + "&" : ""),
new TypeReference<PageData<CalculatedFieldInfo>>() {}, new PageLink(10)).getData();
}
@Test
public void testDeleteCalculatedField() throws Exception {
Device testDevice = createDevice("Test device", "1234567890");

4
common/dao-api/src/main/java/org/thingsboard/server/dao/cf/CalculatedFieldService.java

@ -16,6 +16,8 @@
package org.thingsboard.server.dao.cf;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldFilter;
import org.thingsboard.server.common.data.cf.CalculatedFieldInfo;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.EntityId;
@ -44,6 +46,8 @@ public interface CalculatedFieldService extends EntityDaoService {
PageData<CalculatedField> findCalculatedFieldsByTenantId(TenantId tenantId, PageLink pageLink);
PageData<CalculatedFieldInfo> findCalculatedFieldsByTenantIdAndFilter(TenantId tenantId, CalculatedFieldFilter filter, PageLink pageLink);
PageData<CalculatedField> findCalculatedFieldsByEntityId(TenantId tenantId, EntityId entityId, CalculatedFieldType type, PageLink pageLink);
void deleteCalculatedField(TenantId tenantId, CalculatedFieldId calculatedFieldId);

41
common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedFieldFilter.java

@ -0,0 +1,41 @@
/**
* Copyright © 2016-2025 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.cf;
import lombok.Builder;
import lombok.Data;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.thingsboard.server.common.data.EntityType;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@Data
@Builder
public class CalculatedFieldFilter {
@NonNull
private final CalculatedFieldType type;
@NonNull
private final Set<EntityType> entityTypes;
@Nullable
private final List<UUID> entityIds;
@Nullable
private final String name;
}

34
common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedFieldInfo.java

@ -0,0 +1,34 @@
/**
* Copyright © 2016-2025 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.cf;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class CalculatedFieldInfo extends CalculatedField {
private String entityName;
public CalculatedFieldInfo(CalculatedField calculatedField, String entityName) {
super(calculatedField);
this.entityName = entityName;
}
}

20
dao/src/main/java/org/thingsboard/server/dao/cf/BaseCalculatedFieldService.java

@ -19,8 +19,11 @@ import com.google.common.util.concurrent.FluentFuture;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldFilter;
import org.thingsboard.server.common.data.cf.CalculatedFieldInfo;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.CalculatedFieldConfiguration;
import org.thingsboard.server.common.data.id.CalculatedFieldId;
@ -30,6 +33,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
@ -37,8 +41,10 @@ import org.thingsboard.server.dao.service.validator.CalculatedFieldDataValidator
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.thingsboard.server.dao.service.Validator.validateId;
@ -53,6 +59,7 @@ public class BaseCalculatedFieldService extends AbstractEntityService implements
public static final String INCORRECT_CALCULATED_FIELD_ID = "Incorrect calculatedFieldId ";
public static final String INCORRECT_ENTITY_ID = "Incorrect entityId ";
private final EntityService entityService;
private final CalculatedFieldDao calculatedFieldDao;
private final CalculatedFieldDataValidator calculatedFieldDataValidator;
@ -140,6 +147,19 @@ public class BaseCalculatedFieldService extends AbstractEntityService implements
return calculatedFieldDao.findAllByTenantId(tenantId, pageLink);
}
@Override
public PageData<CalculatedFieldInfo> findCalculatedFieldsByTenantIdAndFilter(TenantId tenantId, CalculatedFieldFilter filter, PageLink pageLink) {
PageData<CalculatedField> calculatedFields = calculatedFieldDao.findByTenantIdAndFilter(tenantId, filter, pageLink);
Set<EntityId> entityIds = calculatedFields.getData().stream()
.map(CalculatedField::getEntityId)
.collect(Collectors.toSet());
Map<EntityId, EntityInfo> entityInfos = entityService.fetchEntityInfos(tenantId, null, entityIds);
return calculatedFields.mapData(calculatedField -> {
EntityInfo entityInfo = entityInfos.get(calculatedField.getEntityId());
return new CalculatedFieldInfo(calculatedField, entityInfo.getName());
});
}
@Override
public PageData<CalculatedField> findCalculatedFieldsByEntityId(TenantId tenantId, EntityId entityId, CalculatedFieldType type, PageLink pageLink) {
log.trace("Executing findAllByEntityId, entityId [{}], pageLink [{}]", entityId, pageLink);

3
dao/src/main/java/org/thingsboard/server/dao/cf/CalculatedFieldDao.java

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.cf;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldFilter;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.EntityId;
@ -49,4 +50,6 @@ public interface CalculatedFieldDao extends Dao<CalculatedField> {
long countByEntityIdAndTypeNot(TenantId tenantId, EntityId entityId, CalculatedFieldType type);
PageData<CalculatedField> findByTenantIdAndFilter(TenantId tenantId, CalculatedFieldFilter filter, PageLink pageLink);
}

9
dao/src/main/java/org/thingsboard/server/dao/sql/cf/CalculatedFieldRepository.java

@ -42,6 +42,15 @@ public interface CalculatedFieldRepository extends JpaRepository<CalculatedField
"AND (:textSearch IS NULL OR ilike(cf.name, CONCAT('%', :textSearch, '%')) = true)")
Page<CalculatedFieldEntity> findByTenantIdAndEntityIdAndTypes(UUID tenantId, UUID entityId, List<String> types, String textSearch, Pageable pageable);
@Query("SELECT cf FROM CalculatedFieldEntity cf WHERE cf.tenantId = :tenantId " +
"AND cf.type = :type " +
"AND cf.entityType IN :entityTypes " +
"AND (:entityIds IS NULL OR cf.entityId IN :entityIds) " +
"AND (:name IS NULL OR cf.name = :name) " +
"AND (:textSearch IS NULL OR ilike(cf.name, CONCAT('%', :textSearch, '%')) = true)")
Page<CalculatedFieldEntity> findByTenantIdAndFilter(UUID tenantId, String type, List<String> entityTypes,
List<UUID> entityIds, String name, String textSearch, Pageable pageable);
List<CalculatedFieldEntity> findAllByTenantId(UUID tenantId);
List<CalculatedFieldEntity> removeAllByTenantIdAndEntityId(UUID tenantId, UUID entityId);

12
dao/src/main/java/org/thingsboard/server/dao/sql/cf/JpaCalculatedFieldDao.java

@ -15,13 +15,16 @@
*/
package org.thingsboard.server.dao.sql.cf;
import com.google.common.base.Strings;
import jakarta.transaction.Transactional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldFilter;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.id.CalculatedFieldId;
import org.thingsboard.server.common.data.id.EntityId;
@ -102,6 +105,15 @@ public class JpaCalculatedFieldDao extends JpaAbstractDao<CalculatedFieldEntity,
return calculatedFieldRepository.countByTenantIdAndEntityIdAndTypeNot(tenantId.getId(), entityId.getId(), type.name());
}
@Override
public PageData<CalculatedField> findByTenantIdAndFilter(TenantId tenantId, CalculatedFieldFilter filter, PageLink pageLink) {
return DaoUtil.toPageData(calculatedFieldRepository.findByTenantIdAndFilter(tenantId.getId(), filter.getType().name(),
filter.getEntityTypes().stream().map(Enum::name).toList(),
CollectionUtils.isNotEmpty(filter.getEntityIds()) ? filter.getEntityIds() : null,
Strings.emptyToNull(filter.getName()),
pageLink.getTextSearch(), DaoUtil.toPageable(pageLink)));
}
@Override
protected Class<CalculatedFieldEntity> getEntityClass() {
return CalculatedFieldEntity.class;

Loading…
Cancel
Save