Fundstellen fuer Taetigkeiten, Maschinen und Kostenstellen sowie die Buchungsendpunkte unter module/arbeitszeit/api/ (Nachtragen, Verteilung anlegen/aendern/loeschen, Schicht) mit Feldern, Antworten und offenen Fragen fuer die Poettker-App. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 KiB
Zeitbuchung in Agrarmonitor – Analyse
Stand: 2026-10-14 · Grundlage: Live-Erkundung in admin7.agrarmonitor.de (Web-Oberfläche, eingeloggt im Browser) und das aktuelle Frontend-Bundle assets/Admin.min.js. Die Kopie Fahrzeugübersicht/public/js/main.js ist veraltet (alte Endpunkte ajax-v3/arbeitszeit.php?id=… liefern heute 404).
Schreibende Requests wurden nur für den Testmitarbeiter 3309 abgesetzt (Freigabe durch Björn) und danach vollständig wieder gelöscht.
1. Stammdaten
Alle Livesearch-Endpunkte liefern ein HTML-Fragment. Paging: Der generische Livesearch-Client liest .pagination[data-pages] aus der Antwort; fehlt das Element oder ist data-pages ≤ 1, gibt es nur eine Seite. Bei Tätigkeiten und Maschinen gibt es aktuell kein Paging (alle Zeilen auf Seite 1, seite=2 liefert dieselben Zeilen).
Tätigkeiten (Tätigkeitsarten)
- Seite:
/arbeitszeit/taetigkeiten(„Arbeiten auf dem Betrieb verwalten“) - Livesearch:
GET /module/arbeitszeit/taetigkeiten-livesearch.php?seite=1&taetigkeiten_aktiv=1taetigkeiten_aktiv:0= nur aktive (Standard der Seite),1= aktive und inaktive,2= nur inaktive- aktuell 54 Tätigkeiten (33 aktiv)
- Aufbau: je „Bereich“ eine Überschrift
<h2><b class="bereich" data-id="17">100 Werkstatt (Mobil sichtbar)</b></h2>, darauf folgendtable.taetigkeit_table - Zeile:
tr[data-id][data-activityuuid]data-id= stabile Tätigkeits-ID (wird alstaetigkeit_idgebucht)- Spalten: 0 Nummer · 1 Bezeichnung · 2 Maschinen zuordnen (Ja/Nein) · 3 Abwesenheit · 4 Als Urlaub werten · 5 Notiz erzwingen · 6 Wartungsplan · 7 Erweiterte Effizienz · 8 Aktiv (
td.togglemit.fa-check= aktiv,.fa-close= inaktiv)
- Bereiche (aktuell): 100 Werkstatt, 200 Auftragsnebenzeiten, 300 Büro, 400 Hof-/Feldarbeit, 500 Gülle Mann solo, 600 LKW, 700 Rüstzeiten, 800 Pause, 900 Abwesenheit
- Hinweis: Bezeichnungen sind in Agrarmonitor teils abgeschnitten gespeichert (z. B. „Arbeiten, die keiner Maschine oder anderen Tätigkeit z“) – identisch in Liste und Buchungsformular.
Maschinen
- Seite:
/maschinen - Livesearch:
GET /module/maschinen/livesearch.php?suchstring=&maschinen_aktiv=1&maschinengruppe=0&seite=1maschinen_aktiv:0= nur aktive (Standard der Seite),1= aktive und inaktive,2= nur inaktivemaschinengruppe:0= alle Kategorien,-98= alle Zugmaschinen,-99= alle Anbaumaschinen, sonst Kategorie-ID
- Aufbau: je Kategorie eine Überschrift
<h2>Schlepper</h2>undtable.maschinen_table#maschinen_table_{kategorieId} - Zeile:
tr[data-id], Spalten: 0 Nummer · 1 Bezeichnung · 2 Kennzeichen · 3 Zähler · 4 Aktiv (.fa-check/.fa-close). Leere Werte werden als-angezeigt. - Eine Maschine kann in mehreren Kategorien stehen: 382 Zeilen, aber nur 263 verschiedene Maschinen (99 Maschinen mehrfach).
getMaschinen(gruppenId)sendet bereitsmaschinen_aktiv: 1, liefert also – anders als angenommen – aktive und inaktive Maschinen einer Kategorie. Paging ist für Maschinen nicht relevant (eine Seite).- Das Buchungsformular bietet nur eine Teilmenge an (147 Maschinen im Verteilungs-Formular, 243 im Nachtragen-Formular). Welche Maschinen dort fehlen (inaktive? nicht mobil sichtbare?), ist nicht geprüft.
Kostenstellen
- Es gibt keine Kostenstellen-Stammdaten (keine Seite, keine Livesearch, kein Auswahlfeld).
- „Kostenstelle“ ist nur ein Freitextfeld (max. 10 Zeichen) an Maschine (
/maschinen/detail/{id}, Feldkostenstelle), Mitarbeiter und Artikel. Es wird beim DATEV-Export verwendet (Einstellung „Kostenstellen exportieren“). - Das Modul „Betriebszweige“ (
/betriebszweige) ist in diesem Mandanten nicht freigeschaltet („Diese Seite existiert nicht“). - Eine Arbeitszeit-Buchung hat kein Kostenstellen-Feld. Am nächsten kommt das Feld Projekt (
projekt_id, 16 Projekte unter/projekte).
Mitarbeiter
getMitarbeiter()nutztmodule/mitarbeiter/livesearch.phpmitmitarbeiter_aktiv=1(= aktive und inaktive) unditemsperpage=100000– reicht für die Zuordnungam_mitarbeiter_id.
2. Buchungsschnittstelle
Gefunden: ja (Web-Oberfläche, JSON-Endpunkte unter module/arbeitszeit/api/). Die Token-API api.agrarmonitor.de/v1 ist nicht öffentlich dokumentiert (Weiterleitung auf agrarmonitor.de/schnittstellen, „Sprechen Sie uns an“); der Connector nutzt dort nur /kunden.
Datenmodell in Agrarmonitor
- Schicht (Anwesenheit): ein Zeitraum pro Mitarbeiter und Tag (
schicht_id), mehrere pro Tag möglich. - Verteilung: ein Tätigkeitsblock innerhalb einer Schicht (
verteilung_id), mit Tätigkeit, optional Maschine und Projekt, Notizen und Artikel-Ausgängen. - Pause: eigener Datensatz in der Schicht (
pause_id). - Zeit ohne Verteilung erscheint in der Tagesansicht als „Nicht zugeordnet“.
- Tagesansicht:
GET /arbeitszeit/detail/{mitarbeiterId}/{YYYY-MM-DD}; je Schichttable.verteilung_table#verteilung_table_{schichtId}[data-schicht], Zeilentr.betrieb[id={verteilungId}](Spalten: Zeit „HH:MM - HH:MM“, Arbeit, Kunde, Notiz, Kontrolle, Dauer). Auftrags-Zeiten stehen alstr.auftragdaneben.
Endpunkte (getestet mit Mitarbeiter 3309 am 14.10.2026)
Alle POST mit Content-Type: application/json, sofern nicht anders angegeben. Zeitformat in Formularen: dd.mm.yy (HH:MM) (z. B. 14.10.26 (08:00)), Ortszeit Europe/Berlin, minutengenau.
| Zweck | Request | Antwort |
|---|---|---|
| Tag nachtragen (legt Schicht + Verteilung an) | POST module/arbeitszeit/api/nachtragen.php, form-urlencoded (jQuery-Kodierung): form[…], tage[]=YYYY-MM-DD, anzahl_datum=1, planungAusMitarbeiterId=0 |
{"action":"link","target":"arbeitszeit/plan"} – keine ID |
| Formular einer bestehenden Verteilung laden (lesend) | module/arbeitszeit/api/editVerteilungForm.php {employeeID, date, distributionID} |
HTML form#verteilung_form[data-id] + form#notiz-form |
| Neue Verteilung in bestehender Schicht | editVerteilungForm.php {employeeID, date, shiftID} |
HTML-Formular; legt sofort eine leere Verteilung an, ihre ID steht in #verteilung_form[data-id]. Das UI löscht sie bei „Abbrechen“ wieder. |
| Verteilung speichern/ändern | module/arbeitszeit/api/updateVerteilung.php {mitarbeiterId, verteilungId, verteilungForm, notizForm} |
200 leerer Body; Validierungsfehler 422 mit JSON, z. B. {"verteilungForm":"ganzertag must be present"} |
| Verteilung löschen | module/arbeitszeit/api/deleteVerteilung.php {distributionID, employeeID, date} |
200 null; war es die letzte Verteilung: {"action":"link","target":"arbeitszeit"} und die Schicht wird mitgelöscht (ist_deleted: 1) |
| Schicht lesen | GET module/arbeitszeit/api/getSchicht.php?schicht_id= |
JSON (timestamp_start, timestamp_ende als YYYY-MM-DD HH:MM:SS, ist_deleted, …) |
| Schicht ändern | module/arbeitszeit/api/updateSchicht.php {shiftID, timestampStart, timestampEnd} (Format dd.mm.yy (HH:MM)) |
200 true |
| Schicht löschen | module/arbeitszeit/api/deleteSchicht.php {shiftID, employeeID, date} |
nicht getestet |
| Plausibilität prüfen | GET module/arbeitszeit/api/checkPlausibelInSchicht.php?timestamp_start×tamp_ende&mitarbeiterId |
[] oder {timestamp_start:{code,typ,msg}, …} – nicht getestet |
Weitere vorhandene Endpunkte (nicht getestet): updatePause.php/editPauseForm.php/deletePause.php, addNotiz.php ({verteilungId, notizfeld, verfasser_id} → {id,…}), startTaetigkeit.php/startPause.php/beendePause.php/beende-schicht.php (Stempeluhr des eingeloggten Benutzers).
Felder
verteilungForm (alle Werte als String):
| Feld | Bedeutung |
|---|---|
timestamp_start, timestamp_ende |
dd.mm.yy (HH:MM) |
taetigkeit_id |
Tätigkeits-ID |
alte_taetigkeit_id |
bisherige Tätigkeit (0 bei neuer Verteilung) |
maschine_id |
Maschinen-ID, 0 = keine |
projekt_id |
Projekt-ID, 0 = keines |
ganzertag |
Pflicht (1 oder 0.5; nur bei Abwesenheiten fachlich relevant) |
notizForm: notizfeld (Text; nicht leer → wird als neue Notiz an die Verteilung gehängt), verfasser_id (Mitarbeiter-ID des eingeloggten Benutzers, steht im Formular).
nachtragen.php → form[…]: mitarbeitertyp=1, mitarbeiter_id, taetigkeit_id, maschine_id, projekt_id, arbeitszeit_start/arbeitszeit_ende (HH:MM), pause_start/pause_ende (leer = keine Pause), notiz, uebernehmen=1 („In Arbeitszeit mit gewählter Dauer übernehmen“; 2 = ohne Dauer, 0 = nur Planung), kategorie_id=0, arbeitzeit_sollstunden=''.
Beobachtetes Verhalten
- Nachtragen legt eine Schicht exakt über den angegebenen Zeitraum und darin eine Verteilung an; die Notiz wird als Notizeintrag an der Verteilung gespeichert.
- Eine neue Verteilung über
editVerteilungForm+updateVerteilungverlängert die Schicht nicht (Zugeordnet 1,50 h bei Anwesend 0,75 h). Die Schicht muss perupdateSchicht.phpangepasst werden. updateVerteilungunddeleteVerteilungverkürzen die Schicht dagegen teils automatisch auf die verbleibenden Verteilungen.- Ändern und Löschen sind möglich; die Referenz ist die
verteilung_id(Zahl).
3. Vorschlag: App-Block → Agrarmonitor
| App | Agrarmonitor |
|---|---|
Mitarbeiter (users.am_mitarbeiter_id) |
mitarbeiterId / mitarbeiter_id / employeeID |
| Datum (Start des Arbeitstags) | date der Schicht (YYYY-MM-DD) |
Start, Ende (timestamptz) |
timestamp_start/timestamp_ende in Europe/Berlin, dd.mm.yy (HH:MM) – Sekunden gehen verloren |
Tätigkeitsart (activity_types.am_id) |
taetigkeit_id |
Maschine (machines.am_id) |
maschine_id (0 = keine) |
| Kostenstelle | kein Feld – siehe offene Fragen |
| Notiz | notizForm.notizfeld (bzw. form[notiz] beim Nachtragen) |
am_ref |
verteilung_id |
Ablauf createZeitbuchung:
- Tagesansicht
arbeitszeit/detail/{mitarbeiterId}/{datum}laden und Schicht(en) ermitteln. - Keine Schicht →
nachtragen.phpfür genau diesen Block; danach die Tagesansicht erneut laden und die neue Verteilung über Zeit (und Tätigkeit) finden →ref. - Schicht vorhanden →
editVerteilungForm.phpmitshiftID(liefert die neue ID) →updateVerteilung.phpmit den Daten; schlägt das fehl, den Platzhalter perdeleteVerteilung.phpwieder entfernen. Danach die Schicht perupdateSchicht.phpauf [frühester Start, spätestes Ende] erweitern.
updateZeitbuchung: updateVerteilung.php mit vollständigem Formular (alte Tätigkeit aus editVerteilungForm mit distributionID), danach Schicht erweitern. Notiz nur senden, wenn sie sich geändert hat (sonst entsteht ein doppelter Notizeintrag).
deleteZeitbuchung: deleteVerteilung.php.
4. Offene Fragen
- Kostenstelle: Agrarmonitor hat keine Kostenstellen-Stammdaten und kein Kostenstellen-Feld an der Buchung. Optionen: (a) Kostenstelle in der App streichen, (b) stattdessen Projekte (
projekt_id) verwenden, (c) Kostenstelle nur in die Notiz schreiben.getKostenstellen()habe ich deshalb in Schritt 2 nicht umgesetzt. - Pausen: Die App überträgt keine Pausen. Die Lücke zwischen zwei Blöcken erscheint in Agrarmonitor dann als „Nicht zugeordnet“ innerhalb der Schicht und zählt als Anwesenheit/Arbeitszeit. Sollen Pausen als Agrarmonitor-Pause (
updatePause.php) übertragen werden, oder soll jede Lücke eine eigene Schicht bekommen? - Parallele Erfassung: Stempeln Mitarbeiter zusätzlich in der Agrarmonitor-App, gibt es am selben Tag schon eine Schicht mit Verteilungen; App-Blöcke würden hineingebucht und können sich überschneiden. Vorher
checkPlausibelInSchicht.phpprüfen und bei Überschneidung ablehnen? - Über Mitternacht: Verteilungs-Zeitstempel enthalten das Datum, das Nachtragen nur
HH:MM. Blöcke über Mitternacht sind ungetestet. - Maschinenpflicht: Tätigkeiten mit „Maschinen zuordnen = Ja“ verlangen im UI eine Maschine (clientseitige Prüfung über
data-extra). Ob der Server das ebenfalls erzwingt, ist ungetestet – die App sollte es vorher prüfen (FeldmaschineZuordneningetTaetigkeiten). - Tätigkeitsauswahl: Das Buchungsformular bietet nur aktive Tätigkeiten an; Abwesenheiten (Bereich 900) und „800 Pause“ sollten in der App vermutlich ausgeblendet werden.
- Verfasser der Notiz:
verfasser_idist der Agrarmonitor-Benutzer des Connectors, nicht der Mitarbeiter.