Vertec AI Chatbot

Der Chatbot hilft Ihnen bei Fragen rund um das Produkt und die Anpassbarkeit der Software. Wie bei allen AI-generierten Daten sollten die Antworten bei kritischen Informationen verifiziert werden. Nehmen Sie dafür gerne Kontakt mit uns auf. Weitere Informationen zur Verarbeitung der Chat-Daten bieten wir auf der Datenschutzseite.

Die besten Antworten liefert der Chatbot, wenn Ihr Input möglichst viele Informationen enthält. Zum Beispiel:

«Welche Apps stehen im Vertec Cloud Abo zur Verfügung?»

OCL, Python, Custom Renderer und List Controller rund um die Ressourcenplanung

OCL, Python, Renderer und List Controller rund um die Ressourcenplanung

Produktlinie

Standard

|

Expert

Betriebsart

CLOUD ABO

|

ON-PREMISES

Module

Leistung & CRM

Budget & Teilprojekt

Fremdkosten

Ressourcenplanung

Business Intelligence

Erstellt: 27.03.2023
Aktualisiert: 14.12.2023 | Neue Renderer vtcplanning.CustomNetCapacityRenderer und vtcplanning.CustomRemainingCapacityRenderer mit Vertec 6.7.0.5.

Inhalt

Custom Renderer für Ressourcenplanungstabellen Soll-Ist-Vergleiche / Weitere Kennzahlen anzeigen

In Listen innerhalb der Ressourcenplanung

In Listen ausserhalb der Ressourcenplanung

Python Methode zum Setzen von Ressourcenplanwerten
OCL Variablen für die Ressourcenplanung
List Controller in der Ressourcenplanung
Auswertungen mittels Business Intelligence (BI) Modul
In a Nutshell

Custom Renderer für Ressourcenplanungstabellen

Für die Verwendung in Zeit- und Pivottabellen der Ressourcenplanung gibt es folgende mitgelieferte Custom Renderer für die Listeneinstellungen:

Custom Renderer Wert
vtcplanning.PlannedMinutesRenderer

Eingabe (und Anzeige) der Planwerte in den einzelnen Zellen

vtcplanning.NetCapacityRenderer

Netto-Verfügbarkeit von Bearbeitern

vtcplanning.CustomNetCapacityRenderer

Ab Vertec 6.7.0.5. Netto-Verfügbarkeit von Bearbeitern unter Berücksichtigung der Systemeinstellung Angepasste Nettokapazität (Prozent).

vtcplanning.GrossCapacityRenderer

Brutto-Verfügbarkeit von Bearbeitern

vtcplanning.RemainingCapacityRenderer

Rest-Verfügbarkeit von Bearbeitern

vtcplanning.CustomRemainingCapacityRenderer

Ab Vertec 6.7.0.5. Rest-Verfügbarkeit von Bearbeitern unter Berücksichtigung der Systemeinstellung Angepasste Nettokapazität (Prozent).

All diese Renderer können auf zwei Arten verwendet werden:

  • Dynamisch (pro Spalte wiederholt)

    Dynamisch bedeutet, dass die Spalte für jeden Eintrag nach rechts wiederholt wird, also in Zeittabellen pro Intervall, in Pivottabellen pro Bearbeiter, Projekt oder Phase.

    In diesem Fall zeigt die Zelle den Wert an, welcher zur Kombination Zeile/Spalte passt.

    • Expression: %col%
    • Dynamisch: Ja
  • Statisch (als Summe pro Zeile)

    Ist die Spalte nicht als dynamisch markiert, wird sie nur einmal pro Liste angezeigt.

    Der angezeigte Wert bezieht sich also auf die ganze Liste und zeigt den summierten Wert über alle Spalten.

    • Expression: leer
    • Dynamisch: Nein

Diese Renderer basieren auf den im Modul vtcplanning mitgelieferten List Controllern und können darum innerhalb der Ressourcenplanung in den Listen einfach eingefügt werden.

Um sie auch ausserhalb der Ressourcenplanung zu verwenden, muss von einem dieser Controller geerbt und gewisse Methoden implementiert werden. Informationen dazu finden Sie im Abschnitt Ausserhalb der Ressourcenplanung.

Python Methode zum Setzen von Ressourcenplanwerten

