verdigado / odoo-customize

GNU Affero General Public License v3.0
0 stars 1 forks source link

Gesetzliche Pausenzeiten automatisch abziehen #14

Closed albig closed 11 months ago

albig commented 1 year ago

In Deutschland ist nach Arbeitszeitgesetz eine Pause von 30 Minuten nach 6 Stunden einzuhalten. Nach 9 Stunden müssen es sogar 45 Minuten sein.

Es soll eine Option geben, dass diese Pause automatisch abgezogen werden, wenn ein MA keine oder zu wenig Pausen bucht.

Beispiel:

Bucht der MA sich zwischendurch aus, werden die Pause berücksichtigt, wenn sie mindestens 15 Minuten betragen.

Beispiel:

tv-openbig commented 1 year ago

@albig @hbrunn Ich fange zunächst einmal an mit einer Möglichkeit überhaupt "smooth" Pausenzeiten zu erfassen. Hier wäre die erste Spezifikation dafür. Im ersten Entwicklungsschritt kann vlt. die automatische Korrektur der Pausenzeiten (noch) außen vor bleiben. Ich denke allerdings, dass wir hierfür auch bereits einen Weg vorzeichnen können:

https://cloud.verdigado.com/index.php/s/FNqxN2oLyZo6sFH?dir=undefined&path=%2F&openfile=454092

tv-openbig commented 1 year ago

@albig @hbrunn

Hier wäre das kurze Recording des POC von Holger, der es ermöglicht Pausenzeiten vorschlagen zu lassen (Einstellungen am Mitarbeiter) , Pausenzeiten manuell einzutragen (auch mehrere Intervalle), Pausenzeiten abzuändern (wenn ein Standard unterschritten wird):

https://drive.google.com/file/d/188nMr3l6pNfwggsbBcziTL1NgEPD4GZB/view

Technisch wird der Arbeitstag in zwei Zeilen aufgesplittet, wobei dann z.B. zum Ende eines Zeitintervalls aus dem Working Calendars (40 Stunden, Montag Vormittag 08:00 bis 12:00) in der ersten Zeile das Log-Out Date automatisch gesetzt wird. In der zweiten Zeile wird dann das Login-Date berechnet aus Log-Out Date vorheriger Eintrag in hr.attendance + erfasste oder ermittelte Pausenzeit.

Hierdurch ergibt sich dann die Arbeitszeit wie im odoo Standard: Summiere für einen Tag das Delta aus Sign-Out Time - Sign-In Time.

Momentan ist im POC die Standard Pausenzeit beim Mitarbeiter hinterlegt. Hier wäre auch eine Tabelle denkbar, z.B. in Staffelform: Standardpause ab 4 Stunden: 00:30 ab 08 Stunden: 00:45 u.s.w.

Es werden auch Aktivitäten erstellt: z.B. "Du hast zuwenig Pause erfasst. Bitte korrigiere Deine Pausenzeit" Dies wird momentan beim hr.employee als activity geführt. Verlinkt werden soll die Referenz zum konkreten hr.attendance Eintrag an diesem Tag, um die Korrektur zu vereinfachen.

albig commented 1 year ago

Ich hatte den Stand der Implementierung von https://github.com/OCA/hr-attendance/pull/142 ausprobiert und bin mit dem Ansatz des Aufsplittens der Buchungen gar nicht glücklich. Klar, versteh ich das, dass das jetzt der billigste Weg ist.

Aber es ist nicht mehr nachvollziehbar, was der MA tatsächlich gebucht hat. Und das ist vermutlich in Zukunft auch notwendig, das nachweisen zu können.

Beispiel: Odoo - Anwesenheiten (2)

Der MA hat von 05:00 bis 07:30 Uhr gebucht und von 08:00 bis 14:52 Uhr. Die Pause von 11:00 Uhr bis 11:30 Uhr ist durch hr_attendance_break, was man nicht sehen kann und kalkulatorisch auch falsch ist (dürfte nur 15 Minuten sein).

Ich denke wir müssen die Pausen separat buchen und auch unterscheiden, ob die Pausenzeiten vom MA eingetragen wurden oder technisch hinzugefügt wurden.

hbrunn commented 1 year ago

Ich habe jetzt in dem branch das Datenmodell für die Pausen gepushed, und in der Listview von attendances funktioniert das auch. Da könnt Ihr dann die Woche über mit spielen ob das unerwünschte Nebenwirkungen hat bei Überstundenberechnung etc, sollte eigentlich nicht.

