Microsoft Dynamics CRM 2011 | Arbeitszeiten per SDK abgefragt

Schon in meinem ersten Artikel bin ich auf einige Besonderheiten des Benutzers und der Arbeitszeiten eingegangen, die ich im heutigen Artikel noch weiter vertiefen möchte.

AZ_User_WorkingHours_DetailFür mein Beispiel habe ich dem Nutzer folgendes Arbeitszeitenmodell angelegt. Wie Ihr seht, habe ich eine Pause hinzugefügt, da ich auf dieses spezielle Element ebenfalls eingehen möchte.

User_Working_Hours_Overview

Des Weiteren habe ich noch eine Arbeitsfreie Zeit (Time-Off) hinzugefügt, um auch diesen speziellen Typ in der Abfrage zu berücksichtigen.

Und da ein Arbeitstag nicht nur durch diese beiden Stammdaten-informationen bestimmt wird, sondern auch durch Termine bzw. Service-Aktivitäten, habe ich auch jene noch für den aktuellen Tag hinzugefügt.

User_Calendar

Daraus ergibt sich in der Ansicht des Nutzer-Kalenders das dargestellte Bild. Die Termine wurden mit dem Status “gebucht”, die Service-Aktivität mit dem Status “Abwesend” angelegt.

Diese Status sind für die folgende Abfrage noch von besonderer Bedeutung.

Die Aufgabe: Wir wollen mit einer möglichst einfachen Abfrage die verfügbare Arbeitszeit des Nutzers ermitteln, um beispielsweise eine neue Terminplanung per SDK anstoßen zu können.

Dabei soll natürlich verhindert werden, dass der neue Termin mit einem vorhandenen Termin oder dem Arbeitszeitenmodell in Konflikt gerät.

Zur Verdeutlichung bediene ich mich dem SoapLogger-Beispiel aus dem SDK, sowie der Abfrage eines einzelnen Nutzer-Kalenders.

// Retrieve the working hours of the current user.

QueryScheduleRequest scheduleRequest = new QueryScheduleRequest

{

ResourceId = userResponse.UserId,

Start = DateTime.Now,

End = DateTime.Today.AddDays(1),

TimeCodes = new TimeCode[] { TimeCode.Available }

};

QueryScheduleResponse scheduleResponse = (QueryScheduleResponse)slos.Execute(scheduleRequest);

Beginnen wir zunächst mit der Abfrage über das Schlüsselwort “Available”.

Als Ergebnis erhalten wir zwei Array-Elemente:

<c:value i:type=“b:ArrayOfTimeInfo“>
  <b:TimeInfo>
    <b:ActivityStatusCode>-1</b:ActivityStatusCode>
    <b:CalendarId>47a5d57e-21dc-e211-9795-000c299a9455</b:CalendarId>
    <b:DisplayText />
    <b:Effort>1</b:Effort>
    <b:End>2013-06-23T15:00:00Z</b:End>                    17:00
    <b:IsActivity>false</b:IsActivity>
    <b:SourceId>48a5d57e-21dc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4004</b:SourceTypeCode>
    <b:Start>2013-06-23T08:15:00Z</b:Start>               10:15
    <b:SubCode>Schedulable</b:SubCode>
    <b:TimeCode>Available</b:TimeCode>
  </b:TimeInfo>
  <b:TimeInfo>
    <b:ActivityStatusCode>-1</b:ActivityStatusCode>
    <b:CalendarId>47a5d57e-21dc-e211-9795-000c299a9455</b:CalendarId>
    <b:DisplayText />
    <b:Effort>1</b:Effort>
    <b:End>2013-06-23T08:00:00Z</b:End>                    10:00
    <b:IsActivity>false</b:IsActivity>
    <b:SourceId>48a5d57e-21dc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4004</b:SourceTypeCode>
    <b:Start>2013-06-23T06:00:00Z</b:Start>                08:00
    <b:SubCode>Schedulable</b:SubCode>
    <b:TimeCode>Available</b:TimeCode>
  </b:TimeInfo>