Für die Ressourcenplanung steht die Methode setresourceplanvalue zur Verfügung, mit welcher Ressourcenplanwerte via Python Code gesetzt werden können:

  • Auf Projektbearbeiter , PlanningWorker (Planungsbearbeiter) und AbstractWorker (Basisklasse der beiden):

    setresourceplanvalue(project_or_phase, date, value)

    project / phase Je nach eingestellter Planungsebene muss hier ein Projekt oder eine Projektphase angegeben werden.
    date Es wird diejenige Periode mit dem Value gefüllt, in welcher sich das Datum befindet.
    value Wert in Minuten.
    bearb = vtcapp.currentlogin()
    projekt = argobject
    bearb.setresourceplanvalue(projekt, vtcapp.strtodate('15.05.2023'), 180)
  • Auf Projekt oder Phase :

    setresourceplanvalue(worker, date, value)

    worker Als worker wird ein Planungsbearbeiter oder ein Projektbearbeiter übergeben.
    date Es wird diejenige Periode mit dem Value gefüllt, in welcher sich das Datum befindet.
    value Wert in Minuten.
    bearb = vtcapp.currentlogin()
    projekt = argobject
    projekt.setresourceplanvalue(bearb, vtcapp.strtodate('15.05.2023'), 180)

Die bereits in Versionen vor 6.6 verfügbare Methode auf vtcapp : vtcapp.setresourceplanvalue(bearbeiter, projekt, phase, date, intervalType, value) funktioniert weiterhin, der intervalType wird jedoch nicht mehr berücksichtigt (muss jedoch trotzdem angegeben werden).

OCL Variablen für die Ressourcenplanung

Die speziell verfügbaren OCL Variablen stehen unter anderem auch in der Ressourcenplanung zur Verfügung. Hier wichtig sind vor allem die folgenden:

varStartDate Das Start-Datum der Ressourcenplanungsansicht:
  • Zeittabelle: Start-Datum des ersten Intervalls in Periode
  • Pivottabelle: Start-Datum des Intervalls
varEndDate Das End-Datum der Ressourcenplanungsansicht:
  • Zeittabelle: End-Datum des letzten Intervalls in Periode
  • Pivottabelle: End-Datum des Intervalls
varContext

Enthält den aktuell im Baum ausgewählten Eintrag (siehe Bild unten).

Die Variable ermöglicht in der Ressourcenplanung die Anpassung von Listen in Abhängigkeit davon, ob eine Ressourcenplanungsansicht für Einzelobjekte oder Listen angezeigt wird.

varParent Enthält das Objekt, welchem der im Baum ausgewählte Container gehört (siehe Bild unten). Auf Einzelobjekten ist diese Variable leer.

In Listenspalten von Ressourcenplanungstabellen sowie in darin enthaltenen List Controllern und Custom Renderern kann auf diese Variablen zugegriffen werden, da in der self.evalocl() Methode ein spezifischer OCL Evaluator angewendet wird, in welchem diese Variablen verfügbar sind.

List Controller in der Ressourcenplanung

Im Gegensatz zu den sonstigen Listen in Vertec, wo auf List Controller aus den Spalten heraus zugegriffen werden kann, werden die Darstellungen in der Ressourcenplanung von den List Controllern direkt berechnet.

Bei Verwendung von List Controllern in der Ressourcenplanung stehen zusätzlich folgende Methoden zur Verfügung:

initialize_with_period(self, start, end, subscriber)
Spezielle Variante von initialize für die Ressourcenplanung, welche zusätzlich Start und Ende der gesamten Periode erhält und den ResourcePlanningProvider initialisiert.
get_row_objects(self, subscriber)

Berechnet die Zeilenobjekte, die in der Liste dargestellt werden.

Für Ressourcenplanungsansichten werden so alle Zeilen bestimmt, für die ein Planwert eingetragen ist.

get_row_objects_type(self)

Berechnet den Typ der Zeilenobjekte. Falls dieser konstant ist, kann er auch als Attribut row_objects_type angegeben werden.

Nur in Kombination mit get_row_objects sinnvoll. Nur für Ressourcenplanungsansichten unterstützt.

add_row_object(self, obj)

Wird verwendet für die Sternzeilen-Funktionalität, um weitere zu planende Einträge in die Liste einzufügen.

Diese Methode muss vorhanden sein, damit bei Listen mit List Controller und eingeschalteter Option "Hinzufügen-Zeile anzeigen" eine Sternzeile angezeigt wird. Nur für Ressourcenplanungsansichten unterstützt.