Achtung: Im aktuellen Stand koexistiert das nicht gut mit hr_attendance_autoclose, weil das ein eigenes Feld für die Arbeitszeit ausrechnet und das Originalfeld versteckt. Zum Testen daher am besten das Originalfeld mittels Debug-Modus wieder sichtbar machen. Auf weitere Berechnungen sollte das keine Auswirkungen haben, weil da immer das Originalfeld benutzt werden sollte.

Nächste Woche mache ich dann die UI fertig, und füge die Pausen noch in die Attendance Analysis ein?

albig commented 1 year ago

Danke Dir @hbrunn.

Drei Dinge:

  1. Ich habe beim Check-In über das Widget folgenden Fehler. Der kam auch mit dem Code-Stand gestern schon:
    
    UncaughtClientError > TypeError
    Uncaught Javascript Error > break_moment.hours is not a function

TypeError: break_moment.hours is not a function at Class._rpc (http://localhost:8169/web/assets/133-8bc5ede/web.assets_backend.min.js:9951:296) at Class. (http://localhost:8169/web/assets/68-2207f75/web.assets_common.min.js:4739:616) at Class._rpc (http://localhost:8169/web/assets/133-8bc5ede/web.assets_backend.min.js:9958:13) at Class._rpc (http://localhost:8169/web/assets/68-2207f75/web.assets_common.min.js:4739:371) at Class.update_attendance (http://localhost:8169/web/assets/133-8bc5ede/web.assets_backend.min.js:9789:897) at Class.update_attendance (http://localhost:8169/web/assets/133-8bc5ede/web.assets_backend.min.js:9958:319) at Class.update_attendance (http://localhost:8169/web/assets/68-2207f75/web.assets_common.min.js:4739:371) at Class. (http://localhost:8169/web/assets/133-8bc5ede/web.assets_backend.min.js:9789:392) at Class. (http://localhost:8169/web/assets/68-2207f75/web.assets_common.min.js:187:438) at Class. (http://localhost:8169/web/assets/68-2207f75/web.assets_common.min.js:149:39)



2. Wann erfolgt jetzt die Pausenberechnung? Einen Cron-Job find ich nicht.
3. Ja, die Pausen in der Attendance Analyse wäre sehr sinnvoll.
hbrunn commented 1 year ago
  1. das muss ich dann auf Eurem Testserver debuggen, ggf Unterschied zwischen ?debug=assets und ohne debug-Modus? Falls ja, sollte 'Regenerate assets' vom Debug-Menu helfen.
  2. den gibts auch noch nicht, bloss die Funktion die er rufen wird - die dann auch noch nicht auf das Pausen-Konzept aktualisiert ist
  3. prima
albig commented 1 year ago

hr_attendance_break ist jetzt auch in der Demo-Instanz installiert. Selbes verhalten wie lokal.

UncaughtClientError > TypeError
Uncaught Javascript Error > break_moment.hours is not a function
TypeError: break_moment.hours is not a function
    at Class._rpc (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_backend.js:145831:47) (/hr_attendance_break/static/src/js/hr_attendance_break.js:63)
    at Class.<anonymous> (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_common.js:61669:38) (/web/static/src/legacy/js/core/class.js:134)
    at Class._rpc (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_backend.js:145894:21) (/hr_attendance_reason/static/src/js/my_attendances.esm.js:47)
    at Class._rpc (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_common.js:61659:38) (/web/static/src/legacy/js/core/class.js:124)
    at Class.update_attendance (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_backend.js:139816:14) (/hr_attendance/static/src/js/my_attendances.js:39)
    at Class.update_attendance (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_backend.js:145910:18) (/hr_attendance_reason/static/src/js/my_attendances.esm.js:63)
    at Class.update_attendance (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_common.js:61659:38) (/web/static/src/legacy/js/core/class.js:124)
    at Class.<anonymous> (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_backend.js:139791:18) (/hr_attendance/static/src/js/my_attendances.js:14)
    at Class.<anonymous> (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_common.js:2867:36) (/web/static/lib/underscore/underscore.js:900)
    at Class.<anonymous> (https://odoo.demo.os.verdigado.net/web/assets/debug/web.assets_common.js:2089:29) (/web/static/lib/underscore/underscore.js:122)

2023-08-29_14-26

Es gibt in der Ansicht kein Element mit id="break-hours", was offenbar die Ursache ist.

Wenn man über den Kiosk-Mode geht, dann funktioniert der Check-In. Den Kiosk-Mode nutzen wir aber nicht.

hbrunn commented 1 year ago

mit dem fixup-commit sollte es gehen. Aber wie geschrieben, das macht noch die alte in-der-Mitte-splitten-Logik, dieser UI-Teil kommt erst nachste Woche mit dem Pausen-Modell.

albig commented 1 year ago

Ja, mit dem fixup-commit funktioniert der Check-In ohne Fehler. Dann warte ich mal das neue Pausen-Modell nächste Woche ab und teste dann weiter.

hbrunn commented 1 year ago

was machen wir jetzt eigentlich mit dem Konzept der Standard-Pause in dem neuen Setup? Wann fängt sie an, wann hört sie auf?

albig commented 1 year ago

was machen wir jetzt eigentlich mit dem Konzept der Standard-Pause in dem neuen Setup? Wann fängt sie an, wann hört sie auf?

Wir brauchen die Standard-Pause nach aktuellem deutschen Recht. D.h. 30 Minuten nach 6 Stunden und 15 Minuten nach 9 Stunden. Das sollte durch den Cronjob geprüft und ggf. Pausen hinzugefügt werden. Die Pausen-Records sind ja dann einem Attendance-Record zugeordnet, richtig? Dann wäre die Pause eben nach 6 bzw. 9 Stunden.

Beispiel: Check-In 8:00 Uhr Check-Out: 18 Uhr Pause: 14:00-14:30 Uhr und 17:00-17:15 Uhr Anwesenheitszeit: 10 h Netto-Arbeitszeit: 9:15 h

Der User kann eine Standard-Pausenlänge vorgeben - das meinst Du vermutlich auch, oder? Da bin ich mir auch unschlüssig, was das für einen Nutzen hat.

Beispiel: Nutzer konfiguriert 30 Minuten Check-In: 8:00 Uhr Check-Out: 14:00 Uhr Pause: 13:30 - 14:00 Uhr (Pause am Ende, Standardpause) --> Anwesenheitszeit: 6 h --> eigentlich keine Pause notwendig --> Netto-Arbeitszeit: 5:30 h

hbrunn commented 1 year ago

ja genau, der zweite Teil. Lasse ich dann erstmal weg

hbrunn commented 1 year ago

ich pushe mal den Zwischenstand mit funktionierender UI fur Pause via Checkin/out widget - bin nicht wirklich glücklich mit dem Handling, vielleicht könnt Ihr da vor dem Meeting noch draufschauen?

image

Mir scheint die Chance sehr hoch dass Menschen statt der Kaffeetasse den Checkout-Button erwischen. Und die Zahnräder als wieder-an-die-Arbeit-Knopf finde ich auch nicht ideal. Meinungen/Vorschläge?

Ich arbeite jetzt am Pausen-Warn-Cronjob + Konfiguration dafür, danach das glue-Modul dass das mit _autoclose funktioniert.

albig commented 1 year ago

Ich hab den Stand in der Demo-Instanz installiert.

Spontanes Feedback: Wenn ich in der Pause bin, sollte nur der Button für "Pause beenden" erscheinen. Dann wird es verständlicher.

Wenn man aus der Pause tatsächlich einen Check-Out machen möchte, müsste man zwei Mal klicken.

hbrunn commented 1 year ago

gerade noch zuwenig-Pausen-Flagging + Konfiguration geposted:

image

Erwartete Eingabe bei den Schwellen ist dann 9:00, 0:45 und 6:00, 0:30. Die Aktion auf die hier verlinkt wird kann ein beliebiger Typ sein, schauen wir uns am besten spater zusammen an

tv-openbig commented 1 year ago

@albig @hbrunn Hier ist der Testfall für normale Pausen an einem Arbeitstag (konkret zwei Pausen, je eine An- und Abmeldung): https://cloud.verdigado.com/index.php/s/FNqxN2oLyZo6sFH?dir=undefined&openfile=457143

hbrunn commented 1 year ago

ich habe jetzt dann den neuen Code für hr_attendance_break gepushed. Es sollte dann automatisch auch hr_attendance_break_autoclose installieren, um das sicher zu stellen habe ich dieses Modul dann im PR hier auch einfach zu den dependencies zugefügt.

Wenn das so für Euch gut ist, würde ich den PR im hr-attendance repo auf ready to review setzen.

albig commented 1 year ago

Ich bin dabei das Feature auszuprobieren.

Die Warnung über fehlende Pausen durch den Cron-Job scheint zu funktionieren.

Seh ich das richtig, dass das aber nur eine Warnung ist und die fehlende Pause nicht automatisch eingetragen wird? Haben wir uns da missverstanden, fehlt da noch was oder funktioniert nur mein Use-Case nicht (bevor ich jetzt lange suche...).

hbrunn commented 1 year ago

Missverständnis, ich dachte Ihr wollt es erstmal bei der Warnung belassen. Gib einfach an was genau passieren soll, dann implementiere ich das als Standardverhalten.

albig commented 1 year ago

Wenn der Cron feststellt, dass die Pausen nicht ausreichen, soll

hbrunn commented 1 year ago

1) soll ich die Pause in die Mitte der Anwesenheit setzen, oder ans Ende? Die Pause wird dann durch den User admin erstellt sein, ist das ausreichend zur Nachverfolgung oder soll ich ein Flag 'autogenerated' hinzufugen? 2) soll das dann besser eine Email sein statt einer Activity? Activities können (mit Bordmitteln) keinen record-spezifischen Text enthalten, in der Email kann ich dagegen beliebiges schreiben.

