Basics of OCL
Product line
Standard
|Expert
Operating mode
CLOUD ABO
|ON-PREMISES
Modules
Services & CRM
Budget & Phases
Purchases
Resource Planning
Business Intelligence
|
List operators |
Navigation and querying in the Vertec object model is done via an object-oriented query language called OCL. A complete language definition can be downloaded as a PDF file via the following link: Ocl manual .
OCL stands for object constraint language and was originally developed as part of the UML standard to formulate validity conditions for object models. Due to its object-oriented capabilities, OCL can also be used as a query language.
The Vertec core includes an OCL interpreter that processes OCL expressions as text and returns the result data from the Vertec objects. The OCL interpreter uses information from the Vertec Model .
OCL is used in Vertec in a variety of locations:
An OCL expression is always evaluated against a specific object and returns a result of a specific type. Possible types of results are:
For displaying results, e.g. in list columns, the result is automatically converted to a string. For numbers and strings, this conversion is simple. Booleans are represented as “Y” (yes) or “N” (no). For objects, the default string representation is displayed, which depends on the object class (e.g. code in projects). The representation of lists as a string shows the size of the list.
For expressions in expression folders, the result type must be a list of objects.
The current Vertec session can be accessed in OCL via
TimSession.allInstances->first
A Vertec session has the following attributes:
Result | app | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
.login | Returns the up-to-date logged-in user. See also the article Up-to-date user in expressions . |
||||||||||||||||
.instance | A database section can contain a value called InstanceName in the Vertec.ini file. This will then be shown on the Vertec desktop app interface, see the InstanceName section for identifying test installations. For access via OCL, there is an attribute called InstanceName: TimSession.allInstances->first.instanceName |
||||||||||||||||
.hasGui | The hasGui operator allows you to determine from OCL expressions or scripts whether the client is capable of showing user-specific dialogs, i.e. whether the client is one of the full-featured apps .
Return value is either
It is important that scripts – especially Event Scripts – do not show dialogs if this is not possible on the client being used, as this may block Vertec. |
||||||||||||||||
.appType | Starting with version 6.0. The AppType operator allows you to determine which app you are in from OCL expressions or scripts.
Returns a string with the following possible values:
|
||||||||||||||||
.checkfeature(featurecode: string) | Checks whether a particular feature is licensed.
The feature codes are according to Vertec feature matrix (e.g. Return value is False or True. |
A member is a property of an object. It is either an association with one or more other objects or an attribute of the object.
Starting from an object, a member name can be specified to access a member. If such a member reference does not appear at the beginning of an expression, it must be separated by a period. Member names must always be lowercase. Examples: code
in a list expression of a project list displays the project code in the corresponding column; kunde.name
, also in a project list, displays the customer name. This is a link reference (customer) followed by the attribute reference (attributes name
of the class Adresseintrag
).
By stringing member references together in an OCL expression, arbitrary links in the Vertec object model can be queried.
For m:n links, there is a link table. The link table can be accessed via the lowercase class name of the link table. Here is an example of an excerpt from the UML model user:
To find out what the corresponding link table is called, please refer to the corresponding UML model or contact your Vertec advisor.
A somewhat special type of members in Vertec are computed list attributes. In the OCL editor these are represented as type ObjectList
. A so-called Derived ObjectList calculates their value at run time. Unlike Derived Attributes, they do not contain individual values, but return a list.
An example is the list of services on a project. In the model, there are actually only two lists on the project: openservices and billedservices. The list of services, i.e. all open and billed services together, is calculated at runtimes.
The lists provide type information in OCL and can be called as follows:
<Proj>.leistungen.wertext->sum
A class list is the list of all objects of a specific type (class), e.g. all projects or all users of a Vertec installation.
OCL is case sensitive. The OCL interpreter tries to understand everything capitalized as a class name (metatype). On a class, OCL knows the operator allInstances
, which gives a list of all instances of the class. For example, Projekt->allInstances
gives a list of all projects.
Since class lists are used quite often, Vertec has an abbreviation for them. If a class name is lowercase, it will be interpreted as a class list. Therefore, projekt
also means the list of all projects.
Class lists are primarily used as a starting point for expressions from expression folders. Most predefined expression folders in Vertec (e.g. root data users) contain a simple class list as an OCL expression.
Caution: Be careful with class lists, because there are Vertec classes that can contain a lot of objects. If you specify a class list in OCL, all objects of that class will be loaded into memory. This can lead to high memory requirements and poor performance, especially with the OpenPerformance or BilledPerformance classes.
The following operators perform certain transformations on OCL values. An operator is separated within an expression by a leading arrow (->). If there is no likelihood of confusion with a member, a period is also accepted as a separator.
Based on a list, there are several operators in OCL that modify the list. Other operators, not mentioned here, appear in “available fields” in the Ocl expression editor .
->size | The size operator provides the quantity (quantity of entries) of a list, for example as a list column in a list of address entries projects->size specifies the quantity of projects of each customer. |
->select | The select operator allows you to filter the contents of a list based on a condition. addressentry->select(projects->size > 0) as an expression of an expression folder returns all addresses assigned to projects (i.e. customers). The argument of the select operator must be a logical (true/false) value. |
->reject | The reject operator is the opposite of the select operator. It excludes all entries from the list that match the expression. For example, the expression project worker->reject(name='Administrator’) returns a list that contains all project workers except the administrator. |
->first | The first operator returns the first entry from a list. Most often, the first operator is used when an object is to be used as a result of a selection. Since the ->select operator returns a list as a result, ->first must be applied to it for the result to be a single object. Example: phase->select(code= 'OFFER’)->first.offenservices->sizeindicates the quantity of open services of the “OFFER” phase in a list of projects. |
->orderby | With the orderby operator, lists can be sorted. address entry->orderby(projects->size) sorts the list of address entries according to the quantity of projects for which they are customers. |
->order descending | With the orderdescending operator lists can be sorted in descending order (otherwise the same as ->orderby): address entry->orderdescending(projects->size)Note: Used as an expression in an expression folder, these operators have no meaning since the list does the sorting itself. |
->orderMulti | The orderMulti operator allows you to sort a list according to different sort criteria. It can be applied to a list in an OCL expression and takes a string as argument. This string contains the different sort criteria as individual OCL expressions, separated by semicolons: project->ordermulti('projectleiter.name;code.asstring’)as an expression of an expression folder, it returns a list of all projects, sorted first by the name of the project leader, second by the project code. However, this sorting will only be visible in the list view if you remove the sorting on list columns. Double-click a sorted list column until it no longer displays a sorting arrow. |
ordermulti with additional fields | If you want to sort by custom items, you have the problem that you cannot use quotes in the expression. For custom items, this requires a detour via the internal ID of the custom item (settings > custom fields > right mouse button > properties > internal ID): projekt->ordermulti('projektleiter.name;zusatzfelder ->select(metaZusatzfeld.boldID=<interne ID>)->first.wert') Depending on the field type, you can query the value as follows: .wert .wertBlob .wertBoolean .wertInteger .wertCurrency .wertDatum .wertObject |
->asSet | Starting from a list, you can also specify a member reference. The member reference is then applied to each object in the list. Thus, the result is a list of elements of the member type. Example project.customer returns a list of all customers in an expression folder. The disadvantage of this list is that the customers sometimes appear duplicate, because the expression aggregates all customers by project. This can be solved by using the asSet operator, which converts a list into a set (in the sense of set theory): projekt.customer->asSet returns a distinct list of all customers. |
->asSequence | Turns an object (or a list) into a list containing the individual object (or, in the case of execution on a list, the items of the list). |
->asBag | Returns the list with all entries, including duplicates (in contrast to asSet, see above). Since calling a list in the vertec will return a collection with all entries, the explicit specification of asBag is unnecessary. |
->union | The union operator allows two lists to be combined into one. It can be applied to a list in an OCL expression and expects another list (collection) as an argument: openbenefits->union(offeredbenefits)as an expression on a project returns all open and billed services of the project. This list can be used as normal. The type is always the common base class whose attributes are available. So the above example returns a list of entries of type service. For an expression project->union(address entry), the common base class would be, for example, UserEntry. |
->collect | The collect operator allows a variable to formulate a complex partial expression only once, but to use it several times. For example, you want to show the total of the invoices (net) for the last year: invoices->select(date.year=date.year-1)->collect(turnover+amount of advance-effective advance)->sumwithout the collect operator you would have to repeat the whole '->select’ expression for each value (revenue, advance amount etc). You can also go a step further by assigning the value resulting from the collect to a variable and continuing with it. As an example, let’s take a list of projects. Each project is located (in this example) either in a “Customer Projects” folder, or in an “Internal Projects” folder, or in an “Order Projects” folder. These folders are subfolders of the “Project Category” folder. In the list, we now want to show either 1, 2, or 3, depending on which folder the project is in the list: ordner->select(parentordner.bezeichnung='Projektkategorie') ->first.bezeichnung.substring(1,1)->asSet->collect(x|if x ='K'then '1'else if x='I'then'2'else if x='A'then'3' else'Keine Angabe'endif endif endif)->first The expression assumes a project (every project in the list). folder means the folders in which the project is located. We first look for the subfolder of the project category folder. From this we take the first letter (name.substring(1,1)). This is now a single letter, either “K” or “I” or “A”. Since the collect operator can only be executed on a list, we add a ->asSet. Now we have the ->collect operator: instead of repeating the entire folder->select(...) section for each if query, we can simply use the variable x several times. The x in the brackets refers to the current value. This is our single letter at the moment. Now we can use the x to query this letter and insert the desired value. The whole thing is still a list, but we want to show the single value in the field, so we add a ->first again. |
->append(obj) | Returns the list that the obj has appended at the end |
->at(i) | Returns the object at location i. The index i begins with 1. |
->count(obj) | Specifies how many times obj is included in the list. |
->difference(list2) | Returns the list that corresponds to the original list without the elements of list2. |
->excluding(obj) | Returns the list from which the obj was removed. |
->includes(obj) | Specifies whether obj is included in the list |
->includesAll(list2) | Specifies whether all objects in list2 are included in the list. |
->including(obj) | Same as ->append |
->intersection(list2) | Returns the intersection of the two lists, that is, a list of all objects contained in both lists. |
->isEmpty | True if no list or length of list=0, otherwise False. |
->prepend(obj) | Returns the list with the obj at the beginning. |
->subsequence(start, stop) | Returns a list from index start to and including index stop. The indices are based on 1 and are automatically corrected for valid values (i.e. stop can also be larger than the list length without any errors). |
->symmetricDifference(list2) | Returns a list of all items in the list that are not in Liste2 and all items in Liste2 that are not in the list. |
->sum | Sums the numeric values of a list and returns the sum. |
Often the task is to convert a string to a date value, convert a number to a string, etc. The following is a list of the available conversion operators:
->asString (also .asString) | Converts a number or date value to a string. |
->dateToFloat | Converts a date value into a number (the number tells you little: (quantity of days since 1.1.1900). This operation is mainly used for calculating date values (e.g. adding 30 days to today’s date, see example below). |
->floatToDate | Converts a number to a date. The following expression counts 31 days to the date of the entry (e.g. a service): (datum->dateToFloat+31)->floatToDate |
->strToDate | Converts a string to a date. This operator is useful when you need to work with a date that is not previously known or exists only as a string (e.g. when the user queries a date). The use of strToDate is tricky, because it refers to the current country settings. A strToDate with a string literal of '01.09.2020' goes wrong if a client uses a US date format, for example. In the web app this does not even refer to the local Windows, but to the settings in the web browser (e.g. “English”). In fixed OCL expressions, therefore, the operator should instead |
->stringToFloat | Converts a string to a number. If the string is not a number, 0 is returned. |
->stringToList | Represents a string as a list. Individual words are separated by the word boundary or by a delimeter. Words enclosed in double quotation marks are counted as one word.
Returns the name of the logged-in user as a list. For example,
only the surname will be shown. |
->isEmpty | The operator ->isEmpty returns whether a link member is empty. For example, the expression projektleiter->isEmpty , executed on a project, returns with a Boolean value (true, false) whether a project leader is assigned (true) or not (true). |
.isNull/.notNull | It is often useful to detect a null value. Starting with version 5.5, this no longer has to be done via a string comparison, but can be queried via the OCL operators isNull and notNull. Example: instead
you can now
to carry out. Note: These operators are not to be confused with the isEmpty operator, which queries a shortcut. For example, to know whether a project has assigned a customer, you cannot query with isNull, but with customer->isEmpty. |
.asnull/.null | Starting with Vertec 6.2.0.4. The OCL null operator makes it possible to obtain null values for any attribute type. This is useful to render nothing for numeric values instead of 0 without having to convert the entire expression to a string. For example, expressions like: if usespesen then spesenint.asstring else '' endifis replaced by the following expression: if usespesen then spesenint else spesenint.asnull endif Since OCL is a static and strictly typed language, a null value must also have a type in order to determine the validity of the expression. Therefore, a
|
->listToString | Using this operator, lists can be represented in strings. For example, the expression returns:
executed on a project (e.g. via list settings) the list of phase codes, separated by “,”. |
.toLower/.toUpper | Very often, the result of an expression is a string. The .toLower operator converts the string to lowercase, the .toUpper operator converts it to uppercase. |
.asHMString | Interprets a number as a quantity of minutes and formats it as hours:minutes. Negative time values are also supported. |
.asTimeString | Interprets a number as a quantity of minutes and formats it as the time of day. Negative values are not displayed. |
.asMinuteString | Interprets a number as a quantity of minutes and formats it according to the format in the system settings. Negative time values are also supported. |
.asStringBy Language(<Sprache>) |
Query the corresponding language version of a member. This applies to all MLStrings, which are values that each have their own field for the different languages (examples are services, expense and outlay types). For example, for outlays on an invoice: If you want the French designation of the type, you can use the expression Possible languages / parameters are 'DE’, 'DD’ (from 6.5.0.9), 'FR’, 'IT’, 'EN’ or 'NV’. Note: This feature returns only the value entered in the MLString field. No translation takes place in the specified language, so if no value is entered in that language, an empty string is returned instead of the native term. |
.pad(quantity, placeholder) | The .pad operator populates an integer value with the wildcard symbol up to the quantity of specified symbols. The result is a string. This is useful, for example, when you need leading zeros for alphanumeric sorting.
|
abs | This operator returns the absolute value of a number. (-2.8).abs = 2.8 |
floor | Round function. Returns the nearest smaller integer from a real number. (-2.8).floor = -3 |
round | Rounds a numeric value to the nearest integer according to the round-to-even rule and returns it as a result. (-2.8).round = -3 Round to five chunks:
Round to two decimal places:
Rounding up from the 5th:
See also rounds in scripts on this topic. |
length | This operator returns the quantity of symbols in a string. For example, the expression addressentry->select(standardzip.length=4) returns all addresses with a four-digit zip code. |
substring(start, end) | This operator cuts out the symbols between “beginning” (starting at 1) and “end” from a string. For example, the expression code->substring(1,1), executed on a project, returns the first letter of the project code. Another example: you want to show the entry year of the current entry. Vertec saves the entry date in the member “creationdatetime”. The following expression takes the “creationdatetime,” converts it to a string, and sets the last 4 symbols: creationdatetime->asstring->substring(7,10). This method can of course also be used for the up-to-date system date (expression now, can be useful e.g. in connection with memory paths in Word reports, see corresponding articles) |
replaceString | The syntax is as follows: <string>->replaceString(substring, replacement)You specify the part you want to replace (substring) and the part you want to replace (replacement). The return value is again a string. For example, you would like to replace all Meyer with Maier in a text: <text>->replaceString('Meyer’, 'Maier’)The replace string is case sensitive, i.e. it is case sensitive. |
replaceRegex | The syntax is as follows: <string>->replaceRegex(template, replacement)Here you can specify a regular expression, a so-called regular expression, both for the part you want to replace (template) and for the part you want to replace (replacement). The return value is again a string. A small example of what is possible with this: In a text there are designations of the type <Abschnitt>:<Kapitel>, for example 2:15 or 3:10. You want to swap these designations so that they are represented as 15:2 or 10:3 respectively. This can be done with the following expression: <text>->replaceRegex('([0-9]*):([0-9]*)', '$2:$1') |
Translate | As of Vertec 6.4.0.20. Translates a string value to the latest Vertec Surface Language . Example: if projekte->size > 0 then 'Client'.translate else 'Address'.translate endif on an address list shows in the column the following result for English: |
On UserEntry (all objects that can be placed in folders, e.g. services, projects, addresses, users, activities, etc.) there are the following operators:
Operator | description |
---|---|
->hasBIDataRight: boolean from Vertec 6.4.0.14: ->hasBIDataRight('Number’):boolean |
This operator can be used to check whether the up-to-date logged-in user has the right to the specified BI object. With the implementation of the rights on the KPIs with version 6.4.0.14, this OCL operator has been changed. From then on, a string with the internal name of the KPI must be specified as a parameter. Example: projekt->hasBiDataRight('MinutesExt') checks whether the up-to-date logged-in user on the specified project has the right to the MinutesExt KPI. This is not backward compatible. The corresponding calls need to be adjusted. |
->hastag(tagname): boolean |
As of version 6.1.0.10. Query whether the object has set a tag of this name. For more information, see the article about tags on user records. |
->keystring(key): string ->keybool(key): boolean ->keydate(key): datetime or empty ->keyint(key): integer or 0 ->keycurr(key): currency or 0.00 |
Starting with version 6.1.0.10. Operators for typed query of key values on the object. For more information, see the article about key values on user records. |
Specifically for the class Projektbearbeiter
there are the following operators:
Operator | description | from version |
---|---|---|
->gettarget time(from, to) |
Standard hour in period (minutes) |
|
->getWorking time(from, to) |
Working time in the period (minutes). Calculated from the sum of all available services plus vacations entered as absences. |
|
->received deferral(date) |
brings the overtime balance by date-1, unless a forward is entered on date, then this forward is delivered. |
|
->Delay date(date) |
returns date of last deferral before date |
5.4 |
->Overtime balance(date) |
provides overtime balance by date |
5.4 |
->getHolidayDefault(from,to) |
Holiday credit within period |
|
->getHolidayReference(from,to) |
Holiday pay, both absences and holiday benefits |
5.4 |
->getHolidayLecture(date) |
brings the vacation balance per date-1, unless a forward is entered on date, then this forward is delivered. |
|
->getHolidayLecture date(date): |
carries date of last vacation carryover before date |
5.4 |
->getHolidayStart(date) |
brings the start date for calculating the holiday credit. Is the next holiday cut-off date after the last forward |
5.4 |
->getHolidayEnd(date) |
provides end date for calculation of holiday credit. Is the next holiday period end |
5.4 |
->getHolidayBalance(date) |
delivers holiday balance by date |
5.4 |
->getHoliday BalanceDelimited(date) |
Calculates the accrued vacation balance per date, taking into account the vacation credit up to the date. Example: A vacation credit of 200 hours per year is given, specified by the group. The holiday cut-off date is 01.01. On this cut-off date, the employee was credited with a vacation carry-over of 20 hours. This means: The employee has a total vacation credit for the year 2013 of 220 hours. Now I want to calculate the vacation balance of this employee as of March 31, 2013. There are the following options:
|
5.8 |
->getsalary(from,to) |
Salary within the specified period |
5.4 |
->getCommon costs(from,to) |
Overheads within the specified period |
5.4 |
->getTargetTimeDefault(from, to) |
Calculates the standard time from, to only based on the settings, without taking into account holidays. Entry / exit date is taken into account. | 5.4.0.21 |
->getTargetTimeGroupDefault(from, to) |
Calculates the standard hours from, to based on the user’s group preferences. This results in the standard hours if the employee would work 100%. | 5.4.0.21 |
->getTargetTimeOnlyGroupAbw(from, to) |
Calculates an employee’s standard hours, taking into account only group-based absences (holidays, etc.). In contrast to the GetSollzeit operator, absences are taken into account only by the groups. Absences entered on the employee are not taken into account. The employment level of the employee is taken into account. |
5.8 |
->getEmployment degree(date) |
Returns the employee’s employment level on a specific date. The employment level is calculated regardless of whether the employee has standard hours on the effective date or not. The ratio of the standard weekly hours of the user and the group is decisive. |
5.4.0.21 |
->getAbsenceFree(Absence type, from, to) |
Operator to determine the free time of a particular type of absence. Example: Editor->getAwayFree('Holiday’, encodedate(2013, 1, 1), encodedate(2013, 1, 31)) The calculation is as follows:
If a non-existent or incorrect (not free) absence type is specified, the result is 0. Versions before 5.8 In versions before 5.8, the (language-dependent) designation is used to query the absence type. If several absences are entered on the same day, Vertec cannot unambiguously determine the impact of each absence because the absence types do not have a sorting according to importance. So if you are also sick on Easter Monday (“holiday”) then the standard hour is correct, but this operator specifies 0 for both “holiday” and “sickness,” since the other absence type also occupies the whole day. Versions from 5.8 For querying the absence type, the (language-independent) code is used in versions 5.8 and above. Starting with this version, absence types have a priority attribute. This is taken into account in case of overlapping absences. Any number of overlapping entries are taken into account and the “visibility” of the eligible absences is determined by the priority value on their type. If the priorities are equal, the following priority rules apply:
|
5.7 |
->getHoliday referenceFromw(from, to) |
Operator for calculating vacation entitlement taking into account vacations entered only as absences. Example: Editor->getVacationReferenceAbw(encodedate(2012, 1, 1), encodedate(2012, 1, 31)) As a result, the absences of the type vacation in the corresponding period are returned, in minutes (integer). For normal vacation calculation the operator |
5.7 |
->getTargetTimeGroup(from, to) |
This operator returns the standard hour for the group (100%), taking into account absences on the group. Example: Editor->getTargetGroup(encodedate(2012, 1, 1), encodedate(2012, 1, 31)) As a result, the corresponding standard hour is returned, in minutes (integer). |
5.7 |
->currentAbsences(date) |
This operator returns a list of absences used for the specified day. Example: Editor->currentAbsences(encodedate(2012,6,11)) provides a list of absences entered for this user for 11.06.2012. |
5.7 |
->getTrackingUsers |
The getTrackingUsers operator provides a list of all users for which the user is allowed to record services, expenses and outlays. This is used in the Editor selection field on services, expenses and outlays and can also be queried via OCL. Example: TimSession.allinstances->first.login->getTrackingUsers Returns the list of all users for which the user is allowed to record for the up-to-date logged-in user. |
6.0 |
getPresenceEntries(date) |
Returns a list of the day’s presence entries for the user. |
6.2 |
OCL operators are one way of working with resource planning data. However, there are a variety of other ways. These are described in the article Ocl, python, custom renderer and list controller for resource planning .
.getResPlanMinutes(Date From, Date To) |
Available on project and scheduling editors. Returns the scheduled time for the user in minutes for the specified period. . |
.getResRsrcMinutes(Date From, Date To) |
Available on project and scheduling editors. Returns the resource time for the user, in minutes, for the specified period. This is not the time still available, but the total standard hours relevant to the resource plan. The difference to standard hours is that only absences of the type “free” affect the standard hours, whereas all types of absences (free, vacation, compensation) are deducted from the resource time (see also the table on working time exceptions in the article Absences). |
If the effective compensatory absences per user are to be determined for a certain period of time, this can be done as follows:
getSollzeit(von, bis) - getResRsrcMinuten(von, bis) - getferienbezug(von, bis)
The non-working days (Saturday, Sunday, public holidays, etc.) are automatically taken into account.
Example of calculating the compensation period for the month of July:
self.getSollzeit(encodeDate(2013,07,01),encodeDate(2013,07,31)) - self.getResRsrcMinuten(encodeDate(2013,07,01),encodeDate(2013,07,31)) - self.getFerienbezug(encodeDate(2013,07,01),encodeDate(2013,07,31))
Absences of the type Free affect the standard hour (minus).
Absences of the type free, vacation and compensation as well as vacations entered as services affect the resource time (minus).
The absences of the free type are thus cancelled out. There are vacations and compensation left over. That is why the vacations still have to be deducted. The time difference is the compensation period.
From Vertec 6.7.0.16 onwards, the OCL operators are available for querying System Settings settings:
These return the value or object stored in the system settings.
For detailed information, see Properties via ocl .
Since version 6.0 there are OCL operators for querying user rights. Basically there are 3 types of user rights:
The following permission query operators return a Boolean (True/False) value.
The permissions on individual members are queried on the object and the name of the member is passed as an argument:
Operator | Legal name |
---|---|
Object->isMemberReadable(memberName) | rtRead |
Object->isMemberWritable(memberName) | rtWrite |
Operator | Legal name |
---|---|
Class->isCreatable | rtCreate |
Object->isDeletable | rtDelete |
Object->isExecutable | rtExecute (Reports and Scripts) |
Object->isViewable | rtSingleForm (can the object be shown in its own window?) |
When querying the user rights, the name of the corresponding right must be passed:
User->hasRight(rightname)
Legal names for hasRight | Standard user rights |
---|---|
'admin’ | Awesome |
'supervisor’ | Project Administrator |
'manager’ | Project Manager |
'self-tracking’ | Project Time Tracker |
'folderlinks_admin’ | Folder links Administrator |
'folderlinks_user’ | Folder links User |
'address_admin’ | Address Administrator |
'address_user’ | Address User |
'benchmarking’ | Benchmarking |
'treeview’ | Tree view |
'systemproperties’ | system settings |
'trackingcontroller’ | third party tracker |
'book’ | Post invoices |
'book_creditor’ | Post accounts payable |
'benchmarking_no_users’ | Benchmarking without operator numbers |
'teamleader’ | Team Leader |
'export’ | Export |
'sqlquery’ | SQL Query |
If an unknown right name is specified, the hasRight operator returns False.
Project entries is the collective term for services, expenses and outlays. These, in turn, are divided into open and charged. The assignments to projects, phases and users are defined in the model at the lowest level, i.e. on the open or charged services, expenses or outlays.
For easy access to project, phase and user, the following operators are available from version 5.7:
Operator | description |
---|---|
getProject |
Returns the project on which the service, expense or outlay was entered. |
getPhase |
Returns the phase of the project to which the service, expense, or outlay is assigned. |
getEditor |
Returns the user who entered the service, expense or outlay. |
For example, a list of users based on services of an invoice:
services.getEditor->asSet
Vertec versions before 5.7 require casts when accessing a list with a more general type (service, expenses, outlays). For example, a list of users based on services of an invoice:
leistungen->collect(if oclIsTypeOf (VerrechneteLeistung) then oclAsType (VerrechneteLeistung).bearbeiter else oclAsType(OffeneLeistung).bearbeiter endif)->asSet
phaseGetProject | In versions prior to 6.3, the subphases of a project phase do not have a direct connection to the project to which they belong. The OCL operator phaseGetProject returns the project for any phase or subphase:
Starting with Vertec 6.3, the member |
userentry->getLinks(role) | Returns a list of objects linked to the entry under this role. Project Editor->getLinks('archive entries’) |
For optimizing custom evaluations with expression folders and list columns, or for use in custom reports, accelerated summation and grouping is available in the form of an OCL operator groupLeistungen
. For more information on the performance totals operators, see the performance totals article.
date |
the date operator returns the up-to-date date. |
now |
the now operator returns the up-to-date date incl. time |
dateToFloat |
converts a date/time value to a floating point number. The integer percentage is the number of days since December 30, 1899. The fraction indicates the time. |
floatToDate |
converts a number into a date/time value. |
dateToStrGerman |
As of Vertec 6.2. Returns the date in German date format as a string. It sometimes needs date values in German format at certain locations, regardless of up-to-date locale settings (see e.g. from/to arguments in groupPerformance operators). argobject.eval('creationdatetime.datetostrgerman') |
year |
calculates the year of a date value. |
month |
calculates the month (1-12) of a date value. |
day |
calculates the day of the month of a date value. |
hours |
returns the hours of the time value as an integer. |
minutes |
returns the minutes of the time value as an integer. |
seconds |
returns the seconds of the time value as an integer. |
milliseconds |
returns the milliseconds of the time value as an integer. |
incMonth(quantity) |
adds quantity months to a date. You can also use it to count backwards: for example, date.incMonth(-1) counts back one month from the current date. Note: If the date is at the end of the month and the respective months have different quantities of days, the last day of the month is taken. Example: |
incDay(quantity) |
adds quantity of days to a date. You can also count back: for example, date.incDay(-10) counts back ten days from the current date. |
firstOfYear |
calculates for a date the date of the first day of the year (1 January). |
lastOfYear |
calculates for a date the date of the last day of the year (31 December). |
firstOfQuarter |
calculates the first day of the quarter. |
lastOfQuarter |
calculates the last day of the quarter. Example: self->groupleistungenP(date.firstOfQuarter.asstring, date.lastOfQuarter.asstring, '')->collect(minutenintoffen+minutenintverrechnet)->sumas a column expression in a project list shows the entered hours (open) in the up-to-date quarter. |
firstOfMonth |
calculates the first day of the month. |
lastOfMonth |
calculates the last day of the month. |
MondayOfWeek |
calculates the date of the Monday of a week. |
encodeDate
|
calculates a date based on numerical values for year, month and day. Example: folder with all invoices created in 2012: invoice->select((date >= encodeDate(2012,01,01)) and (date <= encodeDate(2012,12,31))) |
formatdatetime
|
Formats date and time according to format string (from version 5.2.0.15). Example: creationdatetime.formatdatetime('c’)-> '16.10.2010 15:24:31'The format string can contain:
|
In certain locations, there are OCL variables that can be used to access specific objects. These are:
OCL Variable | Use |
---|---|
varLogin |
In Expressions on rights
, the up-to-date login can be accessed via the variable varLogin can be accessed. |
varContainer |
From Vertec 6.4.0.21. Access in OCL expressions in lists to the container (folder or LinkContainer). In addition to the column expressions in the list, the also have access to this context variable. |
varContext |
As of Vertec 6.6.0.1. Access in OCL expressions to customize list settings. Contains the currently selected entry in the tree. For containers, the value is identical to varContainer (see above).
Specifically in Resource Planning , the variable makes it possible to customize lists depending on whether a resource planning view is shown for individual objects or lists. It is also available in List Controllers and Custom Renderers . To make the OCL variable easy to use here, both have the self.evalocl() method available, which uses this specific OCL evaluator. The OCL variable is defined only in this evaluator. |
varParent |
Starting with Vertec 6.4.0.21. Access in OCL expressions in lists to the object to which the container belongs (parent object of the link container). In addition to the column expressions in the list, the Listexpression and ghostrowlistexpression of a control also have access to this context variable. |
varStartDate | Starting with Vertec 6.6.0.1, for use in resource planning tables. Contains the start date of the current resource planning view to:
It is available in resource planning views and the corresponding list controllers, as well as in the custom renderers. To make it easy to use the OCL variable in and , both have the self.evalocl() method available, which uses this specific OCL evaluator. The OCL variable is defined only in this evaluator. The container variables varContainer and varParent contain |
varEndDate | Starting with Vertec 6.6.0.1, for use in resource planning tables. Contains the end date of the resource planning view:
It is available in resource planning views and the corresponding list controllers, as well as in the custom renderers. To make it easy to use the OCL variable in List Controllers and Custom Renderers , both have the self.evalocl() method available, which uses this specific OCL evaluator. The OCL variable is defined only in this evaluator. The container variables varContainer and varParent contain |
varView |
Starting with Vertec 6.6.0.1. Specifies the type of list view. Possible values are:
(varView='default') or (varView='bi') . |
var<Feldname> |
Starting with Vertec 6.1. Access Query parameters in columns of sql and expression folders . |
Comparisons of 2 values (usually a member reference and a constant) are common in OCL expressions, usually as a condition in a select
operator.
The simplest form of a comparison is the identity comparison in the form of a “=” symbol:
projekt->select(code='ABC')
returns a list of all projects whose code exactly matches the string ABC. Normally, this list should include only one project.
The well-known operators for greater, lesser, or unequal (<, >, <>) provide additional possibilities for comparisons. Comparisons can be made with strings and with numbers.
Booleans (true/false values) can also be compared.
If you want to query a Boolean value to true, this is done implicitly (if aktiv then..
or bearbeiter->select(aktiv)
etc.)
The following Boolean operators return all or all and are used to query values, filter lists, etc.
and | Logical AND, that is, both elements associated with AND must be met. invoice->select((date >= encodeDate(2012,01,01)) and (date <= encodeDate(2012,12,31))) |
or | Logical OR, that is, at least one of the two elements which are connected with OR, must be fulfilled. |
xor | Contravalent OR, that is, exactly one of the two elements is fulfilled, either one or the other; neither are both at the same time true nor both at the same time false. |
not | The not operator queries Boolean elements for false. editor->select(not active) |
For string comparisons (or string comparisons) there is also the option to consider substrings. For this purpose there are the following comparison operators:
sqlLike |
It has nothing to do with SQL, except that the format of the pattern string follows the convention in the SQL standard. sqllike uses a pattern string for comparison, which can include wildcard characters. The following example returns all projects whose code begins with “AB”: projekt->select(code->sqllike('AB%')) |
sqlLikeCaseInsensitive |
Same as the previous sqllike, but case insensitive. The following symbols can be used as wildcards:
|
regExpMatch |
Is the most universal operator of the three. It expects a so-called regular expression. The following basic elements can be used in Vertec, case-insensitive: ., *, +, [, ], ^, $, –, \ |
An OCL expression can also contain conditions, but because an expression must always have a certain value, unlike programming languages, only if ... then ... else ... endif
constructs are possible. An example of an if condition follows in the next section about type operators.
To find out what type (class) an object is, you can use oclType
. For example, in a list column, you can show the type of each entry. An example of this is the Data Type column in Vertec’s standard search.
If you query oclType in expressions or a script, oclType.asstring
must be queried, since the oclType itself is None. The list columns do this automatically, but in other locations this must be done explicitly.
There are a number of operators in OCL for converting object types. Of course, you cannot really change the type of an object, OCL is just a query language. However, you may need to specify a type conversion for an OCL expression to be valid.
An example of this are lists of address entries. The class Address entry is the base class for the classes Person, couple, company, contact, Simpleaddress. In most cases, lists of address entries are of the type Collection(address entry). Now the first name attribute of a person object should be displayed in an address list. The OCL expression vorname
in the column settings of an address list leads to the error message “first name is not a member of address entry”.
In order to show the desired information (but only for people), the following expression could be given:
if oclIsTypeOf(Person) then oclAsType(Person).vorname else '' endif
The expression refers to the object in the list and contains two type operators. oclIsTypeOf
checks if the object is of a specific type, and oclAsType
makes the OCL interpreter treat this address as a person and accept the member first name.
If you want to know if an object is an address entry (no matter if it is a person, company, etc.), you can query it with oclIsKindOf
. For example, in a list of mixed objects, you want to show the name if it is an address:
if oclIsKindOf(Adresseintrag) then name.asstring else '' endif
Attributes of type TypeList
– these are the “classes” attributes e.g. on folders, scripts, reports etc. – contain a list of classes. However, the above operators only work on a single object. To find out if a particular class is included, from Vertec 6.7.0.15 onwards there is the operator containsType
on this TypeList attribute. It can be used to query whether a particular class is included in it:
ordner.types.containsType(Projekt)
Starting with Vertec version 6.3.0.12. With the OCL Call operators, specific Python methods can be called from OCL. This makes it possible to write additions to the business logic in Python and use them in different locations instead of the built-in business logic, e.g. in scripts and for presentation in reports.
Because OCL is static and strictly typed, a separate OCL operator is needed for each required combination of return value and arguments. The following are available:
The OCL operators are applied to BusinessclassesRoot and all have the name of the implementing Python function as their first argument. This name is given in the form <Modul>.<Funktionsnamen>
.
A script module called customlogic is created, in which a feature with the signature
def percentofcompletion(project, eff_date)
The call in OCL would then look like this:
proj->callCurrDate('customlogic.percentofcompletion', somedate)
, the result of the OCL expression is a Currency
value.
The name of the call operator used contains the type of the return value and the arguments (return value Currency “Curr,” argument “Date”).
It is important to know that the call operators are queries that execute the corresponding Python code at the time of the query and then show the result. If the data changes in the background, this has no effect on the results of the call operators. These are not automatically recalculated, so the displayed result is only valid at the time of execution.
This means that the call operators are not suitable for locations where dynamic data is to be worked with, e.g. for display on a page.
For list columns, we recommend to use the Custom Renderer instead of call operators, which are subscribed, allow write access, and offer the possibility to set a variety of parameters.
The call operators are suitable in the following cases:
In addition, call operators should not be used to modify data, but only to read data. They are not used to trigger operations such as in an event script, but purely for read access.