Sämtlichen Ressourcenplanungsansichten und Auslastungsdimensionen steht ein List Controller zugrunde. Diese werden im Modul vtcplanning mitgeliefert.

Um Tabellen oder Grafiken in der Ressourcenplanung zu erstellen oder zu erweitern, kann von diesen Controllern geerbt werden. Damit stehen je nach Controller noch weitere Methoden zur Verfügung, siehe Beispiel Erben von einem bestehenden List Controller.

Soll-Ist-Vergleiche / Weitere Kennzahlen anzeigen

Aus Gründen der Performance raten wir davon ab, Ist-Werte direkt in Ressourcentabellen anzuzeigen, wo auch geplant wird, insbesondere nicht für jedes Intervall.

Für Auswertungen mit Ressourcenplanwerten gibt es verschiedene Möglichkeiten.

In Listen innerhalb der Ressourcenplanung

Erben von einem bestehenden List Controller

Wir raten, Auswertungs-Spalten nicht direkt in Ressourcentabellen anzuzeigen, in welchen auch geplant wird, um diese Listen jederzeit performant zu halten.

Es lassen sich aber leicht weitere Ressourcenplanungsansichten erstellen, welche zu Auswertungszwecken angezeigt werden können. Dafür kann vom List Controller der Tabelle, welche man erweitern möchte, geerbt werden.

Zuerst wird der Name des List Controllers eruiert, von welchem man erben möchte. Im Beispiel möchten wir eine Zeittabelle mit weiteren Werten ausstatten.

Unter Einstellungen > Ressourcenplanung > Ressourcenplanungsansichten suche ich die Tabelle heraus, von der ich erben möchte. Hier zum Beispiel die Projekte - Bearbeiter Zeittabelle:

Im Feld List Controller ist der Controller angegeben, von welchem wir erben möchten: vtcplanning.SingeObjectTimeTableController. Über den Button mit den drei Punkten kann der entsprechende Code eingesehen werden. Eine Liste aller mitgelieferten Controller finden Sie in der Beschreibung des Moduls "vtcplanning".

Nun erstellen wir einen Scripteintrag für unseren List Controller und erben vom oben genannten Controller:

import vtcplanning
class Controller(vtcplanning.SingleObjectTimeTableController):
    pass

Damit haben wir nun einen vollwertigen Controller, der dasselbe macht und die gleichen Renderer zur Verfügung stellt wie der originale.

Diesen können wir bereits als List Controller in unserer Ansicht eintragen. Dafür erstellen wir eine neue Ressourcenplanungsansicht und fügen ihn hinzu, in unserem Beispiel:

Zum Test kann die Tabelle in der Ressourcenplanung nun angezeigt werden. Sie sollte genau gleich aussehen wie die, von welcher wir ausgingen.

Hier stehen uns nun alle Methoden und Attribute eines List Controllers sowie der ResourcePlanningProvider zur Verfügung.

Nun erweitern wir unseren Controller um die um die gewünschten Auswertungswerte. In unserem Beispiel möchten wir folgende zusätzliche Spalten anzeigen:

  1. Bereits geleistete Zeit in diesem Intervall.
  2. Anteil der bereits geleisteten Zeit an der geplanten Zeit.

Die Werte sollen vorberechnet werden, also nicht in jeder Zelle einzeln evaluiert werden. Dafür erweitern wir die initialize_with_period Methode unseres Controllers und berechnen die Werte vor.

Es gilt: Sobald eine Methode überschrieben wird, wird die originale Methode nicht mehr ausgeführt. Möchte man also eine Methode erweitern, muss das, was die originale Methode macht, nochmal ausgelöst werden. Dafür rufen wir sie zuerst nochmal auf (einfach 1:1 kopieren):

import vtcplanning

class Controller(vtcplanning.SingleObjectTimeTableController):

    def initialize_with_period(self, start, end, subscriber):

        vtcplanning.SingleObjectTimeTableController.initialize_with_period(self, start, end, subscriber)

Nun sind wir gleich weit und können unsere Werte vorberechnen.

Zu beachten ist folgendes: Die mitgelieferten Controller wie der vtcplanning.SingleObjectTimeTableController sind allgemein gehalten, können also auf Bearbeitern, Projekten und Projektphasen gleichermassen verwendet werden. Möchten wir unseren Controller ebenso erweitern, müssen wir darauf achten, dass die Expressions, die wir verwenden, für alle Fälle verwendbar sind.