albig commented 1 year ago
  1. Ja, pack die Pause in die Mitte. Eine Markierung ähnlich bei attendance_reasons wäre sehr sinnvoll. Oder wollen wir einfach einen "Attendance Reason" nutzen, wie "Break(s) autogenerated"? Wenn natürlich mehrere Pausen während einer Attendance existieren, wissen wir nicht mehr, welche "autogenerated" ist.
  2. E-Mail wäre gut. Bekommt man da einen Link zum Attendance-Record hin? Quasi: "Bitte prüfen Sie Ihren Eintrag vom ... wir haben hier eine Pause von 0:30 Uhr automatisch hinzugefügt." O.ä.?
  3. Die allgemeinere Action ist dann trotzdem möglich?
  4. Wie lässt sich die E-Mail-Benachrichtigung dann abschalten? Pro User oder Global?
hbrunn commented 1 year ago
  1. prima, und den reason wurde ich dann auf die Pause selbst setzen, dann ist klar welche Pause woher kommt - Pausen via widget bekommen dann reason 'Break via Kiosk', und manuell erstellte per Default 'Manual break'? Eigentlich wollte ich die extra dependency auf hr_attendance_reason vermeiden, aber das Rad neu erfinden scheint mir noch weniger wünschenswert
  2. ja. Die Mail geht an employee_id.email + employee_id.parent_id.email in CC?
  3. klar, können Admins sich so zusammenklicken wie sie wollen
  4. Pro User ausschalten: 4.1. Entweder mir machen aus attendances mail.threads (das ist die Implementierung vom chatter), dann läuft das über den Odoo-Benachrichtigungs-Mechanismus der im User-Profil konfiguriert werden kann. Das kommt aber mit etwas Overhead, der Chatter wird auch nur in Form Views angezeigt, dh das integriert nicht gut mit dem Kiosk-Mode und dem editable Tree den es gerade gibt. 4.2. Ein flag auf dem User-Profil fur genau diese Mail 4.3. Ein kleiner Hack der im Email-Template nur Mails generiert fur User die in ihrem Profil Benachrichtigen via Email angeschaltet haben Global ausschalten ware einfach in der Aktion (das wird dann eine Multi-Server-Action) die Mail-Aktion rauswerfen. Ich neige eigentlich dazu pro User gar nichts zu machen, da das doch schon wichtige Information ist? Und wer die Mails nicht will soll halt so Zeit schreiben dass keine Mails generiert werden? Falls doch gewünscht, geht 4.3 mit Abstand am Schnellsten
