Browse Source

Merge pull request #15211 from dskarzh/feat/cf-additional-info

feat: add additionalInfo field to CalculatedField
pull/15212/head
Viacheslav Klimov 4 months ago
committed by GitHub
parent
commit
32d3fdeae8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 67
      application/src/main/data/upgrade/basic/schema_update.sql
  2. 4
      application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java
  3. 3
      application/src/test/java/org/thingsboard/server/edge/CalculatedFieldEdgeTest.java
  4. 2
      common/data/src/main/java/org/thingsboard/server/common/data/Customer.java
  5. 2
      common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java
  6. 2
      common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java
  7. 31
      common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java
  8. 1
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  9. 11
      dao/src/main/java/org/thingsboard/server/dao/model/sql/CalculatedFieldEntity.java
  10. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java
  11. 1
      dao/src/main/resources/sql/schema-entities.sql
  12. 4
      dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java
  13. 1
      ui-ngx/src/app/shared/models/calculated-field.models.ts

67
application/src/main/data/upgrade/basic/schema_update.sql

@ -14,69 +14,8 @@
-- limitations under the License.
--
-- UPDATE TENANT PROFILE CONFIGURATION START
-- CALCULATED FIELD ADDITIONAL INFO ADDITION START
UPDATE tenant_profile
SET profile_data = jsonb_set(
profile_data,
'{configuration}',
jsonb_build_object(
'minAllowedScheduledUpdateIntervalInSecForCF', 10,
'maxRelationLevelPerCfArgument', 2,
'maxRelatedEntitiesToReturnPerCfArgument', 100,
'minAllowedDeduplicationIntervalInSecForCF', 10,
'minAllowedAggregationIntervalInSecForCF', 60,
'intermediateAggregationIntervalInSecForCF', 300,
'cfReevaluationCheckInterval', 60,
'alarmsReevaluationInterval', 60
)
||
jsonb_strip_nulls(profile_data -> 'configuration')
)
WHERE NOT (
jsonb_strip_nulls(profile_data -> 'configuration') ?& ARRAY[
'minAllowedScheduledUpdateIntervalInSecForCF',
'maxRelationLevelPerCfArgument',
'maxRelatedEntitiesToReturnPerCfArgument',
'minAllowedDeduplicationIntervalInSecForCF',
'minAllowedAggregationIntervalInSecForCF',
'intermediateAggregationIntervalInSecForCF',
'cfReevaluationCheckInterval',
'alarmsReevaluationInterval'
]
);
ALTER TABLE calculated_field ADD COLUMN IF NOT EXISTS additional_info varchar;
-- UPDATE TENANT PROFILE CONFIGURATION END
-- CALCULATED FIELD UNIQUE CONSTRAINT UPDATE START
ALTER TABLE calculated_field DROP CONSTRAINT IF EXISTS calculated_field_unq_key;
ALTER TABLE calculated_field ADD CONSTRAINT calculated_field_unq_key UNIQUE (entity_id, type, name);
-- CALCULATED FIELD UNIQUE CONSTRAINT UPDATE END
-- CALCULATED FIELD OUTPUT STRATEGY UPDATE START
UPDATE calculated_field
SET configuration = jsonb_set(
configuration::jsonb,
'{output}',
(configuration::jsonb -> 'output')
|| jsonb_build_object(
'strategy',
jsonb_build_object(
'type', 'RULE_CHAIN'
)
),
false
)
WHERE (configuration::jsonb -> 'output' -> 'strategy') IS NULL;
-- CALCULATED FIELD OUTPUT STRATEGY UPDATE END
-- REMOVAL OF CALCULATED FIELD LINKS PERSISTENCE START
DROP TABLE IF EXISTS calculated_field_link;
ANALYZE calculated_field;
-- REMOVAL OF CALCULATED FIELD LINKS PERSISTENCE END
-- CALCULATED FIELD ADDITIONAL INFO ADDITION END

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