Hier im Beispiel gehen wir von der Planungsebene Projekt aus. Wir decken also Projekte und Bearbeiter ab. Unsere Ist-Werte evaluieren wir mittels Leistungssummen.

import vtcplanning

class Controller(vtcplanning.SingleObjectTimeTableController):

    def initialize_with_period(self, start, end, subscriber):
    
        vtcplanning.SingleObjectTimeTableController.initialize_with_period(self, start, end, subscriber)
        
        # Calculation of the leistsum objects. Consider the different Object types
        obj = self.context
        if obj.istypeof("Projekt"):
            self.leistSumList = obj.evalocl("self->groupleistungenP('{}','{}','MONTH, BEARBEITER')".format(vtcapp.datetostrgerman(start), vtcapp.datetostrgerman(end)))
            self.oclMember = "bearbeiter"
        if obj.istypeof("Projektbearbeiter"):
            self.leistSumList = obj.evalocl("self->groupleistungenB('{}','{}','MONTH, PROJEKT')".format(vtcapp.datetostrgerman(start), vtcapp.datetostrgerman(end)))
            self.oclMember = "projekt"             

Nun haben wir eine Liste der Werte über die gesamte Periode, gruppiert nach Intervall (im Beispiel Monat).

Einen eigenen Renderer schreiben

Damit sind die Werte vorberechnet und im Controller verfügbar. Nun brauchen wir einen Custom Renderer für die Ist-Spalte. Dafür erben wir vom vtcplanning.MinutesRendererBase, um dessen Methode get_column_index_from_expression anwenden zu können.

Wir evaluieren das Start-Datum der aktuellen Spalte und filtern dann die im Controller vorgeladene Liste von Leistungssummen nach Datum sowie nach dem aktuellen Objekt:

class AufwandExtRenderer(vtcplanning.MinutesRendererBase):

    is_readonly = True
    
    # Summiert MinutenExt für den Zeitraum
    def get_value(self, rowobj, expression, subscriber):
        column_index = self.get_column_index_from_expression(expression)  
        start_date = vtcapp.datetostr(self.controller.get_date_by_column_index(column_index))
        return self.controller.leistSumList.evalocl("self->select(datum.asstring = '{}')->select({}.objid={})->collect(minutenextoffen+minutenextverrechnet)->sum".format(start_date, self.controller.oclMember, rowobj.objid),subscriber)

Nun können wir die Ist-Spalte in die Liste einfügen:

Nun möchten wir noch den Anteil der bereits geleisteten Zeit an der geplanten Zeit ausgeben. Dafür erstellen wir einen neuen Renderer, in welchem wir sowohl auf die vorgeladene Liste von Leistungssummen als auch auf die geplanten Werte zugreifen.

class AufwandAnteilRenderer(vtcplanning.MinutesRendererBase):

    is_readonly = True
    converter=None
    value_type="float"
    
    # Berechnet den Anteil der geleisteten an den geplanten Zeiten
    def get_value(self, rowobj, expression, subscriber):
        
        column_index = self.get_column_index_from_expression(expression)  
        start_date = vtcapp.datetostr(self.controller.get_date_by_column_index(column_index))
        planwert = self.controller.get_planned_minutes(column_index, rowobj, subscriber)
        
        aufwandext = self.controller.leistSumList.evalocl("self->select(datum.asstring = '{}')->select({}.objid={})->collect(minutenextoffen+minutenextverrechnet)->sum".format(start_date, self.controller.oclMember, rowobj.objid),subscriber)
        if planwert:            
            return float(aufwandext)/float(planwert)

Einen zusätzlichen ResourcePlanningProvider erstellen

Solange die Werte in der Liste pro Zeile, Spalte und Intervall berechnet werden, braucht es keinen speziellen Provider. Dann reichen die Zugriffe wie im vorherigen Abschnitt gezeigt.

Möchte man aber in derselben Liste Daten anzeigen, die z.B. über den Zeitraum hinausgehen oder sonst Werte miteinbeziehen sollen, welche in der Liste nicht dargestellt werden, braucht es dafür einen eigenen Provider.

In unserem Beispiel möchten wir die obige Tabelle erweitern und pro Zeile das Total der geplanten Werte anzeigen, unabhängig vom ausgewählten Intervall oder der angezeigten Periode, sondern insgesamt.

Dafür erstellen wir nun einen separaten Provider. Zuerst rufen wir die setup_provider Methode unseres Controllers auf:

import vtcplanning
import vtcplanningcore
import datetime

