Leistungssummen

Produktlinien: Standard, Expert
Module: Leistung & CRM, Budget & Teilprojekt
Erstellt: 14.11.2003, Änderung:
Shadow Attribute aus separatem Artikel hier integriert.
Mehr ansehen

Für die Optimierung von kundenspezifischen Auswertungen oder zur Verwendung in benutzerdefinierten Berichten steht eine beschleunigte Summierung und Gruppierung in Form eines OCL Operators zu Verfügung.

Operatoren

Der groupLeistungen Operator existiert in verschiedenen Varianten, die sich vor allem dadurch unterscheiden, dass sie auf verschiedene Typen von Objekten anwendbar sind:

OperatorBeschreibung
groupLeistungenGlobaler Leistungssummen-Operator. Bezieht sich auf alle Leistungen im System. Da OCL Operatoren immer auf einem bestimmten Datentyp basieren müssen, ist der Operator auf TimSession registriert. Die Honorar-Werte werden in Leitwährung ausgegeben.
groupLeistungenPLeistungssummen-Operator für Projekte. Kann auf ein einzelnes Projekt oder auf eine Liste von Projekten angewandt werden. Die Honorar-Werte werden in Leitwährung ausgegeben.
groupLeistungenPWAb Version 5.3.1.19. Leistungssummen-Operator für Projekte. Kann auf einem einzelnen Projekt oder auf einer Liste von Projekten angewandt werden. Die Honorarwerte werden in Projektwährung ausgegeben.
Falls dieser Operator auf einer Liste von Projekten angewandt wird, muss sichergestellt werden, dass alle Projekte in der Liste die gleiche Währung haben. Ansonsten werden einfach die Beträge in den verschiedenen Währungen zusammengezählt, was unsinnige Zahlen ergeben würde.
groupLeistungenPWGAb Version 5.7. Berechnet alle Zahlen in Projektwährung, also ohne Währungsumrechnung. Es handelt sich um einen globalen Operatoren; das heisst, dass der Operator nicht auf einem einzelnen Objekt, sondern auf TimSession aufgerufen wird.
Es muss darauf geachtet werden, dass nach Projekten gruppiert wird, sonst werden die Zahlen in verschiedenen Währungen summiert. Der Aufruf erfolgt also beispielsweise so: TimSession.allInstances->first->groupLeistungenPWG('01.01.2011', '31.12.2011', 'PROJEKT')
groupLeistungenBLeistungssummen-Operator für Bearbeiter. Kann auf Objekte des Typs Projektbearbeiter oder auf Listen davon angewandt werden. Die Honorar-Werte werden in Leitwährung ausgegeben.
groupLeistungenPhLeistungssummen-Operator für Phasen. Kann auf eine einzelne Projektphase oder auf eine Liste davon angewandt werden. Die Honorar-Werte werden in Leitwährung ausgegeben.
groupLeistungenPhWAb Version 5.7. Dieser Operator wird auf Projektphasen aufgerufen und berechnet die Zahlen in Projektwährung.
groupLeistungenW

Ab Version 6.0. Kann auf Projekten, Projektphasen und Bearbeitern aufgerufen werden. Liefert die Ergebnisse in einer beliebigen Währung.

groupLeistungenW(von, bis, group, waehrung)

erwartet ein String-Argument für Währung. Ein Leerstring gibt die Resultate in der Leitwährung zurück. Beispiel in der Spalte einer Bearbeiterliste:

self->groupLeistungenW('01.01.2016','31.12.2016', '', 'EUR')->collect(wertextOffen+wertExtVerrechnet)->sum

gibt die Honorarwerte aller Leistungen 2016 des Bearbeiters umgerechnet in EUR aus.

Syntax

Die Syntax für alle diese Operatoren lautet wie folgt:

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

Die Argumente (in spitzen Klammern) des groupLeistungen Operators haben folgende Bedeutungen:

obj das Basisobjekt, auf das der Operator angewendet wird. Kann vom Typ Projekt, Projektbearbeiter oder Projektphase, sowie Listen derselben sein. Vielfach ist das Basisobjekt das Ergebnis einer Teil-OCL Expression. Bei groupLeistungen muss der Operator auf der Session aufgerufen werden. Die aktuelle Session kann aufgerufen werden über TimSession.allInstances->first:
TimSession.allInstances->first->groupLeistungen(...
von, bis von, bis Datum einer Datumsperiode. Die Leistungen werden nur aus der angebebenen Periode summiert.

Die Daten von und bis müssen als Zeichenkette im Format dd.mm.yyyy übergeben werden. Wird ein Leerstring angegeben, werden alle Leistungen verwendet.

Es muss sichergestellt sein, dass auch mit anderssprachigen Einstellungen das deutsche Datumsformat (dd.mm.yyyy) übergeben wird, sonst gibt es einen Fehler. Dafür gibt es (ab Vertec 6.2) die Methode dateToStrGerman:

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

In älteren Vertec Versionen kann das z.B. mit folgendem Code sichergestellt werden:

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 Gruppierungsanweisung. Enthält verschiedene Gruppierbegriffe, durch Kommas getrennt und steuert die Gruppierung und Sortierung der Ergebnissummen. Wird ein Leerstring angegeben, wird die Liste nicht gruppiert.
Folgende Gruppierbegriffe können verwendet werden:
  • PROJEKT: gruppiert die Leistungssummen nach Projekten
  • BEARBEITER: gruppiert nach Bearbeitern
  • PHASE: gruppiert nach Phasen
  • TYP: gruppiert nach Tätigkeiten
  • RECHNUNG: gruppiert die Summen nach Rechnungen
  • YEAR: gruppiert nach Jahren
  • MONTH: gruppiert nach Monaten
  • DAY: gruppiert nach Tagen

Als Ergebnis erhalten Sie eine Liste von Objekten des Typs LeistSum. Diese werden jeweils gemäss der angegebenen Gruppierung sortiert.

LeistSum

Diese Leistungssummen-Objekte besitzen verschiedene Summenattribute sowie einen Wert für jeden Gruppierbegriff. Im Detail sind dies die folgenden Eigenschaften:

MemberBeschreibung
minutenExtOffenSumme der externen, noch nicht verrechneten Minuten.
minutenExtOffenUnprodSumme der externen, noch nicht verrechneten Minuten von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
minutenExtVerrechnetSumme der externen, verrechneten Minuten.
minutenExtVerrechnetUnprodSumme der externen, verrechneten Minuten von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
minutenIntOffenSumme der internen, noch nicht verrechneten Minuten.
minutenIntOffenUnprodSumme der internen, noch nicht verrechneten Minuten von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
minutenIntVerrechnetSumme der internen, verrechneten Minuten.
minutenIntVerrechnetUnprodSumme der internen, verrechneten Minuten von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
leistungCountAnzahl der Leistungen in dieser Teilsumme.
projektProjekt dieser Teilsumme, falls nach Projekt gruppiert.
bearbeiterBearbeiter, falls nach Bearbeiter gruppiert.
phasePhase falls nach Phasen gruppiert.
typTätigkeit falls nach Tätigkeiten gruppiert.
rechnungRechnung falls Gruppierung nach Rechnungen.
datumAnfangsdatum der Datumsgruppe (Jahr, Monat, Tag), falls entsprechende Gruppierung.
wertBearbeiterOffenSumme der Honorarwerte nach Ansatz Bearbeiter, nicht verrechnet.
wertBearbeiterVerrechnetSumme der Honorarwerte nach Ansatz Bearbeiter, verrechnet.
wertExtOffenSumme der externen, noch nicht verrechneten Honorarwerte.
wertExtOffenUnprodSumme der externen, noch nicht verrechneten Honorarwerte von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
wertExtVerrechnetSumme der externen, verrechneten Honorarwerte.
wertExtVerrechnetUnprodSumme der externen, verrechneten Honorarwerte von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
wertIntOffenSumme der internen, noch nicht verrechneten Honorarwerte.
wertIntOffenUnprodSumme der internen, noch nicht verrechneten Honorarwerte von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
wertIntVerrechnetSumme der internen, verrechneten Honorarwerte.
wertIntVerrechnetUnprodSumme der internen, verrechneten Honorarwerte von Leistungen, die auf Projekten mit unproduktiven Projekttypen erfasst wurden.
wertKostenOffenSumme der Honorarwerte nach Kostensatz, nicht verrechnet.
wertKostenVerrechnetSumme der Honorarwerte nach Kostensatz, verrechnet.

Beispiel

Auf einem Projekt (oder einer Liste von Projekten) wird der Operator groupLeistungenP angewendet. Als Datumsperiode wird Januar bis Dezember angegeben. Wir möchten die Summen gruppiert nach Monaten und Projekten, die angegebene Gruppieranweisung ('MONTH,PROJEKT') macht dies.

->groupLeistungenP('01.01.2016','31.12.2016','MONTH,PROJEKT')

Als Resultat erhalten wir eine Liste von LeistSum Objekten. Diese enthalten beispielsweise folgende Attribute:

  • Monat: datum.formatDateTime('mm.yyyy')
  • Projekt: projekt
  • Aufwand intern: minutenintOffen + minutenIntVerrechnet
  • Wert extern: wertExtOffen + wertExtVerrechnet

Spezialfälle

Speziallfälle für die Berechnung ergeben sich zum Beispiel bei pauschalen Rechnungen ohne Leistungen oder bei Rechnungsrabatten. In diesem Fall kann nicht einfach der externe Wert der Leistungen für die Berechnung der Leistungssummen verwendet werden. Wie diese Spezialfälle im Detail behandelt werden, ist hier nachfolgend erklärt:

Spezialfall Berechnung

Pauschale Phasen ohne Leistungen

(falls sich die Phase auf einer pauschalen Rechnung ohne Leistungen befindet, siehe dort)

Wird wie folgt als Leistungssumme abgebildet:

  • Datum: Abschlussdatum der Phase
  • Bearbeiter: Projektleiter des Projekts. Falls auf verrechneter Rechnung, fixierter Projektleiter der Rechnung (verrProjektleiter)
  • WertExt: PlanWertExt der Phase. Falls es auf der Rechnung einen Rabatt hat, wird dieser anteilsmässig (phase.planwertext / rechnung.LeistWertExt) vom WertExt wieder abgezogen.
  • WertInt: PlanWertInt der Phase
  • WertKosten: PlanWertKosten der Phase
Dies gilt für pauschale Phasen ohne Leistungen, welche keine Subphasen haben. Sobald eine pauschale Phase ohne Leistungen Subphasen hat, wird die Berechnung auf den Subphasen durchgeführt. Für die Parentphase gibt es dann keine Berechnung bzw. keine Leistungssumme.
Pauschale Rechnung ohne Leistungen

Wird wie folgt als Leistungssumme abgebildet:

  • Datum: Valutadatum der Rechnung
  • Bearbeiter: Projektleiter des Projekts. Falls auf verrechneter Rechnung, fixierter Projektleiter der Rechnung (verrProjektleiter)
  • WertExt: Pauschalbetrag der Rechnung. Falls es auf der Rechnung einen Rabatt hat, wird dieser wieder abgezogen (-totalrabattbetrag).
  • WertInt: Pauschalbetrag der Rechnung.
Rechnungen mit Rabatt

Falls es eine Rechnung hat, wird vom WertExt der Leistungssumme anteilsmässig der Rabatt abgezogen.
Dieser Anteil wird wie folgt berechnet:

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

Pauschalphasen und -rechnungen mit fixierten Leistungen

Bei pauschalen Rechnungen bzw. bei Pauschalphasen wird der Pauschalwert immer anteilsmässig auf die externen Werte der sich darauf befindlichen Leistungen verteilt (siehe auch Werte bei Pauschalphasen und -rechnungen), welche nicht fixiert sind, also das externe Werte fixieren-Häkchen nicht gesetzt haben. Deshalb spielt das für die Berechnung der Leistungssummen keine Rolle, es wird einfach der Wert der Leistungen genommen.

Sind jedoch ALLE Leistungen einer Rechnung fixiert, dann kann der Pauschalbetrag nicht auf die Leistungen umgelegt werden. In diesem Fall können die Leistungssummen den Pauschalbetrag nicht abbilden.

Leistungssummen <> Summe der Leistungen

Aufgrund dieser Spezialfälle können sich natürlich Abweichungen ergeben zwischen der Summe der Leistungen und den summierten Leistungssummen. In diesem Fall ergibt dann beispielsweise:

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

einen anderen Wert als:

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

Ist das bei Ihnen der Fall, schauen Sie, ob es im analysierten Zeitraum obengenannte Spezialfälle hat.

Im Falle der fixierten Leistungen auf pauschalen Phasen bzw. Rechnungen kann hier keine Differenz festgestellt werden, da weder die Leistungen noch die Leistungssummen den Pauschalbetrag enthalten. In diesem Fall erkennen Sie die Differenz nur, wenn Sie die Summen der Leistungen mit den Summen der Rechnungen vergleichen.

Einschränkung bei grossen Datenmengen und Firebird

Wird ein groupLeistungenX Operator auf einer Liste von Projekten, Phasen oder Bearbeiter aufgerufen, gibt es folgende Einschränkung:

Wenn die Liste der aufrufenden Objekte (also nicht die Anzahl Leistungen im Ergebnis, sondern die Projekte, Phasen oder Bearbeiter, auf denen der Operator aufgerufen wird) grösser ist als 1500 Einträge, gibt es einen Fehler vom Firebird-Server wegen unzulässigem SQL:

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

Eine Möglichkeit, dieses Problem zu umgehen, ist die Verwendung des globalen groupLeistungen Operators, der sich auf alle Leistungen bezieht.

Beispiel: Sind mehr als 1500 Projekte vorhanden, und es soll projekt->groupLeistungenP(...) aufgerufen werden, kann das so umgangen werden:

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

Ergibt eine Liste von LeistSums über alle Leistungen im System, gruppiert nach Projekten.

Performance Verhalten von Leistungssummen

Da die Leistungssummen optimiert via SQL berechnet werden, ist das Verhalten bei Veränderungen von Grundlagendaten geringfügig anders als sonst in Vertec.

Leistungssummen werden grundsätzlich neu berechnet, sobald irgendeine Leistung im System verändert wird. Die Neuberechnung erfolgt jedoch nur, wenn die Zahlen der Leistungssumme auch sichtbar sind. Zum Beispiel ist es nicht empfehlenswert beim Erfassen von neuen Leistungen gleichzeitig eine Liste mir Leistungssummen auf dem Bildschirm zu haben, da diese bei jeder neuen Leistung neu berechnet würde. Die Berechnung von Leistungssummen geht zwar relativ schnell, aber bei unnötig häufigem Neuberechnen ist die Verzögerung trotzdem spürbar.

Insbesondere ist es nicht zu empfehlen, groupLeistungen Operatoren in Spaltenexpressions von Listen zu verwenden, da der Performance Gewinn beim Berechnen der Summe durch die grosse Anzahl einzelner SQL Anfragen in der Regel überkompensiert wird.

Shadow Attribute

Diverse Werte im Vertec sind derived, das heisst, sie werden jeweils bei Zugriff berechnet. Das bedeutet, sie sind dadurch immer aktuell, aber nicht in der Datenbank abrufbar.

Damit diese Werte für die beschleunigte Summierung trotzdem zur Verfügung stehen, gibt es sogenannte Shadow Attribute, welche bei der Berechnung der derived Attribute geschrieben werden. Diese Shadow Attributes sind persistent, das heisst, sie befinden sich in der Datenbank und können direkt abgefragt werden.

Folgende Shadow Attribute sind verfügbar. Sie haben als Präfix jeweils sql.

Attribut Klasse

sqlWertExt

Leistung, Spesen, Auslagen

sqlMinutenExt

Leistung

sqlWertInt, sqlRabattBetrag

Spesen und Auslagen

sqlRabattBetrag

Rechnung

sqlValutaDatum

Rechnung