@ -18,6 +18,7 @@ package org.thingsboard.server.controller;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
@ -108,6 +109,7 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest {
assertThat(savedCalculatedField.getType()).isEqualTo(calculatedField.getType());
assertThat(savedCalculatedField.getName()).isEqualTo(calculatedField.getName());
assertThat(savedCalculatedField.getConfiguration()).isEqualTo(getSimpleCalculatedFieldConfig());
assertThat(savedCalculatedField.getAdditionalInfo()).isEqualTo(calculatedField.getAdditionalInfo());
assertThat(savedCalculatedField.getVersion()).isEqualTo(1L);
savedCalculatedField.setName("Test CF");
@ -115,6 +117,7 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest {
CalculatedField updatedCalculatedField = doPost("/api/calculatedField", savedCalculatedField, CalculatedField.class);
assertThat(updatedCalculatedField.getName()).isEqualTo(savedCalculatedField.getName());
assertThat(updatedCalculatedField.getAdditionalInfo()).isEqualTo(savedCalculatedField.getAdditionalInfo());
assertThat(updatedCalculatedField.getVersion()).isEqualTo(savedCalculatedField.getVersion() + 1);
doDelete("/api/calculatedField/" + savedCalculatedField.getId().getId().toString())
@ -322,6 +325,7 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest {
calculatedField.setType(cfType);
calculatedField.setName("Test Calculated Field for " + entityId);
calculatedField.setConfigurationVersion(1);
calculatedField.setAdditionalInfo(JacksonUtil.newObjectNode());
if (customConfiguration != null) {
calculatedField.setConfiguration(customConfiguration);
} else switch (cfType) {

3
application/src/test/java/org/thingsboard/server/edge/CalculatedFieldEdgeTest.java

@ -73,6 +73,7 @@ public class CalculatedFieldEdgeTest extends AbstractEdgeTest {
Assert.assertEquals(DEFAULT_CF_NAME, calculatedFieldFromMsg.getName());
Assert.assertEquals(savedDevice.getId(), calculatedFieldFromMsg.getEntityId());
Assert.assertEquals(config, calculatedFieldFromMsg.getConfiguration());
Assert.assertEquals(calculatedField.getAdditionalInfo(), calculatedFieldFromMsg.getAdditionalInfo());
edgeImitator.expectMessageAmount(1);
savedCalculatedField.setName(UPDATED_CF_NAME);
@ -229,6 +230,7 @@ public class CalculatedFieldEdgeTest extends AbstractEdgeTest {
config.setOutput(output);
calculatedField.setConfiguration(config);
calculatedField.setAdditionalInfo(JacksonUtil.newObjectNode());
return calculatedField;
}
@ -260,6 +262,7 @@ public class CalculatedFieldEdgeTest extends AbstractEdgeTest {
CalculatedField calculatedField = doGet("/api/calculatedField/" + uuid, CalculatedField.class);
Assert.assertNotNull(calculatedField);
Assert.assertEquals(resourceTitle, calculatedField.getName());
Assert.assertEquals(JacksonUtil.newObjectNode(), calculatedField.getAdditionalInfo());
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/Customer.java

@ -140,7 +140,7 @@ public class Customer extends ContactBased<CustomerId> implements HasTenantId, E
return super.getEmail();
}
@Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class)
@Schema(description = "Additional parameters of the customer",implementation = com.fasterxml.jackson.databind.JsonNode.class)
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();

2
common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java

@ -116,7 +116,7 @@ public class EntityView extends BaseDataWithAdditionalInfo<EntityViewId>
return super.getCreatedTime();
}
@Schema(description = "Additional parameters of the device", implementation = com.fasterxml.jackson.databind.JsonNode.class)
@Schema(description = "Additional parameters of the entity view", implementation = com.fasterxml.jackson.databind.JsonNode.class)
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();

2
common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java

@ -164,7 +164,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId, HasTi
return super.getEmail();
}
@Schema(description = "Additional parameters of the device", implementation = com.fasterxml.jackson.databind.JsonNode.class)
@Schema(description = "Additional parameters of the tenant", implementation = com.fasterxml.jackson.databind.JsonNode.class)
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();

31
common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java

@ -17,15 +17,15 @@ package org.thingsboard.server.common.data.cf;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasAdditionalInfo;
import org.thingsboard.server.common.data.HasDebugSettings;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
@ -39,7 +39,6 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.validation.Length;
import org.thingsboard.server.common.data.validation.NoXss;
import java.io.Serial;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
@ -48,10 +47,7 @@ import java.util.Set;
@Schema
@Data
@EqualsAndHashCode(callSuper = true)
public class CalculatedField extends BaseData<CalculatedFieldId> implements HasName, HasTenantId, HasVersion, HasDebugSettings {
@Serial
private static final long serialVersionUID = 4491966747773381420L;
public class CalculatedField extends BaseData<CalculatedFieldId> implements HasName, HasTenantId, HasVersion, HasDebugSettings, HasAdditionalInfo {
public static final Map<EntityType, Set<CalculatedFieldType>> SUPPORTED_ENTITIES = Map.of(
EntityType.DEVICE, CalculatedFieldType.all,
@ -90,28 +86,17 @@ public class CalculatedField extends BaseData<CalculatedFieldId> implements HasN
@Valid
@NotNull
private CalculatedFieldConfiguration configuration;
@Getter
@Setter
private Long version;
@NoXss
@Schema(description = "Additional parameters of the calculated field")
private JsonNode additionalInfo;
public CalculatedField() {
super();
}
public CalculatedField() {}
public CalculatedField(CalculatedFieldId id) {
super(id);
}
public CalculatedField(TenantId tenantId, EntityId entityId, CalculatedFieldType type, String name, int configurationVersion, CalculatedFieldConfiguration configuration, Long version) {
this.tenantId = tenantId;
this.entityId = entityId;
this.type = type;
this.name = name;
this.configurationVersion = configurationVersion;
this.configuration = configuration;
this.version = version;
}
public CalculatedField(CalculatedField calculatedField) {
super(calculatedField);
this.tenantId = calculatedField.tenantId;
@ -123,6 +108,7 @@ public class CalculatedField extends BaseData<CalculatedFieldId> implements HasN
this.configurationVersion = calculatedField.configurationVersion;
this.configuration = calculatedField.configuration;
this.version = calculatedField.version;
this.additionalInfo = calculatedField.additionalInfo;
}
@Schema(description = "JSON object with the Calculated Field Id. Referencing non-existing Calculated Field Id will cause error.")
@ -159,6 +145,7 @@ public class CalculatedField extends BaseData<CalculatedFieldId> implements HasN
.append(", name='").append(name)
.append(", configurationVersion=").append(configurationVersion)
.append(", configuration=").append(configuration)
.append(", additionalInfo=").append(additionalInfo)
.append(", version=").append(version)
.append(", createdTime=").append(createdTime)
.append(", id=").append(id).append(']')

1
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -730,6 +730,7 @@ public class ModelConstants {
public static final String CALCULATED_FIELD_CONFIGURATION_VERSION = "configuration_version";
public static final String CALCULATED_FIELD_CONFIGURATION = "configuration";
public static final String CALCULATED_FIELD_VERSION = "version";
public static final String CALCULATED_FIELD_ADDITIONAL_INFO = ADDITIONAL_INFO_PROPERTY;
/**
* Tasks constants.

11
dao/src/main/java/org/thingsboard/server/dao/model/sql/CalculatedFieldEntity.java

@ -36,6 +36,7 @@ import org.thingsboard.server.dao.util.mapping.JsonConverter;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.CALCULATED_FIELD_ADDITIONAL_INFO;
import static org.thingsboard.server.dao.model.ModelConstants.CALCULATED_FIELD_CONFIGURATION;
import static org.thingsboard.server.dao.model.ModelConstants.CALCULATED_FIELD_CONFIGURATION_VERSION;
import static org.thingsboard.server.dao.model.ModelConstants.CALCULATED_FIELD_ENTITY_ID;
@ -81,9 +82,11 @@ public class CalculatedFieldEntity extends BaseVersionedEntity<CalculatedField>
@Column(name = DEBUG_SETTINGS)
private String debugSettings;
public CalculatedFieldEntity() {
super();
}
@Convert(converter = JsonConverter.class)
@Column(name = CALCULATED_FIELD_ADDITIONAL_INFO)
private JsonNode additionalInfo;
public CalculatedFieldEntity() {}
public CalculatedFieldEntity(CalculatedField calculatedField) {
this.setUuid(calculatedField.getUuidId());
@ -97,6 +100,7 @@ public class CalculatedFieldEntity extends BaseVersionedEntity<CalculatedField>
this.configuration = JacksonUtil.valueToTree(calculatedField.getConfiguration());
this.version = calculatedField.getVersion();
this.debugSettings = JacksonUtil.toString(calculatedField.getDebugSettings());
this.additionalInfo = calculatedField.getAdditionalInfo();
}
@Override
@ -111,6 +115,7 @@ public class CalculatedFieldEntity extends BaseVersionedEntity<CalculatedField>
calculatedField.setConfiguration(JacksonUtil.treeToValue(configuration, CalculatedFieldConfiguration.class));
calculatedField.setVersion(version);
calculatedField.setDebugSettings(JacksonUtil.fromString(debugSettings, DebugSettings.class));
calculatedField.setAdditionalInfo(additionalInfo);
return calculatedField;
}

2
dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java

@ -74,6 +74,7 @@ public class DefaultNativeCalculatedFieldRepository implements NativeCalculatedF
JsonNode configuration = JacksonUtil.toJsonNode((String) row.get("configuration"));
long version = row.get("version") != null ? (long) row.get("version") : 0;
String debugSettings = (String) row.get("debug_settings");
JsonNode additionalInfo = JacksonUtil.toJsonNode((String) row.get("additional_info"));
CalculatedField calculatedField = new CalculatedField();
calculatedField.setId(new CalculatedFieldId(id));
@ -91,6 +92,7 @@ public class DefaultNativeCalculatedFieldRepository implements NativeCalculatedF
}
calculatedField.setVersion(version);
calculatedField.setDebugSettings(JacksonUtil.fromString(debugSettings, DebugSettings.class));
calculatedField.setAdditionalInfo(additionalInfo);
return calculatedField;
}).collect(Collectors.toList());

1
dao/src/main/resources/sql/schema-entities.sql

@ -935,6 +935,7 @@ CREATE TABLE IF NOT EXISTS calculated_field (
configuration varchar(1000000),
version BIGINT DEFAULT 1,
debug_settings varchar(1024),
additional_info varchar,
CONSTRAINT calculated_field_unq_key UNIQUE (entity_id, type, name)
);

4
dao/src/test/java/org/thingsboard/server/dao/service/CalculatedFieldServiceTest.java

@ -17,6 +17,7 @@ package org.thingsboard.server.dao.service;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.cf.CalculatedField;
@ -74,6 +75,7 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
assertThat(savedCalculatedField.getType()).isEqualTo(calculatedField.getType());
assertThat(savedCalculatedField.getName()).isEqualTo(calculatedField.getName());
assertThat(savedCalculatedField.getConfiguration()).isEqualTo(calculatedField.getConfiguration());
assertThat(savedCalculatedField.getAdditionalInfo()).isEqualTo(calculatedField.getAdditionalInfo());
assertThat(savedCalculatedField.getVersion()).isEqualTo(1L);
savedCalculatedField.setName("Test CF");
@ -81,6 +83,7 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
CalculatedField updatedCalculatedField = calculatedFieldService.save(savedCalculatedField);
assertThat(updatedCalculatedField.getName()).isEqualTo(savedCalculatedField.getName());
assertThat(updatedCalculatedField.getAdditionalInfo()).isEqualTo(savedCalculatedField.getAdditionalInfo());
assertThat(updatedCalculatedField.getVersion()).isEqualTo(savedCalculatedField.getVersion() + 1);
calculatedFieldService.deleteCalculatedField(tenantId, savedCalculatedField.getId());
@ -281,6 +284,7 @@ public class CalculatedFieldServiceTest extends AbstractServiceTest {
calculatedField.setName("Test Calculated Field");
calculatedField.setConfigurationVersion(1);
calculatedField.setConfiguration(getCalculatedFieldConfig(referencedEntityId));
calculatedField.setAdditionalInfo(JacksonUtil.newObjectNode());
return calculatedField;
}

1
ui-ngx/src/app/shared/models/calculated-field.models.ts

@ -38,6 +38,7 @@ export const FORBIDDEN_NAMES = ['ctx', 'e', 'pi'];
interface BaseCalculatedField extends Omit<BaseData<CalculatedFieldId>, 'label'>, HasVersion, HasEntityDebugSettings, HasTenantId, ExportableEntity<CalculatedFieldId> {
entityId: EntityId;
additionalInfo?: any;
}
export interface CalculatedFieldSimple extends BaseCalculatedField {

Loading…
Cancel
Save