Projects:Enhanced Preferences/Functional Documentation
Throughout a system as Openbravo there is a need to store properties and property values. Properties can range from system level properties, module-specific properties to user specific settings. The Property Configuration functionality aims to provide a generic solution: store application/module/user properties in an over-rideable way and make them available to the rest of the system through an easy-to-use api.
As an example consider modularity: A common issue with modularity is how to configure a centralized resource in the system by an optional module. The main point is that the configuration of that centralized resource should support "overwriteable configurations" in order to support configuration by modules. It means that each module can deliver its own configuration and there is a rule/mechanism to define which one prevails.
This project aims to provide tools for a module to define configuration properties so the business logic of that module depends on the value of those properties. Then other modules depending on this one should be able to assign different values to this property in order to change the behavior of the process of the original module. The same toolset should also be used for storing user-specific settings.
The purpose of this project is to create a infrastructure to:
- Allow modules to register properties
- Allow modules (the same registering the property or another one depending on this one) to assign values to this properties.
- Make it possible to set property values directly from a user action (so not through a module)
- Provide an api which makes it easy for an application to retrieve and set property values.
This infrastructure will be created by extending existing AD_Preference table.
User/developer documentation can be found here ERP/2.50/Developers_Guide/Concepts/AD/Dynamic_Expressions#Preferences
Due to technical limitations, currently it is not supported to maintain data in a single table as source data and reference data at the same time. If a table contains source data, it cannot contain reference data.
Because of this limitation, even the infrastructure is designed to allow properties at any client/organization level, at a first stage it will only be capable to have data at System level.
User roles & profiles
Business process definition
Control of customer used credit is a feature provided by core, it is made by a handler in core or in an optional external module. Core would define the property which value would be the implementation of the handler. If any module wants to implement a handler for this feature, it would have to include a value for the property pointing to the handler implementation within this module. The main Control of customer used credit process in core is in charge of reading the value of this property and calling the implementator defined with it. In case of several modules defining values for this property, when trying to obtain the value of the property an error message will be shown prompted the user to solve conflicts. In this case the user will be able to solve them by going to a manual window where all properties with more than one value will be showed and he will be able to select which of them will be used in each case.
Jrxml templates used in core document types. Each document type defined in core has a template to print reports. Core define a property per document with the template location. Typically the format of these documents is different among countries, so localization modules can optionally include a template and a value for document property pointing to this template. In a similar way than described above, the template selection would be made taken into account possible values in this property.
Last clicked menu items: when a user selects entries in the application menu then the system needs to keep track of the last three entries so that they can presented to the user as a shortcut. The last three selected entries are a property for the application menu component which is stored in the property table. The property is stored on role and user level (so when the same user switches role another last click list is shown).
Column width/visibility in a grid: a user can adapt the look and feel of a grid by changing the column and the column visibility. This user preference can be stored in the property table as a user preference on user or role level.
The last two user stories described settings set by user, it is also possible for a module to override or provide default values for these properties. In this way a module can be used to create specific complete system configurations.
Functional requirements based on business processes
- List to hold configuration properties. A list reference that will hold all the configuration property types. In this project this list will not contain any value. The way a module can define a property to make use of it, is by just adding a new value to this list. For example following the Control of customer used credit story, core would add a Customer Used Credit Implementator value to the list.
- Table to hold values for those properties. This table maintains the actual values for each property. New records for this table are added by different modules. It is a table with all access level (?). The table will be the current AD_Preference adding the required changes to allow this type of configuration. The columns it has are:
- Standard infrastructure: ID, audit fields, active.
- AD_Module_ID: Properties can be defined within a module or without module (ad_module_id==null).
- visibleat_user_id, visibleat_role_id, visibleat_org_id, visibleat_client_id: Defines the visibility of the property, if all of them are null then the preference is visible at all levels. Note more than one of the fields can be not-null.
- Property/attribute: It is a boolean to make use of property or attribute definition
- Property: It is the property that is populated in this record. It is one of the values in the List to hold configuration properties.
- Attribute: It is the current AD_Preference way of defining the property, it is a free text where the property name is set.
- Value: It is a string with the actual value assigned to the property. It must be a long type (CLob)
- Selected: In case of conflict: multiple values for a single property. The user will be forced to select which one of the conflicting values will be used. This selection is done through this column.
- Property value getter. A method to obtain a value for a property. This method accepts as parameter property name, user, role, client, organization and window. It determines the value for that property or it raises an exception in case of non solved conflict. It takes into account that it is possible to have the values for the same property at different user/role/client/organization/window levels. The system should first try to find the most detailed defined property and if not find relax the search filter one-by-one. For the organization level searches the organization tree should be taken into account (so for the org parameter above you should read the accessible organization from the searched org).
- Property value setter: the system should provide an api to set a property value. The parameters are: module, client, org, role, user, property, value. The first 5 parameters can be null.
- Mechanism to manage conflicts. A conflict consists in duplicated entries for same property at the same client/organization level. As mentioned above, the property getter raises an exception when trying to get a property in this situation. The business logic making use of this property should be locked till the conflict is solved. The way of solving the conflict is through a manual window that presents all the properties with several values at a same level and allows the user to select a single value to be used for each of them.
- Business logic depending on those values. The property dependent logic is not implemented in this project, but it is implemented in each of the modules that define a new property.
- Window to edit conflicts (nice to have). Manual window to edit possible conflicts.
User Interface Mockups
Open Discussion Items
Closed Discussion Items
- MT: I would not throw an exception in case of conflicts. I would log a warning. Throwing an exception means that the system can become unworkable by just accidentally changing a property value.
- ALO: Exception is only thrown when using the property getter, this exception should be managed by the piece of code making use of it. This is done in this way because different behaviors could be expected for different usages of this capability.
- MT: the 'attribute' column is only there for backward compatibility?
- ALO: Yes, it is kept for backward compatibility.
- ALO: The value of the property is a text that can be long (higher than the 2000 characters limited by NVarchar in DB). So it should be a CLOB (Text in PG). Is there any limitation for this?
- ALO: This seems to not to be a limitation, except for the reported issue , in any case this issue does not affect this project directly.
- ALO: Should AD_Preference table be access level System or All. Currently it is all.
- ALO:Yes, it is at access level all to allow manual edition for any role with access to this window. Visibility is not calculated by the ad_client and ad_org columns but by the visility* ones.
- ALO: Currently there's a limitation in dbsm, to support tables with data to be stored in source and reference info for the same table. This problem must be solved as an issue .
- ALO: This issue has been solved.
- ALO: In 2.50MP15, a new table AD_PropertyConfiguration has been added to support property configuration, this table (and its content) must be merged to AD_Preference.
- ALO: AD_PropertyConfiguration will be deprecated but all the infrastructure related to it will be maintained for backward compatibility. A new validation will be added to modules not to allow to package them in case the contain entries in this table to prevent new modules making use of it.
- install.source + check db-consistency on (pg8.4.3, ora11r1, ora10g)
- update from pi just prior to the project + check consistency (pg8.4,3, ora11r1, ora10g)
- Check project documentation + documentation related to the changes functionality for completeness+consistency
- Execute written junit tests
- Code-review for all code-changes done
- Check (changed) correct behaviour or existing preferences
- Check coverage of junit tests against changed code
- Check correct behaviour of new features (property lists), definition and export in modules
- Check added build-validation
- Test new configurable start-page system (will be done together with development work on new UI
Project is currently merged back to pi and will be publishes in 2.50MP16.
Some notes for qa:
- As currently is not possible to create jUnit tests for session status, preferences correctly loaded in session after logging in the application and role change, has not been tested through jUnit test cases. In the QA cycle pay special attention to preferences in session, specially the ones that were working in mp15 continue working.
- Preferences session loading has slightly changed. This can cause behavior changes which should be shown as warnings during the upgrade process. This should be also be taking into account in the qa-cycle.
Configuration Properties to Preferences Migration
In 2.50MP15 Configuration Properties infrastructure was created. It has been deprecated in 2.50MP16 by the Preference Extension.
This deprecated infrastructure is still present in MP16 core but it shouldn't be used by new version of modules. Utilty.getPropertyValue method has been deprecated and the core methods using it has now SupressWarning to prevent warnings when compiling core. ad_get_property_value pl function is still present. When packaging modules, it will not be allowed to have within them records in ad_property_configuration table.
As there is only one module that is using configuration properties, the migration to preferences will be:
- In the new version of the module configuration properties will be removed and equivalent preferences will be created.
- In the core part that makes use of it:
- To maintain compability with the current module version: keep the configuration property getting.
- To support preferences: add preferences get. Try to get the preference and in case it is not defined try to get the configuration property.
- After deciding until which core version the module is compatible, it will be possible to remove from core property getting, making core not compatible with the first module version.