Da die Antworten in UTC-Zeit erfolgen, habe ich die Zeiten für den Kalendervergleich fett dargestellt.

Was fällt Euch auf?

Wir erhalten zwei Zeitfenster von 08:00 – 10:00 und von 10:15 – 17:00. In diesen wurde die arbeitsfreie Zeit von 10:00 bis 10:15 bereits berücksichtigt. Die Pause von 12:30 – 13.00 Uhr hingegen wurde nicht von der verfügbaren Zeit abgezogen!

Des Weiteren fällt auf, dass diese Abfrage keinen der weiteren Termine, bzw. Service-Aktivitäten berücksichtigt.

……

Versuchen wir daher die Abfrage mit einem weiteren TimeCode-Parameter “Unavailable”.

Das Ergebnis sieht schon anders aus. Diesmal erhalten wir 4 Array-Elemente zurück:

<c:value i:type=“b:ArrayOfTimeInfo“>
  <b:TimeInfo>
    <b:ActivityStatusCode>6</b:ActivityStatusCode>
    <b:CalendarId>00000000-0000-0000-0000-000000000000</b:CalendarId>
    <b:DisplayText />
    <b:Effort>2139095040</b:Effort>
    <b:End>2013-06-23T10:00:00Z</b:End>                       12:00
    <b:IsActivity>true</b:IsActivity>
    <b:SourceId>57808dc5-1fdc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4201</b:SourceTypeCode>
    <b:Start>2013-06-23T09:30:00Z</b:Start>                    11:30
    <b:SubCode>Appointment</b:SubCode>
    <b:TimeCode>Unavailable</b:TimeCode>
  </b:TimeInfo>
  <b:TimeInfo>
    <b:ActivityStatusCode>-1</b:ActivityStatusCode>
    <b:CalendarId>4f233da6-21dc-e211-9795-000c299a9455</b:CalendarId>
    <b:DisplayText />
    <b:Effort>0</b:Effort>
    <b:End>2013-06-23T08:15:00Z</b:End>                       10:15
    <b:IsActivity>false</b:IsActivity>
    <b:SourceId>50233da6-21dc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4004</b:SourceTypeCode>
    <b:Start>2013-06-23T08:00:00Z</b:Start>                    10:00
    <b:SubCode>Vacation</b:SubCode>
    <b:TimeCode>Unavailable</b:TimeCode>
  </b:TimeInfo>
  <b:TimeInfo>
    <b:ActivityStatusCode>5</b:ActivityStatusCode>
    <b:CalendarId>00000000-0000-0000-0000-000000000000</b:CalendarId>
    <b:DisplayText />
    <b:Effort>2139095040</b:Effort>
    <b:End>2013-06-23T09:30:00Z</b:End>                        11:30
    <b:IsActivity>true</b:IsActivity>
    <b:SourceId>021d22ad-1fdc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4201</b:SourceTypeCode>
    <b:Start>2013-06-23T08:30:00Z</b:Start>                    10:30
    <b:SubCode>Appointment</b:SubCode>
    <b:TimeCode>Unavailable</b:TimeCode>
  </b:TimeInfo>
  <b:TimeInfo>
    <b:ActivityStatusCode>-1</b:ActivityStatusCode>
    <b:CalendarId>47a5d57e-21dc-e211-9795-000c299a9455</b:CalendarId>
    <b:DisplayText />
    <b:Effort>0</b:Effort>
    <b:End>2013-06-23T11:00:00Z</b:End>                        13:00
    <b:IsActivity>false</b:IsActivity>
    <b:SourceId>49a5d57e-21dc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4004</b:SourceTypeCode>
    <b:Start>2013-06-23T10:30:00Z</b:Start>                    12:30
    <b:SubCode>Break</b:SubCode>
    <b:TimeCode>Unavailable</b:TimeCode>
  </b:TimeInfo>