class Controller(vtcplanning.SingleObjectTimeTableController):

    def setup_provider(self, subscriber):
    
        vtcplanning.SingleObjectTimeTableController.setup_provider(self, subscriber)
        
        # Zusätzlichen Provider erstellen
        source_entry = self.get_source_entry()
        source_entries = vtcplanning.get_as_list(source_entry)

        self.total_start = datetime.date(2000, 1, 1)
        self.total_end = datetime.datetime(2100, 1, 1)
        self.total_provider = vtcplanningcore.ResourcePlanningProvider(source_entries, self.total_start, self.total_end)

Damit haben wir nun zwei Provider:

  • self.provider: Der standardmässig verfügbare Provider wird durch den Aufruf von vtcplanning.SingleObjectTimeTableController.setup_provider(self, subscriber) erstellt wie in der originalen Methode.
  • self.total_provider: Das ist der zusätzliche Provider, den wir selbst erstellt haben mit einem Datumsintervall, welches ganz sicher alle Daten umfasst.

Nun erstellen wir einen weiteren Custom Renderer für die Anzeige des Totalwerts in der Liste. Darin können wir nun auf den zusätzlichen Provider zugreifen:

class TotalGeplantRenderer(vtcplanning.MinutesRendererBase):

    is_readonly = True

    # Summiert die Planzeiten ohne Einschränkung des Zeitraums
    def get_value(self, rowobj, expression, subscriber):

        return self.controller.total_provider.get_planned_minutes_aggregated(
            self.controller.context, rowobj, self.controller.total_start, self.controller.total_end, subscriber)        

Nun können wir die Totalspalte in der Liste einfügen:

In Listen ausserhalb der Ressourcenplanung

Mittels List Controller und ResourcePlanningProvider

Ausserhalb der Ressourcenplanung, also in den normalen Vertec Listen, müssen wir den List Controller selber erstellen und via ResourcePlanningProvider auf die Plandaten zugreifen.

Als erstes Beispiel möchten wir in einer Projektliste pro Projekt anzeigen, wie viel Zeit gesamthaft darauf geplant wurde.

Dafür erstellen wir folgenden List Controller:

import vtcplanningcore
import datetime

class Controller:
    def initialize(self, subscriber):
        self.startdatum = datetime.date(2000, 1, 1)
        self.enddatum = datetime.datetime(2100, 1, 1)
        source_entries = self.get_context_entries()
        self.rscprovider = vtcplanningcore.ResourcePlanningProvider(source_entries, self.startdatum, self.enddatum)
  • Als Start- und Enddatum wählen wir die Periode, die wir abdecken möchten.
  • Die Einträge in der Liste eruieren wir mit der Controller-Methode self.get_context_entries().
  • Dann erstellen wir einen Provider für die Einträge in der Liste und das gewählte Datumsintervall.

Diesen Controller können wir nun auf unserer Projektliste als List Controller hinterlegen:

  • Handelt es sich um einen Ordner, hinterlegen wir den List Controller in den Ordnereigenschaften:
  • Handelt es sich um einen Link-Container, hinterlegen wir den List Controller auf dem Link-Typ auf der entsprechenden Seite:

Nun benötigen wir für die Spalte wiederum einen Custom Renderer, in welchem wir auf den oben erstellten Provider zugreifen:

class ProjektPlanwertRenderer:

    value_type = "integer"
    converter = "minutes"
    
    def get_value(self, rowobj, expression, subscriber):
        return self.controller.rscprovider.get_planned_minutes_aggregated(rowobj, None, self.controller.startdatum, self.controller.enddatum, subscriber)

Diesen fügen wir dann in den Listeneinstellungen unserer Projektliste als Renderer in der Spalte ein:

Via OCL Methoden

Es gibt folgende OCL Methoden, welche für Projekt- und Planungsbearbeiter verwendet werden können:

.getResPlanMinuten(von, bis)

Gibt die verplante Zeit für den Bearbeiter für die angegebene Periode (von, bis Datum) in Minuten zurück.

Macht dasselbe wie der ResourcePlanningProvider.get_planned_minutes (siehe vorherigen Abschnitt).

.getResRsrcMinuten(von, bis)

