Timekeepings: Unterschied zwischen den Versionen

Aus ARTECO Wiki
Zur Navigation springen Zur Suche springen
 
(32 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 3: Zeile 3:
  
 
= Entwicklernotizen =
 
= Entwicklernotizen =
Ein Timekeeping ist ein Ereignis innerhalb des Arbeitszeiterfassungssystems. Im konkreten Fall kann der Mitarbeiter zum Beispiel "Arbeit Beginn" und "Arbeit Ende" stempeln (über unsere Station, die MAE o.ä.). Es ist hervorzuheben, dass diese Ereignisse nur '''einen Zeitpunkt''' repräsentieren, also keine Aussage über die Dauer bieten.
+
Ein Timekeeping ist ein Ereignis innerhalb des Arbeitszeiterfassungssystems. Im konkreten Fall kann der Mitarbeiter zum Beispiel "Arbeit Beginn" und "Arbeit Ende" stempeln (über unsere Station, die MAE o.ä.). Es ist hervorzuheben, dass diese Ereignisse nur '''einen Zeitpunkt''' repräsentieren, also keine Aussage über die Dauer bieten.  
  
Dieses Ereignis ist vor allem durch seinen Zeitpunkt und seinen Typ charakterisiert.
+
Wenn im Client ein Timekeeping nicht vorhanden ist, heißt das unter Umständen nur, dass es noch nicht vom Server geladen wurde. Aufgrund der Menge an Zeiterfassungsdaten werden immer nur zeitliche Abschnitte angefragt. Zum Beispiel werden beim erstmaligen Anlegen eines Coworkers nur seine Timekeepings der letzten sieben Tage erfragt.
  
Folgende Ereignistypen sind in der Datenbank definiert und können vom Timekeeping angenommen werden:
+
== Aufbau ==
* work_start, work_stop
+
Die Timekeepings werden wie alle Ressourcen über WebAccessoren vom REST-Service abgehohlt und in den üblichen internen Listen abgespeichert. In diesem speziellen Fall jedoch existieren diese nicht im ResourcePool, sondern jeweils einer in einem Coworker.
* private_start, private_stop
+
 
* driver_start, driver_stop
+
<code>WebAccessor<Timekeeping>* timekeepingAcc() { return m_timekeepingAcc; } // coworker.h</code>
* break_start, break_stop
+
 
* customer_start, customer_stop
+
=== event ===
* waiting_start, waiting_stop
+
Ein Timekeeping ist neben seinem Zeitpunkt vor allem auch durch seinen Typ charakterisiert (z.B. "Arbeit", "Pause" etc.) und seinen Zustand (z.B. "Start" oder "Stop"). Diese beiden Sachen sind zusammen im "event"-Attribut des Timekeepings als String gespeichert (z.B. "work_start" oder "break_stop"). Zur besseren Verarbeitung dieser hat das Timekeeping intern zwei Structs definiert: "EventState" und "EventType" und über die getter-Funktionen eventType() und eventState() lässt sich für jedes Timekeeping der entsprechende Wert abfragen.
* alert
+
 
* function_1, function_2, function_3,
+
=== timestamps ===
* garmin_id_1,garmin_id_2,garmin_id_3,garmin_id_4,garmin_id_5, garmin_id_6,garmin_id_7,garmin_id_8, garmin_driver_id
+
Alle Timestamps aus dem XML sind in UTC-Zeit und müssen auch so wieder an den webservice übergeben werden. Dazu gehören
* holiday_start, holiday_stop
+
* '''created_at''' - Zeitpunkt der Erstellung in der Datenbank
* ill_start, ill_stop
+
* '''updated_at''' - Zeitpunkt der letzten Aktualisierung in der Datenbank
 +
* '''user_timestamp''' - Zeitpunkt an dem der Benutzer/Mitarbeiter das Ereignis abgeschickt/gestempelt hat
 +
* '''telematik_timestamp''' - Zeitpunkt an dem das entsprechende Telematik-System das Ereignis rausgeschickt hat
 +
 
 +
Der im OSCpc üblicherweise zu nutzende Timestamp ist der '''user_timestamp'''.
 +
 
 +
Da die Zeitstempel sehr oft und überall abgefragt werden existiert im Objekt eine Art Caching und es wird dringend geraten die '''userTimestamp(...)''' Funktion zu benutzen. Sie gibt eine QDateTime Referenz zurück. Ihr erster Parameter legt fest ob man die Zeit in lokaler oder UTC-Zeit(default) möchte. Ihr zweiter Parameter, ob eine den eingestellten Aufrundungsregeln(siehe unten) entsprechend veränderter Zeitstempel geliefert werden soll oder nicht(default).
 +
 
 +
Zum Setzen des user_timestamps existiert die '''setUserTimestampUTC(...)''' Funktion die einen korrekt formatierten Zeitstempel als QString erfordert. Z.B. durch
 +
 
 +
<code>QString isoFrom = from.toUTC().toString(Qt::ISODate); // QDateTime from;</code>
 +
 
 +
=== Sonstiges ===
 +
* '''coworker_uuid''' - Der Mitarbeiter zu dem das Ereignis gehört
 +
* '''garmin_uuid''' - Optional - Der Garmin von dem das Ereignis gesendet wurde.
 +
* '''system_uuid''' - Optional - Das Fahrzeug von dem das Ereignis gesendet wurde.
 +
* '''world_x, world_y, map_text''' - Wenn vorhanden Koordinaten und die dafür gefundene Adresse an dem das Ereignis gestempelt wurde.
 +
 
 +
Bevor auf die Benutzung der Timekeepings eingegangen wird, muss eine davon abgeleitete Struktur erläutert werden.
 +
== Erweiterte Timekeepings - CombinedTimekeeping ==
 +
Um die Arbeit mit den Timekeepings zu erleichtern wurde eine Wrapper-Struktur geschaffen, die Klasse '''CombinedTimekeeping'''
 +
 
 +
Sie stellt, soweit möglich, einen vollständigen Ereigniszeitraum von Anfang bis Ende dar. Hat also auch Informationen über die Dauer des Ereignisses. Es ist dabei wichtig anzumerken, dass die Vollständigkeit nicht zwingend ist. So kann z.B. ein Start- oder Endzeitpunkt des Ereignisses durchaus fehlen.
 +
 
 +
Die CombinedTimekeepings werden im Hintergrund beim Anlegen und Ändern von Timekeepings mitverwaltet und synchronisiert. Wer an diesen internen Strukturen etwas verändert sollte genau wissen was er tut, da sonst sehr schnell fehlerhafte Einträge entstehen und Programmabstürze die Folge sind.
 +
 
 +
=== Benutztung der Ctks ===
 +
Der Zugriff auf die CombinedTimekeepings erfolgt ebenfalls über den jeweiligen Coworker. Dabei gibt es verschiedene Hashes und Mappings um möglichst schnell die gewünschten Daten zu erhalten
 +
 
 +
* '''QList<CombinedTimekeeping*> m_listCombinedTimekeepings'''
 +
** Eine einfache Liste aller geladenen Ctks.
 +
** Benutzt im ''CombinedWorktimeBySystemModel''.
 +
* '''QMap<QDate, QList<CombinedTimekeeping*>*> m_combinedTimekeepingsByDayList'''
 +
** Dies ist eine spezielle Map um eine Liste aller CombinedTimekeepings eines bestimmten Tages zu bekommen. Dabei ist zu beachten das Ereignisse die über mehrere Tage gehen (z.B. Urlaub oder Arbeit über Mitternacht hinaus) auch für jeden dieser Tage einmal in der Map gespeichert sind. Der Programmierer muss daher entsprechend beachten z.B. etwaige Ereignissdauern nicht doppelt zu verrechnen.
 +
** Benutzt im ''TimekeepingModelMonthly'', ''CombinedWorktimesModel'', ''TimekeepingReportDaily''
 +
* '''QMap<QDate, QHash<Timekeeping::EventType, QList<CombinedTimekeeping*>*>*> m_combinedTimekeepingsByDayHash'''
 +
** Dies ist eine spezielle Map um eine Liste aller CombinedTimekeepings eines bestimmten Tages und eines bestimmten Typs zu bekommen. Ansonsten gilt das gleiche wie bei der zuvor genannten Struktur.
 +
** Benutzt im ''HolidayIllModel'', ''HolidayIllReport'', ''PlanningByCoworkerModel''
 +
 
 +
== Benutztung der Timekeepings ==
 +
Timekeepings werden wie alle Resourcetypen nur als Smartpointer erstellt (genauer: QExplicitlySharedDataPointer) um die Speicherverwaltung zu vereinfachen. Über den entsprechenden Coworker kann über den dort angelegten Timekeeping-WebAccessor auf dessen Liste an geladenen Timekeepings zugegriffen werden.
 +
 
 +
Im Zuge der Umstellung auf die Erweiterung mit CombinedTimekeepigns wird jedoch stark empfohlen die ebenfalls im Coworker vorhandenen extra Listen zu benutzen:
 +
* QList<PTimekeeping> '''m_loadedTimekeepings'''
 +
** Die ist eine einfache Liste aller geladenen Timekeepings. Bei allen in dieser Liste vorkommenden Timekeepings ist sichergestellt, dass sie korrekt in die Strukturen der CombinedTimekeepigns eingegliedert sind und diese auch entsprechend synchron gehalten werden.
 +
** Auf dieser Liste basiert zum Beispiel das Basis Modell der ''TimekeepingModelDaily'' (Coworker->Zeiterfassung->Täglich)
 +
* QMap<QDateTime, PTimekeeping>  '''m_mapTimekeepings'''
 +
** Eine Map um alle Timekeepings eines bestimmten Zeitpunkts zu bekommen. '''Achtung:''' Im allgemeinen gibt es pro Zeitpunkt nur ein Timekeeping und die Datenbank erlaubt auch keine Timekeepings gleichen Typs zum gleichen Zeitpunkt (zB zweimal "work_start" mit ts "01.01.2013T14:00:00") jedoch liegt es im Bereich des möglichen und erlaubten, dass zB. ein "work_start" und ein "break_start" zum exakt gleichen Zeitpunkt anzulegen. In diesem Fall würde sich hinter dem QDateTime also eine Liste an Timekeepings verbergen, was der Programmierer entsprechend beachten muss (Beispiele dafür finden sich in der Qt Doku).
 +
** Benutzt aktuell ebenfalls im ''TimekeepingModelDaily''
 +
 
 +
== Folgende Ereignistypen sind in der Datenbank definiert und können vom Timekeeping angenommen werden ==
 +
* work_start, work_stop (Arbeit)
 +
* private_start, private_stop (Privat)
 +
* driver_start, driver_stop (Fahrer)
 +
* break_start, break_stop (Pause)
 +
* customer_start, customer_stop (Kunde)
 +
* waiting_start, waiting_stop (Wartend)
 +
* holiday_start, holiday_stop (Urlaub)
 +
* ill_start, ill_stop (Krankheit)
 +
* alert (Alarm)
 +
* function_1, function_2, function_3 (Funktion 1-3)
 +
* garmin_id_1, garmin_id_2, garmin_id_3, garmin_id_4, garmin_id_5, garmin_id_6, garmin_id_7, garmin_id_8, garmin_driver_id
 +
 
 +
== Beispiel des XML eines Timekeepings ==
 +
<nowiki>
 +
<timekeeping generated-at="2013-07-02T17:30:37Z">
 +
  <world-x type="float">9.290938</world-x>
 +
  <world-y type="float">49.077442</world-y>
 +
  <remarks nil="true"/>
 +
  <created-at type="datetime">2013-07-02T17:24:36Z</created-at>
 +
  <system-uuid type="string">90DB8C71-297D-4F34-A3AB-B3840DCC42B3</system-uuid>
 +
  <user-timestamp type="datetime">2013-07-02T17:24:36Z</user-timestamp>
 +
  <uuid type="string">44D3611E-E33C-11E2-9064-12314303963F</uuid>
 +
  <updated-at type="datetime">2013-07-02T17:24:36Z</updated-at>
 +
  <garmin-uuid type="string">D89BE2ED-82F8-43E1-BB3E-3FFE32ED9A0C</garmin-uuid>
 +
  <telematik-timestamp type="datetime">2013-07-02T17:24:28Z</telematik-timestamp>
 +
  <event type="string">garmin_id_3</event>
 +
  <coworker-uuid type="string">5906DB16-6D11-4ECF-AA09-CC35EC88C406</coworker-uuid>
 +
  <description nil="true"/>
 +
  <map-text type="string">
 +
    Staat: DE Land: Baden-Württemberg Landkreis: Heilbronn Postleitzahl: 74232 Stadt: Abstatt Strasse: Etrastraße 2
 +
  </map-text>
 +
</timekeeping>
 +
</nowiki>
  
== Sub 1 ==
 
=== Sub 2 ===
 
  
 
[[Category:WebserviceResources]]
 
[[Category:WebserviceResources]]

Aktuelle Version vom 4. Juli 2013, 17:41 Uhr

!!! ACHTUNG - IN ARBEIT !!!
Diese Seite ist unvollständig und noch in Bearbeitung.



Ein Timekeeping ist ein Ereignis innerhalb des Arbeitszeiterfassungssystems.

Entwicklernotizen

Ein Timekeeping ist ein Ereignis innerhalb des Arbeitszeiterfassungssystems. Im konkreten Fall kann der Mitarbeiter zum Beispiel "Arbeit Beginn" und "Arbeit Ende" stempeln (über unsere Station, die MAE o.ä.). Es ist hervorzuheben, dass diese Ereignisse nur einen Zeitpunkt repräsentieren, also keine Aussage über die Dauer bieten.

Wenn im Client ein Timekeeping nicht vorhanden ist, heißt das unter Umständen nur, dass es noch nicht vom Server geladen wurde. Aufgrund der Menge an Zeiterfassungsdaten werden immer nur zeitliche Abschnitte angefragt. Zum Beispiel werden beim erstmaligen Anlegen eines Coworkers nur seine Timekeepings der letzten sieben Tage erfragt.

Aufbau

Die Timekeepings werden wie alle Ressourcen über WebAccessoren vom REST-Service abgehohlt und in den üblichen internen Listen abgespeichert. In diesem speziellen Fall jedoch existieren diese nicht im ResourcePool, sondern jeweils einer in einem Coworker.

WebAccessor<Timekeeping>* timekeepingAcc() { return m_timekeepingAcc; } // coworker.h

event

Ein Timekeeping ist neben seinem Zeitpunkt vor allem auch durch seinen Typ charakterisiert (z.B. "Arbeit", "Pause" etc.) und seinen Zustand (z.B. "Start" oder "Stop"). Diese beiden Sachen sind zusammen im "event"-Attribut des Timekeepings als String gespeichert (z.B. "work_start" oder "break_stop"). Zur besseren Verarbeitung dieser hat das Timekeeping intern zwei Structs definiert: "EventState" und "EventType" und über die getter-Funktionen eventType() und eventState() lässt sich für jedes Timekeeping der entsprechende Wert abfragen.

timestamps

Alle Timestamps aus dem XML sind in UTC-Zeit und müssen auch so wieder an den webservice übergeben werden. Dazu gehören

  • created_at - Zeitpunkt der Erstellung in der Datenbank
  • updated_at - Zeitpunkt der letzten Aktualisierung in der Datenbank
  • user_timestamp - Zeitpunkt an dem der Benutzer/Mitarbeiter das Ereignis abgeschickt/gestempelt hat
  • telematik_timestamp - Zeitpunkt an dem das entsprechende Telematik-System das Ereignis rausgeschickt hat

Der im OSCpc üblicherweise zu nutzende Timestamp ist der user_timestamp.

Da die Zeitstempel sehr oft und überall abgefragt werden existiert im Objekt eine Art Caching und es wird dringend geraten die userTimestamp(...) Funktion zu benutzen. Sie gibt eine QDateTime Referenz zurück. Ihr erster Parameter legt fest ob man die Zeit in lokaler oder UTC-Zeit(default) möchte. Ihr zweiter Parameter, ob eine den eingestellten Aufrundungsregeln(siehe unten) entsprechend veränderter Zeitstempel geliefert werden soll oder nicht(default).

Zum Setzen des user_timestamps existiert die setUserTimestampUTC(...) Funktion die einen korrekt formatierten Zeitstempel als QString erfordert. Z.B. durch

QString isoFrom = from.toUTC().toString(Qt::ISODate); // QDateTime from;

Sonstiges

  • coworker_uuid - Der Mitarbeiter zu dem das Ereignis gehört
  • garmin_uuid - Optional - Der Garmin von dem das Ereignis gesendet wurde.
  • system_uuid - Optional - Das Fahrzeug von dem das Ereignis gesendet wurde.
  • world_x, world_y, map_text - Wenn vorhanden Koordinaten und die dafür gefundene Adresse an dem das Ereignis gestempelt wurde.

Bevor auf die Benutzung der Timekeepings eingegangen wird, muss eine davon abgeleitete Struktur erläutert werden.

Erweiterte Timekeepings - CombinedTimekeeping

Um die Arbeit mit den Timekeepings zu erleichtern wurde eine Wrapper-Struktur geschaffen, die Klasse CombinedTimekeeping

Sie stellt, soweit möglich, einen vollständigen Ereigniszeitraum von Anfang bis Ende dar. Hat also auch Informationen über die Dauer des Ereignisses. Es ist dabei wichtig anzumerken, dass die Vollständigkeit nicht zwingend ist. So kann z.B. ein Start- oder Endzeitpunkt des Ereignisses durchaus fehlen.

Die CombinedTimekeepings werden im Hintergrund beim Anlegen und Ändern von Timekeepings mitverwaltet und synchronisiert. Wer an diesen internen Strukturen etwas verändert sollte genau wissen was er tut, da sonst sehr schnell fehlerhafte Einträge entstehen und Programmabstürze die Folge sind.

Benutztung der Ctks

Der Zugriff auf die CombinedTimekeepings erfolgt ebenfalls über den jeweiligen Coworker. Dabei gibt es verschiedene Hashes und Mappings um möglichst schnell die gewünschten Daten zu erhalten

  • QList<CombinedTimekeeping*> m_listCombinedTimekeepings
    • Eine einfache Liste aller geladenen Ctks.
    • Benutzt im CombinedWorktimeBySystemModel.
  • QMap<QDate, QList<CombinedTimekeeping*>*> m_combinedTimekeepingsByDayList
    • Dies ist eine spezielle Map um eine Liste aller CombinedTimekeepings eines bestimmten Tages zu bekommen. Dabei ist zu beachten das Ereignisse die über mehrere Tage gehen (z.B. Urlaub oder Arbeit über Mitternacht hinaus) auch für jeden dieser Tage einmal in der Map gespeichert sind. Der Programmierer muss daher entsprechend beachten z.B. etwaige Ereignissdauern nicht doppelt zu verrechnen.
    • Benutzt im TimekeepingModelMonthly, CombinedWorktimesModel, TimekeepingReportDaily
  • QMap<QDate, QHash<Timekeeping::EventType, QList<CombinedTimekeeping*>*>*> m_combinedTimekeepingsByDayHash
    • Dies ist eine spezielle Map um eine Liste aller CombinedTimekeepings eines bestimmten Tages und eines bestimmten Typs zu bekommen. Ansonsten gilt das gleiche wie bei der zuvor genannten Struktur.
    • Benutzt im HolidayIllModel, HolidayIllReport, PlanningByCoworkerModel

Benutztung der Timekeepings

Timekeepings werden wie alle Resourcetypen nur als Smartpointer erstellt (genauer: QExplicitlySharedDataPointer) um die Speicherverwaltung zu vereinfachen. Über den entsprechenden Coworker kann über den dort angelegten Timekeeping-WebAccessor auf dessen Liste an geladenen Timekeepings zugegriffen werden.

Im Zuge der Umstellung auf die Erweiterung mit CombinedTimekeepigns wird jedoch stark empfohlen die ebenfalls im Coworker vorhandenen extra Listen zu benutzen:

  • QList<PTimekeeping> m_loadedTimekeepings
    • Die ist eine einfache Liste aller geladenen Timekeepings. Bei allen in dieser Liste vorkommenden Timekeepings ist sichergestellt, dass sie korrekt in die Strukturen der CombinedTimekeepigns eingegliedert sind und diese auch entsprechend synchron gehalten werden.
    • Auf dieser Liste basiert zum Beispiel das Basis Modell der TimekeepingModelDaily (Coworker->Zeiterfassung->Täglich)
  • QMap<QDateTime, PTimekeeping> m_mapTimekeepings
    • Eine Map um alle Timekeepings eines bestimmten Zeitpunkts zu bekommen. Achtung: Im allgemeinen gibt es pro Zeitpunkt nur ein Timekeeping und die Datenbank erlaubt auch keine Timekeepings gleichen Typs zum gleichen Zeitpunkt (zB zweimal "work_start" mit ts "01.01.2013T14:00:00") jedoch liegt es im Bereich des möglichen und erlaubten, dass zB. ein "work_start" und ein "break_start" zum exakt gleichen Zeitpunkt anzulegen. In diesem Fall würde sich hinter dem QDateTime also eine Liste an Timekeepings verbergen, was der Programmierer entsprechend beachten muss (Beispiele dafür finden sich in der Qt Doku).
    • Benutzt aktuell ebenfalls im TimekeepingModelDaily

Folgende Ereignistypen sind in der Datenbank definiert und können vom Timekeeping angenommen werden

  • work_start, work_stop (Arbeit)
  • private_start, private_stop (Privat)
  • driver_start, driver_stop (Fahrer)
  • break_start, break_stop (Pause)
  • customer_start, customer_stop (Kunde)
  • waiting_start, waiting_stop (Wartend)
  • holiday_start, holiday_stop (Urlaub)
  • ill_start, ill_stop (Krankheit)
  • alert (Alarm)
  • function_1, function_2, function_3 (Funktion 1-3)
  • garmin_id_1, garmin_id_2, garmin_id_3, garmin_id_4, garmin_id_5, garmin_id_6, garmin_id_7, garmin_id_8, garmin_driver_id

Beispiel des XML eines Timekeepings

<timekeeping generated-at="2013-07-02T17:30:37Z">
  <world-x type="float">9.290938</world-x>
  <world-y type="float">49.077442</world-y>
  <remarks nil="true"/>
  <created-at type="datetime">2013-07-02T17:24:36Z</created-at>
  <system-uuid type="string">90DB8C71-297D-4F34-A3AB-B3840DCC42B3</system-uuid>
  <user-timestamp type="datetime">2013-07-02T17:24:36Z</user-timestamp>
  <uuid type="string">44D3611E-E33C-11E2-9064-12314303963F</uuid>
  <updated-at type="datetime">2013-07-02T17:24:36Z</updated-at>
  <garmin-uuid type="string">D89BE2ED-82F8-43E1-BB3E-3FFE32ED9A0C</garmin-uuid>
  <telematik-timestamp type="datetime">2013-07-02T17:24:28Z</telematik-timestamp>
  <event type="string">garmin_id_3</event>
  <coworker-uuid type="string">5906DB16-6D11-4ECF-AA09-CC35EC88C406</coworker-uuid>
  <description nil="true"/>
  <map-text type="string">
    Staat: DE Land: Baden-Württemberg Landkreis: Heilbronn Postleitzahl: 74232 Stadt: Abstatt Strasse: Etrastraße 2
  </map-text>
</timekeeping>