</c:value>

Diesmal bekommen wir sowohl die arbeitsfreie Zeit 10:00 – 10:15 als “Vacation” zurückgeliefert, wie auch die Pause von 12:30 – 13:00 als “Break”. Und auch unsere beiden Termine von 10:30 – 11:30 und 11:30 – 12:00 werden als “Appointment” zurückgeliefert.

“Appointments” können in diesem Fall sowohl Termine, als auch Service-Aktivitäten sein. Daher lohnt sich der Blick auf den SourceTypeCode. Hier findet Ihr die 4201 für einen Termin oder auch die 4214 für eine Service-Aktivität.

Vorausgesetzt die Service-Aktivität enthält im Feld Ressourcen den aktuellen Nutzer zugewiesen, findet sich dieser Termin auch in der o.g. Abfrage.

……

Aber möglicherweise hilft uns ja noch ein weiterer TimeCode-Parameter “Busy”.

<c:value i:type=“b:ArrayOfTimeInfo“>
  <b:TimeInfo>
    <b:ActivityStatusCode>4</b:ActivityStatusCode>
    <b:CalendarId>00000000-0000-0000-0000-000000000000</b:CalendarId>
    <b:DisplayText />
    <b:Effort>1</b:Effort>
    <b:End>2013-06-23T14:30:00Z</b:End>                16:30
    <b:IsActivity>true</b:IsActivity>
    <b:SourceId>ac9c3ae4-1fdc-e211-9795-000c299a9455</b:SourceId>
    <b:SourceTypeCode>4214</b:SourceTypeCode>
    <b:Start>2013-06-23T13:30:00Z</b:Start>            15:30
    <b:SubCode>Committed</b:SubCode>
    <b:TimeCode>Busy</b:TimeCode>
  </b:TimeInfo>
</c:value>

Bei dieser Abfrage erhalten wir nur ein Array-Element zurückgeliefert. Und dabei handelt es sich um unsere Service-Aktivität.

Als Fazit dieses kleinen SDK-Exkurses können wir festhalten: Es gibt keine einfache Abfrage, mit der sich die tatsächlich verfügbare freie Arbeitszeit ermitteln lässt. Diese muss aus den verschiedenen Abfragen “geschnitten” werden. Nachfolgende Tabelle soll das Ergebnis noch mal verdeutlichen.

TimeCode .Available .Unavailable .Busy
Erhalten Arbeitsbeginn

importwizard_solidgreentick

16_error

16_error

Erhalten Arbeitszeitende

importwizard_solidgreentick

16_error

16_error

Erhalten Pausen

16_error

importwizard_solidgreentick

16_error

Erhalten Arbeitsfreie Zeiten

16_error

importwizard_solidgreentick

16_error

Erhalten Termine, die Status des Bereichs “Geplant” haben

16_error

importwizard_solidgreentick

16_error

Erhalten Service-Aktivitäten, die Status des Bereichs “Geplant” haben

16_error

importwizard_solidgreentick

importwizard_solidgreentick

Haben die Termine, bzw. Service-Aktivitäten einen Status aus dem Bereich “Offen”, werden diese nicht in den dargestellten Abfragen berücksichtigt. Das ist aus meiner Sicht auch korrekt, da geplante (offene) Termine nicht unmittelbar die Planung beeinflussen sollten. Sofern Euer Business-Case dies jedoch vorsieht, müsst Ihr definitiv die jeweiligen Termine bzw. Service-Aktivitäten einzeln abfragen.

Soweit meine weiteren Tipps für Euch zum Thema Arbeitszeiten, verfügbare Arbeitszeit und Abfragen via SDK.

 

Technorati Tags:

Ein Gedanke zu “Microsoft Dynamics CRM 2011 | Arbeitszeiten per SDK abgefragt

  1. Pingback: Microsoft Dynamics CRM & Co

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s