Gibt die Ressourcenzeit für den Bearbeiter für die angegebene Periode (von, bis Datum) in Minuten zurück. Das ist nicht die noch verfügbare Zeit, sondern die gesamte Ressourcenplan-relevante Sollzeit. Der Unterschied zur Sollzeit ist, dass nur Abwesenheiten vom Typ "Frei" die Sollzeit beeinflussen, von der Ressourcenzeit hingegen werden alle Arten von Abwesenheiten (Frei, Ferien, Kompensation) abgezogen (siehe dazu auch die Tabelle über die Arbeitszeit-Ausnahmen im Artikel Abwesenheiten).

Macht dasselbe wie der ResourcePlanningProvider.get_net_capacity_minutes (siehe vorherigen Abschnitt).

Dann kann noch die Ist-Zeit für die gleiche Periode angezeigt und damit gearbeitet werden. Beispiel:

Das Beispiel zeigt einen SQL-Ordner für die Klasse Projektbearbeiter. Als Abfrage gibt es zwei Datumsfelder Von, Bis.

In der Liste kann auf diese Datumsfelder zugegriffen werden (varVon, varBis). Die einzelnen Expressions lauten demnach:

  • Verfügbare Ressourcen: self.getResRsrcMinuten(varVon, varBis)
  • Davon geplant: self.getResPlanMinuten(varVon, varBis)
  • Bereits geleistet: self.getArbeitszeit(varVon, varBis)
  • Restverfügbarkeit: self.getResPlanMinuten(varVon, varBis)-self.getArbeitszeit(varVon, varBis)

Hinweis: Dies ist nur ein Anschauungsbeispiel. Aus Performancegründen sollten nicht alle Projektbearbeiter in der Liste dargestellt, sondern eine gefilterte Liste angezeigt werden. Aber hier ist gut ersichtlich, warum diese Liste nicht performant ist: Alle Werte müssen für jeden Bearbeiter separat geladen und nach Datum gefiltert werden, z.T. sogar mehrmals.

Empfehlenswerter ist auf jeden Fall die Variante über den ResourcePlanningProvider, da dort erstens mehr Werte zur Verfügung stehen (z.B. auch für Projekte oder Phasen) und ausserdem von einem besseren Caching profitiert werden kann. Insbesondere Plandaten, also die ResourceLinks direkt, müssen aus Performancegründen immer über den ResourcePlanningProvider abgefragt werden.

Via geerbtem Controller und Standard Custom Renderern

Für denselben SQL-Ordner braucht es dafür folgenden Controller:

import vtcplanning

class Controller(vtcplanning.TimeTableControllerBase):

    def initialize(self, subscriber):
        start = self.evalocl("varVon")
        end = self.evalocl("varBis")
        vtcplanning.TimeTableControllerBase.initialize_with_period(self, start, end, subscriber)
    
    def setup_provider(self, subscriber):
        source_entries = self.get_context_entries()
        self.create_and_set_provider(source_entries, self.period_start, self.period_end, subscriber)

    def get_capacity_method_arguments(self, column_index, rowobj, subscriber):
        return (rowobj, self.period_start, self.period_end)
        
    def get_planned_minutes_aggregated(self, rowobj, subscriber):
        return self.get_provider().get_planned_minutes_aggregated(rowobj, None, self.period_start, self.period_end, subscriber)
Erklärung

Der Controller erbt vom vtcplanning.TimeTableControllerBase, da wir die normalen Renderer benutzen möchten, ohne alles nochmal selbst berechnen zu müssen.

  • Im initialize(self, subscriber) übergeben wir die Datumsperiode.
  • Im setup_provider(self, subscriber) übergeben wir die aktuelle Bearbeiterliste.
  • Die Methode get_capacity_method_arguments muss vorhanden sein, wenn auf die Kapazitätsrenderer zugegriffen wird.
  • Die Methode get_planned_minutes_aggregated muss vorhanden sein, wenn auf den Planungsrenderer zugegriffen wird.

Ist dieser auf dem SQL-Ordner als List Controller hinterlegt, können in den Spalten danach die gewohnten Custom Renderer der Ressourcenplanung verwendet werden:

  • Verfügbare Ressourcen: vtcplanning.NetCapacityRenderer
  • Benutzerdefinierte verfügbare Ressourcen: vtcplanning.CustomNetCapacityRenderer
  • Davon geplant: vtcplanning.PlannedMinutesRenderer
  • Restverfügbarkeit: vtcplanning.RemainingCapacityRenderer
  • Benutzerdefinierte Restverfügbarkeit: vtcplanning.CustomRemainingCapacityRenderer

Kapazitätsliste

