Generators for calculating business intelligence measures
Product line
Standard
|Expert
Operating mode
CLOUD ABO
|ON-PREMISES
Modules
Services & CRM
Budget & Phases
Purchases
Resource Planning
Business Intelligence
For the deployment of the data for the business intelligence module, we use a data storage according to the data warehouse concept, in some cases also called “OLAP Cube”. Depending on the selection of the dimensions, a slice of a cube is then cut accordingly.
Essentially, the data warehouse consists of a large data table (cube) with pre-calculated data values. This enables efficient, business logic-independent access to the BI data and thus a high-performance display even with large amounts of data.
The calculation is time-independent and with full business logic support via regular scheduled tasks. If required, the calculation can be done in individual packages (e.g. individual months) in own processes or even parallelized.
The calculation logic is defined in Python scripts called “generators”. These are stored on the measures. To view the code of a generator, click on the browse button next to the field Generator on the measure:
The generator must contain a calculation for the measures on which it is stored. The internal name of the measure must therefore match the values returned by the generator.
Generators can also be extended or new generators written. To do this, create a new script in the folder Settings > Reports & Scripts > Scripts and write the generator code as a Python script.
The designation of the script is the module name. Together with the class name of the generator, it forms the generator ID. You can specify this as a generator for the BI measures calculated by the generator.
Module names must be unique. You do not “overwrite” an existing generator by creating a module with the same name, but by creating a new generator and storing it on the corresponding measures.
The declaration of the generator is as follows:
class <Generatorname>(object):
The generator object can be accessed at any time in the script via self
. Within the generator, the following methods are available:
Method | Description |
---|---|
get_dimensions(self) | This method specifies for which dimensions (classes) the generator calculates values:
def get_dimensions(self): return ['Projekt', 'Projektbearbeiter'] The measures must include as many dimensions as are provided, in the order given: For example, if you want to show values for both users as project leaders and users as key users, the dimension def get_dimensions(self): return ['Projekt', 'Projektbearbeiter', 'Projektbearbeiter'] And on the measure: |
get_measures(self) | This method specifies which measures it will calculate. The return values must match the internal names on the measures.
def get_measures(self): return ['OffersQuantity'] The generator can then be stored on all measures that are returned here. |
initialize(self, startdate, enddate) |
The first step is to run through this method. The variables Here you can preload the lists of used objects in a performance-optimized way. This way you have all relevant data for the entire period. In the method |
generate(self, startdate, enddate) |
The The variables The data preloaded in Return valueThe return value returns a tuple of dimensions and a tuple of measures, in exactly the order stated above. The return value is not returned with yield((project, project.projektleiter), (OffersQuantity,)) Using CurrenciesIf you work with more than one currency in Vertec, you have to take this into account when calculating. For this purpose, you can optionally provide one currency per return line (example from the included InvoiceGenerator): yield ((project), turnover_tuple, project.waehrung) Vertec then takes care of the correct conversion into the key currency. The values are always shown in the key currency. |
finalize(self) | Finally, the finalize method is run through. For example, objects that are no longer needed can be removed from the memory. |
# Generator for data related to project offers. # # 12.03.2020, Vertec AG, sth: Version 100: created VERSION = 100 class OffersGenerator(object): """ Calculate all offers """ def get_dimensions(self): return ['Projekt', 'Projektbearbeiter'] def get_measures(self): return ['OffersQuantity'] def initialize(self, startdate, enddate): """ Preload all projects that could have offers in given date range """ # collect all corresponding offers offers = vtcapp.getwithsql("Offerte", "datum<=%s AND datum>=%s" % (vtcapp.sqldateliteral(enddate), vtcapp.sqldateliteral(startdate)), "") if offers: # collect all corresponding projects self.projects = vtcapp.getwithsql("Projekt", "bold_id IN (SELECT projekt from offerte where bold_id in (%s))" % offers.idstring(), "") else: self.projects = [] def generate(self, startdate, enddate): """ Calculate measures for given period. Uses the stored projects from the initialization step. """ for project in self.projects: # calculate quantity for current month OffersQuantity = project.evalocl("offerten->select((datum<=%s) and (datum>=%s))->size" % (vtcapp.ocldate(enddate), vtcapp.ocldate(startdate))) yield((project, project.projektleiter), (OffersQuantity,)) def finalize(self): pass
Vertec supplies the following generators as standard:
Generator name | Data used |
Calculated measures |
ServicesGenerator.ServicesGenerator | Service totals (global groupServices operator) grouped by project, phase, user and service type. |
|
ProjectGenerator.ProjectGenerator |
Performance totals (global groupPerformance operator) grouped by project and invoice. Uses only the productive projects. |
|
UsersGenerator.UsersGenerator |
Users who joined before the end date and have not yet quit, or whose exit date is after the start date. |
|
InvoicesGenerator.InvoicesGenerator | Invoices that have been charged and whose value date is within the calculated date range. |
|
PhasesGenerator.PhasesGenerator |
Top-level project phases which have a grant date and whose grant date is before the end date and which were not completed or completed after the start date:
|
|
The data is calculated periodically over one (or more) scheduled task during the night. The scheduled tasks can be found in the Settings > Customizing > Scheduled Tasks folder.
This process triggers all generators stored within the active measures and calculates the values for the period from January of the year before last to the end of the next year.
The status of the task shows whether the calculation was successful or failed. The feedback of the calculation is displayed in the output window.
A Vertec App does not have to be running, only a running Cloud Server is required. For the batch calculation, a user is defined on the scheduled task, which will be used for the calculation. This user must have administrator rights in order to be able to perform the calculations.
In the Cloud Suite, the time cannot be changed on the interface. The calculation is always done overnight. The exact time is shown under Next execution
:
A BI calculation can also be initiated manually. There are two variants:
This triggers the calculation of all generators on all active measures.
Caution: The calculation is started directly in the running Vertec app, and not in a separate task runner process as in the timed execution. This should not be done while running, as the calculation takes a very long time and Vertec may be blocked.
The generator stored on the measure is started and the corresponding measures are recalculated. The date interval can still be set in each case:
At the end there is a message indicating which measures have been calculated.
Once calculated values for a period of time and the relevant measures remain available in the system.
If the data is recalculated, existing values are deleted only for that period and the measures concerned, and the new values are inserted. All other values remain.
There are two Python methods for calculating BI data.
vtcapp.standardprocessbi() |
Triggers the calculation of all generators on all active measures. Requires administrator rights. Corresponds to the execution of the standard scheduled task, see above. |
vtcapp.processbi(from: String, to: String, generator: String) |
Triggers the calculation of the generator supplied as a parameter. Requires administrator rights. From and To dates are specified as a string in the format “Year-Month”. The generator must be specified in the same way as for the measures, i.e. “<Modulname>.<Generatorname>”. vtcapp.processbi("2018-01", "2020-02", "OffersGenerator.OffersGenerator") Corresponds to the calculation of the BI data on a measure, see above. This method can also be automated, for example, via a scheduled task. |