Advanced settings - Step by Step
With Advanced settings for Custom Fields functionality you can:
1) create new data structures :
-
Add New Dimensions
-
Add new Properties
-
Add new Measures
-
Add new Hierarchies
-
Add new Data cubes (See Example HERE)
2) define custom views and advanced sharing
-
Share measures between data cubes
-
Define Custom Drill Options
What is a considered as a "custom field" for flex.bi ?
-
field in Source system that is not imported in flex.bi by default
For example : Custom Field that is customer specific -
transaction Register Field in Source system that is not imported in flex.bi by default,
For example : Custom Module that is customer specific and is based on customer register -
any addition data structure that exists in Source system that needs be used in flex.bi as dimension/ Measures or property etc. in reports
Where to find Advanced settings ?
Advanced settings is a section in flex.bi applications that allow you to define custom data input for flex.bi data cubes, create new data cubes and adjust them.
How to use this function?
STEP 1
Define what you want to add in “Advanced settings” sectioning XXX language.
Custom field Code has to be described in blocks and organised based on type
STEP 2
Select in Cube Properties section — Custom Fields section what you want to import and how.
Advanced setting key components & detailed instructions example for Standard ERP
Below is a description of necessary parameters to define simple custom fields and a description of the process by steps.
1. Find the field name
First, you need to find out the register and REST API code for the field. You can find codes for registers in the HansaWorld source File import documentation page. Then you can use the code to find code for REST API field in HansaWorld Module Technics → Reports → Import/Export format.
You can see in the example screenshot below the register code (1.) and codes for REST API fields (2.).
2. Configure custom field settings
2.1 General custom field structure
Every custom field definition starts with a header identifying the source and the field:
[register_code.register_rest_api_code]
register_code identifies the source register or table; register_rest_api_code identifies the specific field or column within it — a REST API field code for REST-based connections, or a database column code for database-based ones. This opens the block of configuration parameters for that field.
Within that block, you need to give the field a unique name. This is normally just a human-readable label. There are a couple of exceptions where it takes on a more specific role: when defining a measure, name becomes the measure's name; when defining a dimension with dimension = true, it becomes the dimension's name.
name = "Price"
You also need to specify cube_name, the cube the field belongs to. This can name an existing cube — the full names are visible in the Analyze section — or a name for a new cube.
cube_name = "HansaWorld Invoices"
If the field's value isn't a plain string, you need to set data_type — one of string, text, integer, decimal, date, datetime, array.
data_type = "string"
-
stringdefaults to a 255-character maximum; uselimitto raise it. -
decimaldefaults to precision 15, scale 2; override withprecisionandscale. -
Fields flagged
key_field,name_field, orbind_fieldare recognized as strings automatically, sodata_typecan be omitted for them. -
If
data_typeis not specified, it defaults tostring, with these exceptions:-
For a measure (
measure = true), the default isdecimal. -
For a field binding to the standard Time dimension (
for_standard_dimension = "Time"), the default isdate. -
For a measure using
unique_count_measure_dimensions, the default isinteger.
-
If the source field name contains a full stop (.), or the same source field needs to be referenced by more than one custom field, you can set rest_api_field to specify which field this custom field actually reads its value from, instead of relying on the field's own code (the part after the dot in the header).
rest_api_field = 'T.NAME'
2.2 Defining a Measure
In order to define a measure, you need to add measure = true to a custom field.
measure = true
This example imports a Sales Order's amount field as a measure called "Order Amount":
[ORVc.Amount]
name = "Order Amount"
cube_name = "HansaWorld Sales Orders"
data_type = "decimal"
measure = true
2.3 Defining Dimensions and Hierarchy
A dimension is assembled from up to three fields: one that holds its key, one that acts as its bind — linking the dimension to the measures that use it — and, optionally, one that holds its name. The key and bind fields are always required; if the name field is skipped then members are simply labeled by their key.
If record's source data returns an empty value for key_field or name_field, flex.bi falls back by filling this value with "(none)".
dimension_name field ties them together — it's what tells flex.bi these separate field definitions describe one dimension, and it creates that dimension if it doesn't exist yet.
dimension_name = "Invoice"
level_name is optional and is only needed if that dimension has more than one level. If it's left unset, the dimension has a single level whose name matches dimension_name.
level_name = "Invoice Item"
Example of a key field is marked with key_field = true:
[INVc.item_code]
name = 'Item Code'
dimension_name = 'Item'
cube_name = "HansaWorld Invoices"
rest_api_field = "Code"
key_field = true
Example of a name field, if you define one, is marked with name_field = true:
[INVc.item_name]
name = 'Item Name'
dimension_name = 'Item'
cube_name = "HansaWorld Invoices"
name_field = true
rest_api_field = "Name"
The bind field lives on the measures register rather than the dimension's own register, and does the actual linking: bind_field_name points at the key field's code, and for_custom_dimension names the dimension being bound to. If that bind value only shows up at item/row level, add rest_api_item_field too.
[IVVc.item_code_bind]
name = 'Item Code bind'
cube_name = "HansaWorld Invoices"
for_custom_dimension = 'Item'
rest_api_item_field = "rows"
bind_field_name = 'item_code'
rest_api_field = 'ArtCode'
Note: don't use for_custom_dimension to self-bind a register to its own dimension (one it also defines key_field/name_field for).
Put together, these three fields create a new "Item" dimension sourced from the Invoices register itself, with its own code and name, bound to the invoice item rows it applies to.
When the dimension you're binding to is a standard dimension which flex.bi provides without any custom fields, key_field and name_field field definitions are not needed — just swap for_custom_dimension for for_standard_dimension on the bind field (with for_standard_dimension_level for a multi-level one).
for_standard_dimension = "Customer"
for_standard_dimension_level = "Customer"
2.4 Defining a Property
In order to define a property, you need to add property = true to a custom field. This marks it as a plain descriptive attribute on a dimension member — extra information available for reference, but not something you can slice or measure by.
This example adds the customer's VAT number as a property on the Customer dimension:
[TDdmKlBaseSar.customer_pvn_reg_no]
name = 'VAT Registration No'
dimension_name = 'Customer'
cube_name = 'Horizon Financials'
rest_api_field = "K.PVN_REGNR"
property = true
2.5 Virtual dimensions
A virtual dimension can be used when there is no separate register or table for the dimension, or no distinct name field is available. If the dimension needs a hierarchy, a separate key and name, or additional properties, you need to define it in a separate table instead (see flex.bi Custom Fields).
A virtual dimension does not have a separate database table — it is created directly from a property field on the measures table.
Known limitations, not limited to the following:
-
Properties cannot be added to the dimension members.
-
The dimension cannot have multiple levels.
-
The dimension can only consist of one field's value.
To create a virtual dimension use this parameter:
dimension = true
This example will create a new dimension called "Language code" based on ORVc register's LangCode field:
[ORVc.LangCode]
name = "Language code"
cube_name = "HansaWorld Sales Orders"
data_type = "string"
dimension_name = "Sales Order"
level_name = "Sales Order"
dimension = true
2.6 javascript
In order to run custom logic on incoming data before it's imported — transforming, computing, filtering, or mapping values — you can add javascript_code to a custom field. doc refers to the header record; doc.rows is the array of line items. If the field uses rest_api_field to read its value, any javascript_code on that field must reference that name too, not the field's own code.
This example turns each Quotation row's gross profit negative:
[QTVc.negative_rowGP]
name = "Quotation negative GP"
cube_name = "HansaWorld Quotations"
data_type = "decimal"
rest_api_item_field = "rows"
measure = true
javascript_code ='''
if (doc.rows) {
doc.rows.forEach(function(row){
row.negative_rowGP = String(Number(row.rowGP) * -1);
})
}
'''
If the field is calculated entirely in javascript_code, or its value has already been requested by another custom field, you need to add skip_request to skip the dedicated request for this field's own value.
skip_request = true
This example maps customer type boolean value into a readable type:
[TDdmKlBaseSar.customer_type_name]
cube_name = 'Horizon Financials'
dimension_name = 'Customer'
level_name = 'Customer Type'
name = 'Customer Type Name'
skip_request = true
name_field = true
javascript_code = '''
cust_type = doc.K_KTIPS;
switch(cust_type) {
case "0":
doc.customer_type_name = "Active";
break;
case "1":
doc.customer_type_name = "Potential";
break; }
'''
The javascript code can also reference other custom fields from the same register.
3. Import the custom field
Finally, Edit the HansaWorld source application again and in "Cube properties" section select your new defined custom field for import.
Save the application settings and start the import. After the import is finished start using your property, measure or dimension in your reports.
In case of any questions please contact support@flex.bi for more information.
Available parameters for Advanced Settings
Below you can find a list of all the available custom field parameters.
|
Parameter Name |
Example |
Description |
|---|---|---|
|
default_custom_field |
default_custom_field = true |
This parameter specifies that this field is loaded from the default custom fields file and is required for building the standard cube structure. A custom field with this parameter enabled can't be de-selected for import. Also, if this parameter is set, then the custom field definition is not validated. |
|
key_field |
key_field = true |
This parameter specifies that this field will be used as the key field for binding the dimension to the measures and as the first part of dimension member's name (" |
|
name_field |
name_field = true |
This parameter specifies that this field will be used as the second part of dimension member's name (" |
|
level_name |
level_name = "Invoice Item" |
If a dimension has multiple levels |
|
source_id_field |
source_id_field = true |
This parameter specifies that this field should be used for binding the dimension to the measures instead of the key field. For example, when importing data from a relational database, this could be the primary key of the table that is used for dimension creation. |
|
rest_api_field |
rest_api_field = 'T.NAME' |
If an REST API field contains a full stop characters (“.“) or the same REST API should be used twice you can use rest_api_field to define the REST API field name instead. If rest_api_field is used then in order to change the returned value for the whole custom field using Javascript the name in rest_api_field needs to be referenced instead as well. |
|
for_custom_dimension |
for_custom_dimension = 'Customer' |
This parameter specifies that this field from the measures register or table will be used for binding the measures to the particular dimension. This parameter should be used together with the following parameters, to specify the particular use of the custom field: |
|
for_custom_dimension_level |
for_custom_dimension_level = 'Customer' |
This field is an addition to |
|
import_sort_date |
import_sort_date = true |
This parameter specifies that this field will be used for limiting data requests from the particular register or table. For instance, it will be used to get data starting from a particular start date, to rewrite data for a specified refresh period and also for incremental import of only those data lines that have been changed since the last import run. |
|
skip_request |
skip_request = true |
This parameter specifies that the REST API request should be skipped for this field. This can be useful when the field has been already requested in another custom field or the field is calculated with Javascript. |
|
bind_field_name |
bind_field_name = 'status_code' |
This parameter specifies what custom field's register code should be used for binding measures to another dimension. With this parameter the same field can be referenced multiple times. |
|
matrix_field |
matrix_field = true |
This parameter specifies that the information should be taken from matrix level of a record for creating a dimension. |
|
ordinal_field |
ordinal_field = true |
This parameter specifies that the field should be used as an ordinal column for dimensions in a separate table. |
|
for_standard_dimension |
for_standard_dimension = "Customer" |
Similar to |
|
for_standard_dimension_level |
for_standard_dimension_level = "Customer" |
Similar to |
|
property_with_mdx |
property_with_mdx = true |
Automatically creates a calculated measure for the imported property. |
|
drill_through_return |
drill_through_return = true |
drill_through_return parameter can be used to specify that the dimension should be included in the result as a column when "Drill through cell" is used on a cell. |
|
drill_through_default_measure |
drill_through_default_measure = true |
|
|
drill_through_dimension_level |
drill_through_dimension_level = true |
|
|
default_measure |
default_measure = true |
|
|
rest_api_item_field |
rest_api_item_field = "TRANSORDER_P" |
This field can be used to specify how to reference item level from a record correctly. Using this field once is sufficient as this will overwrite the item level name reference from request for the same dimension for other custom fields as well. |
|
rest_api_nested_field |
rest_api_nested_field = "SHIPTO2" |
This parameter can be used to specify a record sub-level that's field will be requested through the REST API for the register, and available for custom field definition on the record level. If the sub-level is an array then the first element from the array will be used. |
|
cubes_for_measure_sharing |
cubes_for_measure_sharing = ["HansaWorld Invoices", "HansaWorld Sales Orders"] |
When defining a new custom field this field can be used to specify in what other cubes this measures should be shared in. |
|
display_name |
display_name = "URL" |
This parameter can be used alongside "name" property to specify the property or measure name displayed in the data cube. This can be useful when the same field name has to be used multiple times (otherwise there would be an error that the same name can't be used twice). |
|
empty_before_import |
empty_before_import = true |
Allows to specify that a particular register data should be deleted before each import operation. This parameter is specified for a single register in the custom fields definition. |
|
dimension_bind_field_name |
dimension_bind_field_name = 'classificator_id' |
Can be used to import additional data (property values) for a custom dimension, using another register as a source. For instance, you can create a Customer dimension from Register1 and then add Customer Classification values from Register2, using |
|
import_order |
import_order = 1 |
This parameter can be used:
|
|
unique_count_measure_dimensions |
unique_count_measure_dimensions = ["Customer", "Project"] |
This parameter can be used with a custom field that defines a measure to count how many unique members from the specified dimension have results from this measure (where this field is added) in the report context. For example, how many unique customers are there this month. |
|
import_from_flex_table |
import_from_flex_table = true |
This parameter imports data from a database table within the same account. When enabled, the register name at the start of the custom field definition serves as the database table name. For example, if the custom field begins with |
|
for_extra_dimension_type |
for_extra_dimension_type = “Object types” |
This parameter can be used to bind a field from a register to extra dimensions. Valid values are "Object types", "Item class types", "Customer class types", "Item variety groups", and "Location class types". |
Consolidation
When consolidation is enabled for an account (with parameter max_consolidated_companies) all registers will have 2 more fields available when defining custom fields - source_company_code and source_company_name. During data import these fields will contain code and name that represents the company that the data is imported from and can be used to create a Company dimension and additional hierarchies for all the dimensions.
The example below shows what fields would need to be added to create another “Company” hierarchy level in “Sales Person” dimension. For Horizon application both rest_api_field and skip_request = true parameters have to be used at the same time.
[TNdmPardSar.p_company_code]
default_custom_field = true
cube_name = 'Horizon Invoices'
dimension_name = 'Sales Person'
level_name = "Company"
name = 'Person company code'
rest_api_field = "source_company_code"
skip_request = true
key_field = true
[TNdmPardSar.p_company_name]
default_custom_field = true
cube_name = 'Horizon Invoices'
dimension_name = 'Sales Person'
level_name = "Company"
name = 'Person company name'
rest_api_field = "source_company_name"
skip_request = true
name_field = true
[TNpvzRndAllSar.sales_person_company_bind]
default_custom_field = true
cube_name = 'Horizon Invoices'
name = 'Sales Person Company Bind'
skip_request = true
rest_api_field = 'source_company_code'
for_custom_dimension = 'Sales Person'
for_custom_dimension_level = 'Company'
bind_field_name = 'p_company_code'
Application specific custom field parameters
|
Parameter Name |
Example |
Applications |
Description |
|---|---|---|---|
|
credit_debit_dimension_column |
credit_debit_dimension_column = true |
Jumis, Horizon |
This parameter specifies that the values for the particular custom field should be taken from 2 separate custom fields with name prefixed |
|
request_filter |
request_filter = 'NDOK.D.T.KODS+eq+RREK' |
Horizon |
This parameter can be used to add additional filters to the REST API link when requesting data. |
|
item_level_from_header_key |
item_level_from_header_key = 'NDOK_PK_DOK' |
Horizon |
This parameter can be used as a key value to create the item level from the header level data. The key is used as the unique identifier for aggregating item level rows that belong to the same record. |
|
custom_date_measure_group |
custom_date_measure_group = "Planned" |
HansaWorld |
This parameter can be used to duplicate measures and link the duplicated measures to a different time period. The type for the custom field with this parameter has to be a date. This parameter also groups the duplicated measures with the name specified. |
|
query_params |
query_params = 'DATUMS=today+1.day' |
Horizon |
Can be used to add additional parameters for the Rest API request. The parameter values are specific to the source application. The example allows to pass a dynamic date value to the Rest API request.
|
|
query_params = '''
|
Jumis, SQL Extended |
When using custom fields for SQL Extended application, For example, this part of the query will be always constructed automatically based on the field’s ID’s: SELECT Balance AS Balance, Account AS Account FROM and DB1 WHERE Account = '572028' AND WHERE TaxDate >= '2025-07-01' If SELECT Balance AS Balance, Account AS Account FROM DB1 |
|
|
source_cube_name |
source_cube_name = 'HansaWorld Sales Orders' |
HansaWorld |
Can be used to share measures from standard data cubes to other cubes. This parameter specifies from what cube the measure comes from. Should be used together with "source_measure_name". |
|
source_measure_name |
source_measure_name = "Item base amount" |
HansaWorld |
Can be used to share measures from standard data cubes to other cubes. This parameter specifies the name for the measure that should be shared. Should be used together with "source_cube_name". |
|
model |
model = 'hr.employee' |
Odoo |
This parameter allows to set the Odoo API model name for a particular register import. This can be specified only once per register in custom fields definition. |
|
flex_import_start_date |
query_params = ''' invoices WHERE invoices.date >= 'flex_import_start_date' ''' |
SQL Extended |
Additional option for query_params parameter - flex_import_start_date can be used to reference the application start date. |
Creating custom dimension from multiple registers
In the following example, a custom dimension Employee is created from two registers in Odoo application. The main dimension structure, including key fields, is created from the employees register, but the Employee Category value is imported from the categories register, using the category_id field as a key for binding the categorie values to the relevant employee record.
#===========Employee Dimension (main) in Odoo Timesheets Cube================
[employees.employee_id]
default_custom_field = true
cube_name = 'Odoo Timesheets'
dimension_name = 'Employee'
name = 'Employee Id'
rest_api_field = 'id'
key_field = true
model = 'hr.employee'
query_params = [['active', 'in', [true, false]]]
[employees.name]
default_custom_field = true
cube_name = 'Odoo Timesheets'
dimension_name = 'Employee'
name = 'Employee Name'
name_field = true
[employees.active]
default_custom_field = true
cube_name = 'Odoo Timesheets'
dimension_name = 'Employee'
name = 'Employee Status'
property = true
javascript_code = '''
switch(doc.active) {
case true:
doc.active = "Active";
break;
case false:
doc.active = "Inactive";
break; }
'''
[employees.category_id]
default_custom_field = true
cube_name = 'Odoo Timesheets'
dimension_name = 'Employee'
name = 'Employee Category Id'
rest_api_field = 'category_ids'
property = true
#===========Employee Dimension (additional) in Odoo Timesheets Cube================
[categories.category_id_bind]
default_custom_field = true
cube_name = 'Odoo Timesheets'
dimension_name = 'Employee'
name = 'Category Id Bind'
rest_api_field = 'id'
dimension_bind_field_name = 'category_id'
model = 'hr.employee.category'
[categories.category]
default_custom_field = true
cube_name = 'Odoo Timesheets'
dimension_name = 'Employee'
name = 'Employee Category'
property_with_mdx = true
rest_api_field = 'name'
Unique record identity (_source_id)
_source_id is a unique identifier for records, so flex.bi knows which row/record in the database to replace or delete when the same data is imported again. It can be set in any custom field's javascript_code for the register:
javascript_code = '''
doc._source_id = doc.SomeUniqueField;
'''
Skipping and deleting records
Setting creating a delete_and_skip custom field and setting doc.delete_and_skip = 'true' inside a custom field's javascript_code block instructs the underlying Ruby import engine to purge existing cube records matching the record's _source_id while skipping the creation of a new entry during data processing.
Key Usage Guidelines
-
Targeting: Requires a defined
doc._source_idso the import engine can identify and remove the exact existing record from the cube database. -
Filtering & Purging: Ideal for handling status changes (such as cancelled, voided, or soft-deleted source documents) that must be removed from flex.bi rather than merely skipped.
-
Execution: When
doc.delete_and_skip = 'true'is evaluated, flex.bi suppresses measure and dimension indexing for that row while issuing a deletion command for any previously imported record with the same_source_id.
[TdmGramatSL.delete_and_skip]
default_custom_field = true
name = 'Delete and Skip'
dimension_name = 'Transaction'
cube_name = 'Horizon Financials'
skip_request = true
property = true
javascript_code = '''
switch(doc.STATUSS) {
case "1":
break;
default:
doc.delete_and_skip = 'true';
}
'''
Skipping a record: return false
Returning false from a field's javascript_code causes that row to be returned empty, so it is not imported:
javascript_code = '''
if (doc.SomeStatusField !== "3") {
return false;
}
'''
This differs from delete_and_skip: return false only skips the row. delete_and_skip also checks the database for an existing record with the same _source_id and deletes it. It only works on measure records, or on the main table everything else for a cube binds to.
Measures based on different/multiple date fields
If the data need to be linked to another date field then use custom_date_measure_group to define the name for the measure group and also the prefix for the duplicated measures.
custom_date_measure_group = 'Planned'
Example for both record and item level below.
[SHVc.Planned_Send_date]
rest_api_field = 'PlanSendDate'
name = 'Planned Send Date'
dimension_name = 'Delivery'
cube_name = 'HansaWorld Deliveries'
custom_date_measure_group = 'Planned'
[SHVc.Plan_Send_DateRow]
name = 'Item Planned send Date'
dimension_name = 'Delivery'
level_name = 'Delivery Item'
cube_name = 'HansaWorld Deliveries'
custom_date_measure_group = 'Planned'
javascript_code ='''
if (doc.rows && doc.PlanSendDate) {
doc.rows.forEach(function(row){
row.Plan_Send_DateRow = doc.PlanSendDate;
})
}
'''
Credit and Debit
In the example below, account_code value will be populated from the credit_account_code for the credit transaction and from debit_account_code for debit transaction.
[FinancialDocLine.account_code]
skip_request = true
default_custom_field = true
name = 'Transaction Account Code'
dimension_name = 'Transaction'
cube_name = 'Jumis Financials'
for_custom_dimension = 'Account'
bind_field_name = 'account_code'
credit_debit_dimension_column = true
[FinancialDocLine.credit_account_code]
default_custom_field = true
name = 'Credit Account Code'
dimension_name = 'Transaction'
cube_name = 'Jumis Financials'
rest_api_field = 'CreditAccount.AccountCode'
[FinancialDocLine.debit_account_code]
default_custom_field = true
name = 'Debit Account Code'
dimension_name = 'Transaction'
cube_name = 'Jumis Financials'
rest_api_field = 'DebetAccount.AccountCode'
Dynamic Dimensions
If your system contains a field that references multiple values you can use Dynamic Dimensions functionality to create a new dimensions for each of these field value types. Below is a graph showing on what field structure this functionality supports and which fields need the extra parameters dynamic_dimension_name_field, dynamic_dimension_key_field and dynamic_dimension_key_bind_field. If we take the graph as an example, this functionality would create a new dimension for each of the “Class Types” fields that would contain corresponding members from the “Classes” register/table and when importing the “Register” that contains the multi-value field, it would like each of those fields to a corresponding dimension (“Class Types”) member (“Classes”).
|
Parameter Name |
Example |
Description |
|---|---|---|
|
dynamic_dimension_name_field |
dynamic_dimension_name_field = true |
This field can be used to get the dimension names from the dimension list register - for instance class type names in the “Class Types” register. |
|
dynamic_dimension_key_field |
dynamic_dimension_key_field = true |
This field can be used to get the dimension keys from the dimension list register - for instance class type codes in the “Class types” register. |
|
dynamic_dimension_key_bind_field |
dynamic_dimension_key_bind_field = true |
This field can be used to filter particular dimension values from the full values list in the dimension records register - for instance class codes in the “Class” register. |
🔗 Binding Register to Extra Dimensions
The custom fields in the example below will bind IVVc register to dimensions selected in Extra dimensions Configuration in application settings.
[IVVc.objects]
name = 'Objects'
cube_name = "HansaWorld New Invoices"
rest_api_field = 'Objects'
for_extra_dimension_type = "Object types"
[IVVc.customer_classification]
name = 'Customer Classification'
cube_name = "HansaWorld New Invoices"
skip_request = true
for_extra_dimension_type = "Customer class types"
[IVVc.item_varieties]
name = 'Item Varieties'
cube_name = "HansaWorld New Invoices"
skip_request = true
rest_api_item_field = "rows"
for_extra_dimension_type = "Item variety groups"
[IVVc.item_classes]
name = 'Item Classes'
cube_name = "HansaWorld New Invoices"
skip_request = true
rest_api_item_field = "rows"
for_extra_dimension_type = "Item class types"