Auch in diesem Beispiel verwenden wir einen SQL-Ordner mit Bearbeitern. Diesmal übergeben wir nur ein Datum, welches als Startdatum dient. In der Liste zeigen wir sowohl die noch verfügbare Kapazität der einzelnen Bearbeiter pro Intervall als auch gesamthaft an.

Dafür braucht es folgenden Controller:

import vtcplanning

class Controller(vtcplanning.TimeTableControllerBase):

    def initialize(self, subscriber):
        date = self.evalocl("varDate")
        start = vtcapp.firstdayofmonth(date)
        end = vtcapp.incmonth(start, 5)
        vtcplanning.TimeTableControllerBase.initialize_with_period(self, start, end, subscriber)
    
    def setup_provider(self, subscriber):
        source_entries = self.get_context_entries()
        self.create_and_set_provider(source_entries, self.period_start, self.period_end, subscriber)

    def get_capacity_method_arguments(self, column_index, rowobj, subscriber):
        if column_index is None:
            date_from = self.period_start
            date_to = self.period_end
        else:
            date_from = self.get_date_by_column_index(column_index)
            date_to = None
        return (rowobj, date_from, date_to)
Erklärung
  • Da ich die normalen Kapazitätsrenderer verwenden will, erbe ich von einem bestehenden Controller, hier im Beispiel den TimeTableControllerBase.
  • Ich gehe vom Planungsintervall Monat aus (firstofmonth) und zeige 5 Planungsintervalle (incMonth 5).
  • Das Erstellen des Providers überlasse ich ebenfalls der Standardmethode, übergebe nur die entsprechenden Listeneinträge get_context_entries().
  • Wenn ich Kapazitätsrenderer verwenden will, muss die Methode get_capacity_method_arguments implementiert sein. Ich kopiere einfach den Code aus der Originalfunktion.

Nun können die gewohnten Renderer in der Liste verwendet werden:

  • Verfügbar gesamt: vtcplanning.RemainingCapacityRenderer oder vtcplanning.CustomRemainingCapacityRenderer.
  • Verfügbar (einzelne Intervalle): vtcplanning.RemainingCapacityRenderer oder vtcplanning.CustomRemainingCapacityRenderer, zusätzlich Spalte als Dynamisch markieren, Expression %col%.

Auswertungen mittels Business Intelligence (BI) Modul

Für Auswertungen mit Ressourcenplanwerten eignet sich auch das Business Intelligence Modul, wo eigene Auswertungen erstellt werden können.

Eine solche Auswertung steht als Plug-in: BI Umsatzprognose aus Ressourcenplanung zum Download zur Verfügung.

In a Nutshell

Wichtige Grundlagen beim Arbeiten mit Ressourcenplanungsdaten in Kürze:

  1. Kopieren Sie des Code des Moduls vtcplanning raus und verwenden Sie ihn als Nachschlagewerk. Dafür können Sie in einer beliebigen Ressourcenplanungsansicht beim Feld List Controller auf die drei Punkte klicken. Dieser enthält überall den gesamten Code von vtcplanning.
  2. Immer, wenn von einem der mitgelieferten Ressourcenplanungs Controller geerbt wird, muss die Methode initialize_with_period(self, start, end, subscriber) implementiert werden.
  3. Wird ein eigener List Controller erstellt, welcher nicht von einem Ressourcenplanungs Controller erbt, muss die Methode initialize(self, subscriber) implementiert werden.
  4. Intervall einer Spalte eruieren: Der TimeTableControllerBase (und alle Controller, die von diesem erben) verfügen über die Methode get_date_by_column_index(column_index), siehe Beispiel Kapazitätsliste.
  5. In Zeittabellen gilt:
    • column_index ist immer das Datum (als Integer), ansonsten None
    • rowobj ist immer das Zeilenobjekt
    • source_entry ist immer das Objekt, auf dem die Tabelle aufgerufen wird.
