Service sums

Use of service sums, groupServices OCL Operator

Product line

Standard

|

Expert

Operating mode

CLOUD ABO

|

ON-PREMISES

Modules

Services & CRM

Budget & Phases

Purchases

Resource Planning

Business Intelligence

Created: 14.11.2003
Machine translated
Updated: 16.07.2024 | 1500 limit no longer exists with Vertec 6.7.0.9 or Firebird 5.

Accelerated summation and grouping in the form of an OCL operator is available for optimizing customer-specific evaluations or for use in user-defined reports.

Operators

The groupLeistungen operator exists in several variants, which differ mainly in that they are applicable to different types of objects:

Operator description
groupServices Global service sum operator. Refers to all services in the system. Since OCL operators must always be based on a specific data type, the operator is registered to TimSession. The fee values are output in key currency.
groupServicesP Performance sum operator for projects. Can be applied to a single project or to a list of projects. The fee values are output in key currency.
groupServicesPW Expense sum operator for projects. Can be applied to a single project or to a list of projects. The fee values are output in project currency.
If this operator is applied to a list of projects, make sure that all projects in the list have the same currency. Otherwise, the amounts in the different currencies will simply be added together, resulting in nonsensical numbers.
groupServicesPWG Calculates all numbers in project currency, i.e. without currency conversion. It is a global operator; that is, the operator is called not on a single object, but on TimSession. Care
must be taken to group by projects, otherwise the numbers in different currencies will be summed. For example: TimSession.allInstances->first->groupPerformancePWG('01.01.2011', '31.12.2011', 'PROJECT’)
groupServicesB User performance sum operator. Can be applied to objects of type project user or lists thereof. The fee values are output in key currency.
groupServicesPh Benefits totals operator for phases. Can be applied to a single project phase or to a list of them. Fee values are output in key currency.
groupServicesPhW This operator is called on project phases and calculates the numbers in project currency.
groupServicesW

Can be accessed on projects, project phases and users. Returns the results in any currency.

groupbenefitsW(from, to, group, currency)

expects a string argument for currency. An empty string returns the results in the key currency. Example in the column of an editor list:

self->groupServicesW('01.01.2016','31.12.2016', '', 'EUR’)->collect(valuetextOpen+valueExtCalculated)->sum

outputs the fee values of all the user’s services in 2016 converted into EUR.

Syntax

The syntax for all these operators is as follows:

<obj>->groupLeistungen(<von>, <bis>, <group>)

The arguments (in square brackets) of the groupLeistungen operator have the following meanings:

obj the base object to which the operator is applied. Can be of type project, project user, or project phase, and lists of the same. Often the base object is the result of a partial OCL expression. For groupPerformance, the operator must be called on the session. The current session can be called from TimSession.allInstances->first:
TimSession.allInstances->first->groupPerformance(...
from, to from, to date of a date period. The services are summed only from the specified period.

The data from and to must be passed as a string in the format dd.mm.yyyy. If an empty string is specified, all services are used.

It must be ensured that the German date format (dd.mm.yyyy) is passed also with other language settings, otherwise there will be an error. For this purpose there is (from Vertec 6.2) the method dateToStrGerman:

<obj>->groupLeistungen(encodeDate(2019,01,01).dateToStrGerman, date.dateToStrGerman, 'PROJEKT')

In older Vertec versions this can be ensured e.g. with the following code:

Import datetime

def DatumGermanFormat(datum):
    """Gibt das Datum in deutschem Format zurück, dd.mm.yyy, als String. 
       Ist das Datum leer, wird ein Leerstring zurückgegeben."""
       
    if datum:
        return datum.strftime("%d.%m.%Y")
    else:
        return ''
group Grouping statement. Contains different grouping terms, separated by commas, and controls the grouping and sorting of the result totals. If an empty string is specified, the list is not grouped. The
following grouping terms can be used:
  • PROJECT: groups the sums of services according to projects
  • USER: grouped by user
  • PHASE: grouped by phases
  • TYPE: grouped by services
  • INVOICE: groups the totals by invoices
  • YEAR: grouped by year
  • MONTH: grouped by months
  • DAY: grouped by days

The result is a list of ServiceSum objects, sorted according to the specified grouping.

Servicesum

These performance sum objects have different sum attributes as well as a value for each grouping term. More specifically, these are the following properties:

Memberdescription
minutesExtOpenTotal of external minutes not yet billed.
minutesExtOpenUnprodTotal of external minutes of services entered on projects with non-productive project types that have not yet been billed.
minutesExtBilledTotal of external billed minutes.
minutesExtBilledUnprodTotal of external billed minutes of services entered on projects with non-productive project types.
minutesIntOpenTotal of internal minutes that have not yet been billed.
minutesIntOpenUnprodTotal internal minutes of services entered on projects with non-productive project types that have not yet been billed.
minutesIntBilledTotal internal billed minutes.
minutesIntBilledUnprodTotal internal billed minutes of services entered on projects with non-productive project types.
powerCountQuantity of services included in this sub-total.
projectProject of this subtotal, if grouped by project.
userUsers, if grouped by user.
phasePhase if grouped by phases.
typeType of service if grouped by type of service.
InvoiceInvoice if grouped by invoices.
dateStart date of the date group (year, month, day), if appropriate grouping.
valueEditorOpenTotal fee values by rate user, not charged.
valueEditorInvoicedTotal fee values charged by rate user.
valueExtOpenTotal of external fee values not yet charged.
valueExtOpenUnprodTotal of the external, not yet charged, fee values of services entered on projects with non-productive project types.
valueExtCalculatedTotal of external charged fee values.
valueExtCalculatedUnprodTotal of external charged fee values of services entered on projects with non-productive project types.
valueIntOpenTotal of internal fee values not yet charged.
valueIntOpenUnprodThe sum of the internal, not yet charged, fee values of services entered on projects with non-productive project types.
valueIntCalculatedTotal of internal charged fee values.
valueIntBilledUnprodTotal of internal invoiced fee values of services entered on projects with non-productive project types.
valueCostOpenTotal fee values according to cost rate, not charged.
valueCostsBilledSum of the fee values according to cost rate, charged.

Example

On a project (or a list of projects) the operator groupLeistungenP is applied. The date period is January to December. We want the totals grouped by months and projects, the given grouping statement ('MONTH,PROJECT’) does this.

->groupServicesP('01.01.2016','31.12.2016','MONTH,PROJEKT’)

As a result, we get a list of LeistSum objects. These include, for example, the following attributes:

  • Month: datum.formatDateTime('mm.yyyy')
  • Project: projekt
  • Internal hours: minutenintOffen + minutenIntVerrechnet
  • External value: wertExtOffen + wertExtVerrechnet

Special Cases

Special cases for calculation arise, for example, in the case of fixed-price invoices without services or in the case of invoice discounts. In this case, the external value of the services cannot simply be used to calculate the service sums. How these special cases are dealt with in detail is explained below:

Special case Calculation

Fixed-price phases without services

(if the phase is on a fixed-price invoice without services, see there)

Is shown as the sum of services as follows:

  • Date: End date of the phase
  • User: Project leader of the project. In case of invoiced invoice, fixed project leader of the invoice (verrproject leader)
  • ValueExt: PlanValueExt of the phase. If there is a discount on the invoice, it will be deducted proportionally (phase.planwertext / rechnung.LeistWertExt) from ValueExt.
  • ValueInt: PlanValueInt of the phase
  • ValueCosts: PlanValueCosts of the phase
This applies to fixed-price phases without services which have no subphases. As soon as a fixed-price phase without services has subphases, the calculation is carried out on the subphases. For the parent phase there is then no calculation or service sum.
Fixed-price invoice without services

Is shown as the sum of services as follows:

  • Date: Value date of the invoice
  • User: Project leader of the project. If on invoiced invoice, fixed project leader of the invoice (verrProjektleiter)
  • ValueExt: Fixed amount of the invoice. If there is a discount on the invoice, it will be deducted again (-totalrabattbetrag).
  • ValueInt: fixed amount of the invoice.
Invoices with discount

If it has an invoice, the discount will be deducted from the ValueExt of the sum of services in proportion.
This percentage is calculated as follows:

wertExt – (rechnung.totalRabattBetrag * wertExt / rechnung.leistWertExt)

Flat-rate phases and invoices with fixed services

In the case of flat-rate invoices or flat-rate phases, the flat-rate value is always distributed proportionally to the external values of the services on which they are located (see also values in flat-rate phases and invoices), which are not fixed, i.e. have not set the Fix external values check mark. Therefore, this does not play any role for the calculation of the service sums, the value of the services is simply taken. However,

if ALL services of an invoice are fixed, then the flat-rate amount cannot be allocated to the services. In this case, the sums of benefits cannot reflect the fixed amount.

Sum of services <> sum of services

On the basis of these special cases, deviation can of course arise between the sum of the services and the summed sums of the services. In this case, for example:

offeneleistungen->union(verrechneteleistungen)->select((datum >= encodedate(1990,1,1)) 
and (datum < encodedate(2018,1,1))).wertExt->sum

a value other than:

self->groupleistungenP('01.01.1990','01.01.2018','')->collect(wertExtOffen + wertExtVerrechnet)->sum

If this is the case for you, check if it has any of the above-mentioned special cases in the analysed period.

In the case of fixed services on fixed-price phases or invoices, no difference can be determined here, since neither the services nor the service sums include the lump sum. In this case, you will only recognise the difference if you compare the sums of the services with the sums of the invoices.

Limitation for large amounts of data and firebird < 5

Vertec ships with Firebird 5 from version 6.7.0.9 onwards. Starting with this version, this problem no longer exists. However, if a groupLeistungenX operator is called on a list of projects, phases, or users with an earlier Firebird version, there is the following limitation:

If the list of calling objects (i.e. not the quantity of services in the result, but the projects, phases or users on which the operator is called) is greater than 1500 entries, there is an error from the Firebird server due to invalid SQL:

General SQL Error.
Implementation limit exceeded
too many values (more than 1500) in member list
to match against.

One way to work around this problem is to use the global groupLeistungen operator, which applies to all services.

Example: If there are more than 1500 projects and you want to call projekt->groupLeistungenP(...), you can work around this:

TimSession.allInstances->first->groupLeistungen('', '', 'PROJEKT')

Returns a list of ServiceSums of all services in the system, grouped by project.

Performance behaviour of service sums

Since the service sums are calculated optimally via SQL, the behavior in case of changes to basic data is slightly different than usual in Vertec.

Service sums are generally recalculated as soon as any service is changed in the system. However, the recalculation only takes place if the service sum figures are also visible. For example, it is not advisable to have a list of service sums on the screen at the same time when entering new services, as this would be recalculated for each new service. The calculation of service sums is relatively fast, but the delay is still noticeable if the recalculation is carried out unnecessarily frequently.

In particular, it is not recommended to use groupLeistungen operators in column expressions of lists, since the performance gain in calculating the sum is usually overcompensated by the large quantity of individual SQL queries.

Shadow Attributes

Various values in the Vertec are derived, that is, they are calculated each time they are accessed. This means that they are always up-to-date, but not retrievable in the database.

To ensure that these values are still available for accelerated summing, there are so-called shadow attributes, which are written when calculating the derived attributes. These shadow attributes are persistent, i.e. they are located in the database and can be queried directly.

The following shadow attributes are available. They are prefixed with sql.

Attributes Classes

sqlValueExt

Service, expenses, outlays

sqlMinutesExt

service

sqlValueInt, sqlDiscountAmount

Expenses and outlays

sqlDiscount Amount (only versions before 6.4.0.17)

invoice

sqlCurrencyDate (only versions before 6.4.0.17)

invoice