Verträge / TicketTimerPatch
Ticket-Zeiterfassung Patch
TicketTimerPatch · com.nexoware.connect.events
- Aggregat
- TicketTimer · State TicketTimerState
- Topic
- tickettimer.patch je Mandant mit Präfix, z. B.
<mandant>.tickettimer.patch - Key
- TicketTimerUuid
- Nachrichtenart
- Patch — ausdrückliche Teiländerungen, zusammengeführt vom Zusammenführungsdienst
- Schreiber
- c-entron Webservice (centron) , NEXOWARE.ERP (nexoware-erp)
- Retention
- 30 Tage
- Fassung
- Version 1 (neueste)
- Schema-ID
- 104
Patch-Pfad
- Pflicht bei Anlage
- TicketUuid, Timing, Calculable, IsPlanned, IsDeleted, CreatedAt
- Fix nach Anlage
- TicketUuid, CreatedAt
Vertragsentwurf: typisierte Teilaenderung fuer Ticket-Zeiterfassung. Nur ChangedFields werden angewandt; null leert nur nullable State-Einheiten. Listen und Unterobjekte sind atomare Ersetzungen mit vollstaendigem Inhalt. Fachliche Freigabe und Regeln gekoppelter Werte sind offen; siehe docs/contracts/tickettimer.md.
Fassungen
Felder
-
EventId ↗ extern: EventId uuidBeim ersten Enqueue in die Outbox erzeugt; bei Wiederholung identisch.
-
TicketTimerUuid Key uuidStabile, global eindeutige Identitaet der Zeitbuchung (Matching-Schluessel; zugleich Message-Key).
-
Mode enum(CHANGE|INITIAL_LOAD)
-
ChangedFields Liste string[]Explizite Maske der geaenderten Top-Level-Einheiten; keine Wildcards, Identitaets- oder Auditfelder. Listen und Records werden als Ganzes ersetzt.
-
Data TicketTimerPatchData
10 Felder von
TicketTimerPatchData-
Default:
nullPflicht-Referenz auf das Ticket (Parent, Quelle RequestI3D non-null) ueber dessen UUID. Kann der Producer sie nicht aufloesen, scheitert die Avro-Projektion laut (Failed-Outbox-Zeile) statt still null zu senden. Consumer: Defer-and-Retry, wenn das Ticket noch nicht angekommen ist. Nur bei Anlage; fixedAfterCreate. -
Default:
nullReferenz auf den erfassenden Mitarbeiter (Quelle PersonalI3D) ueber dessen UUID. Fachlich traegt jede Zeitbuchung einen Mitarbeiter (der Save setzt den angemeldeten Benutzer als Default); optional, weil die Quell-Referenz mit NotFound.Ignore gemappt ist (fehlendes Stammdatum -> null). Aufloesbar erst mit employee.state (selbst DSGVO-blockiert) - bis dahin als opake Uuid speichern. -
Default:
nullReferenz auf den Abrechnungs-Artikel der Zeitbuchung (Quelle ArtikelI3D) ueber dessen UUID; DB nullable. -
TypeName optional stringDefault:
nullZeiterfassungs-Art als Wert-Kopie (HelpdeskTimerTypes.Name, z. B. Remote/Vor Ort; installationsspezifischer Katalog ohne eigenes Topic); DB nullable. -
Timing optional TicketTimerTimingDefault:
nullAtomare Zeitangaben: Start, Stop, DurationSeconds und LunchTimeSeconds werden gemeinsam ersetzt. DurationSeconds ist aus Stop - Start abgeleitet; keine einzelnen Patch-Pfade unter Timing. Der Producer liefert den vollstaendigen, konsistent berechneten Wert.4 Felder von
TicketTimerTiming-
Start timestampDefault:
0Beginn der Zeitbuchung als UTC-Instant (Quelle Start, non-null; Host-lokale Zeit, beim Publish nach UTC konvertiert). -
Stop timestampDefault:
0Ende der Zeitbuchung als UTC-Instant (Quelle Stop, non-null). -
DurationSeconds intDefault:
0Dauer in Sekunden (Quelle Timer; wird beim Save aus Stop - Start neu berechnet, Pausen nicht abgezogen). -
LunchTimeSeconds optional intDefault:
nullPausenzeit in Sekunden (Quelle LunchTime); DB nullable, der Save setzt 0 als Default.
-
-
Calculable optional booleanDefault:
nullAbrechenbar-Kennzeichen (Quelle Berechenbar, non-null). -
IsPlanned optional booleanDefault:
nullPlan-Kennzeichen (Quelle Geplant, non-null): true = geplante Zeit (noch keine Ist-Zeit), false = erfasste Ist-Zeit. -
ExternalNote optional stringDefault:
nullExterne Taetigkeitsbeschreibung / Servicebericht-Text (Quelle Bemerkung); DB nullable, der Save setzt Leerstring als Default. Die interne Notiz (InterneNotiz) ist bewusst NICHT Teil des Vertrags. -
IsDeleted optional booleanDefault:
nullLWW-Statusfeld: false bei jedem Save, true im letzten Voll-Snapshot vor dem quellseitigen Hard-Delete (HelpdeskTimerBL.DeleteHelpdeskTimer). Kein Tombstone - der bleibt der DSGVO-Erasure vorbehalten. -
CreatedAt optional timestampDefault:
nullAnlagezeitpunkt der Zeitbuchung als UTC-Instant (Quelle CreatedDate, vom Save immer gesetzt; Host-lokale Zeit, beim Publish nach UTC konvertiert). Nur bei Anlage; fixedAfterCreate.
-
-
Default:
nullUUID des aendernden Mitarbeiters (Employee); null, wenn unbekannt. -
ChangedAt timestampZeitpunkt der Aenderung als UTC-Instant.
Referenziert von
Kein Vertrag verweist auf diesen.
Rohfassung
Schema dieser Fassung (Avro)
{
"type": "record",
"name": "TicketTimerPatch",
"namespace": "com.nexoware.connect.events",
"doc": "Vertragsentwurf: typisierte Teilaenderung fuer Ticket-Zeiterfassung. Nur ChangedFields werden angewandt; null leert nur nullable State-Einheiten. Listen und Unterobjekte sind atomare Ersetzungen mit vollstaendigem Inhalt. Fachliche Freigabe und Regeln gekoppelter Werte sind offen; siehe docs/contracts/tickettimer.md.",
"fields": [
{
"name": "EventId",
"type": {
"type": "string",
"logicalType": "uuid"
},
"doc": "Beim ersten Enqueue in die Outbox erzeugt; bei Wiederholung identisch."
},
{
"name": "TicketTimerUuid",
"type": {
"type": "string",
"logicalType": "uuid"
},
"doc": "Stabile, global eindeutige Identitaet der Zeitbuchung (Matching-Schluessel; zugleich Message-Key)."
},
{
"name": "Mode",
"type": {
"type": "enum",
"name": "PatchMode",
"doc": "CHANGE: lokal autorisierte Aenderung, LWW je Einheit nach Kafka-Reihenfolge. INITIAL_LOAD: Erstbefuellung beim Anschluss eines Produkts - setzt eine Einheit nur, wenn sie noch nie geschrieben wurde; ueberschreibt nie einen vorhandenen oder ausdruecklich geleerten Wert. Bewusst ohne Enum-Default: ein unbekannter kuenftiger Modus darf nicht still als CHANGE gelesen werden.",
"symbols": [
"CHANGE",
"INITIAL_LOAD"
]
}
},
{
"name": "ChangedFields",
"type": {
"type": "array",
"items": "string"
},
"doc": "Explizite Maske der geaenderten Top-Level-Einheiten; keine Wildcards, Identitaets- oder Auditfelder. Listen und Records werden als Ganzes ersetzt."
},
{
"name": "Data",
"type": {
"type": "record",
"name": "TicketTimerPatchData",
"doc": "Werte der maskierten Einheiten. null ausserhalb der Maske wird ignoriert; innerhalb der Maske entscheidet die Nullability im State.",
"fields": [
{
"name": "TicketUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Pflicht-Referenz auf das Ticket (Parent, Quelle RequestI3D non-null) ueber dessen UUID. Kann der Producer sie nicht aufloesen, scheitert die Avro-Projektion laut (Failed-Outbox-Zeile) statt still null zu senden. Consumer: Defer-and-Retry, wenn das Ticket noch nicht angekommen ist. Nur bei Anlage; fixedAfterCreate.",
"default": null
},
{
"name": "EmployeeUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf den erfassenden Mitarbeiter (Quelle PersonalI3D) ueber dessen UUID. Fachlich traegt jede Zeitbuchung einen Mitarbeiter (der Save setzt den angemeldeten Benutzer als Default); optional, weil die Quell-Referenz mit NotFound.Ignore gemappt ist (fehlendes Stammdatum -> null). Aufloesbar erst mit employee.state (selbst DSGVO-blockiert) - bis dahin als opake Uuid speichern.",
"default": null
},
{
"name": "ArticleUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf den Abrechnungs-Artikel der Zeitbuchung (Quelle ArtikelI3D) ueber dessen UUID; DB nullable.",
"default": null
},
{
"name": "TypeName",
"type": [
"null",
"string"
],
"doc": "Zeiterfassungs-Art als Wert-Kopie (HelpdeskTimerTypes.Name, z. B. Remote/Vor Ort; installationsspezifischer Katalog ohne eigenes Topic); DB nullable.",
"default": null
},
{
"name": "Timing",
"type": [
"null",
{
"type": "record",
"name": "TicketTimerTiming",
"fields": [
{
"name": "Start",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
},
"doc": "Beginn der Zeitbuchung als UTC-Instant (Quelle Start, non-null; Host-lokale Zeit, beim Publish nach UTC konvertiert).",
"default": 0
},
{
"name": "Stop",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
},
"doc": "Ende der Zeitbuchung als UTC-Instant (Quelle Stop, non-null).",
"default": 0
},
{
"name": "DurationSeconds",
"type": "int",
"doc": "Dauer in Sekunden (Quelle Timer; wird beim Save aus Stop - Start neu berechnet, Pausen nicht abgezogen).",
"default": 0
},
{
"name": "LunchTimeSeconds",
"type": [
"null",
"int"
],
"doc": "Pausenzeit in Sekunden (Quelle LunchTime); DB nullable, der Save setzt 0 als Default.",
"default": null
}
]
}
],
"doc": "Atomare Zeitangaben: Start, Stop, DurationSeconds und LunchTimeSeconds werden gemeinsam ersetzt. DurationSeconds ist aus Stop - Start abgeleitet; keine einzelnen Patch-Pfade unter Timing. Der Producer liefert den vollstaendigen, konsistent berechneten Wert.",
"default": null
},
{
"name": "Calculable",
"type": [
"null",
"boolean"
],
"doc": "Abrechenbar-Kennzeichen (Quelle Berechenbar, non-null).",
"default": null
},
{
"name": "IsPlanned",
"type": [
"null",
"boolean"
],
"doc": "Plan-Kennzeichen (Quelle Geplant, non-null): true = geplante Zeit (noch keine Ist-Zeit), false = erfasste Ist-Zeit.",
"default": null
},
{
"name": "ExternalNote",
"type": [
"null",
"string"
],
"doc": "Externe Taetigkeitsbeschreibung / Servicebericht-Text (Quelle Bemerkung); DB nullable, der Save setzt Leerstring als Default. Die interne Notiz (InterneNotiz) ist bewusst NICHT Teil des Vertrags.",
"default": null
},
{
"name": "IsDeleted",
"type": [
"null",
"boolean"
],
"doc": "LWW-Statusfeld: false bei jedem Save, true im letzten Voll-Snapshot vor dem quellseitigen Hard-Delete (HelpdeskTimerBL.DeleteHelpdeskTimer). Kein Tombstone - der bleibt der DSGVO-Erasure vorbehalten.",
"default": null
},
{
"name": "CreatedAt",
"type": [
"null",
{
"type": "long",
"logicalType": "timestamp-millis"
}
],
"doc": "Anlagezeitpunkt der Zeitbuchung als UTC-Instant (Quelle CreatedDate, vom Save immer gesetzt; Host-lokale Zeit, beim Publish nach UTC konvertiert). Nur bei Anlage; fixedAfterCreate.",
"default": null
}
]
}
},
{
"name": "ChangedByUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "UUID des aendernden Mitarbeiters (Employee); null, wenn unbekannt.",
"default": null,
"references": "Employee"
},
{
"name": "ChangedAt",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
},
"doc": "Zeitpunkt der Aenderung als UTC-Instant."
}
],
"aggregate": "TicketTimer",
"label": "Ticket-Zeiterfassung",
"topic": "tickettimer.patch",
"key": "TicketTimerUuid",
"cleanupPolicy": "delete",
"retentionMs": 2592000000,
"partitions": 1,
"writers": [
"centron",
"nexoware-erp"
],
"requiredOnCreate": [
"TicketUuid",
"Timing",
"Calculable",
"IsPlanned",
"IsDeleted",
"CreatedAt"
],
"fixedAfterCreate": [
"TicketUuid",
"CreatedAt"
]
}