Definitions - Basics
What
Definitions are templates for creating entities and related entities in a standardised way.
Definitions are available for:
- Access Point
- Asset
- Contract
- Party
- Account
- Address
- Contact
- Site
- Timeseries
Where

Configuration of the different types of Definitions can be found in the ADMIN Portal under the Configuration menu item. The level of Definitions you have access to is based on your authorizations in byNeuron ENERGY.
Standard Structure of a Definition
Attributes:
- name
- externalId
- description
- type
- role
- metaCodes [ ]
- metaIndexSetCodes [ ]
- metaKeywords [ ]
- metaDatetimes [ ]
- metaValues [ ]
- metaBooleans [ ]
- Data: { }
Links:
- isExtensionOf: EntityDefinition β Definitions can be extended on other definitions
- hasFeature: Item
Data JSON object
The data json object contains the template for creating the entity and defines the required inputs for that template. It can also contain meta data which influences the visualisation in the screen of the entity created with this definition.
Properties
Name | Type | Values | Description |
overrideDefinitionLink | boolean | true,false | If true, overrides an existing definition link of an entity when updating with this definition. Will use this definition to calculate 'valid' state of the entity (see valid section for more information) |
description | string | If set, a box with the description will be shown above the form | |
inputDefinitions | list of object | Defines the inputs which can provided when creating or updating the entity from a definition | |
> id | string | The id is used when providing the input in the API call and when using the input as a variable in the entity template with following syntax: {{someInput}} | |
> label | string | The label is shown in the screen when rendering the input form for this definition | |
> tooltip | string | The tooltip will show a (?) icon, which will show the tooltip when hovering over. | |
> defaultValue | The defaultValue will be applied when no input is provided. Constant variables {{today}}, {{now}} and {{userId}} can also be used as defaultValue.
This applicable for all types, except group, entity and object
One can also map a fixed object or array to defaultValue, eg [{ "key1": "value11", "key2": "value21"
},{ "key1": "value12", "key2": "value22"
} ] which can further on be iterated.
For type entity, defaultValue must be set to [], in case a filter is defined. | ||
> type | enum | string,long,boolean,date,enum,entity,object,group,number,datetime, file | The type defines what kind of data is provided with this input and dictates the rendering of the input form for this definition. Also it defines the possible validation configurations.
Type entity and object inputs always need to be provided as a list and is currently only supported in the backend API's.
Type group is only used for rendering purposes and will be ignored by backend. For type group, a list of fields must be specified.
Type file is only used for front-end actions to upload a file and will be ignored by backend. |
> entityType | string | Only applicable for type entity, the entityType defines which entity can be provided with this input:
- AccessPoint, Agreement (Contract), Device (Asset), Document, Form, Invoice, Item (Timeseries), Party, Place (Site), Product | |
> viewType | string | table,form | Determines how to render an input definition of type entity or object |
> fields | list of string | Used in combination with type group. Specifies a list of id's of input definitions. This will be rendered in the form as a 'fieldset'. | |
>> options | list of object | Only applicable for type enum | |
>>> id | string | The id of an option is used when providing the input in the API call and can be used as variable in the entity template with following syntax: {{someInput.id}} | |
>>> name | string | The name of an option is shown in the screen when rendering the input form for this definition. It is also the default when using the input as a variable in the entity template with following syntax: {{someInput}}. Explicitly the name can also be used as variable like this: {{someInput.name}} | |
> validations | list of object | Specifies validations that are checked when providing the input.
> The input form in the screen will check all validations except the filter validation.
> In the backend API's all validations are checked.
> Currently the FE expects always this elements. If no validations are applicable use an empty array: "validations": []
See the section 'validations' for more information | |
> rules | list of object | Specifies rules that are checked with every change in the form. Rules are conditions which trigger action(s) (isVisible , isDisabled)
See the section βrulesβ for more information | |
> inputDefinitions | list of object | Specifies nested inputs. For example an input 'person' can have nested inputs with name, eyeColor and favoriteFood.
Nested input definitions are currently only supported in the backend API's, it will not be rendered in the input form in the screen | |
entity | object | The key of this object is the entity known in the backend API's, and defines the template of creating the entity. It follows the structure of the API objects.
In this template input definitions can be referenced with the syntax {{ }}.
Type entity and object can be referenced in lists with #someInputList. In which there will be iterated over each entry in the input list. Within this list nested input definitions are also accessible, eg:
"relatedAssets#someInputList": [
{
"asset": {
"externalId": "{{someNestedInput}}"
},
"sourceRole": "DEFAULT",
"targetRole": "METER"
}
] | |
metaData | object | Meta data specifies how to render extensions in the detail screen of an entity. Default this section is called 'Additional'. In this meta data configuration you can define groups and fields. | |
> groups | list of object | ||
>> id | string | ||
>> label | string | ||
>> order | number | ||
>> collapsed | boolean | ||
> fields | list of object | ||
> createNewFields | boolean | ||
layout | object | This layout configuration specifies how to render the input definition. If not specified, by default a vertical form is rendered with all the input definition from top to bottom. | |
> variant | enum | stepper | This specifies the configured variant of the layout. Currently only stepper is implemented. |
> orientation | enum | vertical,horizontal | This determines to show the stepper vertically or horizontally. |
> elements | list of object | In case of the stepper, each element is step and contains the data to render the step. | |
>> id | string | Unique id of the element | |
>> label | string | Label of the element | |
>> icon | string | Icon of the element (not yet implemented) | |
>> description | string | Description of the element, will be displayed above the form of this element | |
>> fields | list of string | List of fields which should be rendered within this element. |
Validations
Name | Config | Types | Description |
required | true or false | all | True, if input is required when using the definition |
allowSkipRequired | true or false | all | True, if required input can be skipped. If skipped, the entity valid state will be updated to 'false' |
readonly | true or false | all | True, if input is readonly |
minlength | numeric value | string | Minimum length of a string |
maxlength | numeric value | string | Maximum length of a string |
regex | regex expression | string | String must match the regular expression |
min | numeric value | number,entity,object | Minimum numeric value
If set on a input of type entity or object, it specifies the minimum number of entities required - for entity this is after applying the filter validation. |
max | numeric value | number,entity,object | Maximum numeric value
If set on a input of type entity or object, it specifies the maximum number of entities or objects required - for entity this is after applying the filter validation. If max = 1 is specified a list of one object or entity can be provided |
filter | object | entity | Specifies a query filter which the provided entity must match, if not matched the entity is discarded. The specification of this query filter can be found in the API documentation
When using on backend, the filter can also used to lookup additional data without providing the input, important is to set the defaultValue to an empty array [ ]. This data can then again be used as input for other filters or in the entity template. |
Filters
- Filter timeseries based on owner (Entity)
The purpose of this filter is to retrieve all timeseries that have a certain Entity as owner, meaning the owner (Entity) has a link hasFeature to the timeseries. Owner can be Asset, Partyβ¦.
Example
[
{
"filter": {
"links": [
{
"matches": "owners",
"ownerType": "Asset",
"attributes": [
{
"attribute": "id",
"operator": "equals",
"values": [
"df5c9561-0a76-49ac-8bc5-e5d76c545a4a"
]
},
{
"attribute": "externalId",
"operator": "equals",
"values": [
"dsmrAC67B23BFA7C"
]
}
]
}
]
}
}
]Rules
An input definition can contain rules which triggers actions based on specific conditions. See example below.
{
"id": "businessType",
"label": "Rechtsvorm",
"type": "enum",
"options": [
{
"id": "BESLOTEN_VENNOOTSCHAP",
"name": "B.V."
},
{
"id": "NAAMLOZE_VENNOOTSCHAP",
"name": "N.V."
},
{
"id": "VERENIGING_VAN_EIGENAARS",
"name": "Vereniging van Eigenaars"
},
{
"id": "UNKNOWN",
"name": "Zakelijk, rechtsvorm niet bekend"
}
],
"validations": [],
"rules": [ //this input will be rendered visible when partyType input equals ORGANIZATION.
{
"conditions": [ //multiple conditions can be specified and are interpreted as 'AND', aka all conditions must be true to trigger the action
{
"id": "partyType",
"operator": "equals",
"values": [
"ORGANIZATION"
]
}
],
"actions": [ //multiple actions can be specified and will all be applied when the conditions are met
{
"action": "isVisible" //possible actions: isVisible, isDisabled
"value": "true"
}
]
}
]
},Entity template
Defines how to create or update an entity via the API. Variables can be used as dynamic parts in the template. In the example below: {{ean}} and {{productType.id}} are variables which are identified as the input definitions.
Variables:
- Input definitions
- Referenced by id:
{{someInput}} - Type enum value of input can be referenced by id or name:
{{someInput.id}}-{{someInput.name}}
- Constants:
- Current date (in local timezone of tenant):
{{today}} - Timestamp of start of day (of timezone of tenant):
{{today.start.of.day}} - Current timestamp (in UTC):
{{now}} - Current logged in user (e-mail address):
{{userId}}
As the API request also has an 'action' property with create_if_not_exists and update_if_exists. You can also use this in definitions.
- For example when creating a new entity, and providing the externalId, if no action is provided, it will return an error if the entity with this external ID already exists. When the action update_if_exists is provided, it will not return an error but instead updates the existing entity with this external ID.
- actions:
activate, Β -> set flag active true
create -> only create, error if exists
create_if_not_exists -> β, but no error
deactivate -> set flag active false
delete -> delete entity
update β update, error if not exists
update_if_exists -> ony update if exists
upsert -> create and update a POST will always try a create but if the entity exists, it will give an error. By using action update_if_exists you will not generate an error but behave as a patch
"accessPoint": {
"name": "{{ean}}",
"description": "{{accessPointType.name}} Access Point created by {{userId}} at {{now}}"
"identification": {
"externalId": "{{ean}}"
},
"type": "{{accessPointType.id}}",
"relatedParties#partyList": [
{
"party": {
"externalId": "{{cocNumber}}"
},
"sourceRole": "DEFAULT",
"targetRole": "DEFAULT",
"fromDate": "{{today}}"
}
]
}Batch Request
When using the batchRequest syntax, you can iterate over an input list and create multiple (of the same type) entities at once.
"batchRequest": { //this enables to iterate to create multiple entities
"party#customers": [ //here you can use #inputlist to specify the input which contains the list.
{
"idGeneration": [
"publicId"
],
"type": "{{type.id}}",
"roles": [
"CUSTOMER"
],
"name": "{{name}}"
}
]
}Example - Create a party for every entry in the input list of customers and use the nested input definitions as variables.
{
"inputDefinitions": [
{
"id": "customerName",
"label": "Customer Name",
"type": "string"
},
{
"id": "customers",
"label": "Customers",
"type": "object",
"asObject": false, // default if true -> the entity is returned instead of the id
"inputDefinitions": [
{
"id": "type",
"label": "Customer Type",
"type": "enum",
"options": [
{
"id": "PERSON",
"name": "Person"
},
{
"id": "ORGANIZATION",
"name": "Organization"
}
],
"validations": [
{
"name": "required",
"config": "true"
}
]
},
{
"id": "name",
"label": "Name",
"type": "string",
"validations": [
{
"name": "required",
"config": "true"
}
]
}
]
}
],
"batchRequest": {
"party#customers": [
{
"idGeneration": [
"publicId"
],
"type": "{{type.id}}",
"roles": [
"CUSTOMER"
],
"name": "{{name}}"
}
]
}
}Passing arrayβs and objects
"shift": "{{unquote}}{{{shift}}}{{unquote}}", -> search and replace puts shift as object
"workers#workers": ["{{unquote}}{{{this}}}{{unquote}}"] -> search and replace puts array of workers objectsMeta Data
The metaData {} object defines how you group the attribute extensions on the entity and defined the attribute extensions.
groups
"groups": [
{
"id": "edsnGeneral", -> groupId
"label": "General", -> the label as how it is shown in the Front-End on the entity detail screen
"order": 1, -> order in the structure
"collapsed": false -> whether the group should be collapsed or not (either true or false)
}
]createNewFields
"createNewFields": false -> whether new attributes can be added as extension on the entityfields
Possible types:
- Keyword
- Tenant Code
- Boolean
- Date Time
- Text
- Number
"fields": [
{
"key": "edsnProductType", -> the key of the attribute
"type": "Tenant Code", -> defines the type of the attribute
"codeType": "edsnProductType", -> codeType needs to be provided in case "type" is "Tenant Code"
"defaultValue": "edsnProductType#ELK", -> only used in case a entity has timesliced details, when adding the initial timeslice, default values are applied. In case of an Tenant Code, the value need to include codeType#
"list": false,
"order": 1,
"label": "Product", -> the label how the attribute is shown in the Front-End on the entity detail screen
"groupId": "edsnGeneral", -> to which "group" this attribute is added
"badge": "primary" -> which badge color is used, choices are primary, warning, danger, success. In case a entity has timesliced details, fields with a badge will be shown as columns
}
]Layout
Layout is an object in the definition data which can determine the rendering of the form. If no layout is specified, default all input definitions are listed in 1 form.
Example Layout for stepper with four steps
"layout": {
"variant": "stepper", //specifies the variant of the layout. Currently only stepper is implemented, can be extended in future to 'tabs', 'accordion', ...
"orientation": "vertical", //specifies if the stepper is displayed vertically or horizontally
"elements": [ //the elements array contains the steps
{
"id": "customerData", //id of the step
"label": "Enter customer data", //label of the step
"icon": "eva person-outline", //icon of the step
"description": "Please provide the name of the customer", //description of the step (displayed above the form in the step)
"fields": [ //list of fields which should be displayed in this step, this references id's of input definitions.
"firstName",
"lastName",
"birthInformation"
]
},
{
"id": "contactDetails",
"label": "Enter contact details",
"icon": "eva at-outline",
"description": "Please provide the contact details for this customer",
"fields": [
"phoneNumber",
"email",
"communicationPreference"
]
},
{
"id": "paymentInformation",
"label": "Enter customer payment information",
"icon": "eva credit-card-outline",
"description": "Enter the payment information, this can also provided later",
"fields": [
"creditCardNumber",
"creditCardValidUntil"
]
},
{
"id": "customers",
"label": "Add Related Customers",
"icon": "eva credit-card-outline",
"description": "Add here the related customers",
"fields": [
"relatedCustomers"
]
}
]
}Valid calculation logic
- Default an entity is always created as valid
- When setting '
allowSkipRequired' to true, it means that a required input can be skipped but with the consequence that the entity remains invalid until the required input is provided
- Valid state is also calculated in nested situations, when another entity is created from definition within the template of a definition
- Example:
- Given a definition of an asset, in which also the timeseries of this asset are created by definition.
- Then if the timeseries created by their definition results in a invalid state, also the asset becomes invalid
Example Asset Definition
{
"inputDefinitions": [
{
"id": "someRequiredInput",
"label": "I am required, but I can be skipped",
"type": "string",
"validations": [
{
"name": "required",
"config": "true"
},
{
"name": "allowSkipRequired",
"config": "true"
}
]
}
],
"asset": {
"name": "{{someRequiredInput}}",
"timeseries": [
{
"definition": {
"identification": {
"externalId": "SOME_TIMESERIES_DEFINITION" //has a required input, but is not provided
}
"inputs": {}
}
}
]
}
}Variables
Input definitions can be mapped as variables in the template. There are several ways to use variables.
Variables are using the mustache syntax. More information can be found here: https://mustache.github.io/mustache.5.html
Map the value of an input
"{{someInputString}}"
"{{someInputEnum.id}}"
"{{someInputEnum.name}}"Map a list of an input
A list of input can be used with input definition type 'object' and 'entity'.
Currently an input definition id can only occur once in the whole definition, this means that also nested inputs needs to be unique.
"timeseries#someInputList": [ //the input list will be iterated and for each entry an array object is created
{
"identification": {
"id": "{{id}}" //id input within the input list entry
}
}
]Use a value of an input as a condition for setting an attribute
A # means the input key exists, a ^ means the input key does not exist. Do not forget to 'close' the statement with /
"active": "{{#someInput}}true{{/someInput}}{{^someInput}}false{{/someInput}}"Use a value of an input as a condition for processing an object or array
Is similar as with mapping a list of an input, but now uses a single input value to determine to create the array or object.
In the case below the whole timeseries array and the gateway object will be skipped if someInputValue is not provided as input.
- If the input variable is a list, it will process it as described above.
"timeseries#someInputValue": [ //if someInputValue exists, then the timeseries array (with one element) is constructed
{
"identification": {
"externalId": "BLA_BLA"
},
"name": "{{someOtherInput}}"
}
],
"gateway#someInputValue": { //if someInputValue exists, then the gateway object is constructed
"identification": {
"externalId": "SOME_GATEWAY_EXT_ID"
},
...
}Convert date(time) variables
- Date conversions from date to datetime and vice versa
"date": "{{#toLocalDateTenantZone}} {{myDateTimeInput}} {{/toLocalDateTenantZone}}",
"date": "{{#toLocalDateUtc}} {{myDateTimeInput}} {{/toLocalDateUtc}}",
"date": "{{#toLocalDate}} {{myDateTimeInput}} {{/toLocalDate}}"
"creationDateTime": "{{#toDateTimeUtc}} {{myDateInput}} {{/toDateTimeUtc}}",
"creationDateTime": "{{#toDateTimeTenantZone}} {{myDateInput}} {{/toDateTimeTenantZone}}",
"creationDateTime": "{{#toDateTime}} {{myDateInput}} {{/toDateTime}}"Example
"inputDefinitions": [
{
"id": "ean",
"label": "EAN",
"type": "string",
"validations": [
{
"name": "required", -> name of the validation //in this case whether the attribute is required to be filled in
"config": "true" -> configuration of the validation rule
},
{
"name": "minlength",
"config": "18"
},
{
"name": "maxlength",
"config": "18"
},
{
"name": "regex",
"config": "^[0-9]{18}$"
}
]
}
]Example
Example Access Point Definition:
{
"overrideDefinitionLink": true,
"inputDefinitions": [
{
"id": "ean",
"label": "EAN",
"type": "string",
"validations": [
{
"name": "required",
"config": "true"
},
{
"name": "minlength",
"config": "18"
},
{
"name": "maxlength",
"config": "18"
},
{
"name": "regex",
"config": "^[0-9]{18}$"
}
]
},
{
"id": "productType",
"label": "Product Type",
"type": "enum",
"defaultValue": "",
"options": [
{
"id": "ELK",
"name": "ELECTRICITY"
},
{
"id": "GAS",
"name": "GAS"
}
],
"validations": [
{
"name": "required",
"config": "true"
}
]
}
],
"accessPoint": {
"name": "{{ean}}",
"identification": {
"externalId": "{{ean}}"
},
"type": "{{productType::name}}"
},
"metaData": {
"groups": [
{
"id": "edsnGeneral",
"label": "General",
"order": 1,
"collapsed": false
},
{
"id": "edsnMeter",
"label": "Energy Meter",
"order": 2,
"collapsed": true
}
],
"createNewFields": false,
"fields": [
{
"key": "edsnProductType",
"type": "Tenant Code",
"codeType": "edsnProductType",
"list": false,
"order": 1,
"label": "Product",
"groupId": "edsnGeneral",
"badge": "primary"
},
{
"key": "edsnMarketSegment",
"type": "Tenant Code",
"codeType": "edsnMarketSegment",
"list": false,
"order": 3,
"label": "Market Segment",
"groupId": "edsnGeneral"
},
{
"key": "edsnGridArea",
"type": "Keyword",
"list": false,
"order": 2,
"label": "Grid Area",
"groupId": "edsnGeneral"
},
{
"key": "edsnEnergyMeterType",
"type": "Tenant Code",
"codeType": "edsnEnergyMeterType",
"list": false,
"order": 3,
"label": "Energy Meter Type",
"groupId": "edsnMeter"
},
{
"key": "edsnEnergyMeterTechnicalCommunicationSM",
"type": "Tenant Code",
"codeType": "edsnEnergyMeterTechnicalCommunicationSM",
"list": false,
"order": 3,
"label": "Technical Commmunication Smart Meter",
"groupId": "edsnMeter"
}
]
}
}Last updated on December 27, 2022