Innerhalb der Ressourcenplanung
  1. Möchten Sie eine Tabelle innerhalb der Ressourcenplanung erweitern, können Sie einfach vom entsprechenden Controller erben und dann Ihre Erweiterung einfügen, siehe Abschnitt Erben von einem bestehenden List Controller.
  2. Die mitgelieferten Controller sind allgemein gehalten, können also auf Bearbeitern, Projekten und Projektphasen gleichermassen verwendet werden. Möchten Sie Ihren Controller ebenso erweitern, müssen Sie darauf achten, dass die Expressions, die Sie verwenden, für alle möglichen Fälle verwendbar sind. Da sich die Planungsebene sowie das Planungsintervall in Ihrem Betrieb jedoch kaum ändern wird, können Sie der Einfachheit halber auch davon absehen und nur die benötigten Fälle implementieren, wie im Beispiel Erben von einem bestehenden List Controller.
  3. Einen eigenen ResourcePlanningProvider braucht es nur, wenn Daten evaluiert werden sollen, die über die Standardwerte hinausgehen, z.B. ein anderes Datumsintervall, Bearbeiter, Projekte oder Projektphasen, die nicht in der Liste angezeigt werden bzw. nicht das Objekt sind, auf welchem eine Auswertung angezeigt wird, siehe Abschnitt Einen zusätzlichen ResourcePlanningProvider erstellen.
Ausserhalb der Ressourcenplanung
  1. Wenn Sie einer Liste (Link Container, Ordner) ausserhalb der Ressourcenplanung einen List Controller zuweisen, bedeutet das nicht, dass die gesamte Liste dann auf diesen List Controller zugreift. Es bedeutet nur, dass Sie in den Custom Renderern auf diesen List Controller und die darin berechneten Werte zugreifen können.
  2. Sie können auch ausserhalb der Ressourcenplanung von einem bestehenden Ressourcenplanungs-Controller erben. Machen Sie das, wenn Sie die Standard Renderer für die Ressourcenplanung verwenden möchten, siehe Abschnitt Via geerbtem Controller und Standard Custom Renderern. In diesem Fall erben Sie normalerweise vom TimeTableControllerBase, der beinhaltet alles, was man braucht.
  3. Erstellen Sie selbst einen ResourcePlanningProvider mit einem eigenen Datumsintervall, wird dafür die Methode setup_provider(self, subscriber) implementiert und darin die Methode create_and_set_provider(self, source_entries, start_date, end_date, subscriber) mit den entsprechenden Argumenten aufgerufen, siehe Via geerbtem Controller und Standard Custom Renderern.
  4. Möchten Sie auch ausserhalb der Ressourcenplanung die Standard Kapazitätsrenderer verwenden (vtcplanning.NetCapacityRenderer, vtcplanning.CustomNetCapacityRender, vtcplanning.GrossCapacityRenderer, vtcplanning.RemainingCapacityRenderer, vtcplanning.CustomRemainingCapacityRenderer), muss die Methode get_capacity_method_arguments im Controller implementiert werden. Dafür können Sie einfach die Standardmethode aus dem Modul vtcplanning 1:1 rauskopieren und einfügen, siehe Beispiel Via geerbtem Controller und Standard Custom Renderern.
  5. Möchten Sie auch ausserhalb der Ressourcenplanung den Standard Planungsrenderer verwenden (vtcplanning.PlannedMinutesRenderer), muss die Methode planned_minutes_aggregated(source_entry, rowobj, self.period_start, self.period_end, subscriber) im Controller implementiert werden. Hier kopieren Sie am besten die Standardmethode aus dem Modul vtcplanning raus und übergeben, je nach Liste, die entsprechenden Argumente. Diese sind im Artikel über die Vertec Python Funktionen genau beschrieben. Siehe Beispiel Via geerbtem Controller und Standard Custom Renderern.
  6. Mit der Methode get_planned_minutes_aggregated(source_entry, rowobj, self.period_start, self.period_end, subscriber) kann auf einem ResourcePlanningProvider jeder beliebige Planwert abgefragt werden, siehe Mittels List Controller und ResourcePlanningProvider
  7. Sie können auch in einem normalen Controller (der nicht von einem Ressourcenplanungs-Controller erbt) einen ResourcePlanningProvider verwenden. Das eignet sich vor allem dann, wenn Ressourcenplandaten in einer schon bestehenden Liste ausserhalb der Ressourcenplanung angezeigt werden sollen, siehe Abschnitt Mittels List Controller und ResourcePlanningProvider.
Renderer
  1. Sie können in allen Custom Renderern via self.controller auf den in der Liste hinterlegten List Controller zugreifen.
  2. Möchten Sie in der Liste einen Planwert anzeigen, welcher sich auf ein bestimmtes Datumsintervall bezieht, erben Sie am besten vom vtcplanning.MinutesRendererBase. Dieser verfügt über die Methode get_column_index_from_expression(expression), mit welchem das Intervall der Spalte eruiert werden kann, siehe Einen eigenen Renderer schreiben.
Bitte wählen Sie Ihren Standort