Stechuhr

    • VB.NET

    Es gibt 1 Antwort in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

      Proggi zur differenzierten Zeiterfassung

      Mit Stechuhr kann man die Bearbeitung von Aufgaben loggen, und er rechnet die Tages-arbeitszeit zusammen.
      Ausserdem anhand der zugrundegelegten Wochenarbeitszeit tages-aktuell die Plus-/Minus-Stunden
      Ausserdem kann man einen oder mehrere Tage wählen, und sich einen nach Tätigkeiten gruppierten "Zeiten-Bericht" anzeigen lassen.

      technische Besonderheiten

      Optimierte Schnell-Eingabe
      Man startet, schreibt den Aufgaben-Namen, und 2 * [Enter] - das fügt den Zeitpunkt zu, speichert und schließt. Somit ist die vorherige Aufgabe beendet, und die neue angefangen.
      Nur 2 * [Enter] - ohne Namen - fügt auch den Zeitpunkt zu, aber ohne AufgabenName fällt die Zeitspanne bis zur nächsten Aufgabe aus der Zeitberechnung raus (Pause oder Feierabend).
      2 * [Escape] schließt ohne Speichern

      TimeDoubleBehaviors
      Zeitspannen werden nicht als Timespan persistiert, sondern als Double, weil mit Timespan können berechnete Dataset-Spalten nicht rechnen (und Linq auch nicht).
      Das bedeutet für die Anzeige ein userdefined Parsing/Formatting, damit User mit gewohnter ZeitDarstellung "hh:mm" arbeiten können. Das Parsing ist unkaputtbar und super-praktisch: beliebige non-digit-Minuten-Separatoren werden akzeptiert, bzw. kann auch weggelassen werden.
      Bsp Eingaben: "135"-> "1:35", "13,5"-> "13:05", "13"-> "13:00"

      AutoCompletion
      aus den gespeicherten Texten wird eine AutoCompletion gebastelt und im Dgv-EditingControl bereitgestellt

      Feiertags-Berechnung
      in DateTimeX

      DataColumn-Expressions
      wird exzessiv eingesetzt - Extremfall ist StechuhrDts.Tag.SollColumn.Expression - eine so komplizierte Berechnung, dass sie codeseitig gesetzt werden muss, bei der Dts-Initialisierung

      Dts-Businesslogic
      in StechuhrDts.SmallClasses.vb. Überträge, Zeitdauern werden eventgesteuert berechnet und eingetragen, auch unter Zuhilfename der Event-Suspendierungs-Logik meines Dataset-Frameworks

      DgvCellStyler(Of T As DataRow)
      feuert praktischere Parsing/Formatting/CellPainting - Events als DatagridView

      Screenshot1:

      Man sieht folgende Situation:

      WochenArbeitsZeiten:
      Am 1.5.2017 wurde bei einer WochenArbeitsZeit von 32h begonnen - diese wurde am 23.5.2017 auf 40h erhöht. (Normal rechnet er die Überträge richtig, nur hab ich nachträglich noch in alten Datensätzen rumgepfuscht.)

      Tage:
      25, 27 + 28.5 weisen als Feiertag ("Holyday") keine Soll-Arbeitszeit auf, der 26.5. ist Frei genommen worden. (weitere TagTypen sind Krank und Uelaub - "K", "U")
      Das Bild ist vom 25.5.2017, deshalb ergibt sich für den 23.5. ein Saldo von -8h, ab 26.5. aber keine Salden, weil diese Tage liegen ja noch inne Zukunft.

      Geleistete Zeiten:
      Default-Wert ist <n.a.>, und so eine Zeit ist auszeit (Pause, Feierabend).
      Die anderen Texte sind Frei-Eingaben, denen ich als Prefix entweder # oder - verpasst hab. Das ist praktisch, denn wenn ich nun # eingebe, bietet Autocompletion mir alle # - Texte an, und bei - halt die anderen.
      Also AutoCompletionist wirklich unerhört praktisch: Ohne dass ich irgendeine weitere BusinessLogik coden musste, kann ich aus bestehenden Aufgaben auswählen, kann ohne Umstände neue Aufgaben zufügen, habe eine Kategorisierung der Aufgaben über die Prefixe.


      Screenshot2:

      Gezeigt ist ein Bericht über die (selectierten) Tage 24. und 25.5. Ebenso kann man natürlich auch nur einen Tag selecten oder Woche oder was wolle. Die Messagebox kann man auch mit Strg-C in den copy nehmen, und zB in einen Texteditor pasten.

      Verwendete Programmiersprache(n) und IDE(s):
      VB.Net 2013

      Systemveränderungen:
      keine
      (Naja, zur effizienten Benutzung muss der User eine DateiEndung (etwa .stu) auf die Exe registrieren - s. "Getting Started".
      Aber das macht ja nicht das Programm, sondern ihr selbst.)

      Lizenz/Weitergabe:
      OpenSource

      Getting Started:
      Ich stelle hier die Sources rein, keine Exe - wer das Proggi nutzen will, solls sich kompilieren.
      Kompiliert man als Debug-Version, so ist als "Heute" der 25.5.2017 eingestellt - das war inne Entwicklung nützlich, dass ich nicht jeden Tag einen neuen aktuellen Tag hatte.
      Kompiliert man Release gilt natürlich das wirkliche aktuelle Datum.
      Dem Datenfile habich die Extension .stu verpasst - ist ja egal.
      Konzept ist, dass man im WinExplorer auf eine .stu "KontextMenu-Öffnen-Mit" ausführt, und dann die Release-kompilierte Exe sucht, und "immer damit öffnen" einstellt.
      Dann kann man eine .stu-Datei auf den Desktop schmeissen, und einen Window-ShortCut einstellen, der diese Datei öffnet, etwa [Alt-Gr-S].
      Wenn ich also auf Arbeit beim Coden an einem Projekt herausgerissen werde zu einer Besprechung, drücke ich [Alt-Gr-S], #, b, [Enter], [Enter], und das Proggi schliesst wieder, und hat den Wechsel der Tätigkeit geloggt.
      Dank Auto-Zeit-Eintragen und AutoCompletion steht da auch #besprechung, obwohl ich ja nur #b drücktete.

      Selber dran schrauben:
      Wie gesagt, inne Debug-Version gilt ein fixes Datum.
      Ausserdem greift er bei Testläufen auf die im Projektordner mitgelieferte .stu zu - also wer mag kann die Release-Exe praktisch nutzen, mit einer .stu auffm Desktop, und paralell dazu eine Debug-Version weiterentwickeln.
      Dateien
      • StechUhr00.zip

        (222,97 kB, 314 mal heruntergeladen, zuletzt: )

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

      Nachtrag - Datenmodell

      Auch das Datenmodell ist etwas unüblich, weil es dem Phänomen Zeit in besonderer Weise gerecht zu werden sucht.
      Naiv gedacht hat eine Tätigkeit ja immer einen Anfang und ein Ende.
      In hiesiger Auffassung aber nicht. Eine Tätigkeit (Tat) hat nur einen Anfang. Das Ende extra noch zu erheben wäre redundant, weil dieses ist ja schon der Anfang der nächsten Tat.
      Diese redundanzfreie Modellierung von "Tätigkeit" vereinfacht nicht nur die Verarbeitung - sie verhindert auch von vornherein, dass Tätigkeiten sich zeitlich überlappen (wodurch Arbeitsstunden doppelt abgerechnet würden).

      Trotzdem hat meine Tat-DataTable eine Spalte Dauer - die enthält aber nur "Pseudo-Daten", sogenannte "berechnete Werte" (und dient auch nur zum Berechnen weiterer Werte)
      Also der User trägt nie die Dauer einer Tätigkeit ein, oder deren Ende, sondern immer nur die nächste Tat.
      NichtsTun in diesem Sinne ist somit auch eine Tat (nur wird deren Dauer nicht dem Stundenkonto gutgeschrieben).

      Ebenso verhält es sich mit den vertraglichen Stunden-Vereinbarungen (Wochen-Stunden-Soll). Bei einem Arbeitsvertrag mag man ja mit 40h/Wo anfangen, und dann auf 30h/Wo runtergehen oder sowas. Dadurch entsteht eine Historie (History) von Stunden-Vereinbarungen.
      Auch diese Zeitbereiche haben bei mir nur den Anfang, aber kein Ende. Sondern sie enden, wenn eine neue Stunden-Vereinbarungen in Kraft tritt.
      Hier also das rohe Datenmodell:

      Neben Tat, Tag und History gibts auch noch die Tabelle TagTyp, mit den Spalten Value und LongName.
      TagTyp sind Stammdaten, und kann sowas sein wie A/Arbeit, K/Krank, U/Urlaub, F/Feiertag.




      Und hier das erweiterte Datenmodell, welches zusätzlich allerlei Spalten für berechnete Werte enthält:

      Die History hat nun einen Wert TagesstundenSoll, berechnet aus der WochenArbeitsZeit.
      Tat hat berechnete Werte für Dauer und Bis, und kommt damit dem naiven Verständnis einer Tätigkeit entgegen.
      Tag hat nun StundenIst - berechnet als Summe aller Dauers aller Taten eines Tages.
      Tag.Soll ist einfach das TagesstundenSoll der zugehörigen History, und Tag.Saldo berechnet sich (bekanntermassen) aus StundenIst - StundenSoll.
      History hat SaldoSum - die Summe aller Tages-Salden, und SaldoTotal: das ist SaldoSum + Übertrag der SaldoSum der vorherigen History.
      Also meine Stechuhr kann das aktuelle Saldo des Stundenkontos tagesgenau anzeigen (deswegen habich sie programmiert ;) ).

      Dann gibts noch eine Extra-Tabelle ZeitenReport - die ist nur temporär. Da hinein kommen Zwischenergebnisse, wenn man mehrere Tage selektiert und berechnet, welche Taten im Zeitraum mit wievielen Stunden zu Buche schlugen und sowas.



      Ich denke, diesen Gedanken kann man verallgemeinern:
      Liegt eine History vor, also die zeitliche Abfolge verschiedener Zustände, so sollte man diese Zustände nicht modellieren mit Anfang und Ende (bzw Anfang und Dauer), sondern nur mit Anfang.
      Dauer / Ende sind berechnete Werte, die sich ergeben aus dem Anfang des nächsten Zustandes

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „ErfinderDesRades“ ()