albig commented 1 year ago
  1. Abhängigkeiten sind natürlich immer doof. Aber ja, machen wir erst mal so.
  2. Ja, Mail in CC an Parent.
  3. Brauch ich ggf. nur eine Einrichtungshilfe.
  4. Ok, dann lassen wir das zunächst so. Ggf. dann die 4.3. Wer die Benachrichtigungen per Mail ausschaltet, sollte dann auch diese nicht erhalten.
hbrunn commented 1 year ago

soeben die besprochenen Punkte gepushed. Achtung: Bei bestehenden DBs braucht das auch ein -i hr_attendance_break weil ich ein paar noupdate-records verändert habe.

albig commented 12 months ago

@hbrunn Ich habe den Stand von https://github.com/verdigado/odoo-customize/pull/18 und https://github.com/OCA/hr-attendance/pull/142 installiert.

Die Überstunden-Berechnung ist aber falsch:

1. Pause wird in Überstunden nicht berücksichtigt.

Im Beispiel hat der MA von 10:00 bis 18:54 Uhr gearbeitet. Seine Soll-Arbeitszeit sind 8:00 Stunden. hr_attendance_break hat korrekt eine Pause von 30 Minuten hinzugefügt. Manuell habe ich im Beispiel danach eine weitere Pause von 1 Stunde hinzugefügt. Ergibt netto eine Arbeitszeit von 07:24h. Es "fehlen" also 36 Minuten. Die "Überstunden" müssten -0:36 betragen.

