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

Notion image

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}}
Β 
πŸ’‘
Per entity the json structure is as defined in the Rest API Reference can be found.
πŸ’‘

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 objects

Meta 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 entity
Β 

fields

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"
      }
    ]
  }
}
Β 
Β 
Did this answer your question?
😞
😐
🀩

Last updated on December 27, 2022