2023-09-27_11-16

In den Überstunden findet das aber keine Berücksichtigung. Es werden 0:54 errechnet und zum Stundensaldo hinzugefügt.

2023-09-27_11-15

2. Im Bericht verdoppelt sich die Pausenzeit

Im Bericht ist die Pausenzeit verdoppelt. Hier sind es plötzlich 3h Pause. 2023-09-27_11-11

3. Bericht braucht noch die Soll-Arbeitszeit

Der Bericht ist so schwierig auszuwerten. Ohne Soll-Arbeitszeit kann man mit den Werten in der Spalte nicht auf Plausibilität prüfen.

Wünschenswert wäre

Soll-Arbeitszeit - Worked Hours = Überstunden, dabei wären die Pause zur Information

oder

Soll-Arbeitszeit - Ist-Arbeitszeit - Pausen = Überstunden

hbrunn commented 12 months ago

1+2 das sind Bugs sie ich heute gelöst bekommen sollte 3 das ist nicht trivial zu implementieren, wird diese Woche sicher nichts

albig commented 12 months ago

1+2 wäre super.

Könntest Du dann noch in verdigado_attendance ein Beispiel machen, wie ich das hr_attendance_break.template_mandatory_break richtig überschreibe, wäre das cool. Ich hatte mich daran gestern schon versucht, aber weiß nicht, ob das richtig war und sichergestellt ist, dass auch das angepasste Email-Template verwendet wird.

hbrunn commented 12 months ago

@albig wie gehen wir mit Pausen < 15min (bzw company.hr_attendance_break_min_break) um, werden die auch von den Überstunden abgezogen?

albig commented 12 months ago

Tja, gute Frage @hbrunn.

Nach dem aktuellen Konzept, werden die kürzeren Pausen nicht bei worked hours abgezogen, weil nur Pausen mit der Mindest-Länge in die Gesamt-Pausen-Berechnung einfließen.

Mmh. Das ist formal korrekt. Wenn man das nicht will, kann man den Schwellwert auf 00:00 setzen, richtig?

Dann sollten wir weiterhin so verfahren. Bei den Überstunden müsste dann folgendes berechnet werden:

Soll-Arbeitszeit - Ist-Arbeitszeit - (Pausen >= Schwellwert) = Überstunden

hbrunn commented 12 months ago
  1. war trickier als erwartet weil der core-code da recht erweiterungsunfreundlich geschrieben ist
  2. erledigt in #18

Was das email-Template angeht: Das ist ein noupdate-Record, deshalb kannst Du das mit einem normalen Update nicht überschreiben. -i oder Code der das noupdate-Flag auf False setzt würde funktionieren, aber Du willst ja auch nicht bei Updates immer das Template überschreiben, um nicht die Möglichkeit zu verbauen dass das nach Auslieferung angepasst wird, richtig? Für neue Installationen ist das egal, weil bei der Installation von neuen Modulen noupdate-Records doch überschrieben werden.

Bei bestehenden Installationen führt kein Weg um ein Migrationsscript, das das Template überschreibt und die Übersetzungen (achja, Übersetzungen bekommst Du gar nicht überschrieben, auch nicht mit -i. Dafür gibt es --i18n-overwrite, das dann aber alle Übersetzungen des Moduls überschreibt) aktualisiert. Wenn Du Template + Übersetzung auf einen Branch pushst, kann ich nächste Woche ein entsprechendes Migrationsscript dazusetzen.

Zum Entwickeln/Testen kannst Du am Besten in Deiner dev-Datenbank im Debug-Modus das noupdate-Flag wegnehmen, und die Übersetzung aus ir_translation löschen (letzteres geht auch halbwegs komfortabel in Einstellungen/Übersetzungen/Übersetzte Begriffe).